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

  Program:   Visualization Toolkit
  Module:    vtkXMLRectilinearGridWriter.cxx

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

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

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

#include "vtkCellData.h"
#include "vtkErrorCode.h"
#include "vtkExtentTranslator.h"
#include "vtkFloatArray.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkRectilinearGrid.h"
#define vtkOffsetsManager_DoNotInclude
#include "vtkOffsetsManagerArray.h"
#undef  vtkOffsetsManager_DoNotInclude

vtkCxxRevisionMacro(vtkXMLRectilinearGridWriter, "1.12");
vtkStandardNewMacro(vtkXMLRectilinearGridWriter);

//----------------------------------------------------------------------------
vtkXMLRectilinearGridWriter::vtkXMLRectilinearGridWriter()
{
  this->CoordinateOM = new OffsetsManagerArray;
}

//----------------------------------------------------------------------------
vtkXMLRectilinearGridWriter::~vtkXMLRectilinearGridWriter()
{
  delete this->CoordinateOM;
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//----------------------------------------------------------------------------
vtkRectilinearGrid* vtkXMLRectilinearGridWriter::GetInput()
{
  return static_cast<vtkRectilinearGrid*>(this->Superclass::GetInput());
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::GetInputExtent(int* extent)
{
  this->GetInput()->GetExtent(extent);
}

//----------------------------------------------------------------------------
const char* vtkXMLRectilinearGridWriter::GetDataSetName()
{
  return "RectilinearGrid";
}

//----------------------------------------------------------------------------
const char* vtkXMLRectilinearGridWriter::GetDefaultFileExtension()
{
  return "vtr";
}

//----------------------------------------------------------------------------
vtkDataArray*
vtkXMLRectilinearGridWriter::CreateExactCoordinates(vtkDataArray* a, int xyz)
{
  int inExtent[6];
  int outExtent[6];
  this->GetInput()->GetExtent(inExtent);
  this->ExtentTranslator->GetExtent(outExtent);
  int* inBounds = inExtent+xyz*2;
  int* outBounds = outExtent+xyz*2;

  if(!a)
    {
    // There are no coordinates.  This can happen with empty input.
    return vtkFloatArray::New();
    }

  if((inBounds[0] == outBounds[0]) && (inBounds[1] == outBounds[1]))
    {
    // Use the entire coordinates array.
    a->Register(0);
    return a;
    }
  else
    {
    // Create a subset of the coordinates array.
    int components = a->GetNumberOfComponents();
    int tupleSize = components*this->GetWordTypeSize(a->GetDataType());
    vtkDataArray* b = a->NewInstance();
    b->SetNumberOfComponents(components);
    b->SetName(a->GetName());
    int tuples = outBounds[1] - outBounds[0] + 1;
    int offset = outBounds[0] - inBounds[0];
    b->SetNumberOfTuples(tuples);
    memcpy(b->GetVoidPointer(0), a->GetVoidPointer(offset), tuples*tupleSize);
    return b;
    }
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::AllocatePositionArrays()
{
  this->Superclass::AllocatePositionArrays();

  this->CoordinateOM->Allocate(this->NumberOfPieces);
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::DeletePositionArrays()
{
  this->Superclass::DeletePositionArrays();
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteAppendedPiece(int index,
                                                     vtkIndent indent)
{
  this->Superclass::WriteAppendedPiece(index, indent);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  this->WriteCoordinatesAppended(this->GetInput()->GetXCoordinates(),
                                 this->GetInput()->GetYCoordinates(),
                                 this->GetInput()->GetZCoordinates(),
                                 indent, &this->CoordinateOM->GetPiece(index));
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteAppendedPieceData(int index)
{
  // Split progress range by the approximate fractions of data written
  // by each step in this method.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[3];
  this->CalculateSuperclassFraction(fractions);

  // Set the range of progress for the superclass.
  this->SetProgressRange(progressRange, 0, fractions);

  // Let the superclass write its data.
  this->Superclass::WriteAppendedPieceData(index);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  // Set the range of progress for the coordinates arrays.
  this->SetProgressRange(progressRange, 1, fractions);

  // Write the coordinates arrays.
  this->WriteCoordinatesAppendedData(this->GetInput()->GetXCoordinates(),
                                     this->GetInput()->GetYCoordinates(),
                                     this->GetInput()->GetZCoordinates(),
                                     this->CurrentTimeIndex,
                                     &this->CoordinateOM->GetPiece(index));
  this->CoordinateOM->GetPiece(index).Allocate(0); //mark it invalid
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteInlinePiece(vtkIndent indent)
{
  // Split progress range by the approximate fractions of data written
  // by each step in this method.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[3];
  this->CalculateSuperclassFraction(fractions);

  // Set the range of progress for the superclass.
  this->SetProgressRange(progressRange, 0, fractions);

  // Let the superclass write its data.
  this->Superclass::WriteInlinePiece(indent);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  // Set the range of progress for the coordinates arrays.
  this->SetProgressRange(progressRange, 1, fractions);

  // Write the coordinates arrays.
  this->WriteCoordinatesInline(this->GetInput()->GetXCoordinates(),
                               this->GetInput()->GetYCoordinates(),
                               this->GetInput()->GetZCoordinates(),
                               indent);
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::CalculateSuperclassFraction(float* fractions)
{
  int extent[6];
  this->ExtentTranslator->GetExtent(extent);
  int dims[3] = {extent[1]-extent[0]+1,
                 extent[3]-extent[2]+1,
                 extent[5]-extent[4]+1};

  // The amount of data written by the superclass comes from the
  // point/cell data arrays.
  vtkIdType superclassPieceSize =
    (this->GetInput()->GetPointData()->GetNumberOfArrays()*dims[0]*dims[1]*dims[2]+
     this->GetInput()->GetCellData()->GetNumberOfArrays()*(dims[0]-1)*(dims[1]-1)*(dims[2]-1));

  // The total data written includes the coordinate arrays.
  vtkIdType totalPieceSize =
    superclassPieceSize + dims[0] + dims[1] + dims[2];
  if(totalPieceSize == 0)
    {
    totalPieceSize = 1;
    }
  fractions[0] = 0;
  fractions[1] = fractions[0] + float(superclassPieceSize)/totalPieceSize;
  fractions[2] = 1;
}

//----------------------------------------------------------------------------
int vtkXMLRectilinearGridWriter::FillInputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid");
  return 1;
}
<commit_msg>BUG: Situation occurred where the ExtentTranslator was not setup for the current piece (in multi-piece datasets)<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLRectilinearGridWriter.cxx

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

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

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

#include "vtkCellData.h"
#include "vtkErrorCode.h"
#include "vtkExtentTranslator.h"
#include "vtkFloatArray.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkRectilinearGrid.h"
#define vtkOffsetsManager_DoNotInclude
#include "vtkOffsetsManagerArray.h"
#undef  vtkOffsetsManager_DoNotInclude

vtkCxxRevisionMacro(vtkXMLRectilinearGridWriter, "1.13");
vtkStandardNewMacro(vtkXMLRectilinearGridWriter);

//----------------------------------------------------------------------------
vtkXMLRectilinearGridWriter::vtkXMLRectilinearGridWriter()
{
  this->CoordinateOM = new OffsetsManagerArray;
}

//----------------------------------------------------------------------------
vtkXMLRectilinearGridWriter::~vtkXMLRectilinearGridWriter()
{
  delete this->CoordinateOM;
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//----------------------------------------------------------------------------
vtkRectilinearGrid* vtkXMLRectilinearGridWriter::GetInput()
{
  return static_cast<vtkRectilinearGrid*>(this->Superclass::GetInput());
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::GetInputExtent(int* extent)
{
  this->GetInput()->GetExtent(extent);
}

//----------------------------------------------------------------------------
const char* vtkXMLRectilinearGridWriter::GetDataSetName()
{
  return "RectilinearGrid";
}

//----------------------------------------------------------------------------
const char* vtkXMLRectilinearGridWriter::GetDefaultFileExtension()
{
  return "vtr";
}

//----------------------------------------------------------------------------
vtkDataArray*
vtkXMLRectilinearGridWriter::CreateExactCoordinates(vtkDataArray* a, int xyz)
{
  int inExtent[6];
  int outExtent[6];
  this->GetInput()->GetExtent(inExtent);
  this->ExtentTranslator->SetPiece(this->CurrentPiece);
  this->ExtentTranslator->PieceToExtent();
  this->ExtentTranslator->GetExtent(outExtent);
  int* inBounds = inExtent+xyz*2;
  int* outBounds = outExtent+xyz*2;

  if(!a)
    {
    // There are no coordinates.  This can happen with empty input.
    return vtkFloatArray::New();
    }

  if((inBounds[0] == outBounds[0]) && (inBounds[1] == outBounds[1]))
    {
    // Use the entire coordinates array.
    a->Register(0);
    return a;
    }
  else
    {
    // Create a subset of the coordinates array.
    int components = a->GetNumberOfComponents();
    int tupleSize = components*this->GetWordTypeSize(a->GetDataType());
    vtkDataArray* b = a->NewInstance();
    b->SetNumberOfComponents(components);
    b->SetName(a->GetName());
    int tuples = outBounds[1] - outBounds[0] + 1;
    int offset = outBounds[0] - inBounds[0];
    b->SetNumberOfTuples(tuples);
    memcpy(b->GetVoidPointer(0), a->GetVoidPointer(offset), tuples*tupleSize);
    return b;
    }
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::AllocatePositionArrays()
{
  this->Superclass::AllocatePositionArrays();

  this->CoordinateOM->Allocate(this->NumberOfPieces);
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::DeletePositionArrays()
{
  this->Superclass::DeletePositionArrays();
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteAppendedPiece(int index,
                                                     vtkIndent indent)
{
  this->Superclass::WriteAppendedPiece(index, indent);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  this->WriteCoordinatesAppended(this->GetInput()->GetXCoordinates(),
                                 this->GetInput()->GetYCoordinates(),
                                 this->GetInput()->GetZCoordinates(),
                                 indent, &this->CoordinateOM->GetPiece(index));
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteAppendedPieceData(int index)
{
  // Split progress range by the approximate fractions of data written
  // by each step in this method.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[3];
  this->CalculateSuperclassFraction(fractions);

  // Set the range of progress for the superclass.
  this->SetProgressRange(progressRange, 0, fractions);

  // Let the superclass write its data.
  this->Superclass::WriteAppendedPieceData(index);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  // Set the range of progress for the coordinates arrays.
  this->SetProgressRange(progressRange, 1, fractions);

  // Write the coordinates arrays.
  this->WriteCoordinatesAppendedData(this->GetInput()->GetXCoordinates(),
                                     this->GetInput()->GetYCoordinates(),
                                     this->GetInput()->GetZCoordinates(),
                                     this->CurrentTimeIndex,
                                     &this->CoordinateOM->GetPiece(index));
  this->CoordinateOM->GetPiece(index).Allocate(0); //mark it invalid
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::WriteInlinePiece(vtkIndent indent)
{
  // Split progress range by the approximate fractions of data written
  // by each step in this method.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[3];
  this->CalculateSuperclassFraction(fractions);

  // Set the range of progress for the superclass.
  this->SetProgressRange(progressRange, 0, fractions);

  // Let the superclass write its data.
  this->Superclass::WriteInlinePiece(indent);
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }

  // Set the range of progress for the coordinates arrays.
  this->SetProgressRange(progressRange, 1, fractions);

  // Write the coordinates arrays.
  this->WriteCoordinatesInline(this->GetInput()->GetXCoordinates(),
                               this->GetInput()->GetYCoordinates(),
                               this->GetInput()->GetZCoordinates(),
                               indent);
}

//----------------------------------------------------------------------------
void vtkXMLRectilinearGridWriter::CalculateSuperclassFraction(float* fractions)
{
  int extent[6];
  this->ExtentTranslator->SetPiece(this->CurrentPiece);
  this->ExtentTranslator->PieceToExtent();
  this->ExtentTranslator->GetExtent(extent);
  int dims[3] = {extent[1]-extent[0]+1,
                 extent[3]-extent[2]+1,
                 extent[5]-extent[4]+1};

  // The amount of data written by the superclass comes from the
  // point/cell data arrays.
  vtkIdType superclassPieceSize =
    (this->GetInput()->GetPointData()->GetNumberOfArrays()*dims[0]*dims[1]*dims[2]+
     this->GetInput()->GetCellData()->GetNumberOfArrays()*(dims[0]-1)*(dims[1]-1)*(dims[2]-1));

  // The total data written includes the coordinate arrays.
  vtkIdType totalPieceSize =
    superclassPieceSize + dims[0] + dims[1] + dims[2];
  if(totalPieceSize == 0)
    {
    totalPieceSize = 1;
    }
  fractions[0] = 0;
  fractions[1] = fractions[0] + float(superclassPieceSize)/totalPieceSize;
  fractions[2] = 1;
}

//----------------------------------------------------------------------------
int vtkXMLRectilinearGridWriter::FillInputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid");
  return 1;
}
<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    int hIndex(vector<int>& citations) {
        sort(citations.begin(), citations.end(), greater<int>());
        int h = 0;
        for (int i = 0; i < citations.size(); ++i) {
            if (citations[i] >= i + 1) {
                ++h;
            } else {
                break;
            }
        }
        return h;
    }
};
<commit_msg>Update h-index.cpp<commit_after>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    int hIndex(vector<int>& citations) {
        sort(citations.begin(), citations.end(), greater<int>());
        int h = 0;
        for (const auto& x : citations) {
            if (x >= h + 1) {
                ++h;
            } else {
                break;
            }
        }
        return h;
    }
};
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkStreamingStatistics.cxx

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

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2010 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkStreamingStatistics.h"

#include "vtkDataObjectCollection.h"
#include "vtkInformation.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkStatisticsAlgorithm.h"
#include "vtkTable.h"

vtkStandardNewMacro(vtkStreamingStatistics);

vtkCxxSetObjectMacro(vtkStreamingStatistics,
                     StatisticsAlgorithm,
                     vtkStatisticsAlgorithm);

// ----------------------------------------------------------------------
vtkStreamingStatistics::vtkStreamingStatistics()
{
  // Setup input/output ports
  this->SetNumberOfInputPorts(3);
  this->SetNumberOfOutputPorts(3);

  // Initialize internal stats algorithm to NULL
  this->StatisticsAlgorithm = 0;
  this->SetStatisticsAlgorithm(0);

  // Initialize internal model
  this->internalModel = vtkMultiBlockDataSet::New();
}

// ----------------------------------------------------------------------
vtkStreamingStatistics::~vtkStreamingStatistics()
{
  // Release/delete internal stats algorithm
  this->SetStatisticsAlgorithm(0);
  this->StatisticsAlgorithm = 0;

  // Release/delete internal model to NULL
  this->internalModel->Delete();
  this->internalModel = 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::FillInputPortInformation( int port, vtkInformation* info )
{
  if ( port == INPUT_DATA )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable" );
    return 1;
    }
  else if ( port == INPUT_MODEL )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" );
    return 1;
    }
  else if ( port == LEARN_PARAMETERS )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable" );
    return 1;
    }

  return 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::FillOutputPortInformation( int port, vtkInformation* info )
{
  if ( port == OUTPUT_DATA )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkTable" );
    return 1;
    }
  else if ( port == OUTPUT_MODEL )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet" );
    return 1;
    }
  else if ( port == OUTPUT_TEST )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkTable" );
    return 1;
    }

  return 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::RequestData( vtkInformation*,
                                         vtkInformationVector** inputVector,
                                         vtkInformationVector* outputVector )
{
  // Input handles
  vtkTable*             inData       = vtkTable::GetData( inputVector[INPUT_DATA], 0 );
  vtkMultiBlockDataSet* inModel      = vtkMultiBlockDataSet::GetData( inputVector[INPUT_MODEL], 0 );
  vtkTable*             inParameters = vtkTable::GetData( inputVector[LEARN_PARAMETERS], 0 );

  // Output handles
  vtkTable*             outData  = vtkTable::GetData( outputVector, OUTPUT_DATA );
  vtkMultiBlockDataSet* outModel = vtkMultiBlockDataSet::GetData( outputVector, OUTPUT_MODEL );
  vtkTable*             outTest  = vtkTable::GetData( outputVector, OUTPUT_TEST );

  // Note: Experiment code. Lots of use case are currently not handled in
  // any way and there are a lot of assumptions made about this or that

  // Make sure the statistics algorithm is set
  if ( !this->StatisticsAlgorithm )
    {
    vtkErrorMacro("StatisticsAlgorithm not set! Punting!")
    cerr << "StatisticsAlgorithm not set! Punting!" << endl;
    return 0;
    }

  // Set the input into my stats algorithms
  this->StatisticsAlgorithm->SetInput(inData);
  this->StatisticsAlgorithm->SetInputModel(this->internalModel);

  // Force an update
  this->StatisticsAlgorithm->Update();

  // Grab (DeepCopy) the model for next time
  this->internalModel->DeepCopy(this->StatisticsAlgorithm->GetOutputDataObject(OUTPUT_MODEL));

  // Shallow copy the internal output to external output
  outData->ShallowCopy(this->StatisticsAlgorithm->GetOutput(OUTPUT_DATA));
  outModel->ShallowCopy(this->StatisticsAlgorithm->GetOutputDataObject(OUTPUT_MODEL));

  return 1;
}

// ----------------------------------------------------------------------
void vtkStreamingStatistics::PrintSelf( ostream &os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );
  if (this->StatisticsAlgorithm)
    {
    os << indent << "StatisticsAlgorithm: ";
    this->StatisticsAlgorithm->PrintSelf(os,indent);
    }
}<commit_msg>COMP: Fixing some warnings for the nightly dashboard<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkStreamingStatistics.cxx

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

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2010 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkStreamingStatistics.h"

#include "vtkDataObjectCollection.h"
#include "vtkInformation.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkStatisticsAlgorithm.h"
#include "vtkTable.h"

vtkStandardNewMacro(vtkStreamingStatistics);

vtkCxxSetObjectMacro(vtkStreamingStatistics,
                     StatisticsAlgorithm,
                     vtkStatisticsAlgorithm);

// ----------------------------------------------------------------------
vtkStreamingStatistics::vtkStreamingStatistics()
{
  // Setup input/output ports
  this->SetNumberOfInputPorts(3);
  this->SetNumberOfOutputPorts(3);

  // Initialize internal stats algorithm to NULL
  this->StatisticsAlgorithm = 0;
  this->SetStatisticsAlgorithm(0);

  // Initialize internal model
  this->internalModel = vtkMultiBlockDataSet::New();
}

// ----------------------------------------------------------------------
vtkStreamingStatistics::~vtkStreamingStatistics()
{
  // Release/delete internal stats algorithm
  this->SetStatisticsAlgorithm(0);
  this->StatisticsAlgorithm = 0;

  // Release/delete internal model to NULL
  this->internalModel->Delete();
  this->internalModel = 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::FillInputPortInformation( int port, vtkInformation* info )
{
  if ( port == INPUT_DATA )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable" );
    return 1;
    }
  else if ( port == INPUT_MODEL )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" );
    return 1;
    }
  else if ( port == LEARN_PARAMETERS )
    {
    info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(), 1 );
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable" );
    return 1;
    }

  return 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::FillOutputPortInformation( int port, vtkInformation* info )
{
  if ( port == OUTPUT_DATA )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkTable" );
    return 1;
    }
  else if ( port == OUTPUT_MODEL )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet" );
    return 1;
    }
  else if ( port == OUTPUT_TEST )
    {
    info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkTable" );
    return 1;
    }

  return 0;
}

// ----------------------------------------------------------------------
int vtkStreamingStatistics::RequestData( vtkInformation*,
                                         vtkInformationVector** inputVector,
                                         vtkInformationVector* outputVector )
{
  // Input handles
  vtkTable*             inData       = vtkTable::GetData( inputVector[INPUT_DATA], 0 );

  // Output handles
  vtkTable*             outData  = vtkTable::GetData( outputVector, OUTPUT_DATA );
  vtkMultiBlockDataSet* outModel = vtkMultiBlockDataSet::GetData( outputVector, OUTPUT_MODEL );

  // These will be used later
  /*
  vtkMultiBlockDataSet* inModel      = vtkMultiBlockDataSet::GetData( inputVector[INPUT_MODEL], 0 );
  vtkTable*             inParameters = vtkTable::GetData( inputVector[LEARN_PARAMETERS], 0 );
  vtkTable*             outTest  = vtkTable::GetData( outputVector, OUTPUT_TEST );
  */

  // Note: Experiment code. Lots of use case are currently not handled in
  // any way and there are a lot of assumptions made about this or that

  // Make sure the statistics algorithm is set
  if ( !this->StatisticsAlgorithm )
    {
    vtkErrorMacro("StatisticsAlgorithm not set! Punting!")
    cerr << "StatisticsAlgorithm not set! Punting!" << endl;
    return 0;
    }

  // Set the input into my stats algorithms
  this->StatisticsAlgorithm->SetInput(inData);
  this->StatisticsAlgorithm->SetInputModel(this->internalModel);

  // Force an update
  this->StatisticsAlgorithm->Update();

  // Grab (DeepCopy) the model for next time
  this->internalModel->DeepCopy(this->StatisticsAlgorithm->GetOutputDataObject(OUTPUT_MODEL));

  // Shallow copy the internal output to external output
  outData->ShallowCopy(this->StatisticsAlgorithm->GetOutput(OUTPUT_DATA));
  outModel->ShallowCopy(this->StatisticsAlgorithm->GetOutputDataObject(OUTPUT_MODEL));

  return 1;
}

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


<commit_before>/*
 * Copyright 2018 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Firestore/core/src/firebase/firestore/util/filesystem_detail.h"

#include <fstream>
#include <sstream>

#include "Firestore/core/src/firebase/firestore/util/filesystem.h"
#include "Firestore/core/src/firebase/firestore/util/statusor.h"
#include "Firestore/core/src/firebase/firestore/util/string_format.h"

namespace firebase {
namespace firestore {
namespace util {
namespace detail {

#if !__APPLE__
Status ExcludeFromBackups(const Path& dir) {
  // Non-Apple platforms don't yet implement exclusion from backups.
  return Status::OK();
}
#endif  // !__APPLE__

Status RecursivelyDeleteDir(const Path& parent) {
  std::unique_ptr<DirectoryIterator> iter = DirectoryIterator::Create(parent);
  for (; iter->Valid(); iter->Next()) {
    Status status = RecursivelyDelete(iter->file());
    if (!status.ok()) {
      return status;
    }
  }
  if (!iter->status().ok()) {
    if (iter->status().code() == Error::NotFound) {
      return Status::OK();
    }
    return iter->status();
  }
  return detail::DeleteDir(parent);
}

}  // namespace detail

Status RecursivelyCreateDir(const Path& path) {
  Status result = detail::CreateDir(path);
  if (result.ok() || result.code() != Error::NotFound) {
    // Successfully created the directory, it already existed, or some other
    // unrecoverable error.
    return result;
  }

  // Missing parent
  Path parent = path.Dirname();
  result = RecursivelyCreateDir(parent);
  if (!result.ok()) {
    return result;
  }

  // Successfully created the parent so try again.
  return detail::CreateDir(path);
}

Status RecursivelyDelete(const Path& path) {
  Status status = IsDirectory(path);
  switch (status.code()) {
    case Error::Ok:
      return detail::RecursivelyDeleteDir(path);

    case Error::FailedPrecondition:
      // Could be a file or something else. Attempt to delete it as a file
      // but otherwise allow that to fail if it's not a file.
      return detail::DeleteSingleFile(path);

    case Error::NotFound:
      return Status::OK();

    default:
      return status;
  }
}

StatusOr<std::string> ReadFile(const Path& path) {
  std::ifstream file{path.native_value()};
  if (!file) {
    // TODO(varconst): more error details. This will require platform-specific
    // code, because `<iostream>` may not update `errno`.
    return Status{Error::Unknown,
                  StringFormat("File at path '%s' cannot be opened",
                               path.ToUtf8String())};
  }

  std::stringstream buffer;
  buffer << file.rdbuf();
  return buffer.str();
}

}  // namespace util
}  // namespace firestore
}  // namespace firebase
<commit_msg>Fix definition of ExcludeFromBackups on non-Apple platforms. (#4394)<commit_after>/*
 * Copyright 2018 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Firestore/core/src/firebase/firestore/util/filesystem_detail.h"

#include <fstream>
#include <sstream>

#include "Firestore/core/src/firebase/firestore/util/filesystem.h"
#include "Firestore/core/src/firebase/firestore/util/statusor.h"
#include "Firestore/core/src/firebase/firestore/util/string_format.h"

namespace firebase {
namespace firestore {
namespace util {

#if !__APPLE__
Status ExcludeFromBackups(const Path&) {
  // Non-Apple platforms don't yet implement exclusion from backups.
  return Status::OK();
}
#endif  // !__APPLE__

namespace detail {

Status RecursivelyDeleteDir(const Path& parent) {
  std::unique_ptr<DirectoryIterator> iter = DirectoryIterator::Create(parent);
  for (; iter->Valid(); iter->Next()) {
    Status status = RecursivelyDelete(iter->file());
    if (!status.ok()) {
      return status;
    }
  }
  if (!iter->status().ok()) {
    if (iter->status().code() == Error::NotFound) {
      return Status::OK();
    }
    return iter->status();
  }
  return detail::DeleteDir(parent);
}

}  // namespace detail

Status RecursivelyCreateDir(const Path& path) {
  Status result = detail::CreateDir(path);
  if (result.ok() || result.code() != Error::NotFound) {
    // Successfully created the directory, it already existed, or some other
    // unrecoverable error.
    return result;
  }

  // Missing parent
  Path parent = path.Dirname();
  result = RecursivelyCreateDir(parent);
  if (!result.ok()) {
    return result;
  }

  // Successfully created the parent so try again.
  return detail::CreateDir(path);
}

Status RecursivelyDelete(const Path& path) {
  Status status = IsDirectory(path);
  switch (status.code()) {
    case Error::Ok:
      return detail::RecursivelyDeleteDir(path);

    case Error::FailedPrecondition:
      // Could be a file or something else. Attempt to delete it as a file
      // but otherwise allow that to fail if it's not a file.
      return detail::DeleteSingleFile(path);

    case Error::NotFound:
      return Status::OK();

    default:
      return status;
  }
}

StatusOr<std::string> ReadFile(const Path& path) {
  std::ifstream file{path.native_value()};
  if (!file) {
    // TODO(varconst): more error details. This will require platform-specific
    // code, because `<iostream>` may not update `errno`.
    return Status{Error::Unknown,
                  StringFormat("File at path '%s' cannot be opened",
                               path.ToUtf8String())};
  }

  std::stringstream buffer;
  buffer << file.rdbuf();
  return buffer.str();
}

}  // namespace util
}  // namespace firestore
}  // namespace firebase
<|endoftext|>


<commit_before>/*
    Copyright (C) 2011  Lasath Fernando <kde@lasath.org>
    Copyright (C) 2013  Lasath Fernando <davidedmundson@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "messages-model.h"

#include <KDebug>
#include <KLocalizedString>

#include <TelepathyQt/ReceivedMessage>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/Account>

#include <KTp/message-processor.h>
#include <KTp/message-context.h>
#include <KTp/Logger/scrollback-manager.h>

class MessagePrivate
{
  public:
    MessagePrivate(const KTp::Message &message);

    KTp::Message message;
    MessagesModel::DeliveryStatus deliveryStatus;
    QDateTime deliveryReportReceiveTime;
};

MessagePrivate::MessagePrivate(const KTp::Message &message) :
        message(message),
        deliveryStatus(MessagesModel::DeliveryStatusUnknown)
{
}

class MessagesModel::MessagesModelPrivate
{
  public:
    Tp::TextChannelPtr textChannel;
    Tp::AccountPtr account;
    ScrollbackManager *logManager;
    QList<MessagePrivate> messages;
    // For fast lookup of original messages upon receipt of a message delivery report.
    QHash<QString /*messageToken*/, QPersistentModelIndex> messagesByMessageToken;
    bool visible;
};

MessagesModel::MessagesModel(const Tp::AccountPtr &account, QObject *parent) :
        QAbstractListModel(parent),
        d(new MessagesModelPrivate)
{
    kDebug();

    QHash<int, QByteArray> roles;
    roles[TextRole] = "text";
    roles[TimeRole] = "time";
    roles[TypeRole] = "type";
    roles[SenderIdRole] = "senderId";
    roles[SenderAliasRole] = "senderAlias";
    roles[SenderAvatarRole] = "senderAvatar";
    roles[DeliveryStatusRole] = "deliveryStatus";
    roles[DeliveryReportReceiveTimeRole] = "deliveryReportReceiveTime";
    setRoleNames(roles);

    d->account = account;
    d->visible = false;

    d->logManager = new ScrollbackManager(this);
    connect(d->logManager, SIGNAL(fetched(QList<KTp::Message>)), SLOT(onHistoryFetched(QList<KTp::Message>)));

    //Load configuration for number of message to show
    KConfig config(QLatin1String("ktelepathyrc"));
    KConfigGroup tabConfig = config.group("Behavior");
    d->logManager->setScrollbackLength(tabConfig.readEntry<int>("scrollbackLength", 10));
}

Tp::TextChannelPtr MessagesModel::textChannel() const
{
    return d->textChannel;
}

bool MessagesModel::verifyPendingOperation(Tp::PendingOperation *op)
{
    bool operationSucceeded = true;

    if (op->isError()) {
        kWarning() << op->errorName() << "+" << op->errorMessage();
        operationSucceeded = false;
    }

    return operationSucceeded;
}

void MessagesModel::setupChannelSignals(const Tp::TextChannelPtr &channel)
{
    connect(channel.data(),
            SIGNAL(messageReceived(Tp::ReceivedMessage)),
            SLOT(onMessageReceived(Tp::ReceivedMessage)));
    connect(channel.data(),
            SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
            SLOT(onMessageSent(Tp::Message,Tp::MessageSendingFlags,QString)));
    connect(channel.data(),
            SIGNAL(pendingMessageRemoved(Tp::ReceivedMessage)),
            SLOT(onPendingMessageRemoved()));
}

void MessagesModel::setTextChannel(const Tp::TextChannelPtr &channel)
{
    Q_ASSERT(channel != d->textChannel);
    kDebug();
    setupChannelSignals(channel);

    if (d->textChannel) {
        removeChannelSignals(d->textChannel);
    }

    d->textChannel = channel;

    d->logManager->setTextChannel(d->account, d->textChannel);
    d->logManager->fetchScrollback();

    QList<Tp::ReceivedMessage> messageQueue = channel->messageQueue();
    Q_FOREACH(const Tp::ReceivedMessage &message, messageQueue) {
        bool messageAlreadyInModel = false;
        Q_FOREACH(const MessagePrivate &current, d->messages) {
            //FIXME: docs say messageToken can return an empty string. What to do if that happens?
            //Tp::Message has an == operator. maybe I can use that?
            if (current.message.token() == message.messageToken()) {
                messageAlreadyInModel = true;
                break;
            }
        }
        if (!messageAlreadyInModel) {
            onMessageReceived(message);
        }
    }
}

void MessagesModel::onHistoryFetched(const QList<KTp::Message> &messages)
{
    kDebug() << "found" << messages.count() << "messages in history";
    if (!messages.isEmpty()) {
        //Add all messages before the ones already present in the channel
        beginInsertRows(QModelIndex(), 0, messages.count() - 1);
        for(int i=messages.size()-1;i>=0;i--) {
            d->messages.prepend(messages[i]);
        }
        endInsertRows();
    }
}

void MessagesModel::onMessageReceived(const Tp::ReceivedMessage &message)
{
    int unreadCount = d->textChannel->messageQueue().size();
    kDebug() << "unreadMessagesCount =" << unreadCount;
    kDebug() << "text =" << message.text();
    kDebug() << "messageType = " << message.messageType();
    kDebug() << "messageToken =" << message.messageToken();

    if (message.isDeliveryReport()) {
        d->textChannel->acknowledge(QList<Tp::ReceivedMessage>() << message);

        Tp::ReceivedMessage::DeliveryDetails deliveryDetails = message.deliveryDetails();
        if(!deliveryDetails.hasOriginalToken()) {
            kDebug() << "Delivery report without original message token received.";
            // Matching the delivery report to the original message is impossible without the token.
            return;
        }
        kDebug() << "originalMessageToken =" << deliveryDetails.originalToken();

        QPersistentModelIndex originalMessageIndex = d->messagesByMessageToken.value(
                    deliveryDetails.originalToken());
        if (!originalMessageIndex.isValid() || originalMessageIndex.row() >= d->messages.count()) {
            // The original message for this delivery report was not found.
            return;
        }

        MessagePrivate &originalMessage = d->messages[originalMessageIndex.row()];
        kDebug() << "Got delivery status" << deliveryDetails.status()
                 << "for message with text" << originalMessage.message.mainMessagePart();
        originalMessage.deliveryReportReceiveTime = message.received();
        switch(deliveryDetails.status()) {
        case Tp::DeliveryStatusPermanentlyFailed:
        case Tp::DeliveryStatusTemporarilyFailed:
            originalMessage.deliveryStatus = DeliveryStatusFailed;
            if (deliveryDetails.hasDebugMessage()) {
                kDebug() << "Delivery failure debug message:" << deliveryDetails.debugMessage();
            }
            break;
        case Tp::DeliveryStatusDelivered:
            originalMessage.deliveryStatus = DeliveryStatusDelivered;
            break;
        case Tp::DeliveryStatusRead:
            originalMessage.deliveryStatus = DeliveryStatusRead;
            break;
        default:
            originalMessage.deliveryStatus = DeliveryStatusUnknown;
            break;
        }
        Q_EMIT dataChanged(originalMessageIndex, originalMessageIndex);
    } else {
        int length = rowCount();
        beginInsertRows(QModelIndex(), length, length);

        d->messages.append(KTp::MessageProcessor::instance()->processIncomingMessage(
                               message, d->account, d->textChannel));

        endInsertRows();

        if (d->visible) {
            acknowledgeAllMessages();
        } else {
            Q_EMIT unreadCountChanged(unreadCount);
        }
    }
}

void MessagesModel::onMessageSent(const Tp::Message &message, Tp::MessageSendingFlags flags, const QString &messageToken)
{
    Q_UNUSED(flags);

    int length = rowCount();
    beginInsertRows(QModelIndex(), length, length);
    kDebug() << "text =" << message.text();

    const KTp::Message &newMessage = KTp::MessageProcessor::instance()->processIncomingMessage(
                message, d->account, d->textChannel);
    d->messages.append(newMessage);

    if (!messageToken.isEmpty()) {
        // Insert the message into the lookup table for delivery reports.
        const QPersistentModelIndex &modelIndex(createIndex(length, 0));
        d->messagesByMessageToken.insert(messageToken, modelIndex);
    }

    endInsertRows();
}

void MessagesModel::onPendingMessageRemoved()
{
    Q_EMIT unreadCountChanged(unreadCount());
}

QVariant MessagesModel::data(const QModelIndex &index, int role) const
{
    QVariant result;

    if (index.isValid()) {
        const MessagePrivate m = d->messages[index.row()];

        switch (role) {
        case TextRole:
            result = m.message.finalizedMessage();
            break;
        case TypeRole:
            if (m.message.type() == Tp::ChannelTextMessageTypeAction) {
                result = MessageTypeAction;
            } else {
                if (m.message.direction() == KTp::Message::LocalToRemote) {
                    result = MessageTypeOutgoing;
                } else {
                    result = MessageTypeIncoming;
                }
            }
            break;
        case TimeRole:
            result = m.message.time();
            break;
        case SenderIdRole:
            result = m.message.senderId();
            break;
        case SenderAliasRole:
            result = m.message.senderAlias();
            break;
        case SenderAvatarRole:
            if (m.message.sender()) {
                result = QVariant::fromValue(m.message.sender()->avatarPixmap());
            }
            break;
        case DeliveryStatusRole:
            result = m.deliveryStatus;
            break;
        case DeliveryReportReceiveTimeRole:
            result = m.deliveryReportReceiveTime;
            break;
        };
    } else {
        kError() << "Attempting to access data at invalid index (" << index << ")";
    }

    return result;
}

int MessagesModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return d->messages.size();
}

void MessagesModel::sendNewMessage(const QString &message)
{
    if (message.isEmpty()) {
        kWarning() << "Attempting to send empty string";
    } else {
        Tp::PendingOperation *op;
        QString modifiedMessage = message;
        if (d->textChannel->supportsMessageType(Tp::ChannelTextMessageTypeAction)
                && modifiedMessage.startsWith(QLatin1String("/me "))) {
            //remove "/me " from the start of the message
            modifiedMessage.remove(0,4);
            op = d->textChannel->send(modifiedMessage, Tp::ChannelTextMessageTypeAction);
        } else {
            op = d->textChannel->send(modifiedMessage);
        }
        connect(op,
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(verifyPendingOperation(Tp::PendingOperation*)));
    }
}

void MessagesModel::removeChannelSignals(const Tp::TextChannelPtr &channel)
{
    QObject::disconnect(channel.data(),
                        SIGNAL(messageReceived(Tp::ReceivedMessage)),
                        this,
                        SLOT(onMessageReceived(Tp::ReceivedMessage))
                       );
    QObject::disconnect(channel.data(),
                        SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
                        this,
                        SLOT(onMessageSent(Tp::Message,Tp::MessageSendingFlags,QString))
                       );
}

int MessagesModel::unreadCount() const
{
    return d->textChannel->messageQueue().size();
}

void MessagesModel::acknowledgeAllMessages()
{
    QList<Tp::ReceivedMessage> queue = d->textChannel->messageQueue();

    kDebug() << "Conversation Visible, Acknowledging " << queue.size() << " messages.";

    d->textChannel->acknowledge(queue);
    Q_EMIT unreadCountChanged(queue.size());
}

void MessagesModel::setVisibleToUser(bool visible)
{
    kDebug() << visible;

    if (d->visible != visible) {
        d->visible = visible;
        Q_EMIT visibleToUserChanged(d->visible);
    }

    if (visible) {
        acknowledgeAllMessages();
    }
}

bool MessagesModel::isVisibleToUser() const
{
    return d->visible;
}

MessagesModel::~MessagesModel()
{
    kDebug();
    delete d;
}

bool MessagesModel::shouldStartOpened() const
{
    return d->textChannel->isRequested();
}
<commit_msg>add check for messages loading<commit_after>/*
    Copyright (C) 2011  Lasath Fernando <kde@lasath.org>
    Copyright (C) 2013  Lasath Fernando <davidedmundson@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "messages-model.h"

#include <KDebug>
#include <KLocalizedString>

#include <TelepathyQt/ReceivedMessage>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/Account>

#include <KTp/message-processor.h>
#include <KTp/message-context.h>
#include <KTp/Logger/scrollback-manager.h>

class MessagePrivate
{
  public:
    MessagePrivate(const KTp::Message &message);

    KTp::Message message;
    MessagesModel::DeliveryStatus deliveryStatus;
    QDateTime deliveryReportReceiveTime;
};

MessagePrivate::MessagePrivate(const KTp::Message &message) :
        message(message),
        deliveryStatus(MessagesModel::DeliveryStatusUnknown)
{
}

class MessagesModel::MessagesModelPrivate
{
  public:
    Tp::TextChannelPtr textChannel;
    Tp::AccountPtr account;
    ScrollbackManager *logManager;
    QList<MessagePrivate> messages;
    // For fast lookup of original messages upon receipt of a message delivery report.
    QHash<QString /*messageToken*/, QPersistentModelIndex> messagesByMessageToken;
    bool visible;
    bool logsLoaded;
};

MessagesModel::MessagesModel(const Tp::AccountPtr &account, QObject *parent) :
        QAbstractListModel(parent),
        d(new MessagesModelPrivate)
{
    kDebug();

    QHash<int, QByteArray> roles;
    roles[TextRole] = "text";
    roles[TimeRole] = "time";
    roles[TypeRole] = "type";
    roles[SenderIdRole] = "senderId";
    roles[SenderAliasRole] = "senderAlias";
    roles[SenderAvatarRole] = "senderAvatar";
    roles[DeliveryStatusRole] = "deliveryStatus";
    roles[DeliveryReportReceiveTimeRole] = "deliveryReportReceiveTime";
    setRoleNames(roles);

    d->account = account;
    d->visible = false;

    d->logManager = new ScrollbackManager(this);
    d->logsLoaded = false;
    connect(d->logManager, SIGNAL(fetched(QList<KTp::Message>)), SLOT(onHistoryFetched(QList<KTp::Message>)));

    //Load configuration for number of message to show
    KConfig config(QLatin1String("ktelepathyrc"));
    KConfigGroup tabConfig = config.group("Behavior");
    d->logManager->setScrollbackLength(tabConfig.readEntry<int>("scrollbackLength", 10));
}

Tp::TextChannelPtr MessagesModel::textChannel() const
{
    return d->textChannel;
}

bool MessagesModel::verifyPendingOperation(Tp::PendingOperation *op)
{
    bool operationSucceeded = true;

    if (op->isError()) {
        kWarning() << op->errorName() << "+" << op->errorMessage();
        operationSucceeded = false;
    }

    return operationSucceeded;
}

void MessagesModel::setupChannelSignals(const Tp::TextChannelPtr &channel)
{
    connect(channel.data(),
            SIGNAL(messageReceived(Tp::ReceivedMessage)),
            SLOT(onMessageReceived(Tp::ReceivedMessage)));
    connect(channel.data(),
            SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
            SLOT(onMessageSent(Tp::Message,Tp::MessageSendingFlags,QString)));
    connect(channel.data(),
            SIGNAL(pendingMessageRemoved(Tp::ReceivedMessage)),
            SLOT(onPendingMessageRemoved()));
}

void MessagesModel::setTextChannel(const Tp::TextChannelPtr &channel)
{
    Q_ASSERT(channel != d->textChannel);
    kDebug();
    setupChannelSignals(channel);

    if (d->textChannel) {
        removeChannelSignals(d->textChannel);
    }

    d->textChannel = channel;

    d->logManager->setTextChannel(d->account, d->textChannel);

    //Load messages unless they have already been loaded
    if(!d->logsLoaded) {
        d->logManager->fetchScrollback();
    }

    QList<Tp::ReceivedMessage> messageQueue = channel->messageQueue();
    Q_FOREACH(const Tp::ReceivedMessage &message, messageQueue) {
        bool messageAlreadyInModel = false;
        Q_FOREACH(const MessagePrivate &current, d->messages) {
            //FIXME: docs say messageToken can return an empty string. What to do if that happens?
            //Tp::Message has an == operator. maybe I can use that?
            if (current.message.token() == message.messageToken()) {
                messageAlreadyInModel = true;
                break;
            }
        }
        if (!messageAlreadyInModel) {
            onMessageReceived(message);
        }
    }
}

void MessagesModel::onHistoryFetched(const QList<KTp::Message> &messages)
{
    kDebug() << "found" << messages.count() << "messages in history";
    if (!messages.isEmpty()) {
        //Add all messages before the ones already present in the channel
        beginInsertRows(QModelIndex(), 0, messages.count() - 1);
        for(int i=messages.size()-1;i>=0;i--) {
            d->messages.prepend(messages[i]);
        }
        endInsertRows();
    }
    d->logsLoaded = true;
}

void MessagesModel::onMessageReceived(const Tp::ReceivedMessage &message)
{
    int unreadCount = d->textChannel->messageQueue().size();
    kDebug() << "unreadMessagesCount =" << unreadCount;
    kDebug() << "text =" << message.text();
    kDebug() << "messageType = " << message.messageType();
    kDebug() << "messageToken =" << message.messageToken();

    if (message.isDeliveryReport()) {
        d->textChannel->acknowledge(QList<Tp::ReceivedMessage>() << message);

        Tp::ReceivedMessage::DeliveryDetails deliveryDetails = message.deliveryDetails();
        if(!deliveryDetails.hasOriginalToken()) {
            kDebug() << "Delivery report without original message token received.";
            // Matching the delivery report to the original message is impossible without the token.
            return;
        }
        kDebug() << "originalMessageToken =" << deliveryDetails.originalToken();

        QPersistentModelIndex originalMessageIndex = d->messagesByMessageToken.value(
                    deliveryDetails.originalToken());
        if (!originalMessageIndex.isValid() || originalMessageIndex.row() >= d->messages.count()) {
            // The original message for this delivery report was not found.
            return;
        }

        MessagePrivate &originalMessage = d->messages[originalMessageIndex.row()];
        kDebug() << "Got delivery status" << deliveryDetails.status()
                 << "for message with text" << originalMessage.message.mainMessagePart();
        originalMessage.deliveryReportReceiveTime = message.received();
        switch(deliveryDetails.status()) {
        case Tp::DeliveryStatusPermanentlyFailed:
        case Tp::DeliveryStatusTemporarilyFailed:
            originalMessage.deliveryStatus = DeliveryStatusFailed;
            if (deliveryDetails.hasDebugMessage()) {
                kDebug() << "Delivery failure debug message:" << deliveryDetails.debugMessage();
            }
            break;
        case Tp::DeliveryStatusDelivered:
            originalMessage.deliveryStatus = DeliveryStatusDelivered;
            break;
        case Tp::DeliveryStatusRead:
            originalMessage.deliveryStatus = DeliveryStatusRead;
            break;
        default:
            originalMessage.deliveryStatus = DeliveryStatusUnknown;
            break;
        }
        Q_EMIT dataChanged(originalMessageIndex, originalMessageIndex);
    } else {
        int length = rowCount();
        beginInsertRows(QModelIndex(), length, length);

        d->messages.append(KTp::MessageProcessor::instance()->processIncomingMessage(
                               message, d->account, d->textChannel));

        endInsertRows();

        if (d->visible) {
            acknowledgeAllMessages();
        } else {
            Q_EMIT unreadCountChanged(unreadCount);
        }
    }
}

void MessagesModel::onMessageSent(const Tp::Message &message, Tp::MessageSendingFlags flags, const QString &messageToken)
{
    Q_UNUSED(flags);

    int length = rowCount();
    beginInsertRows(QModelIndex(), length, length);
    kDebug() << "text =" << message.text();

    const KTp::Message &newMessage = KTp::MessageProcessor::instance()->processIncomingMessage(
                message, d->account, d->textChannel);
    d->messages.append(newMessage);

    if (!messageToken.isEmpty()) {
        // Insert the message into the lookup table for delivery reports.
        const QPersistentModelIndex &modelIndex(createIndex(length, 0));
        d->messagesByMessageToken.insert(messageToken, modelIndex);
    }

    endInsertRows();
}

void MessagesModel::onPendingMessageRemoved()
{
    Q_EMIT unreadCountChanged(unreadCount());
}

QVariant MessagesModel::data(const QModelIndex &index, int role) const
{
    QVariant result;

    if (index.isValid()) {
        const MessagePrivate m = d->messages[index.row()];

        switch (role) {
        case TextRole:
            result = m.message.finalizedMessage();
            break;
        case TypeRole:
            if (m.message.type() == Tp::ChannelTextMessageTypeAction) {
                result = MessageTypeAction;
            } else {
                if (m.message.direction() == KTp::Message::LocalToRemote) {
                    result = MessageTypeOutgoing;
                } else {
                    result = MessageTypeIncoming;
                }
            }
            break;
        case TimeRole:
            result = m.message.time();
            break;
        case SenderIdRole:
            result = m.message.senderId();
            break;
        case SenderAliasRole:
            result = m.message.senderAlias();
            break;
        case SenderAvatarRole:
            if (m.message.sender()) {
                result = QVariant::fromValue(m.message.sender()->avatarPixmap());
            }
            break;
        case DeliveryStatusRole:
            result = m.deliveryStatus;
            break;
        case DeliveryReportReceiveTimeRole:
            result = m.deliveryReportReceiveTime;
            break;
        };
    } else {
        kError() << "Attempting to access data at invalid index (" << index << ")";
    }

    return result;
}

int MessagesModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return d->messages.size();
}

void MessagesModel::sendNewMessage(const QString &message)
{
    if (message.isEmpty()) {
        kWarning() << "Attempting to send empty string";
    } else {
        Tp::PendingOperation *op;
        QString modifiedMessage = message;
        if (d->textChannel->supportsMessageType(Tp::ChannelTextMessageTypeAction)
                && modifiedMessage.startsWith(QLatin1String("/me "))) {
            //remove "/me " from the start of the message
            modifiedMessage.remove(0,4);
            op = d->textChannel->send(modifiedMessage, Tp::ChannelTextMessageTypeAction);
        } else {
            op = d->textChannel->send(modifiedMessage);
        }
        connect(op,
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(verifyPendingOperation(Tp::PendingOperation*)));
    }
}

void MessagesModel::removeChannelSignals(const Tp::TextChannelPtr &channel)
{
    QObject::disconnect(channel.data(),
                        SIGNAL(messageReceived(Tp::ReceivedMessage)),
                        this,
                        SLOT(onMessageReceived(Tp::ReceivedMessage))
                       );
    QObject::disconnect(channel.data(),
                        SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
                        this,
                        SLOT(onMessageSent(Tp::Message,Tp::MessageSendingFlags,QString))
                       );
}

int MessagesModel::unreadCount() const
{
    return d->textChannel->messageQueue().size();
}

void MessagesModel::acknowledgeAllMessages()
{
    QList<Tp::ReceivedMessage> queue = d->textChannel->messageQueue();

    kDebug() << "Conversation Visible, Acknowledging " << queue.size() << " messages.";

    d->textChannel->acknowledge(queue);
    Q_EMIT unreadCountChanged(queue.size());
}

void MessagesModel::setVisibleToUser(bool visible)
{
    kDebug() << visible;

    if (d->visible != visible) {
        d->visible = visible;
        Q_EMIT visibleToUserChanged(d->visible);
    }

    if (visible) {
        acknowledgeAllMessages();
    }
}

bool MessagesModel::isVisibleToUser() const
{
    return d->visible;
}

MessagesModel::~MessagesModel()
{
    kDebug();
    delete d;
}

bool MessagesModel::shouldStartOpened() const
{
    return d->textChannel->isRequested();
}
<|endoftext|>


<commit_before>/*
  Native extension for GHCJS profiling

  Due to tail call optimization, profile data from Haskell call stacks is
  not very useful. GHC uses Cost Centre Stacks (CCS) as an additional mechanism
  for attributing costs to code locations.

  Unfortunately JavaScript profilers have no knowledge of Cost Centre Stacks.

  The v8 profiler periodically takes a sample of the current instruction
  pointer and call stack (by default every 1000 microseconds).

  In order to get useful Haskell profiling data, we need the active cost
  centre stack for each sample.

  We could use the event log to send a message every time the CCS changes,
  but this would add considerable overhead, since CCS changes are very
  frequent.

  Instead we use v8's ReturnAddressLocationResolver to encode the CCS
  directly on the call stack.

  Example call stack:

    someFunction
    h$_prof_ccs_a_0
    h$_prof_ccs_a_1
    h$_prof_ccs_a_2
    h$mainLoop
    h$someCompiledCode

  The ReturnAddressLocationResolver recognizes the h$_prof_ccs_a_x frames
  and returns h$_prof_ccs_b_y frames, with the value y encoding 10 bits
  of the cost centre stack.

    someFunction
    h$_prof_ccs_b_u
    h$_prof_ccs_b_v
    h$_prof_ccs_b_w
    h$mainLoop
    h$someCompiledCode

  For example if the current CCS id is 337345233, then

    ccsid = 337345233
    u = (ccsid >>> 20) & 1023 = 321
    v = (ccsid >>> 10) & 1023 = 734
    w = ccsid & 1023          = 721

  So the recorded call stack sample looks like

    someFunction
    h$_prof_ccs_b_321
    h$_prof_ccs_b_734
    h$_prof_ccs_b_721
    h$mainLoop
    h$someCompiledCode

  The actual data on the stack never change.

  A script in the devtools retrieves all the cost centre information from
  the Haskell runtime and expands the h$_prof_ccs_b_x triples to the full
  cost centre stack.

  Note:

  The functions need to be optimized for this to work. The JavaScript part
  of this extension uses %OptimizeFunctionOnNextCall(f) for this, which
  requires the --allow-natives-syntax v8 startup option.

 */
#include <map>

// use the old-fashioned Node API
#include <node.h>

#include <stdio.h>
// #include <algorithm>
// #include <execinfo.h>
// #include "backtrace.h"

// #define UNW_LOCAL_ONLY
// #include <libunwind.h>

using namespace v8;

const int nCostCentreFuns     = 1024;
const int nCostCentreFunsBits = 10;
const int nFunctions          = nCostCentreFuns + 3;
const int ccsReturnAddress1   = nCostCentreFuns;
const int ccsReturnAddress2   = nCostCentreFuns + 1;
const int ccsReturnAddress3   = nCostCentreFuns + 2;

static uint32_t currentCCS    = 0;

/*
static void** StackStart = 0;
static void** StackEnd   = 0;

static void*  Callbacks[16];
static void** StackSlots[128];

static void**   CostCentres;
static unsigned CostCentres_len = 0;

static uintptr_t* ReturnAddresses    = 0;
static int        ReturnAddresses_len = 0;

static uintptr_t CcReturnAddresses[nCostCentreFuns];
static bool      addressesInitialized = 0;
*/
// static uintptr_t ccsReturnAddress1 = 0;
// static uintptr_t ccsReturnAddress2 = 0;
// static uintptr_t ccsReturnAddress3 = 0;

// static uintptr_t ccsPosition1 = 0;
// static uintptr_t ccsPosition2 = 0;
// static uintptr_t ccsPosition3 = 0;

/*
  a code location of one of the functions we're interested in

    start == 0 && len == 0 <=> the item location is unknown

  cc_code_locations contains an entry for each known item

  item numbering:
    [0,1023]    -> h$_prof_ccs_a_
    [1024,1026] -> h$_prof_ccs_b_
 */
typedef struct code_t {
  uintptr_t start;
  size_t len;
} code_t;

static code_t cc_code[nFunctions];
static std::map<uintptr_t, int> cc_code_locations; // start -> item

bool is_in_code(uintptr_t return_addr, int item) {
  code_t &c = cc_code[item];
  return return_addr >= c.start && return_addr < c.start + c.len;
}

static uintptr_t address_loc_resolver(uintptr_t return_addr_location) {
  uintptr_t ra = *((uintptr_t*)return_addr_location);
  int item = -1;
  if(is_in_code(ra, ccsReturnAddress1)) {
    item = currentCCS & (nCostCentreFuns-1);
  } else if(is_in_code(ra, ccsReturnAddress2)) {
    item = (currentCCS >> nCostCentreFunsBits) & (nCostCentreFuns-1);
  } else if(is_in_code(ra, ccsReturnAddress3)) {
    item = (currentCCS >> (2 * nCostCentreFunsBits)) & (nCostCentreFuns-1);
  }
  if(item != -1 && cc_code[item].start != 0) {
    return (uintptr_t)(&cc_code[item].start);
  } else {
    return return_addr_location;
  }
}

int function_item(const char* name, int len) {
  if(len < 27 || strncmp(name, "LazyCompile:*h$_prof_ccs_", 25) != 0) {
    return -1;
  }
  if(name[26] != '_') return -1;
  char ver = name[25];
  if(ver != 'a' && ver != 'b') return -1;
  name += 27;
  len -= 27;
  if(len == 0 || !isdigit(name[0])) return -1;
  int val = 0;
  for(int i=0;i<len;i++) {
    char c = name[i];
    if(!isdigit(c)) break;
    val = val * 10 + (int)c;
  }
  if(ver == 'a' && val >= 0 && val <= 1023) {
    return val;
  } else if(ver == 'b' && val >= 0 && val <= 2) {
    return val + 1024;
  } else {
    return -1;
  }
}

static void jit_code_handler(const JitCodeEvent* event) {
  // fprintf(stderr, "jit: %i\n", event->type);
  char* name;
  int item;
  uintptr_t cstart = (uintptr_t)event->code_start;
  std::map<uintptr_t, int>::iterator it;
  switch(event->type) {
    case JitCodeEvent::CODE_ADDED:
      name = new char[event->name.len+1];
      name[event->name.len] = 0;
      strncpy(name, event->name.str, event->name.len);
      fprintf( stderr
             , "jit: code added at %p size %lu, name: %s\n"
             , event->code_start
             , event->code_len
             , name);
      delete[] name;
      item = function_item(event->name.str, event->name.len);
      if(item != -1) {
        it = cc_code_locations.find(cstart);
        // code for a different function in same location? shouldn't happen
        if(it != cc_code_locations.end() && it->second != item) {
          cc_code[it->second].start = 0;
          cc_code[it->second].len = 0;

        }
        cc_code[item].start = cstart;
        cc_code[item].len = event->code_len;
        cc_code_locations[cstart] = item;
      }
      break;
    case JitCodeEvent::CODE_MOVED:
      fprintf( stderr
             , "jit: code moved at %p size %lu to: %p\n"
             , event->code_start
             , event->code_len
             , event->new_code_start
             );
      it = cc_code_locations.find(cstart);
      if(it != cc_code_locations.end()) {
        item = it->second;
        cstart = (uintptr_t)event->new_code_start;
        cc_code[item].start = cstart;
        cc_code[item].len   = event->code_len;
        cc_code_locations.erase(it);
        cc_code_locations[cstart] = item;
      }
      break;
    case JitCodeEvent::CODE_REMOVED:
      fprintf( stderr
             , "jit: code removed from %p size %lu\n"
             , event->code_start
             , event->code_len
             );
      it = cc_code_locations.find(cstart);
      if(it != cc_code_locations.end()) {
        item = it->second;
        cc_code[item].start = 0;
        cc_code[item].len = 0;
        cc_code_locations.erase(it);
      }
      break;
    case JitCodeEvent::CODE_ADD_LINE_POS_INFO:
    case JitCodeEvent::CODE_START_LINE_INFO_RECORDING:
    case JitCodeEvent::CODE_END_LINE_INFO_RECORDING:
    default:
      ; // no need to handle these
  }
}

void get_ccs_buffer(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(
    ArrayBuffer::New(isolate, &currentCCS, 4)
  );
}

void Init(Handle<Object> exports, Handle<Object> module) {
  // set all tracked code locations to unknown
  for(int i=0;i<nFunctions;i++) {
    cc_code[i].start = 0;
    cc_code[i].len   = 0;
  }

  // install handlers
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  V8::SetReturnAddressLocationResolver(address_loc_resolver);
  isolate->SetJitCodeEventHandler(kJitCodeEventDefault, jit_code_handler);

  // expose get_ccs_buffer
  NODE_SET_METHOD(exports, "get_ccs_buffer", get_ccs_buffer);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

<commit_msg>fix return address rewriting for sampling cost centre stack in CPU profile<commit_after>/*
  Native extension for GHCJS profiling

  Due to tail call optimization, profile data from Haskell call stacks is
  not very useful. GHC uses Cost Centre Stacks (CCS) as an additional mechanism
  for attributing costs to code locations.

  Unfortunately JavaScript profilers have no knowledge of Cost Centre Stacks.

  The v8 profiler periodically takes a sample of the current instruction
  pointer and call stack (by default every 1000 microseconds).

  In order to get useful Haskell profiling data, we need the active cost
  centre stack for each sample.

  We could use the event log to send a message every time the CCS changes,
  but this would add considerable overhead, since CCS changes are very
  frequent.

  Instead we use v8's ReturnAddressLocationResolver to encode the CCS
  directly on the call stack.

  Example call stack:

    someFunction
    h$_prof_ccs_a_0
    h$_prof_ccs_a_1
    h$_prof_ccs_a_2
    h$mainLoop
    h$someCompiledCode

  The ReturnAddressLocationResolver recognizes the h$_prof_ccs_a_x frames
  and returns h$_prof_ccs_b_y frames, with the value y encoding 10 bits
  of the cost centre stack.

    someFunction
    h$_prof_ccs_b_u
    h$_prof_ccs_b_v
    h$_prof_ccs_b_w
    h$mainLoop
    h$someCompiledCode

  For example if the current CCS id is 337345233, then

    ccsid = 337345233
    u = (ccsid >>> 20) & 1023 = 321
    v = (ccsid >>> 10) & 1023 = 734
    w = ccsid & 1023          = 721

  So the recorded call stack sample looks like

    someFunction
    h$_prof_ccs_b_321
    h$_prof_ccs_b_734
    h$_prof_ccs_b_721
    h$mainLoop
    h$someCompiledCode

  The actual data on the stack never change.

  A script in the devtools retrieves all the cost centre information from
  the Haskell runtime and expands the h$_prof_ccs_b_x triples to the full
  cost centre stack.

  Note:

  The functions need to be optimized for this to work. The JavaScript part
  of this extension uses %OptimizeFunctionOnNextCall(f) for this, which
  requires the --allow-natives-syntax v8 startup option.

 */
#include <map>

// use the old-fashioned Node API
#include <node.h>
#include <stdio.h>

using namespace v8;

const int nCostCentreFuns     = 1024;
const int nCostCentreFunsBits = 10;
const int nFunctions          = nCostCentreFuns + 3;
const int ccsReturnAddress1   = nCostCentreFuns;
const int ccsReturnAddress2   = nCostCentreFuns + 1;
const int ccsReturnAddress3   = nCostCentreFuns + 2;

static uint32_t currentCCS    = 0;

/*
  a code location of one of the functions we're interested in

    start == 0 && len == 0 <=> the item location is unknown

  cc_code_locations contains an entry for each known item

  item numbering:
    [0,1023]    -> h$_prof_ccs_b_
    [1024,1026] -> h$_prof_ccs_a_
 */
typedef struct code_t {
  uintptr_t start;
  size_t len;
} code_t;

static code_t    cc_code[nFunctions];
static uintptr_t cc_return[nFunctions];
static std::map<uintptr_t, int> cc_code_locations; // start -> item

bool is_in_code(uintptr_t return_addr, int item) {
  code_t &c = cc_code[item];
  return return_addr >= c.start && return_addr < c.start + c.len;
}

int code_offset(uintptr_t return_addr, int item) {
  return return_addr - cc_code[item].start;
}

static uintptr_t address_loc_resolver(uintptr_t return_addr_location) {
  uintptr_t ra = *((uintptr_t*)return_addr_location);
  int item = -1;
  uintptr_t offset = 0;
  if(is_in_code(ra, ccsReturnAddress1)) {
    item = currentCCS & (nCostCentreFuns-1);
    offset = code_offset(ra, ccsReturnAddress1);
  } else if(is_in_code(ra, ccsReturnAddress2)) {
    item = (currentCCS >> nCostCentreFunsBits) & (nCostCentreFuns-1);
    offset = code_offset(ra, ccsReturnAddress2);
  } else if(is_in_code(ra, ccsReturnAddress3)) {
    item = (currentCCS >> (2 * nCostCentreFunsBits)) & (nCostCentreFuns-1);
    offset = code_offset(ra, ccsReturnAddress3);
  }
  if(item != -1 && cc_code[item].start != 0) {
    cc_return[item] = cc_code[item].start + offset;
    return (uintptr_t)(&cc_return[item]);
  } else {
    return return_addr_location;
  }
}

int function_item(const char* name, int len) {
  if(len < 27 || strncmp(name, "LazyCompile:*h$_prof_ccs_", 25) != 0) {
    return -1;
  }
  if(name[26] != '_') return -1;
  char ver = name[25];
  if(ver != 'a' && ver != 'b') return -1;
  name += 27;
  len -= 27;
  if(len == 0 || !isdigit(name[0])) return -1;
  int val = 0;
  for(int i=0;i<len;i++) {
    char c = name[i];
    if(!isdigit(c)) break;
    val = val * 10 + (int)c - 48;
  }
  if(ver == 'b' && val >= 0 && val <= 1023) {
    return val;
  } else if(ver == 'a' && val >= 0 && val <= 2) {
    return val + 1024;
  } else {
    return -1;
  }
}

static void jit_code_handler(const JitCodeEvent* event) {
  char* name;
  int item;
  uintptr_t cstart = (uintptr_t)event->code_start;
  std::map<uintptr_t, int>::iterator it;
  switch(event->type) {
    case JitCodeEvent::CODE_ADDED:
      name = new char[event->name.len+1];
      name[event->name.len] = 0;
      strncpy(name, event->name.str, event->name.len);
      fprintf( stderr
             , "jit: code added at %p size %lu, name: %s\n"
             , event->code_start
             , event->code_len
             , name);
      delete[] name;
      item = function_item(event->name.str, event->name.len);
      if(item != -1) {
        it = cc_code_locations.find(cstart);
        // code for a different function in same location? shouldn't happen
        if(it != cc_code_locations.end() && it->second != item) {
          cc_code[it->second].start = 0;
          cc_code[it->second].len = 0;

        }
        cc_code[item].start = cstart;
        cc_code[item].len = event->code_len;
        cc_code_locations[cstart] = item;
      }
      break;
    case JitCodeEvent::CODE_MOVED:
      fprintf( stderr
             , "jit: code moved at %p size %lu to: %p\n"
             , event->code_start
             , event->code_len
             , event->new_code_start
             );
      it = cc_code_locations.find(cstart);
      if(it != cc_code_locations.end()) {
        item = it->second;
        cstart = (uintptr_t)event->new_code_start;
        cc_code[item].start = cstart;
        cc_code[item].len   = event->code_len;
        cc_code_locations.erase(it);
        cc_code_locations[cstart] = item;
      }
      break;
    case JitCodeEvent::CODE_REMOVED:
      fprintf( stderr
             , "jit: code removed from %p size %lu\n"
             , event->code_start
             , event->code_len
             );
      it = cc_code_locations.find(cstart);
      if(it != cc_code_locations.end()) {
        item = it->second;
        cc_code[item].start = 0;
        cc_code[item].len = 0;
        cc_code_locations.erase(it);
      }
      break;
    case JitCodeEvent::CODE_ADD_LINE_POS_INFO:
    case JitCodeEvent::CODE_START_LINE_INFO_RECORDING:
    case JitCodeEvent::CODE_END_LINE_INFO_RECORDING:
    default:
      ; // no need to handle these
  }
}

void get_ccs_buffer(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(
    ArrayBuffer::New(isolate, &currentCCS, 4)
  );
}

void Init(Handle<Object> exports, Handle<Object> module) {
  // set all tracked code locations to unknown
  for(int i=0;i<nFunctions;i++) {
    cc_code[i].start = 0;
    cc_code[i].len   = 0;
  }

  // install handlers
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  V8::SetReturnAddressLocationResolver(address_loc_resolver);
  isolate->SetJitCodeEventHandler(kJitCodeEventDefault, jit_code_handler);

  // expose get_ccs_buffer
  NODE_SET_METHOD(exports, "get_ccs_buffer", get_ccs_buffer);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.htmlo
#include "ADHeatConductionTimeDerivative.h"

registerADMooseObject("HeatConductionApp", ADHeatConductionTimeDerivative);

defineADValidParams(
    ADHeatConductionTimeDerivative,
    ADTimeDerivative,
    params.addClassDescription(
        "AD Time derivative term $\\rho c_p \\frac{\\partial T}{\\partial t}$ of "
        "the heat equation for quasi-constant specific heat $c_p$ and the density $\\rho$.");
    params.set<bool>("use_displaced_mesh") = true;
    params.addParam<MaterialPropertyName>("specific_heat",
                                          "specific_heat",
                                          "Property name of the specific heat material property");
    params.addParam<MaterialPropertyName>("density_name",
                                          "density",
                                          "Property name of the density material property"););

template <ComputeStage compute_stage>
ADHeatConductionTimeDerivative<compute_stage>::ADHeatConductionTimeDerivative(
    const InputParameters & parameters)
  : ADTimeDerivative<compute_stage>(parameters),
    _specific_heat(adGetADMaterialProperty<Real>("specific_heat")),
    _density(adGetADMaterialProperty<Real>("density_name"))
{
}

template <ComputeStage compute_stage>
ADResidual
ADHeatConductionTimeDerivative<compute_stage>::computeQpResidual()
{
  return _specific_heat[_qp] * _density[_qp] *
         ADTimeDerivative<compute_stage>::computeQpResidual();
}
<commit_msg>Formatting (#12633)<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.htmlo
#include "ADHeatConductionTimeDerivative.h"

registerADMooseObject("HeatConductionApp", ADHeatConductionTimeDerivative);

defineADValidParams(
    ADHeatConductionTimeDerivative,
    ADTimeDerivative,
    params.addClassDescription(
        "AD Time derivative term $\\rho c_p \\frac{\\partial T}{\\partial t}$ of "
        "the heat equation for quasi-constant specific heat $c_p$ and the density $\\rho$.");
    params.set<bool>("use_displaced_mesh") = true;
    params.addParam<MaterialPropertyName>("specific_heat",
                                          "specific_heat",
                                          "Property name of the specific heat material property");
    params.addParam<MaterialPropertyName>("density_name",
                                          "density",
                                          "Property name of the density material property"););

template <ComputeStage compute_stage>
ADHeatConductionTimeDerivative<compute_stage>::ADHeatConductionTimeDerivative(
    const InputParameters & parameters)
  : ADTimeDerivative<compute_stage>(parameters),
    _specific_heat(adGetADMaterialProperty<Real>("specific_heat")),
    _density(adGetADMaterialProperty<Real>("density_name"))
{
}

template <ComputeStage compute_stage>
ADResidual
ADHeatConductionTimeDerivative<compute_stage>::computeQpResidual()
{
  return _specific_heat[_qp] * _density[_qp] * ADTimeDerivative<compute_stage>::computeQpResidual();
}
<|endoftext|>


<commit_before>/* This source file is part of the Tomviz project, https://tomviz.org/.
   It is released under the 3-Clause BSD License, see "LICENSE". */

#include "OperatorPythonWrapper.h"
#include "PybindVTKTypeCaster.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "core/DataSourceBase.h"

#include "PipelineStateManager.h"
#include "PythonTypeConversions.h"
#include "vtkImageData.h"

namespace py = pybind11;

using tomviz::DataSourceBase;
using tomviz::MetadataType;

PYBIND11_VTK_TYPECASTER(vtkImageData)

PYBIND11_PLUGIN(_wrapping)
{
  py::module m("_wrapping", "tomviz wrapped classes");

  py::class_<OperatorPythonWrapper>(m, "OperatorPythonWrapper")
    .def(py::init([](void* op) { return new OperatorPythonWrapper(op); }))
    .def_property_readonly("canceled", &OperatorPythonWrapper::canceled)
    .def_property_readonly("completed", &OperatorPythonWrapper::completed)
    .def_property("progress_maximum",
                  &OperatorPythonWrapper::totalProgressSteps,
                  &OperatorPythonWrapper::setTotalProgressSteps)
    .def_property("progress_value", &OperatorPythonWrapper::progressStep,
                  &OperatorPythonWrapper::setProgressStep)
    .def_property("progress_message", &OperatorPythonWrapper::progressMessage,
                  &OperatorPythonWrapper::setProgressMessage)
    .def_property("progress_data", &OperatorPythonWrapper::progressData,
                  &OperatorPythonWrapper::setProgressData);

  py::class_<tomviz::DataSourceBase>(m, "DataSource")
    .def_property_readonly("dark_data", &DataSourceBase::darkData,
                           "Get the dark image data")
    .def_property_readonly("white_data", &DataSourceBase::whiteData,
                           "Get the white image data")
    .def_property_readonly(
      "file_name", [](const DataSourceBase& b) { return b.fileName(); },
      "Get the file from which the data source was loaded")
    .def_property_readonly(
      "metadata",
      [](const DataSourceBase& b) {
        auto* obj = tomviz::toPyObject(b.metadata());
        // The PyObject* reference is currently unmanaged.
        // Therefore, we steal it, rather than borrow.
        return py::reinterpret_steal<py::dict>(obj);
      },
      "Get the data source metadata");

  py::class_<PipelineStateManager>(m, "PipelineStateManagerBase")
    .def(py::init())
    .def("serialize", &PipelineStateManager::serialize)
    .def("load", &PipelineStateManager::load)
    .def("module_json", &PipelineStateManager::modulesJson)
    .def("operator_json", &PipelineStateManager::operatorsJson)
    .def("serialize_op", &PipelineStateManager::serializeOperator)
    .def("serialize_module", &PipelineStateManager::serializeModule)
    .def("serialize_datasource", &PipelineStateManager::serializeDataSource)
    .def("update_op", &PipelineStateManager::updateOperator)
    .def("update_module", &PipelineStateManager::updateModule)
    .def("update_datasource", &PipelineStateManager::updateDataSource)
    .def("modified", &PipelineStateManager::modified)
    .def("add_module", &PipelineStateManager::addModule)
    .def("add_operator", &PipelineStateManager::addOperator)
    .def("add_datasource", &PipelineStateManager::addDataSource)
    .def("remove_operator", &PipelineStateManager::removeOperator)
    .def("remove_module", &PipelineStateManager::removeModule)
    .def("remove_datasource", &PipelineStateManager::removeDataSource)
    .def("enable_sync_to_python", &PipelineStateManager::enableSyncToPython)
    .def("disable_sync_to_python", &PipelineStateManager::disableSyncToPython)
    .def("pause_pipeline", &PipelineStateManager::pausePipeline)
    .def("resume_pipeline", &PipelineStateManager::resumePipeline)
    .def("execute_pipeline", &PipelineStateManager::executePipeline)
    .def("pipeline_paused", &PipelineStateManager::pipelinePaused);

  return m.ptr();
}
<commit_msg>Fix clang-format<commit_after>/* This source file is part of the Tomviz project, https://tomviz.org/.
   It is released under the 3-Clause BSD License, see "LICENSE". */

#include "OperatorPythonWrapper.h"
#include "PybindVTKTypeCaster.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "core/DataSourceBase.h"

#include "PipelineStateManager.h"
#include "PythonTypeConversions.h"
#include "vtkImageData.h"

namespace py = pybind11;

using tomviz::DataSourceBase;
using tomviz::MetadataType;

PYBIND11_VTK_TYPECASTER(vtkImageData)

PYBIND11_PLUGIN(_wrapping)
{
  py::module m("_wrapping", "tomviz wrapped classes");

  py::class_<OperatorPythonWrapper>(m, "OperatorPythonWrapper")
    .def(py::init([](void* op) { return new OperatorPythonWrapper(op); }))
    .def_property_readonly("canceled", &OperatorPythonWrapper::canceled)
    .def_property_readonly("completed", &OperatorPythonWrapper::completed)
    .def_property("progress_maximum",
                  &OperatorPythonWrapper::totalProgressSteps,
                  &OperatorPythonWrapper::setTotalProgressSteps)
    .def_property("progress_value", &OperatorPythonWrapper::progressStep,
                  &OperatorPythonWrapper::setProgressStep)
    .def_property("progress_message", &OperatorPythonWrapper::progressMessage,
                  &OperatorPythonWrapper::setProgressMessage)
    .def_property("progress_data", &OperatorPythonWrapper::progressData,
                  &OperatorPythonWrapper::setProgressData);

  py::class_<tomviz::DataSourceBase>(m, "DataSource")
    .def_property_readonly("dark_data", &DataSourceBase::darkData,
                           "Get the dark image data")
    .def_property_readonly("white_data", &DataSourceBase::whiteData,
                           "Get the white image data")
    .def_property_readonly("file_name",
                           [](const DataSourceBase& b) { return b.fileName(); },
                           "Get the file from which the data source was loaded")
    .def_property_readonly("metadata",
                           [](const DataSourceBase& b) {
                             auto* obj = tomviz::toPyObject(b.metadata());
                             // The PyObject* reference is currently unmanaged.
                             // Therefore, we steal it, rather than borrow.
                             return py::reinterpret_steal<py::dict>(obj);
                           },
                           "Get the data source metadata");

  py::class_<PipelineStateManager>(m, "PipelineStateManagerBase")
    .def(py::init())
    .def("serialize", &PipelineStateManager::serialize)
    .def("load", &PipelineStateManager::load)
    .def("module_json", &PipelineStateManager::modulesJson)
    .def("operator_json", &PipelineStateManager::operatorsJson)
    .def("serialize_op", &PipelineStateManager::serializeOperator)
    .def("serialize_module", &PipelineStateManager::serializeModule)
    .def("serialize_datasource", &PipelineStateManager::serializeDataSource)
    .def("update_op", &PipelineStateManager::updateOperator)
    .def("update_module", &PipelineStateManager::updateModule)
    .def("update_datasource", &PipelineStateManager::updateDataSource)
    .def("modified", &PipelineStateManager::modified)
    .def("add_module", &PipelineStateManager::addModule)
    .def("add_operator", &PipelineStateManager::addOperator)
    .def("add_datasource", &PipelineStateManager::addDataSource)
    .def("remove_operator", &PipelineStateManager::removeOperator)
    .def("remove_module", &PipelineStateManager::removeModule)
    .def("remove_datasource", &PipelineStateManager::removeDataSource)
    .def("enable_sync_to_python", &PipelineStateManager::enableSyncToPython)
    .def("disable_sync_to_python", &PipelineStateManager::disableSyncToPython)
    .def("pause_pipeline", &PipelineStateManager::pausePipeline)
    .def("resume_pipeline", &PipelineStateManager::resumePipeline)
    .def("execute_pipeline", &PipelineStateManager::executePipeline)
    .def("pipeline_paused", &PipelineStateManager::pipelinePaused);

  return m.ptr();
}
<|endoftext|>