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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkSliceNavigationController.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderWindow.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkOperation.h"
#include "mitkOperationActor.h"
#include "mitkPositionEvent.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
#include <itkCommand.h>
#include <mitkGlobalInteraction.h>
#include <mitkEventMapper.h>
#include <mitkFocusManager.h>
#include <mitkOpenGLRenderer.h>

//##ModelId=3E189B1D008D
mitk::SliceNavigationController::SliceNavigationController(const char * type)
  : BaseController(type), m_InputWorldGeometry(NULL), m_CreatedWorldGeometry(NULL), m_ViewDirection(Transversal), m_BlockUpdate(false)
{
  itk::SimpleMemberCommand<SliceNavigationController>::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
  sliceStepperChangedCommand = itk::SimpleMemberCommand<SliceNavigationController>::New();
  timeStepperChangedCommand = itk::SimpleMemberCommand<SliceNavigationController>::New();
#ifdef WIN32
  sliceStepperChangedCommand->SetCallbackFunction(this, SliceNavigationController::SendSlice);
  timeStepperChangedCommand->SetCallbackFunction(this,  SliceNavigationController::SendTime);
#else
  sliceStepperChangedCommand->SetCallbackFunction(this, &SliceNavigationController::SendSlice);
  timeStepperChangedCommand->SetCallbackFunction(this,  &SliceNavigationController::SendTime);
#endif

  m_Slice->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
  m_Time->AddObserver(itk::ModifiedEvent(),  timeStepperChangedCommand);
  ConnectGeometryEvents(this);
}

//##ModelId=3E189B1D00BF
mitk::SliceNavigationController::~SliceNavigationController()
{

}

void mitk::SliceNavigationController::SetInputWorldGeometry(const mitk::Geometry3D* geometry)
{
  if(geometry != NULL)
  {
    if(const_cast<BoundingBox*>(geometry->GetBoundingBox())->GetDiagonalLength2()<eps)
    {
      itkWarningMacro("setting an empty bounding-box");
      geometry = NULL;
    }
  }
  if(m_InputWorldGeometry != geometry)
  {
    m_InputWorldGeometry = geometry;
    Modified();
  }
}

void mitk::SliceNavigationController::Update()
{
  if(m_BlockUpdate)
    return;
  m_BlockUpdate = true;
  if(m_LastUpdateTime<GetMTime())
  {
    m_LastUpdateTime = GetMTime();

    if(m_InputWorldGeometry.IsNotNull())
    {
      // initialize the viewplane
      mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();

      ScalarType viewSpacing = 1;

      switch(m_ViewDirection)
      {
        case Original:
          assert(false);
          break;
        case Transversal:
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Transversal, m_InputWorldGeometry->GetExtent(2)-1, false);
          m_Slice->SetSteps((int)m_InputWorldGeometry->GetExtent(2));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(2)/m_InputWorldGeometry->GetExtent(2);
          break;
        case Frontal:
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Frontal);
          m_Slice->SetSteps((int)(m_InputWorldGeometry->GetExtent(1)+1.0));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(1)/m_InputWorldGeometry->GetExtent(1);
          break;
        case Sagittal:
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Sagittal);
          m_Slice->SetSteps((int)(m_InputWorldGeometry->GetExtent(0)+1.0));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(0)/m_InputWorldGeometry->GetExtent(0);
          break;
        default:
          itkExceptionMacro("unknown ViewDirection");
      }

      m_Slice->SetPos(0);

      mitk::SlicedGeometry3D::Pointer slicedWorldGeometry=mitk::SlicedGeometry3D::New();
      slicedWorldGeometry->InitializeEvenlySpaced(planegeometry, viewSpacing, m_Slice->GetSteps(), (m_ViewDirection==Frontal?true:false));

      // initialize TimeSlicedGeometry
      m_CreatedWorldGeometry = TimeSlicedGeometry::New();
      const TimeSlicedGeometry* worldTimeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>(m_InputWorldGeometry.GetPointer());
      if(worldTimeSlicedGeometry==NULL)
      {
        m_CreatedWorldGeometry->InitializeEvenlyTimed(slicedWorldGeometry, 1);
        m_Time->SetSteps(0);
        m_Time->SetPos(0);
      }
      else
      {
        m_BlockUpdate = true;
        m_Time->SetSteps(worldTimeSlicedGeometry->GetTimeSteps());
        m_Time->SetPos(0);
        m_BlockUpdate = false;

        slicedWorldGeometry->SetTimeBoundsInMS(worldTimeSlicedGeometry->GetGeometry3D(0)->GetTimeBoundsInMS());
        //@todo implement for non-evenly-timed geometry!
        m_CreatedWorldGeometry->InitializeEvenlyTimed(slicedWorldGeometry, worldTimeSlicedGeometry->GetTimeSteps());
      }
    }
  }

  //unblock update; we may do this now, because if m_BlockUpdate was already true before this method was entered,
  //then we will never come here.
  m_BlockUpdate = false;

  //Send the geometry. Do this even if nothing was changed, because maybe Update() was only called to
  //re-send the old geometry and time/slice data.
  SendCreatedWorldGeometry();
  SendSlice();
  SendTime();
}

void mitk::SliceNavigationController::SendCreatedWorldGeometry()
{
  //Send the geometry. Do this even if nothing was changed, because maybe Update() was only called to
  //re-send the old geometry.
  if(!m_BlockUpdate)
    InvokeEvent(GeometrySendEvent(m_CreatedWorldGeometry, 0));
}

//##ModelId=3DD524D7038C
void mitk::SliceNavigationController::SendSlice()
{
  if(!m_BlockUpdate)
  {
    if(m_CreatedWorldGeometry.IsNotNull())
    {
      InvokeEvent(GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()));
      InvokeEvent(UpdateEvent());
    }
  }
}

void mitk::SliceNavigationController::SendTime()
{
  if(!m_BlockUpdate)
  {
    if(m_CreatedWorldGeometry.IsNotNull())
    {
      InvokeEvent(GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()));
      InvokeEvent(UpdateEvent());
    }
  }
}

void mitk::SliceNavigationController::SetGeometry(const itk::EventObject & geometrySendEvent)
{
}

void mitk::SliceNavigationController::SetGeometryTime(const itk::EventObject & geometryTimeEvent)
{
}

void mitk::SliceNavigationController::SetGeometrySlice(const itk::EventObject & geometrySliceEvent)
{
}

bool mitk::SliceNavigationController::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent)
{
    bool ok = false;
    //if (m_Destination == NULL)
    //    return false;

    const PositionEvent* posEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
    if(posEvent!=NULL)
    {
      if(m_CreatedWorldGeometry.IsNull())
        return true;
      switch (action->GetActionId())
      {
        case AcMOVEPOINT:
        {
          mitk::BaseRenderer* baseRenderer = posEvent->GetSender();
          if (baseRenderer==NULL)
            {
              mitk::GlobalInteraction *globalInteraction = dynamic_cast<mitk::GlobalInteraction *>(mitk::EventMapper::GetGlobalStateMachine());
              if (globalInteraction!=NULL)
              {
                baseRenderer = const_cast<mitk::BaseRenderer *>(globalInteraction->GetFocus());
              }
            }
          if (baseRenderer!=NULL)
           if (baseRenderer->GetMapperID() == 1)
           {
            mitk::Point3D point;
            point = posEvent->GetWorldPosition();

            //@todo add time to PositionEvent and use here!!
            SlicedGeometry3D* slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(m_CreatedWorldGeometry->GetGeometry3D(0));
            if(slicedWorldGeometry!=NULL)
            {
              int best_slice = -1;
              double best_distance = itk::NumericTraits<double>::max();

              int s, slices;
              slices = slicedWorldGeometry->GetSlices();
              if(slicedWorldGeometry->GetEvenlySpaced())
              {
                mitk::Point3D pointInUnits;
                slicedWorldGeometry->MMToUnits(point, pointInUnits);
                best_slice = (int)pointInUnits[2];
              }
              else
              {
                mitk::Point3D projected_point;
                for(s=0; s < slices; ++s)
                {
                  slicedWorldGeometry->GetGeometry2D(s)->Project(point, projected_point);
                  Vector3D dist = projected_point-point;
                  if(dist.GetSquaredNorm() < best_distance)
                  {
                    best_distance = dist.GetSquaredNorm();
                    best_slice    = s;
                  }
                }
              }
              if(best_slice >= 0)
                GetSlice()->SetPos(best_slice);
            }
          }
          ok = true;
          break;
        }
        case AcFINISHMOVEMENT:
        {
       // /*finishes a Movement from the coordinate supplier:
       //   gets the lastpoint from the undolist and writes an undo-operation so
       //   that the movement of the coordinatesupplier is undoable.*/
       //   mitk::Point3D movePoint, oldMovePoint;
       //   oldMovePoint.Fill(0);
       //   vm2itk(posEvent->GetWorldPosition(), movePoint);
       //   PointOperation* doOp = new mitk::PointOperation(OpMOVE, movePoint, 0);
       //   if (m_UndoEnabled )
       //   {
       //     //get the last Position from the UndoList
       //     OperationEvent *lastOperationEvent = m_UndoController->GetLastOfType(m_Destination, OpMOVE);
       //     if (lastOperationEvent != NULL)
       //     {
       //       PointOperation* lastOp = dynamic_cast<PointOperation *>(lastOperationEvent->GetOperation());
       //       if (lastOp != NULL)
       //       {
       //         oldMovePoint = lastOp->GetPoint();
       //       }
       //     }
       //     PointOperation* undoOp = new PointOperation(OpMOVE, oldMovePoint, 0);
       //     OperationEvent *operationEvent = new OperationEvent(m_Destination, doOp, undoOp);
       //     m_UndoController->SetOperationEvent(operationEvent);
       //   }
       //   //execute the Operation
	  		  //m_Destination->ExecuteOperation(doOp);

          //mitk::BaseRenderer *baseRenderer = posEvent->GetSender();
          //if (baseRenderer==NULL)
          //  {
          //    mitk::GlobalInteraction *globalInteraction = dynamic_cast<mitk::GlobalInteraction *>(mitk::EventMapper::GetGlobalStateMachine());
          //    if (globalInteraction!=NULL)
          //    {
          //      baseRenderer = const_cast<mitk::BaseRenderer *>(globalInteraction->GetFocus());
          //    }
          //  }
          //  if (baseRenderer!=NULL)
          //  {
          //    if (baseRenderer->GetMapperID() == 1)
          //    {
          //      mitk::Point3D point, projected_point;
          //      point = posEvent->GetWorldPosition();
          //
          //      //@todo add time to PositionEvent and use here!!
          //      SlicedGeometry3D* slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(m_CreatedWorldGeometry->GetGeometry3D(0));
          //      if(slicedWorldGeometry!=NULL)
          //      {
          //        int best_slice = -1;
          //        double best_distance = itk::NumericTraits<double>::max();

          //        int s, slices;
          //        slices = slicedWorldGeometry->GetSlices();
          //        for(s=0; s < slices; ++s)
          //        {
          //          slicedWorldGeometry->GetGeometry2D(s)->Project(point, projected_point);
          //          Vector3D dist = projected_point-point;
          //          if(dist.lengthSquared() < best_distance)
          //          {
          //            best_distance = dist.lengthSquared();
          //            best_slice    = s;
          //          }
          //        }
          //        if(best_slice >= 0)
          //          GetSlice()->SetPos(best_slice);
          //      }
          //    }
          //  }
            ok = true;
            break;
          }
        default:
          ok = true;
          break;
        }
       return ok;
    }

    const mitk::DisplayPositionEvent* displPosEvent = dynamic_cast<const mitk::DisplayPositionEvent *>(stateEvent->GetEvent());
    if(displPosEvent!=NULL)
    {
        return true;
    }

	return false;
}
<commit_msg>CHG: initialize geometries with correct mm values, not active right now, due to SEVERE problems in mitkDisplayGeometry :-)<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkSliceNavigationController.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderWindow.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkOperation.h"
#include "mitkOperationActor.h"
#include "mitkPositionEvent.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
#include <itkCommand.h>
#include <mitkGlobalInteraction.h>
#include <mitkEventMapper.h>
#include <mitkFocusManager.h>
#include <mitkOpenGLRenderer.h>

//##ModelId=3E189B1D008D
mitk::SliceNavigationController::SliceNavigationController(const char * type)
  : BaseController(type), m_InputWorldGeometry(NULL), m_CreatedWorldGeometry(NULL), m_ViewDirection(Transversal), m_BlockUpdate(false)
{
  itk::SimpleMemberCommand<SliceNavigationController>::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
  sliceStepperChangedCommand = itk::SimpleMemberCommand<SliceNavigationController>::New();
  timeStepperChangedCommand = itk::SimpleMemberCommand<SliceNavigationController>::New();
#ifdef WIN32
  sliceStepperChangedCommand->SetCallbackFunction(this, SliceNavigationController::SendSlice);
  timeStepperChangedCommand->SetCallbackFunction(this,  SliceNavigationController::SendTime);
#else
  sliceStepperChangedCommand->SetCallbackFunction(this, &SliceNavigationController::SendSlice);
  timeStepperChangedCommand->SetCallbackFunction(this,  &SliceNavigationController::SendTime);
#endif

  m_Slice->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
  m_Time->AddObserver(itk::ModifiedEvent(),  timeStepperChangedCommand);
  ConnectGeometryEvents(this);
}

//##ModelId=3E189B1D00BF
mitk::SliceNavigationController::~SliceNavigationController()
{

}

void mitk::SliceNavigationController::SetInputWorldGeometry(const mitk::Geometry3D* geometry)
{
  if(geometry != NULL)
  {
    if(const_cast<BoundingBox*>(geometry->GetBoundingBox())->GetDiagonalLength2()<eps)
    {
      itkWarningMacro("setting an empty bounding-box");
      geometry = NULL;
    }
  }
  if(m_InputWorldGeometry != geometry)
  {
    m_InputWorldGeometry = geometry;
    Modified();
  }
}

void mitk::SliceNavigationController::Update()
{
  if(m_BlockUpdate)
    return;
  m_BlockUpdate = true;
  if(m_LastUpdateTime<GetMTime())
  {
    m_LastUpdateTime = GetMTime();

    if(m_InputWorldGeometry.IsNotNull())
    {
      // initialize the viewplane
      mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();

      ScalarType viewSpacing = 1;

      switch(m_ViewDirection)
      {
        case Original:
          assert(false);
          break;
        case Transversal:
          //planegeometry->InitializeStandardPlane(
          //  m_InputWorldGeometry->GetExtent(0), m_InputWorldGeometry->GetExtent(1),
          //  m_InputWorldGeometry->GetIndexToWorldTransform(),
          //  PlaneGeometry::Transversal,
          //  m_InputWorldGeometry->GetExtent(2)-1, false);
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Transversal, m_InputWorldGeometry->GetExtent(2)-1, false);
          m_Slice->SetSteps((int)m_InputWorldGeometry->GetExtent(2));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(2)/m_InputWorldGeometry->GetExtent(2);
          break;
        case Frontal:
          //planegeometry->InitializeStandardPlane(
          //  m_InputWorldGeometry->GetExtent(0), m_InputWorldGeometry->GetExtent(2),
          //  m_InputWorldGeometry->GetIndexToWorldTransform(),
          //  PlaneGeometry::Frontal);
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Frontal);
          m_Slice->SetSteps((int)(m_InputWorldGeometry->GetExtent(1)+1.0));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(1)/m_InputWorldGeometry->GetExtent(1);
          break;
        case Sagittal:
          //planegeometry->InitializeStandardPlane(
          //  m_InputWorldGeometry->GetExtent(1), m_InputWorldGeometry->GetExtent(2),
          //  m_InputWorldGeometry->GetIndexToWorldTransform(),
          //  PlaneGeometry::Sagittal);
          planegeometry->InitializeStandardPlane(m_InputWorldGeometry, PlaneGeometry::Sagittal);
          m_Slice->SetSteps((int)(m_InputWorldGeometry->GetExtent(0)+1.0));
          viewSpacing=m_InputWorldGeometry->GetExtentInMM(0)/m_InputWorldGeometry->GetExtent(0);
          break;
        default:
          itkExceptionMacro("unknown ViewDirection");
      }

      m_Slice->SetPos(0);

      mitk::SlicedGeometry3D::Pointer slicedWorldGeometry=mitk::SlicedGeometry3D::New();
      slicedWorldGeometry->InitializeEvenlySpaced(planegeometry, viewSpacing, m_Slice->GetSteps(), (m_ViewDirection==Frontal?true:false));

      // initialize TimeSlicedGeometry
      m_CreatedWorldGeometry = TimeSlicedGeometry::New();
      const TimeSlicedGeometry* worldTimeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>(m_InputWorldGeometry.GetPointer());
      if(worldTimeSlicedGeometry==NULL)
      {
        m_CreatedWorldGeometry->InitializeEvenlyTimed(slicedWorldGeometry, 1);
        m_Time->SetSteps(0);
        m_Time->SetPos(0);
      }
      else
      {
        m_BlockUpdate = true;
        m_Time->SetSteps(worldTimeSlicedGeometry->GetTimeSteps());
        m_Time->SetPos(0);
        m_BlockUpdate = false;

        slicedWorldGeometry->SetTimeBoundsInMS(worldTimeSlicedGeometry->GetGeometry3D(0)->GetTimeBoundsInMS());
        //@todo implement for non-evenly-timed geometry!
        m_CreatedWorldGeometry->InitializeEvenlyTimed(slicedWorldGeometry, worldTimeSlicedGeometry->GetTimeSteps());
      }
    }
  }

  //unblock update; we may do this now, because if m_BlockUpdate was already true before this method was entered,
  //then we will never come here.
  m_BlockUpdate = false;

  //Send the geometry. Do this even if nothing was changed, because maybe Update() was only called to
  //re-send the old geometry and time/slice data.
  SendCreatedWorldGeometry();
  SendSlice();
  SendTime();
}

void mitk::SliceNavigationController::SendCreatedWorldGeometry()
{
  //Send the geometry. Do this even if nothing was changed, because maybe Update() was only called to
  //re-send the old geometry.
  if(!m_BlockUpdate)
    InvokeEvent(GeometrySendEvent(m_CreatedWorldGeometry, 0));
}

//##ModelId=3DD524D7038C
void mitk::SliceNavigationController::SendSlice()
{
  if(!m_BlockUpdate)
  {
    if(m_CreatedWorldGeometry.IsNotNull())
    {
      InvokeEvent(GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()));
      InvokeEvent(UpdateEvent());
    }
  }
}

void mitk::SliceNavigationController::SendTime()
{
  if(!m_BlockUpdate)
  {
    if(m_CreatedWorldGeometry.IsNotNull())
    {
      InvokeEvent(GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()));
      InvokeEvent(UpdateEvent());
    }
  }
}

void mitk::SliceNavigationController::SetGeometry(const itk::EventObject & geometrySendEvent)
{
}

void mitk::SliceNavigationController::SetGeometryTime(const itk::EventObject & geometryTimeEvent)
{
}

void mitk::SliceNavigationController::SetGeometrySlice(const itk::EventObject & geometrySliceEvent)
{
}

bool mitk::SliceNavigationController::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent)
{
    bool ok = false;
    //if (m_Destination == NULL)
    //    return false;

    const PositionEvent* posEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
    if(posEvent!=NULL)
    {
      if(m_CreatedWorldGeometry.IsNull())
        return true;
      switch (action->GetActionId())
      {
        case AcMOVEPOINT:
        {
          mitk::BaseRenderer* baseRenderer = posEvent->GetSender();
          if (baseRenderer==NULL)
            {
              mitk::GlobalInteraction *globalInteraction = dynamic_cast<mitk::GlobalInteraction *>(mitk::EventMapper::GetGlobalStateMachine());
              if (globalInteraction!=NULL)
              {
                baseRenderer = const_cast<mitk::BaseRenderer *>(globalInteraction->GetFocus());
              }
            }
          if (baseRenderer!=NULL)
           if (baseRenderer->GetMapperID() == 1)
           {
            mitk::Point3D point;
            point = posEvent->GetWorldPosition();

            //@todo add time to PositionEvent and use here!!
            SlicedGeometry3D* slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(m_CreatedWorldGeometry->GetGeometry3D(0));
            if(slicedWorldGeometry!=NULL)
            {
              int best_slice = -1;
              double best_distance = itk::NumericTraits<double>::max();

              int s, slices;
              slices = slicedWorldGeometry->GetSlices();
              if(slicedWorldGeometry->GetEvenlySpaced())
              {
                mitk::Point3D pointInUnits;
                slicedWorldGeometry->MMToUnits(point, pointInUnits);
                best_slice = (int)pointInUnits[2];
              }
              else
              {
                mitk::Point3D projected_point;
                for(s=0; s < slices; ++s)
                {
                  slicedWorldGeometry->GetGeometry2D(s)->Project(point, projected_point);
                  Vector3D dist = projected_point-point;
                  if(dist.GetSquaredNorm() < best_distance)
                  {
                    best_distance = dist.GetSquaredNorm();
                    best_slice    = s;
                  }
                }
              }
              if(best_slice >= 0)
                GetSlice()->SetPos(best_slice);
            }
          }
          ok = true;
          break;
        }
        case AcFINISHMOVEMENT:
        {
       // /*finishes a Movement from the coordinate supplier:
       //   gets the lastpoint from the undolist and writes an undo-operation so
       //   that the movement of the coordinatesupplier is undoable.*/
       //   mitk::Point3D movePoint, oldMovePoint;
       //   oldMovePoint.Fill(0);
       //   vm2itk(posEvent->GetWorldPosition(), movePoint);
       //   PointOperation* doOp = new mitk::PointOperation(OpMOVE, movePoint, 0);
       //   if (m_UndoEnabled )
       //   {
       //     //get the last Position from the UndoList
       //     OperationEvent *lastOperationEvent = m_UndoController->GetLastOfType(m_Destination, OpMOVE);
       //     if (lastOperationEvent != NULL)
       //     {
       //       PointOperation* lastOp = dynamic_cast<PointOperation *>(lastOperationEvent->GetOperation());
       //       if (lastOp != NULL)
       //       {
       //         oldMovePoint = lastOp->GetPoint();
       //       }
       //     }
       //     PointOperation* undoOp = new PointOperation(OpMOVE, oldMovePoint, 0);
       //     OperationEvent *operationEvent = new OperationEvent(m_Destination, doOp, undoOp);
       //     m_UndoController->SetOperationEvent(operationEvent);
       //   }
       //   //execute the Operation
	  		  //m_Destination->ExecuteOperation(doOp);

          //mitk::BaseRenderer *baseRenderer = posEvent->GetSender();
          //if (baseRenderer==NULL)
          //  {
          //    mitk::GlobalInteraction *globalInteraction = dynamic_cast<mitk::GlobalInteraction *>(mitk::EventMapper::GetGlobalStateMachine());
          //    if (globalInteraction!=NULL)
          //    {
          //      baseRenderer = const_cast<mitk::BaseRenderer *>(globalInteraction->GetFocus());
          //    }
          //  }
          //  if (baseRenderer!=NULL)
          //  {
          //    if (baseRenderer->GetMapperID() == 1)
          //    {
          //      mitk::Point3D point, projected_point;
          //      point = posEvent->GetWorldPosition();
          //
          //      //@todo add time to PositionEvent and use here!!
          //      SlicedGeometry3D* slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(m_CreatedWorldGeometry->GetGeometry3D(0));
          //      if(slicedWorldGeometry!=NULL)
          //      {
          //        int best_slice = -1;
          //        double best_distance = itk::NumericTraits<double>::max();

          //        int s, slices;
          //        slices = slicedWorldGeometry->GetSlices();
          //        for(s=0; s < slices; ++s)
          //        {
          //          slicedWorldGeometry->GetGeometry2D(s)->Project(point, projected_point);
          //          Vector3D dist = projected_point-point;
          //          if(dist.lengthSquared() < best_distance)
          //          {
          //            best_distance = dist.lengthSquared();
          //            best_slice    = s;
          //          }
          //        }
          //        if(best_slice >= 0)
          //          GetSlice()->SetPos(best_slice);
          //      }
          //    }
          //  }
            ok = true;
            break;
          }
        default:
          ok = true;
          break;
        }
       return ok;
    }

    const mitk::DisplayPositionEvent* displPosEvent = dynamic_cast<const mitk::DisplayPositionEvent *>(stateEvent->GetEvent());
    if(displPosEvent!=NULL)
    {
        return true;
    }

	return false;
}
<|endoftext|>


<commit_before>//===- Clan.cpp ---------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Example clang plugin which simply prints the names of all the top-level decls
// in the input file.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
#include <chrono>
//#include <clan/clan.h>
//#include <osl/scop.h>
//#include <osl/extensions/irregular.h>
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <iostream>
#include <sstream>
#include <map>
#include <fstream>
#include <pluto/libpluto.h>
#include <pluto.h>
#include <string>
#include <pluto_codegen_clang.hpp>

extern "C"{
// TODO PlutoProg is not known outside of libpluto
//      since i want to write my own unparser thats not a big problem but its definitly something i
//      want to change temporarily
//
//int pluto_multicore_codegen(FILE *cloogfp, FILE *outfp, const PlutoProg *prog);
PlutoProg *scop_to_pluto_prog(osl_scop_p scop, PlutoOptions *options);
void pluto_prog_free(PlutoProg* prog);
}

using namespace clang;
using namespace clang::ast_matchers;

osl_scop_p handleForLoop( const ForStmt* for_stmt, const SourceManager& SM, std::string filename );

const char* SCOP_ID = "scop";
const char* FOR_LOOP_ID = "for_loop";
const char* LOOP_ITERATOR_ID = "loop_iterator";
const char* LOOP_INITIALIZER_ID = "loop_initializer";
const char* LOOP_CONDITION_LIST_ID = "loop_condition_list";

const char* DECREMENT_ONE_ID = "decrement_one";
const char* INCREMENT_ONE_ID = "increment_one";

const char* CEILD_ID = "ceild";
const char* FLOORD_ID = "floord";

std::ofstream out;

namespace {

class ForLoopConsumer : public ASTConsumer {
  CompilerInstance &Instance;
  std::set<std::string> ParsedTemplates;

public:
  ForLoopConsumer(CompilerInstance &Instance,
                         std::set<std::string> ParsedTemplates)
      : Instance(Instance), ParsedTemplates(ParsedTemplates) { llvm::errs() << "consumer created\n" ;}

  StatementMatcher makeLoopConditionMatcher(){
      return expr().bind(LOOP_CONDITION_LIST_ID);
  }

  StatementMatcher makeIncrementMatcher(){
    return anyOf(
       unaryOperator( hasOperatorName("++") ).bind(INCREMENT_ONE_ID) ,
       binaryOperator(
	 hasOperatorName("+="),
	 hasRHS(
	   integerLiteral(equals(1))
	 )
       ).bind(INCREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("="),
	 hasLHS( declRefExpr() ),
	 hasRHS(
	   binaryOperator(
	     hasOperatorName("+"),
	     hasLHS( declRefExpr() )
	     //hasRHS(  )
	  )
	)
       ).bind(INCREMENT_ONE_ID)
    );
  }

  StatementMatcher makeDecrementMatcher(){
    return anyOf(
       unaryOperator( hasOperatorName("--") ).bind(DECREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("-="),
	 hasRHS(
	   integerLiteral(equals(1))
	 )
       ).bind(DECREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("="),
	 hasLHS( declRefExpr() ),
	 hasRHS(
	   binaryOperator(
	     hasOperatorName("-"),
	     hasLHS( declRefExpr() )
	     //hasRHS( anything() )
	  )
	)
       ).bind(DECREMENT_ONE_ID)
    );
  }

  StatementMatcher makeLoopStrideMatcher(){
      return anyOf(
	makeIncrementMatcher(),
	makeDecrementMatcher()
      );
  }

  StatementMatcher makeIterationStmtMatcher(){
    return forStmt(
#if 0
	hasLoopInit(
	  makeLoopInitializationMatcher()
	),
#endif
	hasCondition(
	  makeLoopConditionMatcher()
	),
	hasIncrement(
	  makeLoopStrideMatcher()
	),
	unless(
	  hasAncestor(
	    forStmt()
	  )
	)
    ).bind(FOR_LOOP_ID);
  }

  typedef std::pair<std::string,int> path_and_line_t;
  typedef std::map<path_and_line_t, double > line_profile_t;

  line_profile_t loadProfileDB(){
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    using namespace std;

    line_profile_t statement_to_weight;
    string profile_db_name = "perf.data.eval.db"; // TODO make name changeable
    ifstream in(profile_db_name);
    if ( in.good() ){

      // read the file line by line
      string line;
      while( getline( in, line ) ) {
	stringstream sstr( line ) ;
	string path;
	int line;
	double weight;
	sstr >> path;
	sstr >> line;
	sstr >> weight;

	statement_to_weight[make_pair(path,line)] = weight;
      }

    }

    std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;
    return statement_to_weight;
  }

  void HandleTranslationUnit(ASTContext& context) override {

    // TODO call the initialization functions for clan-clang here !!!

    out << "called the function" << std::endl;

    class Callback : public MatchFinder::MatchCallback {
    private:

    public:
      Callback (line_profile_t& _profile_db) :
	profile_db(_profile_db)
      {
      }

      void handleForLoops( const MatchFinder::MatchResult &Result ){
	std::cout << __PRETTY_FUNCTION__ << std::endl;
	const auto* for_loop = Result.Nodes.getNodeAs<ForStmt>(FOR_LOOP_ID);
	ASTContext& context = *Result.Context;
	const SourceManager& SM = context.getSourceManager();

	all_for_loops.push_back(for_loop);

	assoziateForLoopWithWeight( for_loop, SM );
	std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;
      }

      void assoziateForLoopWithWeight( const ForStmt* for_loop, const SourceManager& SM ){
	std::cout << __PRETTY_FUNCTION__ << std::endl;
	using namespace std;
	SourceLocation start =  for_loop->getLocStart();
	SourceLocation end = for_loop->getLocEnd();
	// go through all entries in the map and check whether they are inside the loop
	for( auto&& element : profile_db ){
	  auto& key = element.first;
	  auto& value = element.second;
	  auto filename = SM.getFilename( start );
	  if ( filename != key.first ) continue;

	  auto line_number_start = SM.getSpellingLineNumber( start );
	  auto line_number_end = SM.getSpellingLineNumber( end );

	  if ( key.second >= line_number_start && key.second <= line_number_end ) {
	    for_loop_to_weight[for_loop] += value;
	  }
	}

	for( auto&& element : for_loop_to_weight ){
	    std::cout << "loop " << element.first << " weight " << element.second << std::endl;
	}
	std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;

      }

      void select_target_loop() {
	const ForStmt* max_loop = nullptr;
	double max_weight = -1;

	for( auto&& element : for_loop_to_weight ){
	  if ( element.second > max_weight ){
	    max_weight = element.second;
	    max_loop = element.first;
	  }
	}

	target_for_loop = max_loop;
      }

      // is the function that is called if the matcher finds something
      virtual void run(const MatchFinder::MatchResult &Result){
	std::cout << "callback called" << std::endl;
	handleForLoops( Result ); // from clan-clang
      }

      const ForStmt* getTargetForLoop(){
	// if there is no target for loop
	// select a random one
	if ( !target_for_loop ) {
	  // there is none return nullptr
	  if ( all_for_loops.size() > 0 ) {
	    auto id = drand48() * all_for_loops.size();
	    return all_for_loops[id];
	  }else{
	    return nullptr;
	  }
	}
	return target_for_loop;
      }

    private:
      const ForStmt* target_for_loop = nullptr;
      line_profile_t& profile_db;
      std::map<const ForStmt*, double> for_loop_to_weight;
      std::vector<const ForStmt*> all_for_loops;
    };

    out << "load profile db" << std::endl;
    // this the entry point for finding loops in the code
    // TODO load the profiling db if available
    auto profile_db = loadProfileDB();

    out << "adding matcher"<< std::endl ;
    MatchFinder Finder;
    Callback Fixer(profile_db);
    std::cout << "adding matcher" << std::endl;
    Finder.addMatcher( makeIterationStmtMatcher(), &Fixer);
    std::cout << "running matcher" << std::endl;
    Finder.matchAST(context);

    std::cout << "select a target loop "<< std::endl;
    out << "select a target loop "<< std::endl;
    Fixer.select_target_loop();

    std::cout << "optimize it "<< std::endl;
    out << "optimize it "<< std::endl;
    if ( auto target_for_loop = Fixer.getTargetForLoop() ){
#if 0
      static bool once = true;
      if ( once ) {
	once = false;
      }else{
	return;
      }
#endif
      const SourceManager& SM = context.getSourceManager();
      auto scop = handleForLoop( target_for_loop, SM, "outfile.test.scop.change.this." );
      // if we where able to extract a scop from this loop handle it
      if ( scop ) {
	PlutoOptions* pluto_options = pluto_options_alloc();
	pluto_options->parallel = true;
	pluto_schedule_osl( scop, pluto_options );
#if 1
	std::cout << "generating pluto program from scop" << std::endl;
	auto prog = scop_to_pluto_prog(scop, pluto_options);
	FILE* cloogfp = fopen("cloogp", "w+");
	std::ofstream outfp( "cprog" );
	std::cout << "writing cloog file" << std::endl;
	pluto_gen_cloog_file(cloogfp, prog);
	std::cout << "done writing cloog file" << std::endl;
	fclose(cloogfp);
	cloogfp = fopen("cloogp", "r");
	std::cout << "done rewinding" << std::endl;
	// NOTE: if know this symbol (function) is in the library but i have no header to use it
	std::cout << "generating cloog code" << std::endl;
	pluto_codegen_clang::pluto_multicore_codegen(cloogfp, outfp, prog);
	std::cout << "done generating cloog code" << std::endl;
	pluto_prog_free(prog);

	//fclose( outfp );
	fclose( cloogfp );
#endif

	std::ifstream in("cprog");
	assert( in.good() );

#if 1
	// very bad hack section
	// FIXME temporary hack to get the right content from the cprog file
	{
	  std::string repl;
	  std::string line;
	  bool skip = true;
	  int ctr = 0;
	  while( std::getline( in, line ) ){
	    // skip the first line with the omp header
	    ctr++;
	    if ( ctr == 1 ) {
	      skip = false;
	      continue;
	    }
	    // dont read its content after this line
	    if ( line == "/* End of CLooG code */" ) skip = true;
	    if ( skip ) continue;
	    repl += line + "\n";
	  }
	  in.close();
	  // write the content back to the file
	  std::ofstream out("cprog");
	  out << repl ;
	  out.close();
	  // now the worst of all run gcc and expand all macros
	  system("gcc -E -P -x c cprog > cprog_expanded");

	}
	// read the file back in
	in.open("cprog_expanded");
	// reads the whole file
	std::string repl((
	    std::istreambuf_iterator<char>(in)),
	    std::istreambuf_iterator<char>()
	);
#endif

	std::cout << "emitting diagnositc" << std::endl;
	DiagnosticsEngine &D = Instance.getDiagnostics();
	  unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Warning, "found a scop");
	  D.Report(target_for_loop->getLocStart(), DiagID)
	  << FixItHint::CreateReplacement(SourceRange(target_for_loop->getLocStart(),target_for_loop->getLocEnd()), repl.c_str() );

      }
    }
    out << "exiting normaly "<< std::endl;
    out.close();
  }
};

class ClanAction : public PluginASTAction {
  std::set<std::string> ParsedTemplates;
protected:
  // #stefan this creates the consumer that is given the TU after everything is done
  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef) override {
    out.open("/home/incubus/log/handle_translation_unit.log");
    out << __PRETTY_FUNCTION__ << std::endl;
    return llvm::make_unique<ForLoopConsumer>(CI, ParsedTemplates);
  }

  // #stefan: here one can parse some arugments for this plugin
  bool ParseArgs(const CompilerInstance &CI,
                 const std::vector<std::string> &args) override {
    for (unsigned i = 0, e = args.size(); i != e; ++i) {
      llvm::errs() << "Clan arg = " << args[i] << "\n";

      // Example error handling.
      DiagnosticsEngine &D = CI.getDiagnostics();
      if (args[i] == "-an-error") {
        unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error,
                                            "invalid argument '%0'");
        D.Report(DiagID) << args[i];
        return false;
      } else if (args[i] == "-parse-template") {
        if (i + 1 >= e) {
          D.Report(D.getCustomDiagID(DiagnosticsEngine::Error,
                                     "missing -parse-template argument"));
          return false;
        }
        ++i;
        ParsedTemplates.insert(args[i]);
      }
    }
    if (!args.empty() && args[0] == "help")
      PrintHelp(llvm::errs());

    return true;
  }
  void PrintHelp(llvm::raw_ostream& ros) {
    ros << "Help for Clan plugin goes here\n";
  }

};

}

static FrontendPluginRegistry::Add<ClanAction>
X("clan", "run clan as part of the compiler");
<commit_msg>made it possible to swtich between my clast printing and plutos<commit_after>//===- Clan.cpp ---------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Example clang plugin which simply prints the names of all the top-level decls
// in the input file.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
#include <chrono>
//#include <clan/clan.h>
//#include <osl/scop.h>
//#include <osl/extensions/irregular.h>
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <iostream>
#include <sstream>
#include <map>
#include <fstream>
#include <pluto/libpluto.h>
#include <pluto.h>
#include <string>
#include <pluto_codegen_clang.hpp>

extern "C"{
// TODO PlutoProg is not known outside of libpluto
//      since i want to write my own unparser thats not a big problem but its definitly something i
//      want to change temporarily
//
//int pluto_multicore_codegen(FILE *cloogfp, FILE *outfp, const PlutoProg *prog);
PlutoProg *scop_to_pluto_prog(osl_scop_p scop, PlutoOptions *options);
void pluto_prog_free(PlutoProg* prog);
}

using namespace clang;
using namespace clang::ast_matchers;

osl_scop_p handleForLoop( const ForStmt* for_stmt, const SourceManager& SM, std::string filename );

const char* SCOP_ID = "scop";
const char* FOR_LOOP_ID = "for_loop";
const char* LOOP_ITERATOR_ID = "loop_iterator";
const char* LOOP_INITIALIZER_ID = "loop_initializer";
const char* LOOP_CONDITION_LIST_ID = "loop_condition_list";

const char* DECREMENT_ONE_ID = "decrement_one";
const char* INCREMENT_ONE_ID = "increment_one";

const char* CEILD_ID = "ceild";
const char* FLOORD_ID = "floord";

std::ofstream out;

namespace {

class ForLoopConsumer : public ASTConsumer {
  CompilerInstance &Instance;
  std::set<std::string> ParsedTemplates;

public:
  ForLoopConsumer(CompilerInstance &Instance,
                         std::set<std::string> ParsedTemplates)
      : Instance(Instance), ParsedTemplates(ParsedTemplates) { llvm::errs() << "consumer created\n" ;}

  StatementMatcher makeLoopConditionMatcher(){
      return expr().bind(LOOP_CONDITION_LIST_ID);
  }

  StatementMatcher makeIncrementMatcher(){
    return anyOf(
       unaryOperator( hasOperatorName("++") ).bind(INCREMENT_ONE_ID) ,
       binaryOperator(
	 hasOperatorName("+="),
	 hasRHS(
	   integerLiteral(equals(1))
	 )
       ).bind(INCREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("="),
	 hasLHS( declRefExpr() ),
	 hasRHS(
	   binaryOperator(
	     hasOperatorName("+"),
	     hasLHS( declRefExpr() )
	     //hasRHS(  )
	  )
	)
       ).bind(INCREMENT_ONE_ID)
    );
  }

  StatementMatcher makeDecrementMatcher(){
    return anyOf(
       unaryOperator( hasOperatorName("--") ).bind(DECREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("-="),
	 hasRHS(
	   integerLiteral(equals(1))
	 )
       ).bind(DECREMENT_ONE_ID),
       binaryOperator(
	 hasOperatorName("="),
	 hasLHS( declRefExpr() ),
	 hasRHS(
	   binaryOperator(
	     hasOperatorName("-"),
	     hasLHS( declRefExpr() )
	     //hasRHS( anything() )
	  )
	)
       ).bind(DECREMENT_ONE_ID)
    );
  }

  StatementMatcher makeLoopStrideMatcher(){
      return anyOf(
	makeIncrementMatcher(),
	makeDecrementMatcher()
      );
  }

  StatementMatcher makeIterationStmtMatcher(){
    return forStmt(
#if 0
	hasLoopInit(
	  makeLoopInitializationMatcher()
	),
#endif
	hasCondition(
	  makeLoopConditionMatcher()
	),
	hasIncrement(
	  makeLoopStrideMatcher()
	),
	unless(
	  hasAncestor(
	    forStmt()
	  )
	)
    ).bind(FOR_LOOP_ID);
  }

  typedef std::pair<std::string,int> path_and_line_t;
  typedef std::map<path_and_line_t, double > line_profile_t;

  line_profile_t loadProfileDB(){
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    using namespace std;

    line_profile_t statement_to_weight;
    string profile_db_name = "perf.data.eval.db"; // TODO make name changeable
    ifstream in(profile_db_name);
    if ( in.good() ){

      // read the file line by line
      string line;
      while( getline( in, line ) ) {
	stringstream sstr( line ) ;
	string path;
	int line;
	double weight;
	sstr >> path;
	sstr >> line;
	sstr >> weight;

	statement_to_weight[make_pair(path,line)] = weight;
      }

    }

    std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;
    return statement_to_weight;
  }

  void HandleTranslationUnit(ASTContext& context) override {

    // TODO call the initialization functions for clan-clang here !!!

    out << "called the function" << std::endl;

    class Callback : public MatchFinder::MatchCallback {
    private:

    public:
      Callback (line_profile_t& _profile_db) :
	profile_db(_profile_db)
      {
      }

      void handleForLoops( const MatchFinder::MatchResult &Result ){
	std::cout << __PRETTY_FUNCTION__ << std::endl;
	const auto* for_loop = Result.Nodes.getNodeAs<ForStmt>(FOR_LOOP_ID);
	ASTContext& context = *Result.Context;
	const SourceManager& SM = context.getSourceManager();

	all_for_loops.push_back(for_loop);

	assoziateForLoopWithWeight( for_loop, SM );
	std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;
      }

      void assoziateForLoopWithWeight( const ForStmt* for_loop, const SourceManager& SM ){
	std::cout << __PRETTY_FUNCTION__ << std::endl;
	using namespace std;
	SourceLocation start =  for_loop->getLocStart();
	SourceLocation end = for_loop->getLocEnd();
	// go through all entries in the map and check whether they are inside the loop
	for( auto&& element : profile_db ){
	  auto& key = element.first;
	  auto& value = element.second;
	  auto filename = SM.getFilename( start );
	  if ( filename != key.first ) continue;

	  auto line_number_start = SM.getSpellingLineNumber( start );
	  auto line_number_end = SM.getSpellingLineNumber( end );

	  if ( key.second >= line_number_start && key.second <= line_number_end ) {
	    for_loop_to_weight[for_loop] += value;
	  }
	}

	for( auto&& element : for_loop_to_weight ){
	    std::cout << "loop " << element.first << " weight " << element.second << std::endl;
	}
	std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl;

      }

      void select_target_loop() {
	const ForStmt* max_loop = nullptr;
	double max_weight = -1;

	for( auto&& element : for_loop_to_weight ){
	  if ( element.second > max_weight ){
	    max_weight = element.second;
	    max_loop = element.first;
	  }
	}

	target_for_loop = max_loop;
      }

      // is the function that is called if the matcher finds something
      virtual void run(const MatchFinder::MatchResult &Result){
	std::cout << "callback called" << std::endl;
	handleForLoops( Result ); // from clan-clang
      }

      const ForStmt* getTargetForLoop(){
	// if there is no target for loop
	// select a random one
	if ( !target_for_loop ) {
	  // there is none return nullptr
	  if ( all_for_loops.size() > 0 ) {
	    auto id = drand48() * all_for_loops.size();
	    return all_for_loops[id];
	  }else{
	    return nullptr;
	  }
	}
	return target_for_loop;
      }

    private:
      const ForStmt* target_for_loop = nullptr;
      line_profile_t& profile_db;
      std::map<const ForStmt*, double> for_loop_to_weight;
      std::vector<const ForStmt*> all_for_loops;
    };

    out << "load profile db" << std::endl;
    // this the entry point for finding loops in the code
    // TODO load the profiling db if available
    auto profile_db = loadProfileDB();

    out << "adding matcher"<< std::endl ;
    MatchFinder Finder;
    Callback Fixer(profile_db);
    std::cout << "adding matcher" << std::endl;
    Finder.addMatcher( makeIterationStmtMatcher(), &Fixer);
    std::cout << "running matcher" << std::endl;
    Finder.matchAST(context);

    std::cout << "select a target loop "<< std::endl;
    out << "select a target loop "<< std::endl;
    Fixer.select_target_loop();

    std::cout << "optimize it "<< std::endl;
    out << "optimize it "<< std::endl;
    if ( auto target_for_loop = Fixer.getTargetForLoop() ){
#if 0
      static bool once = true;
      if ( once ) {
	once = false;
      }else{
	return;
      }
#endif
      const SourceManager& SM = context.getSourceManager();
      auto scop = handleForLoop( target_for_loop, SM, "outfile.test.scop.change.this." );
      // if we where able to extract a scop from this loop handle it
      if ( scop ) {
	PlutoOptions* pluto_options = pluto_options_alloc();
	pluto_options->parallel = true;
	pluto_schedule_osl( scop, pluto_options );
#if 1
	std::cout << "generating pluto program from scop" << std::endl;
	auto prog = scop_to_pluto_prog(scop, pluto_options);
	FILE* cloogfp = fopen("cloogp", "w+");
	std::cout << "writing cloog file" << std::endl;
	pluto_gen_cloog_file(cloogfp, prog);
	std::cout << "done writing cloog file" << std::endl;
	fclose(cloogfp);
	cloogfp = fopen("cloogp", "r");
	std::cout << "done rewinding" << std::endl;
	// NOTE: if know this symbol (function) is in the library but i have no header to use it
	std::cout << "generating cloog code" << std::endl;
	// switch between my clast printing or plutos
#if 0
	FILE* outfp = fopen( "cprog", "w" );
	pluto_multicore_codegen(cloogfp, outfp, prog);
	fclose( outfp );
#else
	std::stringstream outfp;
	pluto_codegen_clang::pluto_multicore_codegen(cloogfp, outfp, prog);
	// TODO delete this after the rest of the parsing was adapted to stringstream
	std::ofstream temporary_output("cprog");
	temporary_output << outfp.str();
	temporary_output.close();
#endif
	std::cout << "done generating cloog code" << std::endl;
	pluto_prog_free(prog);

	fclose( cloogfp );
#endif

	std::ifstream in("cprog");
	assert( in.good() );

#if 1
	// very bad hack section
	// FIXME temporary hack to get the right content from the cprog file
	{
	  std::string repl;
	  std::string line;
	  bool skip = true;
	  int ctr = 0;
	  while( std::getline( in, line ) ){
	    // skip the first line with the omp header
	    ctr++;
	    if ( ctr == 1 ) {
	      skip = false;
	      continue;
	    }
	    // dont read its content after this line
	    if ( line == "/* End of CLooG code */" ) skip = true;
	    if ( skip ) continue;
	    repl += line + "\n";
	  }
	  in.close();
	  // write the content back to the file
	  std::ofstream out("cprog");
	  out << repl ;
	  out.close();
	  // now the worst of all run gcc and expand all macros
	  system("gcc -E -P -x c cprog > cprog_expanded");

	}
	// read the file back in
	in.open("cprog_expanded");
	// reads the whole file
	std::string repl((
	    std::istreambuf_iterator<char>(in)),
	    std::istreambuf_iterator<char>()
	);
#endif

	std::cout << "emitting diagnositc" << std::endl;
	DiagnosticsEngine &D = Instance.getDiagnostics();
	  unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Warning, "found a scop");
	  D.Report(target_for_loop->getLocStart(), DiagID)
	  << FixItHint::CreateReplacement(SourceRange(target_for_loop->getLocStart(),target_for_loop->getLocEnd()), repl.c_str() );

      }
    }
    out << "exiting normaly "<< std::endl;
    out.close();
  }
};

class ClanAction : public PluginASTAction {
  std::set<std::string> ParsedTemplates;
protected:
  // #stefan this creates the consumer that is given the TU after everything is done
  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef) override {
    out.open("/home/incubus/log/handle_translation_unit.log");
    out << __PRETTY_FUNCTION__ << std::endl;
    return llvm::make_unique<ForLoopConsumer>(CI, ParsedTemplates);
  }

  // #stefan: here one can parse some arugments for this plugin
  bool ParseArgs(const CompilerInstance &CI,
                 const std::vector<std::string> &args) override {
    for (unsigned i = 0, e = args.size(); i != e; ++i) {
      llvm::errs() << "Clan arg = " << args[i] << "\n";

      // Example error handling.
      DiagnosticsEngine &D = CI.getDiagnostics();
      if (args[i] == "-an-error") {
        unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error,
                                            "invalid argument '%0'");
        D.Report(DiagID) << args[i];
        return false;
      } else if (args[i] == "-parse-template") {
        if (i + 1 >= e) {
          D.Report(D.getCustomDiagID(DiagnosticsEngine::Error,
                                     "missing -parse-template argument"));
          return false;
        }
        ++i;
        ParsedTemplates.insert(args[i]);
      }
    }
    if (!args.empty() && args[0] == "help")
      PrintHelp(llvm::errs());

    return true;
  }
  void PrintHelp(llvm::raw_ostream& ros) {
    ros << "Help for Clan plugin goes here\n";
  }

};

}

static FrontendPluginRegistry::Add<ClanAction>
X("clan", "run clan as part of the compiler");
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparql_tracker_direct.h"
#include "qsparql_tracker_direct_driver_p.h"
#include "qsparql_tracker_direct_select_result_p.h"
#include "qsparql_tracker_direct_sync_result_p.h"
#include "qsparql_tracker_direct_update_result_p.h"

#include <qsparqlconnection.h>

#include <QtCore/qdatetime.h>

#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qsemaphore.h>

QT_BEGIN_NAMESPACE

// Helper functions used both by QTrackerDirectSelectResult and
// QTrackerDirectSyncResult

namespace {

QVariant makeVariant(TrackerSparqlValueType type, TrackerSparqlCursor* cursor, int col)
{
    glong strLen = 0;
    const gchar* strData = 0;

    // Get string data for types returned as strings from tracker
    switch (type) {
    case TRACKER_SPARQL_VALUE_TYPE_URI:
    case TRACKER_SPARQL_VALUE_TYPE_STRING:
    case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
        strData = tracker_sparql_cursor_get_string(cursor, col, &strLen);
        break;
    default:
        break;
    }

    switch (type) {
    case TRACKER_SPARQL_VALUE_TYPE_UNBOUND:
        break;
    case TRACKER_SPARQL_VALUE_TYPE_URI:
    {
        const QByteArray ba(strData, strLen);
        return QVariant(QUrl::fromEncoded(ba));
    }
    case TRACKER_SPARQL_VALUE_TYPE_STRING:
    {
        return QVariant(QString::fromUtf8(strData, strLen));
    }
    case TRACKER_SPARQL_VALUE_TYPE_INTEGER:
    {
        const gint64 value = tracker_sparql_cursor_get_integer(cursor, col);
        return QVariant(qlonglong(value));
    }
    case TRACKER_SPARQL_VALUE_TYPE_DOUBLE:
    {
        const gdouble value = tracker_sparql_cursor_get_double(cursor, col);
        return QVariant(double(value));
    }
    case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
        {
        return QVariant(QDateTime::fromString(QString::fromUtf8(strData, strLen), Qt::ISODate));
        }
    case TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE:
        // Note: this type is not currently used by Tracker.  Here we're storing
        // it as a null QVariant and losing information that it was a blank
        // node.  If Tracker starts using this type, a possible solution would
        // be to store the blank node label into a QVariant along with some type
        // information indicating that it was a blank node, and utilizing that
        // information in binding().
        break;
    case TRACKER_SPARQL_VALUE_TYPE_BOOLEAN:
    {
        const gboolean value = tracker_sparql_cursor_get_boolean(cursor, col);
        return QVariant(value != FALSE);
    }
    default:
        break;
    }

    return QVariant();
}

}  // namespace

QVariant readVariant(TrackerSparqlCursor* cursor, int col)
{
    const TrackerSparqlValueType type =
        tracker_sparql_cursor_get_value_type(cursor, col);
    return makeVariant(type, cursor, col);
}

QSparqlError::ErrorType errorCodeToType(gint code)
{
    switch (static_cast<TrackerSparqlError>(code)) {
    case TRACKER_SPARQL_ERROR_PARSE:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_UNKNOWN_CLASS:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_TYPE:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_CONSTRAINT:
        return QSparqlError::ConnectionError;
    case TRACKER_SPARQL_ERROR_NO_SPACE:
        return QSparqlError::BackendError;
    case TRACKER_SPARQL_ERROR_INTERNAL:
        return QSparqlError::BackendError;
    case TRACKER_SPARQL_ERROR_UNSUPPORTED:
        return QSparqlError::BackendError;
    default:
        return QSparqlError::BackendError;
    }
}

gint qSparqlPriorityToGlib(QSparqlQueryOptions::Priority priority)
{
    switch (priority) {
    case QSparqlQueryOptions::LowPriority:
        return G_PRIORITY_LOW;
    case QSparqlQueryOptions::NormalPriority:
    default:
        return G_PRIORITY_DEFAULT;
    }
}

////////////////////////////////////////////////////////////////////////////
class QTrackerDirectDriverConnectionOpen : public QObject, public QRunnable
{
    Q_OBJECT
public:
    QTrackerDirectDriverConnectionOpen(QTrackerDirectDriverPrivate *d)
        : connection(0), runSemaphore(1), d(d), runFinished(0)
    {
        setAutoDelete(false);
    }

    GError *error;
    TrackerSparqlConnection *connection;

    void runOrWait()
    {
        if (acquireRunSemaphore())
        {
            if (!runFinished)
                run();
            else
                runSemaphore.release(1);
        }
        else
            wait();
    }

    void queue(QThreadPool& threadPool)
    {
        if (acquireRunSemaphore())
            threadPool.start(this);
    }

Q_SIGNALS:
    void connectionOpened();
private:
    QSemaphore runSemaphore;
    QTrackerDirectDriverPrivate *d;
    bool runFinished;

    void run()
    {
        if (!runFinished) {
            error = 0;
            connection = tracker_sparql_connection_get(0, &error);
            Q_EMIT connectionOpened();
            runFinished = true;
        }
        runSemaphore.release(1);
    }

    void wait()
    {
        runSemaphore.acquire(1);
        runSemaphore.release(1);
    }

    bool acquireRunSemaphore()
    {
        return runSemaphore.tryAcquire(1);
    }
};

QTrackerDirectDriverPrivate::QTrackerDirectDriverPrivate(QTrackerDirectDriver *driver)
    : connection(0), dataReadyInterval(1), connectionMutex(QMutex::Recursive), driver(driver),
      asyncOpenCalled(false), connectionOpener(new QTrackerDirectDriverConnectionOpen(this))
{
    QObject::connect(connectionOpener, SIGNAL(connectionOpened()), this, SLOT(asyncOpenComplete()));
}

QTrackerDirectDriverPrivate::~QTrackerDirectDriverPrivate()
{
    delete connectionOpener;
}

void QTrackerDirectDriverPrivate::asyncOpenComplete()
{
    if (connection == 0) {
        GError *error = connectionOpener->error;
        connection = connectionOpener->connection;
        checkConnectionError(connection, error);
        asyncOpenCalled = true;
        Q_EMIT driver->opened();
    }
}

void QTrackerDirectDriverPrivate::checkConnectionError(TrackerSparqlConnection *conn, GError* gerr)
{
    if (!conn) {
        QString trackerErr(QString::fromUtf8("unknown error"));
        if (gerr) {
            if (gerr->message)
                trackerErr = QString::fromUtf8(gerr->message);
            g_error_free(gerr);
        }
        error = QString::fromUtf8("Couldn't obtain a direct connection to the Tracker store: ") + trackerErr;
        qWarning() << error;
        driver->setOpen(false);
    }
}

void QTrackerDirectDriverPrivate::onConnectionOpen(QObject* object, const char* method, const char* slot)
{
    if (connection || asyncOpenCalled) {
        QMetaObject::invokeMethod(object, method, Qt::DirectConnection);
    }
    else if (!asyncOpenCalled) {
        QObject::connect(driver, SIGNAL(opened()), object, slot, Qt::UniqueConnection);
    }
}

void QTrackerDirectDriverPrivate::waitForConnectionOpen()
{
    connectionOpener->runOrWait();
    asyncOpenComplete();
}

void QTrackerDirectDriverPrivate::openConnection()
{
    connectionOpener->queue(threadPool);
}

QTrackerDirectDriver::QTrackerDirectDriver(QObject* parent)
    : QSparqlDriver(parent)
{
    d = new QTrackerDirectDriverPrivate(this);
    /* Initialize GLib type system */
    g_type_init();

}

QTrackerDirectDriver::~QTrackerDirectDriver()
{
    delete d;
}

bool QTrackerDirectDriver::hasFeature(QSparqlConnection::Feature f) const
{
    switch (f) {
    case QSparqlConnection::QuerySize:
    case QSparqlConnection::AskQueries:
    case QSparqlConnection::UpdateQueries:
    case QSparqlConnection::DefaultGraph:
    case QSparqlConnection::SyncExec:
        return true;
    case QSparqlConnection::ConstructQueries:
    case QSparqlConnection::AsyncExec:
        return false;
    default:
        return false;
    }
    return false;
}

bool QTrackerDirectDriver::open(const QSparqlConnectionOptions& options)
{
    QMutexLocker connectionLocker(&(d->connectionMutex));

    d->dataReadyInterval = options.dataReadyInterval();

    if (isOpen())
        close();

    setOpen(true);
    setOpenError(false);

    //Get the options for the thread pool, if no expiry time has been set
    //set our own value of 2 seconds (the default value is 30 seconds)
    if(options.threadExpiryTime() != -1)
        d->threadPool.setExpiryTimeout(options.threadExpiryTime());
    else
        d->threadPool.setExpiryTimeout(2000);

    //get the max thread count from an option if it was set, else
    //we'll set it to 2 * the qt default of number of cores
    if(options.maxThreadCount() > 0)
        d->threadPool.setMaxThreadCount(options.maxThreadCount());
    else {
        int maxThreads = d->threadPool.maxThreadCount() * 2;
        d->threadPool.setMaxThreadCount(maxThreads);
    }

    //Now start a thread to open the connection
    d->openConnection();

    return true;
}

void QTrackerDirectDriver::close()
{
    Q_EMIT closing();

    // We no longer want to emit any signals, since the driver is
    // closing, so block all signals to prevent any exec methods being
    // called
    blockSignals(true);

    QMutexLocker connectionLocker(&(d->connectionMutex));

    // We just check to see if we can get a semaphore here
    d->waitForConnectionOpen();

    if (d->connection) {
        g_object_unref(d->connection);
        d->connection = 0;
    }

    if (isOpen()) {
        setOpen(false);
        setOpenError(false);
    }
}

QSparqlResult* QTrackerDirectDriver::exec(const QString &query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QSparqlResult* result = 0;
    switch (options.executionMethod()) {
    case QSparqlQueryOptions::AsyncExec:
        result = asyncExec(query, type, options);
        break;
    case QSparqlQueryOptions::SyncExec:
        result = syncExec(query, type, options);
        break;
    }

    return result;
}

QSparqlResult* QTrackerDirectDriver::asyncExec(const QString &query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QTrackerDirectResult *result = 0;
    if (type == QSparqlQuery::AskStatement || type == QSparqlQuery::SelectStatement) {
        result = new QTrackerDirectSelectResult(d, query, type);
    } else {
        result = new QTrackerDirectUpdateResult(d, query, type, options);
    }
    connect(this, SIGNAL(closing()), result, SLOT(driverClosing()));
    d->onConnectionOpen(result, "exec", SLOT(exec()));
    return result;
}

QSparqlResult* QTrackerDirectDriver::syncExec
        (const QString& query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QTrackerDirectResult* result = new QTrackerDirectSyncResult(d, query, type, options);
    connect(this, SIGNAL(closing()), result, SLOT(driverClosing()));
    d->waitForConnectionOpen();
    result->exec();
    return result;
}

QT_END_NAMESPACE

#include "qsparql_tracker_direct_driver_p.moc"
<commit_msg>Remove unneeded driver private pointer from direct connection opener<commit_after>/****************************************************************************
**
** Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparql_tracker_direct.h"
#include "qsparql_tracker_direct_driver_p.h"
#include "qsparql_tracker_direct_select_result_p.h"
#include "qsparql_tracker_direct_sync_result_p.h"
#include "qsparql_tracker_direct_update_result_p.h"

#include <qsparqlconnection.h>

#include <QtCore/qdatetime.h>

#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qsemaphore.h>

QT_BEGIN_NAMESPACE

// Helper functions used both by QTrackerDirectSelectResult and
// QTrackerDirectSyncResult

namespace {

QVariant makeVariant(TrackerSparqlValueType type, TrackerSparqlCursor* cursor, int col)
{
    glong strLen = 0;
    const gchar* strData = 0;

    // Get string data for types returned as strings from tracker
    switch (type) {
    case TRACKER_SPARQL_VALUE_TYPE_URI:
    case TRACKER_SPARQL_VALUE_TYPE_STRING:
    case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
        strData = tracker_sparql_cursor_get_string(cursor, col, &strLen);
        break;
    default:
        break;
    }

    switch (type) {
    case TRACKER_SPARQL_VALUE_TYPE_UNBOUND:
        break;
    case TRACKER_SPARQL_VALUE_TYPE_URI:
    {
        const QByteArray ba(strData, strLen);
        return QVariant(QUrl::fromEncoded(ba));
    }
    case TRACKER_SPARQL_VALUE_TYPE_STRING:
    {
        return QVariant(QString::fromUtf8(strData, strLen));
    }
    case TRACKER_SPARQL_VALUE_TYPE_INTEGER:
    {
        const gint64 value = tracker_sparql_cursor_get_integer(cursor, col);
        return QVariant(qlonglong(value));
    }
    case TRACKER_SPARQL_VALUE_TYPE_DOUBLE:
    {
        const gdouble value = tracker_sparql_cursor_get_double(cursor, col);
        return QVariant(double(value));
    }
    case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
        {
        return QVariant(QDateTime::fromString(QString::fromUtf8(strData, strLen), Qt::ISODate));
        }
    case TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE:
        // Note: this type is not currently used by Tracker.  Here we're storing
        // it as a null QVariant and losing information that it was a blank
        // node.  If Tracker starts using this type, a possible solution would
        // be to store the blank node label into a QVariant along with some type
        // information indicating that it was a blank node, and utilizing that
        // information in binding().
        break;
    case TRACKER_SPARQL_VALUE_TYPE_BOOLEAN:
    {
        const gboolean value = tracker_sparql_cursor_get_boolean(cursor, col);
        return QVariant(value != FALSE);
    }
    default:
        break;
    }

    return QVariant();
}

}  // namespace

QVariant readVariant(TrackerSparqlCursor* cursor, int col)
{
    const TrackerSparqlValueType type =
        tracker_sparql_cursor_get_value_type(cursor, col);
    return makeVariant(type, cursor, col);
}

QSparqlError::ErrorType errorCodeToType(gint code)
{
    switch (static_cast<TrackerSparqlError>(code)) {
    case TRACKER_SPARQL_ERROR_PARSE:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_UNKNOWN_CLASS:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_TYPE:
        return QSparqlError::StatementError;
    case TRACKER_SPARQL_ERROR_CONSTRAINT:
        return QSparqlError::ConnectionError;
    case TRACKER_SPARQL_ERROR_NO_SPACE:
        return QSparqlError::BackendError;
    case TRACKER_SPARQL_ERROR_INTERNAL:
        return QSparqlError::BackendError;
    case TRACKER_SPARQL_ERROR_UNSUPPORTED:
        return QSparqlError::BackendError;
    default:
        return QSparqlError::BackendError;
    }
}

gint qSparqlPriorityToGlib(QSparqlQueryOptions::Priority priority)
{
    switch (priority) {
    case QSparqlQueryOptions::LowPriority:
        return G_PRIORITY_LOW;
    case QSparqlQueryOptions::NormalPriority:
    default:
        return G_PRIORITY_DEFAULT;
    }
}

////////////////////////////////////////////////////////////////////////////
class QTrackerDirectDriverConnectionOpen : public QObject, public QRunnable
{
    Q_OBJECT
public:
    QTrackerDirectDriverConnectionOpen()
        : connection(0), runSemaphore(1), runFinished(0)
    {
        setAutoDelete(false);
    }

    GError *error;
    TrackerSparqlConnection *connection;

    void runOrWait()
    {
        if (acquireRunSemaphore())
        {
            if (!runFinished)
                run();
            else
                runSemaphore.release(1);
        }
        else
            wait();
    }

    void queue(QThreadPool& threadPool)
    {
        if (acquireRunSemaphore())
            threadPool.start(this);
    }

Q_SIGNALS:
    void connectionOpened();
private:
    QSemaphore runSemaphore;
    bool runFinished;

    void run()
    {
        if (!runFinished) {
            error = 0;
            connection = tracker_sparql_connection_get(0, &error);
            Q_EMIT connectionOpened();
            runFinished = true;
        }
        runSemaphore.release(1);
    }

    void wait()
    {
        runSemaphore.acquire(1);
        runSemaphore.release(1);
    }

    bool acquireRunSemaphore()
    {
        return runSemaphore.tryAcquire(1);
    }
};

QTrackerDirectDriverPrivate::QTrackerDirectDriverPrivate(QTrackerDirectDriver *driver)
    : connection(0), dataReadyInterval(1), connectionMutex(QMutex::Recursive), driver(driver),
      asyncOpenCalled(false), connectionOpener(new QTrackerDirectDriverConnectionOpen)
{
    QObject::connect(connectionOpener, SIGNAL(connectionOpened()), this, SLOT(asyncOpenComplete()));
}

QTrackerDirectDriverPrivate::~QTrackerDirectDriverPrivate()
{
    delete connectionOpener;
}

void QTrackerDirectDriverPrivate::asyncOpenComplete()
{
    if (connection == 0) {
        GError *error = connectionOpener->error;
        connection = connectionOpener->connection;
        checkConnectionError(connection, error);
        asyncOpenCalled = true;
        Q_EMIT driver->opened();
    }
}

void QTrackerDirectDriverPrivate::checkConnectionError(TrackerSparqlConnection *conn, GError* gerr)
{
    if (!conn) {
        QString trackerErr(QString::fromUtf8("unknown error"));
        if (gerr) {
            if (gerr->message)
                trackerErr = QString::fromUtf8(gerr->message);
            g_error_free(gerr);
        }
        error = QString::fromUtf8("Couldn't obtain a direct connection to the Tracker store: ") + trackerErr;
        qWarning() << error;
        driver->setOpen(false);
    }
}

void QTrackerDirectDriverPrivate::onConnectionOpen(QObject* object, const char* method, const char* slot)
{
    if (connection || asyncOpenCalled) {
        QMetaObject::invokeMethod(object, method, Qt::DirectConnection);
    }
    else if (!asyncOpenCalled) {
        QObject::connect(driver, SIGNAL(opened()), object, slot, Qt::UniqueConnection);
    }
}

void QTrackerDirectDriverPrivate::waitForConnectionOpen()
{
    connectionOpener->runOrWait();
    asyncOpenComplete();
}

void QTrackerDirectDriverPrivate::openConnection()
{
    connectionOpener->queue(threadPool);
}

QTrackerDirectDriver::QTrackerDirectDriver(QObject* parent)
    : QSparqlDriver(parent)
{
    d = new QTrackerDirectDriverPrivate(this);
    /* Initialize GLib type system */
    g_type_init();

}

QTrackerDirectDriver::~QTrackerDirectDriver()
{
    delete d;
}

bool QTrackerDirectDriver::hasFeature(QSparqlConnection::Feature f) const
{
    switch (f) {
    case QSparqlConnection::QuerySize:
    case QSparqlConnection::AskQueries:
    case QSparqlConnection::UpdateQueries:
    case QSparqlConnection::DefaultGraph:
    case QSparqlConnection::SyncExec:
        return true;
    case QSparqlConnection::ConstructQueries:
    case QSparqlConnection::AsyncExec:
        return false;
    default:
        return false;
    }
    return false;
}

bool QTrackerDirectDriver::open(const QSparqlConnectionOptions& options)
{
    QMutexLocker connectionLocker(&(d->connectionMutex));

    d->dataReadyInterval = options.dataReadyInterval();

    if (isOpen())
        close();

    setOpen(true);
    setOpenError(false);

    //Get the options for the thread pool, if no expiry time has been set
    //set our own value of 2 seconds (the default value is 30 seconds)
    if(options.threadExpiryTime() != -1)
        d->threadPool.setExpiryTimeout(options.threadExpiryTime());
    else
        d->threadPool.setExpiryTimeout(2000);

    //get the max thread count from an option if it was set, else
    //we'll set it to 2 * the qt default of number of cores
    if(options.maxThreadCount() > 0)
        d->threadPool.setMaxThreadCount(options.maxThreadCount());
    else {
        int maxThreads = d->threadPool.maxThreadCount() * 2;
        d->threadPool.setMaxThreadCount(maxThreads);
    }

    //Now start a thread to open the connection
    d->openConnection();

    return true;
}

void QTrackerDirectDriver::close()
{
    Q_EMIT closing();

    // We no longer want to emit any signals, since the driver is
    // closing, so block all signals to prevent any exec methods being
    // called
    blockSignals(true);

    QMutexLocker connectionLocker(&(d->connectionMutex));

    // We just check to see if we can get a semaphore here
    d->waitForConnectionOpen();

    if (d->connection) {
        g_object_unref(d->connection);
        d->connection = 0;
    }

    if (isOpen()) {
        setOpen(false);
        setOpenError(false);
    }
}

QSparqlResult* QTrackerDirectDriver::exec(const QString &query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QSparqlResult* result = 0;
    switch (options.executionMethod()) {
    case QSparqlQueryOptions::AsyncExec:
        result = asyncExec(query, type, options);
        break;
    case QSparqlQueryOptions::SyncExec:
        result = syncExec(query, type, options);
        break;
    }

    return result;
}

QSparqlResult* QTrackerDirectDriver::asyncExec(const QString &query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QTrackerDirectResult *result = 0;
    if (type == QSparqlQuery::AskStatement || type == QSparqlQuery::SelectStatement) {
        result = new QTrackerDirectSelectResult(d, query, type);
    } else {
        result = new QTrackerDirectUpdateResult(d, query, type, options);
    }
    connect(this, SIGNAL(closing()), result, SLOT(driverClosing()));
    d->onConnectionOpen(result, "exec", SLOT(exec()));
    return result;
}

QSparqlResult* QTrackerDirectDriver::syncExec
        (const QString& query, QSparqlQuery::StatementType type, const QSparqlQueryOptions& options)
{
    QTrackerDirectResult* result = new QTrackerDirectSyncResult(d, query, type, options);
    connect(this, SIGNAL(closing()), result, SLOT(driverClosing()));
    d->waitForConnectionOpen();
    result->exec();
    return result;
}

QT_END_NAMESPACE

#include "qsparql_tracker_direct_driver_p.moc"
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP
#define SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP

#include "utilities/globalDefinitions.hpp"

class ReferenceProcessor;

// ReferenceProcessorStats contains statistics about how many references that
// have been traversed when processing references during garbage collection.
class ReferenceProcessorStats {
  size_t _soft_count;
  size_t _weak_count;
  size_t _final_count;
  size_t _phantom_count;

 public:
  ReferenceProcessorStats() :
    _soft_count(0),
    _weak_count(0),
    _final_count(0),
    _phantom_count(0) {}

  ReferenceProcessorStats(size_t soft_count,
                          size_t weak_count,
                          size_t final_count,
                          size_t phantom_count) :
    _soft_count(soft_count),
    _weak_count(weak_count),
    _final_count(final_count),
    _phantom_count(phantom_count)
  {}

  size_t soft_count() const {
    return _soft_count;
  }

  size_t weak_count() const {
    return _weak_count;
  }

  size_t final_count() const {
    return _final_count;
  }

  size_t phantom_count() const {
    return _phantom_count;
  }
};
#endif
<commit_msg>8017323: JDK8 b95 source with GPL header errors Reviewed-by: tbell, darcy<commit_after>/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP
#define SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP

#include "utilities/globalDefinitions.hpp"

class ReferenceProcessor;

// ReferenceProcessorStats contains statistics about how many references that
// have been traversed when processing references during garbage collection.
class ReferenceProcessorStats {
  size_t _soft_count;
  size_t _weak_count;
  size_t _final_count;
  size_t _phantom_count;

 public:
  ReferenceProcessorStats() :
    _soft_count(0),
    _weak_count(0),
    _final_count(0),
    _phantom_count(0) {}

  ReferenceProcessorStats(size_t soft_count,
                          size_t weak_count,
                          size_t final_count,
                          size_t phantom_count) :
    _soft_count(soft_count),
    _weak_count(weak_count),
    _final_count(final_count),
    _phantom_count(phantom_count)
  {}

  size_t soft_count() const {
    return _soft_count;
  }

  size_t weak_count() const {
    return _weak_count;
  }

  size_t final_count() const {
    return _final_count;
  }

  size_t phantom_count() const {
    return _phantom_count;
  }
};
#endif
<|endoftext|>


<commit_before>// Arguments: Double, Double, Double, Double
#include <stan/prob/distributions/univariate/continuous/student_t.hpp>

using std::vector;
using std::numeric_limits;
using stan::agrad::var;

class AgradDistributionsStudentT : public AgradDistributionTest {
public:
  void valid_values(vector<vector<double> >& parameters,
                    vector<double>& log_prob) {
    vector<double> param(4);

    param[0] = 1.0;           // y
    param[1] = 1.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 1.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-1.837877); // expected log_prob

    param[0] = -3.0;          // y
    param[1] = 2.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 1.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-3.596843); // expected log_prob

    param[0] = 2.0;           // y
    param[1] = 1.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 2.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-2.531024); // expected log_prob
  }

  void invalid_values(vector<size_t>& index,
                      vector<double>& value) {
    // y

    // nu
    index.push_back(1U);
    value.push_back(0.0);

    index.push_back(1U);
    value.push_back(-1.0);

    index.push_back(1U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(1U);
    value.push_back(-numeric_limits<double>::infinity());

    // mu
    index.push_back(2U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(2U);
    value.push_back(-numeric_limits<double>::infinity());

    // sigma
    index.push_back(3U);
    value.push_back(0.0);

    index.push_back(3U);
    value.push_back(-1.0);

    index.push_back(3U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(3U);
    value.push_back(-numeric_limits<double>::infinity());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log(y, nu, mu, sigma);
  }

  template <bool propto,
	    class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log<propto>(y, nu, mu, sigma);
  }

  template <bool propto,
	    class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9,
	    class Policy>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log<propto>(y, nu, mu, sigma, Policy());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  var log_prob_function(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
			const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    using std::log;
    using stan::math::square;
    using stan::math::log1p;
    using boost::math::lgamma;
    using stan::prob::include_summand;
    using stan::prob::NEG_LOG_SQRT_PI;

    var logp(0);
    if (include_summand<true,T_dof>::value)
      logp += lgamma( (nu + 1.0) / 2.0) - lgamma(nu / 2.0);
    if (include_summand<true>::value)
      logp += NEG_LOG_SQRT_PI;
    if (include_summand<true,T_dof>::value)
      logp -= 0.5 * log(nu);
    if (include_summand<true,T_scale>::value)
      logp -= log(sigma);
    if (include_summand<true,T_y,T_dof,T_loc,T_scale>::value)
      logp -= ((nu + 1.0) / 2.0)
	* log1p( square(((y - mu) / sigma)) / nu);
    return logp;
  }
};

TEST(ProbDistributionsStudentTCDF,Values) {
    EXPECT_FLOAT_EQ(0.75, stan::prob::student_t_cdf(1.0,1.0,0.0,1.0));
    EXPECT_FLOAT_EQ(0.047732983, stan::prob::student_t_cdf(-3.0,2.0,0.0,1.0));
}
<commit_msg>added vector tests for student_t<commit_after>// Arguments: Doubles, Doubles, Doubles, Doubles
#include <stan/prob/distributions/univariate/continuous/student_t.hpp>

using std::vector;
using std::numeric_limits;
using stan::agrad::var;

class AgradDistributionsStudentT : public AgradDistributionTest {
public:
  void valid_values(vector<vector<double> >& parameters,
                    vector<double>& log_prob) {
    vector<double> param(4);

    param[0] = 1.0;           // y
    param[1] = 1.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 1.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-1.837877); // expected log_prob

    param[0] = -3.0;          // y
    param[1] = 2.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 1.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-3.596843); // expected log_prob

    param[0] = 2.0;           // y
    param[1] = 1.0;           // nu
    param[2] = 0.0;           // mu
    param[3] = 2.0;           // sigma
    parameters.push_back(param);
    log_prob.push_back(-2.531024); // expected log_prob
  }

  void invalid_values(vector<size_t>& index,
                      vector<double>& value) {
    // y

    // nu
    index.push_back(1U);
    value.push_back(0.0);

    index.push_back(1U);
    value.push_back(-1.0);

    index.push_back(1U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(1U);
    value.push_back(-numeric_limits<double>::infinity());

    // mu
    index.push_back(2U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(2U);
    value.push_back(-numeric_limits<double>::infinity());

    // sigma
    index.push_back(3U);
    value.push_back(0.0);

    index.push_back(3U);
    value.push_back(-1.0);

    index.push_back(3U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(3U);
    value.push_back(-numeric_limits<double>::infinity());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log(y, nu, mu, sigma);
  }

  template <bool propto,
	    class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log<propto>(y, nu, mu, sigma);
  }

  template <bool propto,
	    class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9,
	    class Policy>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
	   const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    return stan::prob::student_t_log<propto>(y, nu, mu, sigma, Policy());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale,
	    typename T4, typename T5, typename T6,
	    typename T7, typename T8, typename T9>
  var log_prob_function(const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
			const T4&, const T5&, const T6&, const T7&, const T8&, const T9&) {
    using std::log;
    using stan::math::square;
    using stan::math::log1p;
    using boost::math::lgamma;
    using stan::prob::include_summand;
    using stan::prob::NEG_LOG_SQRT_PI;

    var logp(0);
    if (include_summand<true,T_dof>::value)
      logp += lgamma( (nu + 1.0) / 2.0) - lgamma(nu / 2.0);
    if (include_summand<true>::value)
      logp += NEG_LOG_SQRT_PI;
    if (include_summand<true,T_dof>::value)
      logp -= 0.5 * log(nu);
    if (include_summand<true,T_scale>::value)
      logp -= log(sigma);
    if (include_summand<true,T_y,T_dof,T_loc,T_scale>::value)
      logp -= ((nu + 1.0) / 2.0)
	* log1p( square(((y - mu) / sigma)) / nu);
    return logp;
  }
};

TEST(ProbDistributionsStudentTCDF,Values) {
    EXPECT_FLOAT_EQ(0.75, stan::prob::student_t_cdf(1.0,1.0,0.0,1.0));
    EXPECT_FLOAT_EQ(0.047732983, stan::prob::student_t_cdf(-3.0,2.0,0.0,1.0));
}
<|endoftext|>