<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGraphicsFactory.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkObjectFactory.h"

#include "vtkGraphicsFactory.h"
#include "vtkToolkits.h"
#include "vtkDebugLeaks.h"

// if using some sort of opengl, then include these files
#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON)
#include "vtkOpenGLActor.h"
#include "vtkOpenGLCamera.h"
#include "vtkOpenGLImageActor.h"
#include "vtkOpenGLLight.h"
#include "vtkOpenGLProperty.h"
#include "vtkOpenGLPolyDataMapper.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLVolumeTextureMapper2D.h"
#include "vtkOpenGLVolumeRayCastMapper.h"
#include "vtkOpenGLRayCastImageDisplayHelper.h"
#endif

// Win32 specific stuff
#ifdef _WIN32
# ifndef VTK_USE_OGLR
#  include "vtkWin32OpenGLRenderWindow.h"
#  include "vtkWin32RenderWindowInteractor.h"
#  define VTK_DISPLAY_WIN32_OGL
# endif // VTK_USE_OGLR
#endif

// Apple OSX stuff
#ifdef VTK_USE_CARBON
# include "vtkCarbonRenderWindow.h"
# include "vtkCarbonRenderWindowInteractor.h"
# define VTK_DISPLAY_CARBON
#endif

#ifdef VTK_USE_COCOA
# include "vtkCocoaRenderWindow.h"
# include "vtkCocoaRenderWindowInteractor.h"
# define VTK_DISPLAY_COCOA
#endif

// X OpenGL stuff
#ifdef VTK_USE_OGLR
# include "vtkXRenderWindowInteractor.h"
# include "vtkXOpenGLRenderWindow.h"
# define VTK_DISPLAY_X11_OGL
#endif

#if defined(VTK_USE_MANGLED_MESA)
#include "vtkMesaActor.h"
#include "vtkMesaCamera.h"
#include "vtkMesaImageActor.h"
#include "vtkMesaLight.h"
#include "vtkMesaProperty.h"
#include "vtkMesaPolyDataMapper.h"
#include "vtkMesaRenderer.h"
#include "vtkMesaTexture.h"
#include "vtkMesaVolumeTextureMapper2D.h"
#include "vtkMesaVolumeRayCastMapper.h"
#include "vtkXMesaRenderWindow.h"
#endif

#include "vtkCriticalSection.h"

#include "stdlib.h"

static vtkSimpleCriticalSection vtkUseMesaClassesCriticalSection;
int vtkGraphicsFactory::UseMesaClasses = 0;

vtkCxxRevisionMacro(vtkGraphicsFactory, "1.34");
vtkStandardNewMacro(vtkGraphicsFactory);

const char *vtkGraphicsFactory::GetRenderLibrary()
{
  const char *temp;

  // first check the environment variable
  temp = getenv("VTK_RENDERER");

  // Backward compatibility
  if ( temp )
    {
    if (!strcmp("oglr",temp))
      {
      temp = "OpenGL";
      }
    else if (!strcmp("woglr",temp))
      {
      temp = "Win32OpenGL";
      }
    else if (strcmp("OpenGL",temp) &&
             strcmp("Win32OpenGL",temp))
      {
      vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp);
      temp = NULL;
      }
    }

  // if nothing is set then work down the list of possible renderers
  if ( !temp )
    {
#ifdef VTK_DISPLAY_X11_OGL
    temp = "OpenGL";
#endif
#ifdef VTK_DISPLAY_WIN32_OGL
    temp = "Win32OpenGL";
#endif
#ifdef VTK_DISPLAY_CARBON
    temp = "CarbonOpenGL";
#endif
#ifdef VTK_DISPLAY_COCOA
    temp = "CocoaOpenGL";
#endif
    }

  return temp;
}

vtkObject* vtkGraphicsFactory::CreateInstance(const char* vtkclassname )
{
  // first check the object factory
  vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname);
  if (ret)
    {
    return ret;
    }
  // if the factory failed to create the object,
  // then destroy it now, as vtkDebugLeaks::ConstructClass was called
  // with vtkclassname, and not the real name of the class
#ifdef VTK_DEBUG_LEAKS
  vtkDebugLeaks::DestructClass(vtkclassname);
#endif
  const char *rl = vtkGraphicsFactory::GetRenderLibrary();

#ifdef VTK_USE_OGLR
  if (!strcmp("OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkXMesaRenderWindow::New();
        }
#endif
      return vtkXOpenGLRenderWindow::New();
      }
    }
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkXRenderWindowInteractor::New();
    }
#endif

#ifdef VTK_DISPLAY_WIN32_OGL
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkWin32RenderWindowInteractor::New();
    }
  if (!strcmp("Win32OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
      {
      return vtkWin32OpenGLRenderWindow::New();
      }
    }
#endif

#ifdef VTK_USE_CARBON
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkCarbonRenderWindowInteractor::New();
    }
  if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
    {
    return vtkCarbonRenderWindow::New();
    }
#endif
#ifdef VTK_USE_COCOA
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkCocoaRenderWindowInteractor::New();
    }
  if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
    {
    return vtkCocoaRenderWindow::New();
    }
#endif

#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON)
  if (!strcmp("OpenGL",rl) || !strcmp("Win32OpenGL",rl) || !strcmp("CarbonOpenGL",rl) || !strcmp("CocoaOpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkActor") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaActor::New();
        }
#endif
      return vtkOpenGLActor::New();
      }
    if(strcmp(vtkclassname, "vtkCamera") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaCamera::New();
        }
#endif
      return vtkOpenGLCamera::New();
      }
    if(strcmp(vtkclassname, "vtkImageActor") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaImageActor::New();
        }
#endif
      return vtkOpenGLImageActor::New();
      }
    if(strcmp(vtkclassname, "vtkLight") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaLight::New();
        }
#endif
      return vtkOpenGLLight::New();
      }
    if(strcmp(vtkclassname, "vtkProperty") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaProperty::New();
        }
#endif
      return vtkOpenGLProperty::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaPolyDataMapper::New();
        }
#endif
      return vtkOpenGLPolyDataMapper::New();
      }
    if(strcmp(vtkclassname, "vtkRenderer") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaRenderer::New();
        }
#endif
      return vtkOpenGLRenderer::New();
      }
    if(strcmp(vtkclassname, "vtkTexture") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaTexture::New();
        }
#endif
      return vtkOpenGLTexture::New();
      }
    if(strcmp(vtkclassname, "vtkVolumeTextureMapper2D") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaVolumeTextureMapper2D::New();
        }
#endif
      return vtkOpenGLVolumeTextureMapper2D::New();
      }
    if(strcmp(vtkclassname, "vtkVolumeRayCastMapper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaVolumeRayCastMapper::New();
        }
#endif
      return vtkOpenGLVolumeRayCastMapper::New();
      }
    if(strcmp(vtkclassname, "vtkRayCastImageDisplayHelper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaRayCastImageDisplayHelper::New();
        }
#endif
      return vtkOpenGLRayCastImageDisplayHelper::New();
      }
    }
#endif

  return 0;
}

void vtkGraphicsFactory::SetUseMesaClasses(int use)
{
  vtkUseMesaClassesCriticalSection.Lock();
  vtkGraphicsFactory::UseMesaClasses = use;
  vtkUseMesaClassesCriticalSection.Unlock();
}

int vtkGraphicsFactory::GetUseMesaClasses()
{
  return vtkGraphicsFactory::UseMesaClasses;
}

//----------------------------------------------------------------------------
void vtkGraphicsFactory::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>ERR: second attempt to fix mesa issues...<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGraphicsFactory.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkObjectFactory.h"

#include "vtkGraphicsFactory.h"
#include "vtkToolkits.h"
#include "vtkDebugLeaks.h"

// if using some sort of opengl, then include these files
#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON)
#include "vtkOpenGLActor.h"
#include "vtkOpenGLCamera.h"
#include "vtkOpenGLImageActor.h"
#include "vtkOpenGLLight.h"
#include "vtkOpenGLProperty.h"
#include "vtkOpenGLPolyDataMapper.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLVolumeTextureMapper2D.h"
#include "vtkOpenGLVolumeRayCastMapper.h"
#include "vtkOpenGLRayCastImageDisplayHelper.h"
#endif

// Win32 specific stuff
#ifdef _WIN32
# ifndef VTK_USE_OGLR
#  include "vtkWin32OpenGLRenderWindow.h"
#  include "vtkWin32RenderWindowInteractor.h"
#  define VTK_DISPLAY_WIN32_OGL
# endif // VTK_USE_OGLR
#endif

// Apple OSX stuff
#ifdef VTK_USE_CARBON
# include "vtkCarbonRenderWindow.h"
# include "vtkCarbonRenderWindowInteractor.h"
# define VTK_DISPLAY_CARBON
#endif

#ifdef VTK_USE_COCOA
# include "vtkCocoaRenderWindow.h"
# include "vtkCocoaRenderWindowInteractor.h"
# define VTK_DISPLAY_COCOA
#endif

// X OpenGL stuff
#ifdef VTK_USE_OGLR
# include "vtkXRenderWindowInteractor.h"
# include "vtkXOpenGLRenderWindow.h"
# define VTK_DISPLAY_X11_OGL
#endif

#if defined(VTK_USE_MANGLED_MESA)
#include "vtkMesaActor.h"
#include "vtkMesaCamera.h"
#include "vtkMesaImageActor.h"
#include "vtkMesaLight.h"
#include "vtkMesaProperty.h"
#include "vtkMesaPolyDataMapper.h"
#include "vtkMesaRayCastImageDisplayHelper.h"
#include "vtkMesaRenderer.h"
#include "vtkMesaTexture.h"
#include "vtkMesaVolumeTextureMapper2D.h"
#include "vtkMesaVolumeRayCastMapper.h"
#include "vtkXMesaRenderWindow.h"
#endif

#include "vtkCriticalSection.h"

#include "stdlib.h"

static vtkSimpleCriticalSection vtkUseMesaClassesCriticalSection;
int vtkGraphicsFactory::UseMesaClasses = 0;

vtkCxxRevisionMacro(vtkGraphicsFactory, "1.35");
vtkStandardNewMacro(vtkGraphicsFactory);

const char *vtkGraphicsFactory::GetRenderLibrary()
{
  const char *temp;

  // first check the environment variable
  temp = getenv("VTK_RENDERER");

  // Backward compatibility
  if ( temp )
    {
    if (!strcmp("oglr",temp))
      {
      temp = "OpenGL";
      }
    else if (!strcmp("woglr",temp))
      {
      temp = "Win32OpenGL";
      }
    else if (strcmp("OpenGL",temp) &&
             strcmp("Win32OpenGL",temp))
      {
      vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp);
      temp = NULL;
      }
    }

  // if nothing is set then work down the list of possible renderers
  if ( !temp )
    {
#ifdef VTK_DISPLAY_X11_OGL
    temp = "OpenGL";
#endif
#ifdef VTK_DISPLAY_WIN32_OGL
    temp = "Win32OpenGL";
#endif
#ifdef VTK_DISPLAY_CARBON
    temp = "CarbonOpenGL";
#endif
#ifdef VTK_DISPLAY_COCOA
    temp = "CocoaOpenGL";
#endif
    }

  return temp;
}

vtkObject* vtkGraphicsFactory::CreateInstance(const char* vtkclassname )
{
  // first check the object factory
  vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname);
  if (ret)
    {
    return ret;
    }
  // if the factory failed to create the object,
  // then destroy it now, as vtkDebugLeaks::ConstructClass was called
  // with vtkclassname, and not the real name of the class
#ifdef VTK_DEBUG_LEAKS
  vtkDebugLeaks::DestructClass(vtkclassname);
#endif
  const char *rl = vtkGraphicsFactory::GetRenderLibrary();

#ifdef VTK_USE_OGLR
  if (!strcmp("OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkXMesaRenderWindow::New();
        }
#endif
      return vtkXOpenGLRenderWindow::New();
      }
    }
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkXRenderWindowInteractor::New();
    }
#endif

#ifdef VTK_DISPLAY_WIN32_OGL
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkWin32RenderWindowInteractor::New();
    }
  if (!strcmp("Win32OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
      {
      return vtkWin32OpenGLRenderWindow::New();
      }
    }
#endif

#ifdef VTK_USE_CARBON
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkCarbonRenderWindowInteractor::New();
    }
  if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
    {
    return vtkCarbonRenderWindow::New();
    }
#endif
#ifdef VTK_USE_COCOA
  if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0)
    {
    return vtkCocoaRenderWindowInteractor::New();
    }
  if(strcmp(vtkclassname, "vtkRenderWindow") == 0)
    {
    return vtkCocoaRenderWindow::New();
    }
#endif

#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON)
  if (!strcmp("OpenGL",rl) || !strcmp("Win32OpenGL",rl) || !strcmp("CarbonOpenGL",rl) || !strcmp("CocoaOpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkActor") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaActor::New();
        }
#endif
      return vtkOpenGLActor::New();
      }
    if(strcmp(vtkclassname, "vtkCamera") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaCamera::New();
        }
#endif
      return vtkOpenGLCamera::New();
      }
    if(strcmp(vtkclassname, "vtkImageActor") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaImageActor::New();
        }
#endif
      return vtkOpenGLImageActor::New();
      }
    if(strcmp(vtkclassname, "vtkLight") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaLight::New();
        }
#endif
      return vtkOpenGLLight::New();
      }
    if(strcmp(vtkclassname, "vtkProperty") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaProperty::New();
        }
#endif
      return vtkOpenGLProperty::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaPolyDataMapper::New();
        }
#endif
      return vtkOpenGLPolyDataMapper::New();
      }
    if(strcmp(vtkclassname, "vtkRenderer") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaRenderer::New();
        }
#endif
      return vtkOpenGLRenderer::New();
      }
    if(strcmp(vtkclassname, "vtkTexture") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaTexture::New();
        }
#endif
      return vtkOpenGLTexture::New();
      }
    if(strcmp(vtkclassname, "vtkVolumeTextureMapper2D") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaVolumeTextureMapper2D::New();
        }
#endif
      return vtkOpenGLVolumeTextureMapper2D::New();
      }
    if(strcmp(vtkclassname, "vtkVolumeRayCastMapper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaVolumeRayCastMapper::New();
        }
#endif
      return vtkOpenGLVolumeRayCastMapper::New();
      }
    if(strcmp(vtkclassname, "vtkRayCastImageDisplayHelper") == 0)
      {
#if defined(VTK_USE_MANGLED_MESA)
      if ( vtkGraphicsFactory::UseMesaClasses )
        {
        return vtkMesaRayCastImageDisplayHelper::New();
        }
#endif
      return vtkOpenGLRayCastImageDisplayHelper::New();
      }
    }
#endif

  return 0;
}

void vtkGraphicsFactory::SetUseMesaClasses(int use)
{
  vtkUseMesaClassesCriticalSection.Lock();
  vtkGraphicsFactory::UseMesaClasses = use;
  vtkUseMesaClassesCriticalSection.Unlock();
}

int vtkGraphicsFactory::GetUseMesaClasses()
{
  return vtkGraphicsFactory::UseMesaClasses;
}

//----------------------------------------------------------------------------
void vtkGraphicsFactory::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>


<commit_before>#pragma once

#include "World/CEntityInfo.hpp"
#include "zeus/CVector3f.hpp"

namespace urde {
class CStateManager;
class CMaterialFilter;

class CCameraSpline {
  friend class CBallCamera;
  std::vector<zeus::CVector3f> x4_positions;
  std::vector<TUniqueId> x14_wpTracker;
  std::vector<float> x24_t;
  std::vector<zeus::CVector3f> x34_directions;
  float x44_length = 0.f;
  bool x48_closedLoop = false;
  bool GetSurroundingPoints(int idx, rstl::reserved_vector<zeus::CVector3f, 4>& positions,
                            rstl::reserved_vector<zeus::CVector3f, 4>& directions) const;

public:
  CCameraSpline(bool closedLoop);
  void CalculateKnots(TUniqueId cameraId, const std::vector<SConnection>& connections, CStateManager& mgr);
  void Initialize(TUniqueId cameraId, const std::vector<SConnection>& connections, CStateManager& mgr);
  void Reset(int size);
  void AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir);
  void SetKnotPosition(int idx, const zeus::CVector3f& pos);
  const zeus::CVector3f& GetKnotPosition(int idx) const;
  float GetKnotT(int idx) const;
  float CalculateSplineLength();
  void UpdateSplineLength() { x44_length = CalculateSplineLength(); }
  zeus::CTransform GetInterpolatedSplinePointByLength(float pos) const;
  zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range) const;
  float FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const;
  float ValidateLength(float t) const;
  float ClampLength(const zeus::CVector3f& pos, bool collide, const CMaterialFilter& filter,
                    const CStateManager& mgr) const;
  s32 GetSize() const { return x4_positions.size(); }
  float GetLength() const { return x44_length; }
  bool IsClosedLoop() const { return x48_closedLoop; }
};

} // namespace urde
<commit_msg>CCameraSpline: Make constructor explicit<commit_after>#pragma once

#include "World/CEntityInfo.hpp"
#include "zeus/CVector3f.hpp"

namespace urde {
class CStateManager;
class CMaterialFilter;

class CCameraSpline {
  friend class CBallCamera;
  std::vector<zeus::CVector3f> x4_positions;
  std::vector<TUniqueId> x14_wpTracker;
  std::vector<float> x24_t;
  std::vector<zeus::CVector3f> x34_directions;
  float x44_length = 0.f;
  bool x48_closedLoop = false;
  bool GetSurroundingPoints(int idx, rstl::reserved_vector<zeus::CVector3f, 4>& positions,
                            rstl::reserved_vector<zeus::CVector3f, 4>& directions) const;

public:
  explicit CCameraSpline(bool closedLoop);
  void CalculateKnots(TUniqueId cameraId, const std::vector<SConnection>& connections, CStateManager& mgr);
  void Initialize(TUniqueId cameraId, const std::vector<SConnection>& connections, CStateManager& mgr);
  void Reset(int size);
  void AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir);
  void SetKnotPosition(int idx, const zeus::CVector3f& pos);
  const zeus::CVector3f& GetKnotPosition(int idx) const;
  float GetKnotT(int idx) const;
  float CalculateSplineLength();
  void UpdateSplineLength() { x44_length = CalculateSplineLength(); }
  zeus::CTransform GetInterpolatedSplinePointByLength(float pos) const;
  zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range) const;
  float FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const;
  float ValidateLength(float t) const;
  float ClampLength(const zeus::CVector3f& pos, bool collide, const CMaterialFilter& filter,
                    const CStateManager& mgr) const;
  s32 GetSize() const { return x4_positions.size(); }
  float GetLength() const { return x44_length; }
  bool IsClosedLoop() const { return x48_closedLoop; }
};

} // namespace urde
<|endoftext|>


<commit_before>#include "rxcpp/rx.hpp"
namespace rx=rxcpp;
namespace rxu=rxcpp::util;
namespace rxo=rxcpp::operators;
namespace rxs=rxcpp::sources;
namespace rxsc=rxcpp::schedulers;
namespace rxsub=rxcpp::subjects;
namespace rxn=rxcpp::notifications;

#include "rxcpp/rx-test.hpp"
namespace rxt=rxcpp::test;

#include "catch.hpp"

SCENARIO("publish range", "[hide][range][subject][publish][operators]"){
    GIVEN("a range"){
        WHEN("published"){
            auto published = rxs::range<int>(0, 10).publish();
            std::cout << "subscribe to published" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
            std::cout << "connect to published" << std::endl;
            published.connect();
        }
        WHEN("ref_count is used"){
            auto published = rxs::range<int>(0, 10).publish().ref_count();
            std::cout << "subscribe to ref_count" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
        }
        WHEN("connect_forever is used"){
            auto published = rxs::range<int>(0, 10).publish().connect_forever();
            std::cout << "subscribe to connect_forever" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
        }
    }
}

SCENARIO("publish", "[publish][multicast][operators]"){
    GIVEN("a test hot observable of longs"){
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        typedef rxsc::test::messages<int> m;
        typedef rxn::subscription life;
        typedef m::recorded_type record;
        auto on_next = m::on_next;
        auto on_completed = m::on_completed;
        auto subscribe = m::subscribe;

        long invoked = 0;

        record messages[] = {
            on_next(110, 7),
            on_next(220, 3),
            on_next(280, 4),
            on_next(290, 1),
            on_next(340, 8),
            on_next(360, 5),
            on_next(370, 6),
            on_next(390, 7),
            on_next(410, 13),
            on_next(430, 2),
            on_next(450, 9),
            on_next(520, 11),
            on_next(560, 20),
            on_completed(600)
        };
        auto xs = sc.make_hot_observable(messages);

        auto res = w.make_subscriber<int>();

        rx::connectable_observable<int> ys;

        WHEN("subscribed and then connected"){

            w.schedule_absolute(rxsc::test::created_time,
                [&invoked, &ys, &xs](const rxsc::schedulable& scbl){
                    ys = xs.publish().as_dynamic();
                    //ys = xs.publish_last().as_dynamic();
                });

            w.schedule_absolute(rxsc::test::subscribed_time,
                [&ys, &res](const rxsc::schedulable& scbl){
                ys.subscribe(res);
            });

            w.schedule_absolute(rxsc::test::unsubscribed_time,
                [&res](const rxsc::schedulable& scbl){
                    res.unsubscribe();
                });

            {
                rx::composite_subscription connection;

                w.schedule_absolute(300,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(400,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            {
                rx::composite_subscription connection;

                w.schedule_absolute(500,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(550,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            {
                rx::composite_subscription connection;

                w.schedule_absolute(650,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(800,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            w.start();

            THEN("the output only contains items sent while subscribed"){
                record items[] = {
                    on_next(340, 8),
                    on_next(360, 5),
                    on_next(370, 6),
                    on_next(390, 7),
                    on_next(520, 11)
                };
                auto required = rxu::to_vector(items);
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there were 3 subscription/unsubscription"){
                life items[] = {
                    subscribe(300, 400),
                    subscribe(500, 550),
                    subscribe(650, 800)
                };
                auto required = rxu::to_vector(items);
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

<commit_msg>add publish test<commit_after>#include "rxcpp/rx.hpp"
namespace rx=rxcpp;
namespace rxu=rxcpp::util;
namespace rxo=rxcpp::operators;
namespace rxs=rxcpp::sources;
namespace rxsc=rxcpp::schedulers;
namespace rxsub=rxcpp::subjects;
namespace rxn=rxcpp::notifications;

#include "rxcpp/rx-test.hpp"
namespace rxt=rxcpp::test;

#include "catch.hpp"

SCENARIO("publish range", "[hide][range][subject][publish][operators]"){
    GIVEN("a range"){
        WHEN("published"){
            auto published = rxs::range<int>(0, 10).publish();
            std::cout << "subscribe to published" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
            std::cout << "connect to published" << std::endl;
            published.connect();
        }
        WHEN("ref_count is used"){
            auto published = rxs::range<int>(0, 10).publish().ref_count();
            std::cout << "subscribe to ref_count" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
        }
        WHEN("connect_forever is used"){
            auto published = rxs::range<int>(0, 10).publish().connect_forever();
            std::cout << "subscribe to connect_forever" << std::endl;
            published.subscribe(
            // on_next
                [](int v){std::cout << v << ", ";},
            // on_completed
                [](){std::cout << " done." << std::endl;});
        }
    }
}

SCENARIO("publish basic", "[publish][multicast][operators]"){
    GIVEN("a test hot observable of longs"){
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        typedef rxsc::test::messages<int> m;
        typedef rxn::subscription life;
        typedef m::recorded_type record;
        auto on_next = m::on_next;
        auto on_completed = m::on_completed;
        auto subscribe = m::subscribe;

        long invoked = 0;

        record messages[] = {
            on_next(110, 7),
            on_next(220, 3),
            on_next(280, 4),
            on_next(290, 1),
            on_next(340, 8),
            on_next(360, 5),
            on_next(370, 6),
            on_next(390, 7),
            on_next(410, 13),
            on_next(430, 2),
            on_next(450, 9),
            on_next(520, 11),
            on_next(560, 20),
            on_completed(600)
        };
        auto xs = sc.make_hot_observable(messages);

        auto res = w.make_subscriber<int>();

        rx::connectable_observable<int> ys;

        WHEN("subscribed and then connected"){

            w.schedule_absolute(rxsc::test::created_time,
                [&invoked, &ys, &xs](const rxsc::schedulable& scbl){
                    ys = xs.publish().as_dynamic();
                    //ys = xs.publish_last().as_dynamic();
                });

            w.schedule_absolute(rxsc::test::subscribed_time,
                [&ys, &res](const rxsc::schedulable& scbl){
                ys.subscribe(res);
            });

            w.schedule_absolute(rxsc::test::unsubscribed_time,
                [&res](const rxsc::schedulable& scbl){
                    res.unsubscribe();
                });

            {
                rx::composite_subscription connection;

                w.schedule_absolute(300,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(400,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            {
                rx::composite_subscription connection;

                w.schedule_absolute(500,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(550,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            {
                rx::composite_subscription connection;

                w.schedule_absolute(650,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(800,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            w.start();

            THEN("the output only contains items sent while subscribed"){
                record items[] = {
                    on_next(340, 8),
                    on_next(360, 5),
                    on_next(370, 6),
                    on_next(390, 7),
                    on_next(520, 11)
                };
                auto required = rxu::to_vector(items);
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there were 3 subscription/unsubscription"){
                life items[] = {
                    subscribe(300, 400),
                    subscribe(500, 550),
                    subscribe(650, 800)
                };
                auto required = rxu::to_vector(items);
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("publish error", "[publish][error][multicast][operators]"){
    GIVEN("a test hot observable of longs"){
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        typedef rxsc::test::messages<int> m;
        typedef rxn::subscription life;
        typedef m::recorded_type record;
        auto on_next = m::on_next;
        auto on_error = m::on_error;
        auto on_completed = m::on_completed;
        auto subscribe = m::subscribe;

        long invoked = 0;

        std::runtime_error ex("publish on_error");

        record messages[] = {
            on_next(110, 7),
            on_next(220, 3),
            on_next(280, 4),
            on_next(290, 1),
            on_next(340, 8),
            on_next(360, 5),
            on_next(370, 6),
            on_next(390, 7),
            on_next(410, 13),
            on_next(430, 2),
            on_next(450, 9),
            on_next(520, 11),
            on_next(560, 20),
            on_error(600, ex)
        };
        auto xs = sc.make_hot_observable(messages);

        auto res = w.make_subscriber<int>();

        rx::connectable_observable<int> ys;

        WHEN("subscribed and then connected"){

            w.schedule_absolute(rxsc::test::created_time,
                [&invoked, &ys, &xs](const rxsc::schedulable& scbl){
                    ys = xs.publish().as_dynamic();
                });

            w.schedule_absolute(rxsc::test::subscribed_time,
                [&ys, &res](const rxsc::schedulable& scbl){
                ys.subscribe(res);
            });

            w.schedule_absolute(rxsc::test::unsubscribed_time,
                [&res](const rxsc::schedulable& scbl){
                    res.unsubscribe();
                });

            {
                rx::composite_subscription connection;

                w.schedule_absolute(300,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(400,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            {
                rx::composite_subscription connection;

                w.schedule_absolute(500,
                    [connection, &ys](const rxsc::schedulable& scbl){
                        ys.connect(connection);
                    });
                w.schedule_absolute(800,
                    [connection](const rxsc::schedulable& scbl){
                        connection.unsubscribe();
                    });
            }

            w.start();

            THEN("the output only contains items sent while subscribed"){
                record items[] = {
                    on_next(340, 8),
                    on_next(360, 5),
                    on_next(370, 6),
                    on_next(390, 7),
                    on_next(520, 11),
                    on_next(560, 20),
                    on_error(600, ex)
                };
                auto required = rxu::to_vector(items);
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there were 3 subscription/unsubscription"){
                life items[] = {
                    subscribe(300, 400),
                    subscribe(500, 600)
                };
                auto required = rxu::to_vector(items);
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}
<|endoftext|>


<commit_before>#include <AliDefaultPreprocessor.h>

#include <TMap.h>

#include "AliCDBMetaData.h"
#include "AliSimpleValue.h"

//
// This class is used for all subdectectors that dont have an own
// preprocessor.
// The DCS data is written into CDB, no files are processed.
//

ClassImp(AliDefaultPreprocessor)

//______________________________________________________________________________________________
AliDefaultPreprocessor::AliDefaultPreprocessor(const char* detector, AliShuttleInterface* shuttle) :
AliPreprocessor(detector, shuttle)
{
}

//______________________________________________________________________________________________
AliDefaultPreprocessor::~AliDefaultPreprocessor()
{
}

//______________________________________________________________________________________________
UInt_t AliDefaultPreprocessor::Process(TMap* dcsAliasMap)
{
  // store to default CDB object

  AliCDBMetaData metaData;
  metaData.SetProperty("StartTime",
      new AliSimpleValue(fStartTime));
  metaData.SetProperty("EndTime",
      new AliSimpleValue(fEndTime));
  metaData.SetComment("Automatically stored by AliDefaultPreprocessor!");

  return Store(dcsAliasMap, &metaData);
}
<commit_msg>revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2<commit_after>#include <AliDefaultPreprocessor.h>

#include <TMap.h>

#include "AliCDBMetaData.h"
#include "AliDCSValue.h"

//
// This class is used for all subdectectors that dont have an own
// preprocessor.
// The DCS data is written into CDB, no files are processed.
//

ClassImp(AliDefaultPreprocessor)

//______________________________________________________________________________________________
AliDefaultPreprocessor::AliDefaultPreprocessor(const char* detector, AliShuttleInterface* shuttle) :
AliPreprocessor(detector, shuttle)
{
}

//______________________________________________________________________________________________
AliDefaultPreprocessor::~AliDefaultPreprocessor()
{
}

//______________________________________________________________________________________________
UInt_t AliDefaultPreprocessor::Process(TMap* dcsAliasMap)
{
  // store to default CDB object

  AliCDBMetaData metaData;
  metaData.SetProperty("StartEndTime",
      new AliDCSValue(fStartTime, fEndTime));
  metaData.SetComment("Automatically stored by AliDefaultPreprocessor!");

  return Store(dcsAliasMap, &metaData);
}
<|endoftext|>


<commit_before><commit_msg>Fix regression caused by CommandLine change.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/dom_view.h"

#include "content/browser/tab_contents/tab_contents.h"
#include "views/focus/focus_manager.h"

#if defined(TOUCH_UI)
#include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h"
#endif

// static
const char DOMView::kViewClassName[] =
    "browser/ui/views/DOMView";

DOMView::DOMView() : tab_contents_(NULL), initialized_(false) {
  set_focusable(true);
}

DOMView::~DOMView() {
  if (native_view())
    Detach();
}

std::string DOMView::GetClassName() const {
  return kViewClassName;
}

bool DOMView::Init(Profile* profile, SiteInstance* instance) {
  if (initialized_)
    return true;

  initialized_ = true;
  tab_contents_.reset(CreateTabContents(profile, instance));
  // Attach the native_view now if the view is already added to Widget.
  if (GetWidget())
    AttachTabContents();

  return true;
}

TabContents* DOMView::CreateTabContents(Profile* profile,
                                        SiteInstance* instance) {
  return new TabContents(profile, instance, MSG_ROUTING_NONE, NULL, NULL);
}

void DOMView::LoadURL(const GURL& url) {
  DCHECK(initialized_);
  tab_contents_->controller().LoadURL(url, GURL(), PageTransition::START_PAGE);
}

bool DOMView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
  // Don't move the focus to the next view when tab is pressed, we want the
  // key event to be propagated to the render view for doing the tab traversal
  // there.
  return views::FocusManager::IsTabTraversalKeyEvent(e);
}

void DOMView::OnFocus() {
  tab_contents_->Focus();
}

void DOMView::ViewHierarchyChanged(bool is_add, views::View* parent,
                                   views::View* child) {
  // Attach the native_view when this is added to Widget if
  // the native view has not been attached yet and tab_contents_ exists.
  views::NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
  if (is_add && GetWidget() && !native_view() && tab_contents_.get())
    AttachTabContents();
  else if (!is_add && child == this && native_view())
    Detach();
}

void DOMView::AttachTabContents() {
#if defined(TOUCH_UI)
  AttachToView(static_cast<TabContentsViewTouch*>(tab_contents_->view()));
#else
  Attach(tab_contents_->GetNativeView());
#endif
}
<commit_msg>Fixes DomView selection problems.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/dom_view.h"

#include "chrome/browser/renderer_preferences_util.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "views/focus/focus_manager.h"

#if defined(TOUCH_UI)
#include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h"
#endif

// static
const char DOMView::kViewClassName[] =
    "browser/ui/views/DOMView";

DOMView::DOMView() : tab_contents_(NULL), initialized_(false) {
  set_focusable(true);
}

DOMView::~DOMView() {
  if (native_view())
    Detach();
}

std::string DOMView::GetClassName() const {
  return kViewClassName;
}

bool DOMView::Init(Profile* profile, SiteInstance* instance) {
  if (initialized_)
    return true;

  initialized_ = true;
  tab_contents_.reset(CreateTabContents(profile, instance));

  renderer_preferences_util::UpdateFromSystemSettings(
        tab_contents_->GetMutableRendererPrefs(), profile);

  // Attach the native_view now if the view is already added to Widget.
  if (GetWidget())
    AttachTabContents();

  return true;
}

TabContents* DOMView::CreateTabContents(Profile* profile,
                                        SiteInstance* instance) {
  return new TabContents(profile, instance, MSG_ROUTING_NONE, NULL, NULL);
}

void DOMView::LoadURL(const GURL& url) {
  DCHECK(initialized_);
  tab_contents_->controller().LoadURL(url, GURL(), PageTransition::START_PAGE);
}

bool DOMView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
  // Don't move the focus to the next view when tab is pressed, we want the
  // key event to be propagated to the render view for doing the tab traversal
  // there.
  return views::FocusManager::IsTabTraversalKeyEvent(e);
}

void DOMView::OnFocus() {
  tab_contents_->Focus();
}

void DOMView::ViewHierarchyChanged(bool is_add, views::View* parent,
                                   views::View* child) {
  // Attach the native_view when this is added to Widget if
  // the native view has not been attached yet and tab_contents_ exists.
  views::NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
  if (is_add && GetWidget() && !native_view() && tab_contents_.get())
    AttachTabContents();
  else if (!is_add && child == this && native_view())
    Detach();
}

void DOMView::AttachTabContents() {
#if defined(TOUCH_UI)
  AttachToView(static_cast<TabContentsViewTouch*>(tab_contents_->view()));
#else
  Attach(tab_contents_->GetNativeView());
#endif
}
<|endoftext|>


<commit_before><commit_msg>Hide ia32 asm when not building for ARCH_CPU_X86_FAMILY<commit_after><|endoftext|>


<commit_before><commit_msg>Fix painting of the title bar when the window is maximized and then deactivated.<commit_after><|endoftext|>


<commit_before>// Copyright 2014-2019 Vladimir Alyamkin. All Rights Reserved.

#include "VaRest.h"

#include "VaRestDefines.h"
#include "VaRestSettings.h"

#include "Developer/Settings/Public/ISettingsModule.h"

#include "Interfaces/IPluginManager.h"

#define LOCTEXT_NAMESPACE "FVaRestModule"

void FVaRestModule::StartupModule()
{
	ModuleSettings = NewObject<UVaRestSettings>(GetTransientPackage(), "VaRestSettings", RF_Standalone);
	ModuleSettings->AddToRoot();

	// Register settings
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->RegisterSettings("Project", "Plugins", "VaRest",
			LOCTEXT("RuntimeSettingsName", "VaRest"),
			LOCTEXT("RuntimeSettingsDescription", "Configure VaRest plugin settings"),
			ModuleSettings);
	}

	UE_LOG(LogVaRest, Log, TEXT("%s: VaRest (%s) module started"), *VA_FUNC_LINE, *GetPluginVersion());
}

void FVaRestModule::ShutdownModule()
{
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->UnregisterSettings("Project", "Plugins", "VaRest");
	}

	if (!GExitPurge)
	{
		ModuleSettings->RemoveFromRoot();
	}
	else
	{
		ModuleSettings = nullptr;
	}
}

UVaRestSettings* FVaRestModule::GetSettings() const
{
	check(ModuleSettings);
	return ModuleSettings;
}

FString FVaRestModule::GetPluginVersion() const
{
	IPluginManager& manager = IPluginManager::Get();
	TSharedPtr<IPlugin> const plugin = manager.FindPlugin("VaRest");

	return !plugin.IsValid() ? FString() : plugin->GetDescriptor().VersionName;
}

IMPLEMENT_MODULE(FVaRestModule, VaRest)

DEFINE_LOG_CATEGORY(LogVaRest);

#undef LOCTEXT_NAMESPACE
<commit_msg>small fixes<commit_after>// Copyright 2014-2019 Vladimir Alyamkin. All Rights Reserved.

#include "VaRest.h"

#include "VaRestDefines.h"
#include "VaRestSettings.h"

#include "Developer/Settings/Public/ISettingsModule.h"

#include "Interfaces/IPluginManager.h"

#define LOCTEXT_NAMESPACE "FVaRestModule"

void FVaRestModule::StartupModule()
{
	ModuleSettings = NewObject<UVaRestSettings>(GetTransientPackage(), "VaRestSettings", RF_Standalone);
	ModuleSettings->AddToRoot();

	// Register settings
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->RegisterSettings("Project", "Plugins", "VaRest",
			LOCTEXT("RuntimeSettingsName", "VaRest"),
			LOCTEXT("RuntimeSettingsDescription", "Configure VaRest plugin settings"),
			ModuleSettings);
	}

	UE_LOG(LogVaRest, Log, TEXT("%s: VaRest (%s) module started"), *VA_FUNC_LINE, *GetPluginVersion());
}

void FVaRestModule::ShutdownModule()
{
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->UnregisterSettings("Project", "Plugins", "VaRest");
	}

	if (!GExitPurge)
	{
		ModuleSettings->RemoveFromRoot();
	}
	else
	{
		ModuleSettings = nullptr;
	}
}

UVaRestSettings* FVaRestModule::GetSettings() const
{
	check(ModuleSettings);
	return ModuleSettings;
}

FString FVaRestModule::GetPluginVersion() const
{
	TSharedPtr<IPlugin> const plugin = IPluginManager::Get().FindPlugin("VaRest");

	return !plugin.IsValid() ? FString("Unable to get version number") : plugin->GetDescriptor().VersionName;
}

IMPLEMENT_MODULE(FVaRestModule, VaRest)

DEFINE_LOG_CATEGORY(LogVaRest);

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include "Connection.hpp"

namespace et {
Connection::Connection ( std::shared_ptr< SocketHandler > _socketHandler, const string& _key )
  : socketHandler ( _socketHandler ), key ( _key ), shuttingDown(false) {}

Connection::~Connection ( ) {
  if (!shuttingDown) {
    LOG(ERROR) << "Call shutdown before destructing a Connection.";
  }
  closeSocket ( );
}

ssize_t Connection::read ( void* buf, size_t count ) {
  ssize_t bytesRead = reader->read ( buf, count );
  if ( bytesRead == -1 ) {
    if ( errno == ECONNRESET || errno == ETIMEDOUT || errno == EAGAIN || errno == EWOULDBLOCK ) {
      // The connection has reset, close the socket and invalidate, then
      // return 0 bytes
      closeSocket ( );
      bytesRead = 0;
    }
  }
  return bytesRead;
}

ssize_t Connection::readAll ( void* buf, size_t count ) {
  size_t pos = 0;
  while ( pos < count && !shuttingDown ) {
    ssize_t bytesRead = read ( ( ( char* ) buf ) + pos, count - pos );
    if ( bytesRead < 0 ) {
      VLOG ( 1 ) << "Failed a call to readAll: %s\n" << strerror ( errno );
      throw std::runtime_error ( "Failed a call to readAll" );
    }
    pos += bytesRead;
    if ( pos < count ) {
      // Yield the processor
      sleep ( 0 );
    }
  }
  return count;
}

ssize_t Connection::write ( const void* buf, size_t count ) {
  BackedWriterWriteState bwws = writer->write ( buf, count );

  if ( bwws == BackedWriterWriteState::SKIPPED ) {
    return 0;
  }

  if ( bwws == BackedWriterWriteState::WROTE_WITH_FAILURE ) {
    // Error writing.
    if ( !errno ) {
      // The socket was already closed
      VLOG(1) << "Socket closed";
    } else if ( errno == EPIPE || errno == ETIMEDOUT || errno == EAGAIN || errno == EWOULDBLOCK ) {
      VLOG(1) << " Connection is severed";
      // The connection has been severed, handle and hide from the caller
      closeSocket ( );
    } else {
      LOG ( FATAL ) << "Unexpected socket error: " << errno << " " << strerror ( errno );
    }
  }

  return count;
}

void Connection::writeAll ( const void* buf, size_t count ) {
  while ( !shuttingDown ) {
    if ( write ( buf, count ) ) {
      return;
    }
    sleep ( 0 );
  }
}

void Connection::closeSocket ( ) {
  if ( socketFd == -1 ) {
    LOG ( ERROR ) << "Tried to close a non-existent socket";
    return;
  }
  reader->invalidateSocket ( );
  writer->invalidateSocket ( );
  socketHandler->close ( socketFd );
  socketFd = -1;
  VLOG ( 1 ) << "Closed socket\n";
}

bool Connection::recover ( int newSocketFd ) {
  try {
    {
      // Write the current sequence number
      et::SequenceHeader sh;
      sh.set_sequencenumber(reader->getSequenceNumber());
      socketHandler->writeProto(newSocketFd, sh);
    }

    // Read the remote sequence number
    et::SequenceHeader remoteHeader =
      socketHandler->readProto<et::SequenceHeader>(newSocketFd);

    {
      // Fetch the catchup bytes and send
      et::CatchupBuffer catchupBuffer;
      catchupBuffer.set_buffer(writer->recover(remoteHeader.sequencenumber()));
      socketHandler->writeProto(newSocketFd, catchupBuffer);
    }

    et::CatchupBuffer catchupBuffer =
      socketHandler->readProto<et::CatchupBuffer>(newSocketFd);

    socketFd = newSocketFd;
    reader->revive(socketFd, catchupBuffer.buffer());
    writer->revive(socketFd);
    writer->unlock();
    return true;
  } catch ( const runtime_error& err ) {
    LOG ( ERROR ) << "Error recovering: " << err.what ( );
    socketHandler->close ( newSocketFd );
    writer->unlock ( );
    return false;
  }
}

  void Connection::shutdown() {
    LOG(INFO) << "Shutting down connection";
    shuttingDown = true;
    closeSocket();
  }
}
<commit_msg>Log when closing socket becaose connection failed.<commit_after>#include "Connection.hpp"

namespace et {
Connection::Connection ( std::shared_ptr< SocketHandler > _socketHandler, const string& _key )
  : socketHandler ( _socketHandler ), key ( _key ), shuttingDown(false) {}

Connection::~Connection ( ) {
  if (!shuttingDown) {
    LOG(ERROR) << "Call shutdown before destructing a Connection.";
  }
  closeSocket ( );
}

ssize_t Connection::read ( void* buf, size_t count ) {
  ssize_t bytesRead = reader->read ( buf, count );
  if ( bytesRead == -1 ) {
    if ( errno == ECONNRESET || errno == ETIMEDOUT || errno == EAGAIN || errno == EWOULDBLOCK ) {
      // The connection has reset, close the socket and invalidate, then
      // return 0 bytes
      LOG(INFO) << "Closing socket because " << errno << " " << strerror(errno);
      closeSocket ( );
      bytesRead = 0;
    }
  }
  return bytesRead;
}

ssize_t Connection::readAll ( void* buf, size_t count ) {
  size_t pos = 0;
  while ( pos < count && !shuttingDown ) {
    ssize_t bytesRead = read ( ( ( char* ) buf ) + pos, count - pos );
    if ( bytesRead < 0 ) {
      VLOG ( 1 ) << "Failed a call to readAll: %s\n" << strerror ( errno );
      throw std::runtime_error ( "Failed a call to readAll" );
    }
    pos += bytesRead;
    if ( pos < count ) {
      // Yield the processor
      sleep ( 0 );
    }
  }
  return count;
}

ssize_t Connection::write ( const void* buf, size_t count ) {
  BackedWriterWriteState bwws = writer->write ( buf, count );

  if ( bwws == BackedWriterWriteState::SKIPPED ) {
    return 0;
  }

  if ( bwws == BackedWriterWriteState::WROTE_WITH_FAILURE ) {
    // Error writing.
    if ( !errno ) {
      // The socket was already closed
      VLOG(1) << "Socket closed";
    } else if ( errno == EPIPE || errno == ETIMEDOUT || errno == EAGAIN || errno == EWOULDBLOCK ) {
      VLOG(1) << " Connection is severed";
      // The connection has been severed, handle and hide from the caller
      closeSocket ( );
    } else {
      LOG ( FATAL ) << "Unexpected socket error: " << errno << " " << strerror ( errno );
    }
  }

  return count;
}

void Connection::writeAll ( const void* buf, size_t count ) {
  while ( !shuttingDown ) {
    if ( write ( buf, count ) ) {
      return;
    }
    sleep ( 0 );
  }
}

void Connection::closeSocket ( ) {
  if ( socketFd == -1 ) {
    LOG ( ERROR ) << "Tried to close a non-existent socket";
    return;
  }
  reader->invalidateSocket ( );
  writer->invalidateSocket ( );
  socketHandler->close ( socketFd );
  socketFd = -1;
  VLOG ( 1 ) << "Closed socket\n";
}

bool Connection::recover ( int newSocketFd ) {
  try {
    {
      // Write the current sequence number
      et::SequenceHeader sh;
      sh.set_sequencenumber(reader->getSequenceNumber());
      socketHandler->writeProto(newSocketFd, sh);
    }

    // Read the remote sequence number
    et::SequenceHeader remoteHeader =
      socketHandler->readProto<et::SequenceHeader>(newSocketFd);

    {
      // Fetch the catchup bytes and send
      et::CatchupBuffer catchupBuffer;
      catchupBuffer.set_buffer(writer->recover(remoteHeader.sequencenumber()));
      socketHandler->writeProto(newSocketFd, catchupBuffer);
    }

    et::CatchupBuffer catchupBuffer =
      socketHandler->readProto<et::CatchupBuffer>(newSocketFd);

    socketFd = newSocketFd;
    reader->revive(socketFd, catchupBuffer.buffer());
    writer->revive(socketFd);
    writer->unlock();
    return true;
  } catch ( const runtime_error& err ) {
    LOG ( ERROR ) << "Error recovering: " << err.what ( );
    socketHandler->close ( newSocketFd );
    writer->unlock ( );
    return false;
  }
}

  void Connection::shutdown() {
    LOG(INFO) << "Shutting down connection";
    shuttingDown = true;
    closeSocket();
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <vector>
#include <algorithm>
#include <libgen.h>

#include "geopm.h"
#include "geopm_policy_message.h"
#include "Controller.hpp"
#include "Profile.hpp"
#include "Exception.hpp"

#ifndef NAME_MAX
#define NAME_MAX 1024
#endif

extern "C"
{

    enum geopm_controller_cont_e {
        GEOPM_CTL_MAX_FAN_OUT = 16,
    };

    int geopmctl_main(const char *policy_config, const char *policy_key, const char *sample_key, const char *report)
    {
        int err = 0;
        char profile_name[NAME_MAX] = {0};
        strncpy(profile_name, report, NAME_MAX);
        if (profile_name[NAME_MAX-1] != '\0') {
            err = EINVAL;
        }
        if (!err) {
            try {
                std::string policy_config_str(policy_config);
                std::string policy_key_str(policy_key);
                std::string sample_key_str(sample_key);
                std::string report_str(report);
                std::string profile_name_str(basename(profile_name));
                geopm::GlobalPolicy policy(policy_config_str, "");
                geopm::Profile profile(profile_name_str, sample_key_str, 0); //FIXME how should the last parameter be determined?
                geopm::Controller ctl(&policy, &profile, MPI_COMM_WORLD);
                ctl.run();
            }
            catch (...) {
                err = geopm::exception_handler(std::current_exception());
            }
        }
        return err;
    }

    int geopm_ctl_create(struct geopm_policy_c *policy, struct geopm_prof_c *prof, MPI_Comm comm, struct geopm_ctl_c **ctl)
    {
        int err = 0;
        try {
            geopm::GlobalPolicy *global_policy = (geopm::GlobalPolicy *)policy;
            geopm::Profile *profile = (geopm::Profile *)prof;
            *ctl = (struct geopm_ctl_c *)(new geopm::Controller(global_policy, profile, comm));
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }

    int geopm_ctl_destroy(struct geopm_ctl_c *ctl)
    {
        int err = 0;
        geopm::Controller *ctl_obj = (geopm::Controller *)ctl;
        try {
            delete ctl_obj;
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }

    int geopm_ctl_run(struct geopm_ctl_c *ctl)
    {
        int err = 0;
        geopm::Controller *ctl_obj = (geopm::Controller *)ctl;
        try {
            ctl_obj->run();
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }
}

namespace geopm
{
    Controller::Controller(const GlobalPolicy *global_policy, const Profile *profile, MPI_Comm comm)
        : m_global_policy(global_policy)
        , m_profile(profile)
    {
        int num_nodes = 0;
        int err = geopm_num_nodes(comm, &num_nodes);
        if (err) {
            throw Exception("geopm_num_nodes()", err, __FILE__, __LINE__);
        }
        int num_level = 1;
        std::vector<int> fan_out(num_level);
        fan_out[0] = num_nodes;
        while (fan_out[0] > GEOPM_CTL_MAX_FAN_OUT && fan_out[num_level - 1] != 1) {
            ++num_level;
            fan_out.resize(num_level);
            check_mpi(MPI_Dims_create(num_nodes, num_level, fan_out.data()));
        }
        if (num_level > 1 && fan_out[num_level - 1] == 1) {
            --num_level;
            fan_out.resize(num_level);
        }
        std::reverse(fan_out.begin(), fan_out.end());

        m_tree_comm = new TreeCommunicator(fan_out, global_policy, comm);

        int max_size = 0;
        for (int level = 0; level < m_tree_comm->num_level(); ++level) {
            if (m_tree_comm->level_size(level) > max_size) {
                max_size = m_tree_comm->level_size(level);
            }
        }
        m_split_policy.resize(max_size);
        m_child_sample.resize(max_size);
        std::fill(m_last_policy.begin(), m_last_policy.end(), GEOPM_UNKNOWN_POLICY);
    }

    Controller::~Controller()
    {
        delete m_tree_comm;
    }

    void Controller::run()
    {
        int level;
        int err = 0;
        struct geopm_policy_message_s policy;

        // Spin waiting for for first policy message
        level = m_tree_comm->num_level() - 1;
        do {
            try {
                m_tree_comm->get_policy(level, policy);
                err = 0;
            }
            catch (Exception ex) {
                if (ex.err_value() != GEOPM_ERROR_POLICY_UNKNOWN) {
                    throw ex;
                }
                err = 1;
            }
        }
        while (err);

        while (1) {
            if (walk_down()) {
                break;
            }
            if (walk_up()) {
                break;
            }
        }
    }

    int Controller::walk_down(void)
    {
        int level;
        int do_shutdown = 0;
        struct geopm_policy_message_s policy_msg;

        // FIXME Do calls to geopm_is_policy_equal() below belong inside of the Decider?
        // Should m_last_policy be a Decider member variable?

        level = m_tree_comm->num_level() - 1;
        m_tree_comm->get_policy(level, policy_msg);
        for (; policy_msg.mode != GEOPM_MODE_SHUTDOWN && level > 0; --level) {
            if (!geopm_is_policy_equal(&policy_msg, &(m_last_policy[level]))) {
                m_tree_decider[level]->split_policy(policy_msg, m_split_policy);
                m_tree_comm->send_policy(level - 1, m_split_policy);
                m_last_policy[level] = policy_msg;
            }
            m_tree_comm->get_policy(level - 1, policy_msg);
        }
        if (policy_msg.mode == GEOPM_MODE_SHUTDOWN) {
            do_shutdown = 1;
        }
        else {
            if (!geopm_is_policy_equal(&policy_msg, &(m_last_policy[0]))) {
                m_leaf_decider->update_policy(policy_msg);
            }
        }
        return do_shutdown;
    }

    int Controller::walk_up(void)
    {
        int level;
        int do_shutdown = 0;
        struct geopm_policy_message_s policy_msg;
        struct geopm_sample_message_s sample_msg;
        Policy policy;

        m_tree_comm->get_policy(0, policy_msg);
        for (level = 0; policy_msg.mode != GEOPM_MODE_SHUTDOWN && level < m_tree_comm->num_level(); ++level) {
            if (level) {
                try {
                    m_tree_comm->get_sample(level, m_child_sample);
                    m_platform[level]->observe(m_child_sample);
                }
                catch (Exception ex) {
                    if (ex.err_value() != GEOPM_ERROR_SAMPLE_INCOMPLETE) {
                        throw ex;
                    }
                    break;
                }
                m_tree_decider[level]->get_policy(m_platform[level], policy);
                m_platform[level]->enforce_policy(policy);
            }
            else {
                m_platform[0]->observe();
                m_leaf_decider->get_policy(m_platform[0], policy);
                m_platform[0]->enforce_policy(policy);
            }
            if (level && m_tree_decider[level]->is_converged()) {
                m_platform[level]->sample(sample_msg);
                m_tree_comm->send_sample(level, sample_msg);
            }
        }
        if (policy_msg.mode == GEOPM_MODE_SHUTDOWN) {
            do_shutdown = 1;
        }
        return do_shutdown;
    }
}
<commit_msg>- Some fixes to the Controller implementation - There are many missing dependencies including the TreeDecider<commit_after>/*
 * Copyright (c) 2015, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <vector>
#include <algorithm>
#include <libgen.h>

#include "geopm.h"
#include "geopm_policy_message.h"
#include "Controller.hpp"
#include "Profile.hpp"
#include "Exception.hpp"

#ifndef NAME_MAX
#define NAME_MAX 1024
#endif

extern "C"
{

    enum geopm_controller_cont_e {
        GEOPM_CTL_MAX_FAN_OUT = 16,
    };

    int geopmctl_main(const char *policy_config, const char *policy_key, const char *sample_key, const char *report)
    {
        int err = 0;
        char profile_name[NAME_MAX] = {0};
        strncpy(profile_name, report, NAME_MAX);
        if (profile_name[NAME_MAX-1] != '\0') {
            err = EINVAL;
        }
        if (!err) {
            try {
                std::string policy_config_str(policy_config);
                std::string policy_key_str(policy_key);
                std::string sample_key_str(sample_key);
                std::string report_str(report);
                std::string profile_name_str(basename(profile_name));
                geopm::GlobalPolicy policy(policy_config_str, "");
                geopm::Profile profile(profile_name_str, sample_key_str, 0); //FIXME how should the last parameter be determined?
                geopm::Controller ctl(&policy, &profile, MPI_COMM_WORLD);
                ctl.run();
            }
            catch (...) {
                err = geopm::exception_handler(std::current_exception());
            }
        }
        return err;
    }

    int geopm_ctl_create(struct geopm_policy_c *policy, struct geopm_prof_c *prof, MPI_Comm comm, struct geopm_ctl_c **ctl)
    {
        int err = 0;
        try {
            geopm::GlobalPolicy *global_policy = (geopm::GlobalPolicy *)policy;
            geopm::Profile *profile = (geopm::Profile *)prof;
            *ctl = (struct geopm_ctl_c *)(new geopm::Controller(global_policy, profile, comm));
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }

    int geopm_ctl_destroy(struct geopm_ctl_c *ctl)
    {
        int err = 0;
        geopm::Controller *ctl_obj = (geopm::Controller *)ctl;
        try {
            delete ctl_obj;
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }

    int geopm_ctl_run(struct geopm_ctl_c *ctl)
    {
        int err = 0;
        geopm::Controller *ctl_obj = (geopm::Controller *)ctl;
        try {
            ctl_obj->run();
        }
        catch (...) {
            err = geopm::exception_handler(std::current_exception());
        }
        return err;
    }
}

namespace geopm
{
    Controller::Controller(const GlobalPolicy *global_policy, const Profile *profile, MPI_Comm comm)
        : m_global_policy(global_policy)
        , m_profile(profile)
    {
        throw Exception("class Controller", GEOPM_ERROR_NOT_IMPLEMENTED, __FILE__, __LINE__);

        int num_nodes = 0;
        int err = geopm_num_nodes(comm, &num_nodes);
        if (err) {
            throw Exception("geopm_num_nodes()", err, __FILE__, __LINE__);
        }
        int num_level = 1;
        std::vector<int> fan_out(num_level);
        fan_out[0] = num_nodes;
        while (fan_out[0] > GEOPM_CTL_MAX_FAN_OUT && fan_out[num_level - 1] != 1) {
            ++num_level;
            fan_out.resize(num_level);
            check_mpi(MPI_Dims_create(num_nodes, num_level, fan_out.data()));
        }
        if (num_level > 1 && fan_out[num_level - 1] == 1) {
            --num_level;
            fan_out.resize(num_level);
        }
        std::reverse(fan_out.begin(), fan_out.end());
        m_last_policy.resize(num_level);
        std::fill(m_last_policy.begin(), m_last_policy.end(), GEOPM_UNKNOWN_POLICY);

        m_tree_comm = new TreeCommunicator(fan_out, global_policy, comm);

        int max_size = 0;
        for (int level = 0; level < m_tree_comm->num_level(); ++level) {
            if (m_tree_comm->level_size(level) > max_size) {
                max_size = m_tree_comm->level_size(level);
            }
        }
        m_split_policy.resize(max_size);
        m_child_sample.resize(max_size);
    }

    Controller::~Controller()
    {
        delete m_tree_comm;
    }

    void Controller::run()
    {
        int level;
        int err = 0;
        struct geopm_policy_message_s policy;

        // Spin waiting for for first policy message
        level = m_tree_comm->num_level() - 1;
        do {
            try {
                m_tree_comm->get_policy(level, policy);
                err = 0;
            }
            catch (Exception ex) {
                if (ex.err_value() != GEOPM_ERROR_POLICY_UNKNOWN) {
                    throw ex;
                }
                err = 1;
            }
        }
        while (err);

        while (1) {
            if (walk_down()) {
                break;
            }
            if (walk_up()) {
                break;
            }
        }
    }

    int Controller::walk_down(void)
    {
        int level;
        int do_shutdown = 0;
        struct geopm_policy_message_s policy_msg;

        // FIXME Do calls to geopm_is_policy_equal() below belong inside of the Decider?
        // Should m_last_policy be a Decider member variable?

        level = m_tree_comm->num_level() - 1;
        m_tree_comm->get_policy(level, policy_msg);
        for (; policy_msg.mode != GEOPM_MODE_SHUTDOWN && level > 0; --level) {
            if (!geopm_is_policy_equal(&policy_msg, &(m_last_policy[level]))) {
                m_tree_decider[level]->split_policy(policy_msg, m_split_policy);
                m_tree_comm->send_policy(level - 1, m_split_policy);
                m_last_policy[level] = policy_msg;
            }
            m_tree_comm->get_policy(level - 1, policy_msg);
        }
        if (policy_msg.mode == GEOPM_MODE_SHUTDOWN) {
            do_shutdown = 1;
        }
        else {
            if (!geopm_is_policy_equal(&policy_msg, &(m_last_policy[0]))) {
                m_leaf_decider->update_policy(policy_msg);
            }
        }
        return do_shutdown;
    }

    int Controller::walk_up(void)
    {
        int level;
        int do_shutdown = 0;
        struct geopm_policy_message_s policy_msg;
        struct geopm_sample_message_s sample_msg;
        Policy policy;

        m_tree_comm->get_policy(0, policy_msg);
        for (level = 0; policy_msg.mode != GEOPM_MODE_SHUTDOWN && level < m_tree_comm->num_level(); ++level) {
            if (level) {
                try {
                    m_tree_comm->get_sample(level, m_child_sample);
                    m_platform[level]->observe(m_child_sample);
                }
                catch (Exception ex) {
                    if (ex.err_value() != GEOPM_ERROR_SAMPLE_INCOMPLETE) {
                        throw ex;
                    }
                    break;
                }
                m_tree_decider[level]->get_policy(m_platform[level], policy);
                m_platform[level]->enforce_policy(policy);
            }
            else {
                m_platform[0]->observe();
                m_leaf_decider->get_policy(m_platform[0], policy);
                m_platform[0]->enforce_policy(policy);
            }
            if (level && m_tree_decider[level]->is_converged()) {
                m_platform[level]->sample(sample_msg);
                m_tree_comm->send_sample(level, sample_msg);
            }
        }
        if (policy_msg.mode == GEOPM_MODE_SHUTDOWN) {
            do_shutdown = 1;
        }
        return do_shutdown;
    }
}
<|endoftext|>


<commit_before>#include <iostream>

#include <QDir>
#include <QDebug>
#include <QFileInfo>
#include <QEventLoop>
#include <QMutexLocker>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QCoreApplication>

#include "Util.h"
#include "Downloader.h"
#include "DownloadTask.h"

Downloader::Downloader(const QUrl &url, const QString &outputDir, int conns,
                       int chunks, int chunkSize, bool confirm, bool verbose)
  : url{url}, outputDir{outputDir}, conns{conns}, chunks{chunks},
  chunkSize{chunkSize}, downloadCount{0}, rangeCount{0}, contentLen{0},
  bytesDown{0}, confirm{confirm}, verbose{verbose}, continuable{false},
  reply{nullptr}
{
  connect(&commitThread, &CommitThread::finished,
          this, &Downloader::onCommitThreadFinished);
  connect(this, &Downloader::chunkToThread,
          &commitThread, &CommitThread::enqueueChunk,
          Qt::QueuedConnection);
}

void Downloader::start() {
  // Fetch HEAD to find out the size but also if it exists.
  reply = getHead(url);
  if (!reply) {
    QCoreApplication::exit(-1);
    return;
  }
  url = reply->url();

  // Find "Content-Length".
  if (!reply->hasRawHeader("Content-Length")) {
    qCritical() << "ERROR Invalid response from server. No"
                << "'Content-Length' header present!";
    QCoreApplication::exit(-1);
    return;
  }
  bool ok;
  contentLen =
    QString::fromUtf8(reply->rawHeader("Content-Length")).toLongLong(&ok);
  if (!ok || contentLen == 0) {
    qCritical() << "ERROR Invalid content length:" << contentLen;
    QCoreApplication::exit(-1);
    return;
  }
  if (verbose) {
    qDebug() << "SIZE" << contentLen;
  }

  // Check for header "Accept-Ranges" and whether it has "bytes"
  // supported.
  continuable = false;
  if (reply->hasRawHeader("Accept-Ranges")) {
    const QString ranges = QString::fromUtf8(reply->rawHeader("Accept-Ranges"));
    continuable = ranges.toLower().contains("bytes");
  }
  if (verbose) {
    qDebug() << qPrintable(QString("%1CONTINUABLE").
                           arg(continuable ? "" : "NOT "));
  }

  // Clean reply.
  reply->close();
  reply = nullptr;

  createRanges();
  setupThreadPool();

  // Start actual download.
  download();
}

void Downloader::onDownloadTaskFinished(Range range, QByteArray *data) {
  QMutexLocker locker{&finishedMutex};
  chunksMap[range.first] = data;
  downloadCount++;
  bytesDown += data->size();
  updateProgress();
  saveChunk();
}

void Downloader::onDownloadTaskFailed(Range range, int httpCode,
                                      QNetworkReply::NetworkError error) {
  qDebug() << "failed" << range << Util::getErrorString(error);
}

void Downloader::onCommitThreadFinished() {
  qDebug(); // Write newline to end the progress line.
  emit finished();
}

QNetworkReply *Downloader::getHead(const QUrl &url) {
  if (verbose) {
    qDebug() << "HEAD" << qPrintable(url.toString());
  }

  QNetworkRequest req{url};
  auto *rep = netmgr.head(req);
  QEventLoop loop;
  connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  loop.exec();

  if (rep->error() != QNetworkReply::NoError) {
    rep->abort();
    qCritical() << "ERROR" << qPrintable(Util::getErrorString(rep->error()));
    return nullptr;
  }

  int code = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
  if (verbose) {
    qDebug() << "CODE" << code;
    //qDebug() << "HEADERS" << rep->rawHeaderPairs();
  }

  static bool didRedir = false;

  if (code >= 200 && code < 300) {
    if (url != this->url) {
      qDebug() << "Resolved URL:" << qPrintable(url.toString());
    }

    if (confirm && didRedir) {
      if (!Util::askProceed(tr("Do you want to continue?") + " [y/N] ")) {
        rep->abort();
        qCritical() << "Aborting..";
        return nullptr;
      }
    }
  }

  // Handle redirect.
  if (code >= 300 && code < 400) {
    if (!rep->hasRawHeader("Location")) {
      rep->abort();
      qCritical() << "ERROR Could not resolve URL!";
      return nullptr;
    }

    QString locHdr = QString::fromUtf8(rep->rawHeader("Location"));

    QUrl loc{locHdr, QUrl::StrictMode};
    if (!loc.isValid()) {
      rep->abort();
      qCritical() << "ERROR Invalid redirection header:" <<
        qPrintable(loc.toString());
      return nullptr;
    }

    // If relative then try resolving with the previous URL.
    if (loc.isRelative()) {
      loc = url.resolved(loc);
    }

    if (verbose) {
      qDebug() << "REDIRECT" << qPrintable(loc.toString());
    }

    didRedir = true;
    rep->abort();
    rep = getHead(loc);
  }

  // Client errors.
  else if (code >= 400 && code < 500) {
    rep->abort();
    qDebug() << "CLIENT ERROR";
    return nullptr;
  }

  // Server errors.
  else if (code >= 500 && code < 600) {
    rep->abort();
    qDebug() << "SERVER ERROR";
    return nullptr;
  }

  return rep;
}

void Downloader::createRanges() {
  ranges.clear();
  chunksMap.clear();

  qint64 size = 1048576;
  if (chunkSize != -1) {
    size = chunkSize;
  }
  else if (chunks != -1) {
    size = contentLen / chunks;
  }
  else if (conns >= 8) {
    size = contentLen / conns;
    constexpr qint64 MB{10485760}; // 10 MB
    if (size > MB) size = MB;
  }

  if (verbose) {
    qDebug() << "CHUNK SIZE" << size;
  }

  for (qint64 start = 0; start < contentLen; start += size) {
    qint64 end = start + size;
    if (end >= contentLen) {
      end = contentLen;
    }
    ranges.enqueue(Range{start, end - 1});
    chunksMap[start] = nullptr;
  }
  rangeCount = ranges.size();

  if (verbose) {
    qDebug() << "CHUNKS" << rangeCount;
  }
}

void Downloader::setupThreadPool() {
  // Cap connections to the amount of chunks to download.
  if (conns > ranges.size()) {
    int old{conns};
    conns = ranges.size();
    qDebug() << "CAP connection amount capped to amount of chunks:"
             << old << "->" << conns;
  }

  pool.setMaxThreadCount(conns);
}

void Downloader::download() {
  QFileInfo fi{url.path()};
  QDir dir = (outputDir.isEmpty() ? QDir::current() : outputDir);
  QString path{dir.absoluteFilePath(fi.fileName())};
  qDebug() << "Saving to" << qPrintable(path);

  auto *file = new QFile{path};
  if (file->exists()) {
    QFile::remove(path);
  }
  if (!file->open(QIODevice::WriteOnly)) {
    qCritical() << "ERROR Could not open file for writing!";
    delete file;
    QCoreApplication::exit(-1);
    return;
  }
  commitThread.setFile(file);

  // Fill queue with tasks and start immediately.
  started = QDateTime::currentDateTime();
  updateProgress();
  while (!ranges.empty()) {
    auto range = ranges.dequeue();
    auto *task = new DownloadTask{url, range};
    connect(task, &DownloadTask::finished,
            this, &Downloader::onDownloadTaskFinished);
    connect(task, &DownloadTask::failed,
            this,  &Downloader::onDownloadTaskFailed);
    pool.start(task);
  }
}

void Downloader::saveChunk() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  if (chunksMap.isEmpty()) {
    // Wait for commit thread to be done.
    return;
  }

  auto key = chunksMap.firstKey();
  const auto *value = chunksMap[key];
  if (value != nullptr) {
    emit chunkToThread(value, chunksMap.size() == 1);
    if (!commitThread.isRunning()) {
      commitThread.start();
    }
    chunksMap.remove(key);
  }

  // If everything has been downloaded then call method again.
  if (rangeCount == downloadCount) {
    saveChunk();
  }
}

void Downloader::updateProgress() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  using namespace std;
  cout << "\r" // Rewind to beginning with carriage return.
       << "[ ";

  if (bytesDown == 0) {
    cout << "Downloading.. Awaiting first chunk";
  }
  else {
    QDateTime now{QDateTime::currentDateTime()};
    qint64 secs{started.secsTo(now)}, bytesPrSec{0}, secsLeft{0};
    if (secs > 0) {
      bytesPrSec = bytesDown / secs;
      secsLeft = (contentLen - bytesDown) / bytesPrSec;
    }

    float perc = float(downloadCount) / float(rangeCount) * 100.0;

    // Set fixed float formatting to one decimal digit.
    cout.precision(1);
    cout.setf(ios::fixed, ios::floatfield);

    cout << perc << "% | "
         << Util::formatSize(bytesDown, 1).toStdString() << " / "
         << Util::formatSize(contentLen, 1).toStdString() << " @ "
         << Util::formatSize(bytesPrSec, 1).toStdString() << "/s | "
         << Util::formatTime(secsLeft).toStdString() << " left | "
         << "chunk " << downloadCount << " / " << rangeCount;
  }

  cout << " ]";
  cout.flush();
}
<commit_msg>Progress line first rewinds, fills with max length, rewinds again and then writes information to remove any leftover characters.<commit_after>#include <sstream>
#include <iostream>

#include <QDir>
#include <QDebug>
#include <QFileInfo>
#include <QEventLoop>
#include <QMutexLocker>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QCoreApplication>

#include "Util.h"
#include "Downloader.h"
#include "DownloadTask.h"

Downloader::Downloader(const QUrl &url, const QString &outputDir, int conns,
                       int chunks, int chunkSize, bool confirm, bool verbose)
  : url{url}, outputDir{outputDir}, conns{conns}, chunks{chunks},
  chunkSize{chunkSize}, downloadCount{0}, rangeCount{0}, contentLen{0},
  bytesDown{0}, confirm{confirm}, verbose{verbose}, continuable{false},
  reply{nullptr}
{
  connect(&commitThread, &CommitThread::finished,
          this, &Downloader::onCommitThreadFinished);
  connect(this, &Downloader::chunkToThread,
          &commitThread, &CommitThread::enqueueChunk,
          Qt::QueuedConnection);
}

void Downloader::start() {
  // Fetch HEAD to find out the size but also if it exists.
  reply = getHead(url);
  if (!reply) {
    QCoreApplication::exit(-1);
    return;
  }
  url = reply->url();

  // Find "Content-Length".
  if (!reply->hasRawHeader("Content-Length")) {
    qCritical() << "ERROR Invalid response from server. No"
                << "'Content-Length' header present!";
    QCoreApplication::exit(-1);
    return;
  }
  bool ok;
  contentLen =
    QString::fromUtf8(reply->rawHeader("Content-Length")).toLongLong(&ok);
  if (!ok || contentLen == 0) {
    qCritical() << "ERROR Invalid content length:" << contentLen;
    QCoreApplication::exit(-1);
    return;
  }
  if (verbose) {
    qDebug() << "SIZE" << contentLen;
  }

  // Check for header "Accept-Ranges" and whether it has "bytes"
  // supported.
  continuable = false;
  if (reply->hasRawHeader("Accept-Ranges")) {
    const QString ranges = QString::fromUtf8(reply->rawHeader("Accept-Ranges"));
    continuable = ranges.toLower().contains("bytes");
  }
  if (verbose) {
    qDebug() << qPrintable(QString("%1CONTINUABLE").
                           arg(continuable ? "" : "NOT "));
  }

  // Clean reply.
  reply->close();
  reply = nullptr;

  createRanges();
  setupThreadPool();

  // Start actual download.
  download();
}

void Downloader::onDownloadTaskFinished(Range range, QByteArray *data) {
  QMutexLocker locker{&finishedMutex};
  chunksMap[range.first] = data;
  downloadCount++;
  bytesDown += data->size();
  updateProgress();
  saveChunk();
}

void Downloader::onDownloadTaskFailed(Range range, int httpCode,
                                      QNetworkReply::NetworkError error) {
  qDebug() << "failed" << range << Util::getErrorString(error);
}

void Downloader::onCommitThreadFinished() {
  qDebug(); // Write newline to end the progress line.
  emit finished();
}

QNetworkReply *Downloader::getHead(const QUrl &url) {
  if (verbose) {
    qDebug() << "HEAD" << qPrintable(url.toString());
  }

  QNetworkRequest req{url};
  auto *rep = netmgr.head(req);
  QEventLoop loop;
  connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  loop.exec();

  if (rep->error() != QNetworkReply::NoError) {
    rep->abort();
    qCritical() << "ERROR" << qPrintable(Util::getErrorString(rep->error()));
    return nullptr;
  }

  int code = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
  if (verbose) {
    qDebug() << "CODE" << code;
    //qDebug() << "HEADERS" << rep->rawHeaderPairs();
  }

  static bool didRedir = false;

  if (code >= 200 && code < 300) {
    if (url != this->url) {
      qDebug() << "Resolved URL:" << qPrintable(url.toString());
    }

    if (confirm && didRedir) {
      if (!Util::askProceed(tr("Do you want to continue?") + " [y/N] ")) {
        rep->abort();
        qCritical() << "Aborting..";
        return nullptr;
      }
    }
  }

  // Handle redirect.
  if (code >= 300 && code < 400) {
    if (!rep->hasRawHeader("Location")) {
      rep->abort();
      qCritical() << "ERROR Could not resolve URL!";
      return nullptr;
    }

    QString locHdr = QString::fromUtf8(rep->rawHeader("Location"));

    QUrl loc{locHdr, QUrl::StrictMode};
    if (!loc.isValid()) {
      rep->abort();
      qCritical() << "ERROR Invalid redirection header:" <<
        qPrintable(loc.toString());
      return nullptr;
    }

    // If relative then try resolving with the previous URL.
    if (loc.isRelative()) {
      loc = url.resolved(loc);
    }

    if (verbose) {
      qDebug() << "REDIRECT" << qPrintable(loc.toString());
    }

    didRedir = true;
    rep->abort();
    rep = getHead(loc);
  }

  // Client errors.
  else if (code >= 400 && code < 500) {
    rep->abort();
    qDebug() << "CLIENT ERROR";
    return nullptr;
  }

  // Server errors.
  else if (code >= 500 && code < 600) {
    rep->abort();
    qDebug() << "SERVER ERROR";
    return nullptr;
  }

  return rep;
}

void Downloader::createRanges() {
  ranges.clear();
  chunksMap.clear();

  qint64 size = 1048576;
  if (chunkSize != -1) {
    size = chunkSize;
  }
  else if (chunks != -1) {
    size = contentLen / chunks;
  }
  else if (conns >= 8) {
    size = contentLen / conns;
    constexpr qint64 MB{10485760}; // 10 MB
    if (size > MB) size = MB;
  }

  if (verbose) {
    qDebug() << "CHUNK SIZE" << size;
  }

  for (qint64 start = 0; start < contentLen; start += size) {
    qint64 end = start + size;
    if (end >= contentLen) {
      end = contentLen;
    }
    ranges.enqueue(Range{start, end - 1});
    chunksMap[start] = nullptr;
  }
  rangeCount = ranges.size();

  if (verbose) {
    qDebug() << "CHUNKS" << rangeCount;
  }
}

void Downloader::setupThreadPool() {
  // Cap connections to the amount of chunks to download.
  if (conns > ranges.size()) {
    int old{conns};
    conns = ranges.size();
    qDebug() << "CAP connection amount capped to amount of chunks:"
             << old << "->" << conns;
  }

  pool.setMaxThreadCount(conns);
}

void Downloader::download() {
  QFileInfo fi{url.path()};
  QDir dir = (outputDir.isEmpty() ? QDir::current() : outputDir);
  QString path{dir.absoluteFilePath(fi.fileName())};
  qDebug() << "Saving to" << qPrintable(path);

  auto *file = new QFile{path};
  if (file->exists()) {
    QFile::remove(path);
  }
  if (!file->open(QIODevice::WriteOnly)) {
    qCritical() << "ERROR Could not open file for writing!";
    delete file;
    QCoreApplication::exit(-1);
    return;
  }
  commitThread.setFile(file);

  // Fill queue with tasks and start immediately.
  started = QDateTime::currentDateTime();
  updateProgress();
  while (!ranges.empty()) {
    auto range = ranges.dequeue();
    auto *task = new DownloadTask{url, range};
    connect(task, &DownloadTask::finished,
            this, &Downloader::onDownloadTaskFinished);
    connect(task, &DownloadTask::failed,
            this,  &Downloader::onDownloadTaskFailed);
    pool.start(task);
  }
}

void Downloader::saveChunk() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  if (chunksMap.isEmpty()) {
    // Wait for commit thread to be done.
    return;
  }

  auto key = chunksMap.firstKey();
  const auto *value = chunksMap[key];
  if (value != nullptr) {
    emit chunkToThread(value, chunksMap.size() == 1);
    if (!commitThread.isRunning()) {
      commitThread.start();
    }
    chunksMap.remove(key);
  }

  // If everything has been downloaded then call method again.
  if (rangeCount == downloadCount) {
    saveChunk();
  }
}

void Downloader::updateProgress() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  using namespace std;
  stringstream sstream;
  sstream << "[ ";

  if (bytesDown == 0) {
    sstream << "Downloading.. Awaiting first chunk";
  }
  else {
    QDateTime now{QDateTime::currentDateTime()};
    qint64 secs{started.secsTo(now)}, bytesPrSec{0}, secsLeft{0};
    if (secs > 0) {
      bytesPrSec = bytesDown / secs;
      secsLeft = (contentLen - bytesDown) / bytesPrSec;
    }

    float perc = float(downloadCount) / float(rangeCount) * 100.0;

    // Set fixed float formatting to one decimal digit.
    sstream.precision(1);
    sstream.setf(ios::fixed, ios::floatfield);

    sstream << perc << "% | "
            << Util::formatSize(bytesDown, 1).toStdString() << " / "
            << Util::formatSize(contentLen, 1).toStdString() << " @ "
            << Util::formatSize(bytesPrSec, 1).toStdString() << "/s | "
            << Util::formatTime(secsLeft).toStdString() << " left | "
            << "chunk " << downloadCount << " / " << rangeCount;
  }

  sstream << " ]";

  static int maxLen{0};
  string msg{sstream.str()};

  // Rewind to beginning with carriage return and fill with blanks to
  // remove leftovers. Then rewind again and write actual message.
  cout << '\r' << string(maxLen, ' ') << '\r' << msg;
  cout.flush();

  if (msg.size() > maxLen) {
    maxLen = msg.size();
  }
}
<|endoftext|>