<commit_before>// The MIT License (MIT)

// Copyright (c) 2016, Microsoft

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <ostream>
#include <stack>

#include "BitFunnel/Configuration/Factories.h"
#include "BitFunnel/Configuration/IFileSystem.h"
#include "BitFunnel/IFileManager.h"
#include "BitFunnel/Index/DocumentHandle.h"
#include "BitFunnel/Index/Factories.h"
#include "BitFunnel/Index/IDocument.h"
#include "BitFunnel/Index/IDocumentCache.h"
#include "BitFunnel/Index/IDocumentFrequencyTable.h"
#include "BitFunnel/Index/IIngestor.h"
#include "BitFunnel/Index/ISimpleIndex.h"
#include "BitFunnel/Index/RowIdSequence.h"
#include "BitFunnel/Index/Token.h"
#include "CsvTsv/Csv.h"
#include "DocumentHandleInternal.h"
#include "LoggerInterfaces/Check.h"
#include "RowTableAnalyzer.h"
#include "RowTableDescriptor.h"
#include "Shard.h"
#include "Slice.h"
#include "TermToText.h"

namespace BitFunnel
{
    void Factories::AnalyzeRowTables(ISimpleIndex const & index,
                                     char const * outDir)
    {
        CHECK_NE(*outDir, '\0')
            << "Output directory not set. ";

        RowTableAnalyzer statistics(index);
        statistics.AnalyzeColumns(outDir);
        statistics.AnalyzeRows(outDir);
    }

    RowTableAnalyzer::RowTableAnalyzer(ISimpleIndex const & index)
        : m_index(index)
    {
    }

    //*************************************************************************
    //
    // Analyze rows
    //
    //*************************************************************************
    void RowTableAnalyzer::AnalyzeRows(char const * outDir) const
    {
        //
        // Gather row statistics for ingested documents.
        // (documents need not be cached)
        //
        auto & fileManager = m_index.GetFileManager();
        auto & ingestor = m_index.GetIngestor();

        // TODO: Create with factory?
        TermToText termToText(*fileManager.TermToText().OpenForRead());

        for (ShardId shardId = 0; shardId < ingestor.GetShardCount(); ++shardId)
        {
            auto terms(Factories::CreateDocumentFrequencyTable(
                *fileManager.DocFreqTable(shardId).OpenForRead()));

            auto fileSystem = Factories::CreateFileSystem();
            auto outFileManager =
                Factories::CreateFileManager(outDir,
                                             outDir,
                                             outDir,
                                             *fileSystem);

            AnalyzeRowsInOneShard(shardId,
                                  termToText,
                                  *outFileManager->RowDensities(shardId).OpenForWrite());
        }
    }

    void RowTableAnalyzer::AnalyzeRowsInOneShard(
        ShardId const & shardId,
        ITermToText const & termToText,
        std::ostream& out) const
    {
        auto & fileManager = m_index.GetFileManager();
        auto terms(Factories::CreateDocumentFrequencyTable(
            *fileManager.DocFreqTable(shardId).OpenForRead()));

        std::array<std::vector<double>, c_maxRankValue> densities;

        for (Rank rank = 0; rank < c_maxRankValue; ++rank)
        {
            auto & shard = m_index.GetIngestor().GetShard(shardId);
            densities[rank] = shard.GetDensities(rank);
        }

        // Use CsvTableFormatter to escape terms that contain commas and quotes.
        CsvTsv::CsvTableFormatter formatter(out);

        for (auto dfEntry : *terms)
        {
            Term term = dfEntry.GetTerm();
            RowIdSequence rows(term, m_index.GetTermTable());

            formatter.WriteField(termToText.Lookup(term.GetRawHash()));
            formatter.WriteField(dfEntry.GetFrequency());

            std::stack<RowId> rowsReversed;
            for (auto row : rows)
            {
                rowsReversed.push(row);
            }

            while (!rowsReversed.empty())
            {
                auto row = rowsReversed.top();
                formatter.WriteField("r");
                out << row.GetRank();
                formatter.WriteField(row.GetIndex());
                formatter.WriteField(densities[row.GetRank()][row.GetIndex()]);

                rowsReversed.pop();
            }
            formatter.WriteRowEnd();
        }
    }

    //*************************************************************************
    //
    // Analyze columns
    //
    //*************************************************************************
    void RowTableAnalyzer::AnalyzeColumns(char const * outDir) const
    {
        auto & ingestor = m_index.GetIngestor();
        auto & cache = ingestor.GetDocumentCache();

        std::vector<Column> columns;

        for (auto doc : cache)
        {
            const DocumentHandleInternal
                handle(ingestor.GetHandle(doc.second));

            Slice const & slice = handle.GetSlice();
            const ShardId shard = slice.GetShard().GetId();

            columns.emplace_back(doc.second,
                                 shard,
                                 doc.first.GetPostingCount());

            void const * buffer = slice.GetSliceBuffer();
            const DocIndex column = handle.GetIndex();

            for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
            {
                RowTableDescriptor rowTable = slice.GetRowTable(rank);

                size_t bitCount = 0;
                const size_t rowCount = rowTable.GetRowCount();
                for (RowIndex row = 0; row < rowCount; ++row)
                {
                    bitCount +=
                        rowTable.GetBit(buffer, row, column);
                }

                columns.back().SetCount(rank, bitCount);

                double density =
                    (rowCount == 0) ? 0.0 : static_cast<double>(bitCount) / rowCount;
                columns.back().SetDensity(rank, density);
            }
        }

        auto fileSystem = Factories::CreateFileSystem();
        auto outFileManager =
            Factories::CreateFileManager(outDir,
                                         outDir,
                                         outDir,
                                         *fileSystem);

        //
        // Write out raw column data.
        //
        {
            // No need to use CsvTableFormatter for escaping because all values
            // are numbers.
            auto out = outFileManager->ColumnDensities().OpenForWrite();
            Column::WriteHeader(*out);
            for (auto column : columns)
            {
                column.Write(*out);
            }
        }

        //
        // Generate summary.
        //
        {
            auto out = outFileManager->ColumnDensitySummary().OpenForWrite();

            *out << "Summary" << std::endl;

            for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
            {
                Accumulator accumulator;
                for (auto column : columns)
                {
                    accumulator.Record(column.m_densities[rank]);
                }

                *out << "Rank " << rank << std::endl
                    << "  column density: " << std::endl
                    << "      min: " << accumulator.GetMin() << std::endl
                    << "      max: " << accumulator.GetMax() << std::endl
                    << "     mean: " << accumulator.GetMean() << std::endl
                    << "      var: " << accumulator.GetVariance() << std::endl
                    << "    count: " << accumulator.GetCount() << std::endl;
            }
        }

    }

    RowTableAnalyzer::Column::Column(DocId id, ShardId shard, size_t postings)
      : m_id(id),
        m_postings(postings),
        m_shard(shard),
        m_bits{}
    {
    }

    void RowTableAnalyzer::Column::SetCount(Rank rank, size_t count)
    {
        m_bits[rank] = count;
    }

    void RowTableAnalyzer::Column::SetDensity(Rank rank, double density)
    {
        m_densities[rank] = density;
    }

    void RowTableAnalyzer::Column::WriteHeader(std::ostream& out)
    {
        out << "id,postings,shard";

        for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
        {
            out << ",rank" << rank;
        }

        out << std::endl;
    }

    void RowTableAnalyzer::Column::Write(std::ostream& out)
    {
        out << m_id
            << "," << m_postings
            << "," << m_shard;

        for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
        {
            // TODO: Consider writing out or eliminating m_bits.
            out << "," << m_densities[rank];
        }

        out << std::endl;
    }
}
<commit_msg>Fix bug where analyzed column densities are too high.<commit_after>// The MIT License (MIT)

// Copyright (c) 2016, Microsoft

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <ostream>
#include <stack>

#include "BitFunnel/Configuration/Factories.h"
#include "BitFunnel/Configuration/IFileSystem.h"
#include "BitFunnel/IFileManager.h"
#include "BitFunnel/Index/DocumentHandle.h"
#include "BitFunnel/Index/Factories.h"
#include "BitFunnel/Index/IDocument.h"
#include "BitFunnel/Index/IDocumentCache.h"
#include "BitFunnel/Index/IDocumentFrequencyTable.h"
#include "BitFunnel/Index/IIngestor.h"
#include "BitFunnel/Index/ISimpleIndex.h"
#include "BitFunnel/Index/RowIdSequence.h"
#include "BitFunnel/Index/Token.h"
#include "CsvTsv/Csv.h"
#include "DocumentHandleInternal.h"
#include "LoggerInterfaces/Check.h"
#include "RowTableAnalyzer.h"
#include "RowTableDescriptor.h"
#include "Shard.h"
#include "Slice.h"
#include "TermToText.h"

namespace BitFunnel
{
    void Factories::AnalyzeRowTables(ISimpleIndex const & index,
                                     char const * outDir)
    {
        CHECK_NE(*outDir, '\0')
            << "Output directory not set. ";

        RowTableAnalyzer statistics(index);
        statistics.AnalyzeColumns(outDir);
        statistics.AnalyzeRows(outDir);
    }

    RowTableAnalyzer::RowTableAnalyzer(ISimpleIndex const & index)
        : m_index(index)
    {
    }

    //*************************************************************************
    //
    // Analyze rows
    //
    //*************************************************************************
    void RowTableAnalyzer::AnalyzeRows(char const * outDir) const
    {
        //
        // Gather row statistics for ingested documents.
        // (documents need not be cached)
        //
        auto & fileManager = m_index.GetFileManager();
        auto & ingestor = m_index.GetIngestor();

        // TODO: Create with factory?
        TermToText termToText(*fileManager.TermToText().OpenForRead());

        for (ShardId shardId = 0; shardId < ingestor.GetShardCount(); ++shardId)
        {
            auto terms(Factories::CreateDocumentFrequencyTable(
                *fileManager.DocFreqTable(shardId).OpenForRead()));

            auto fileSystem = Factories::CreateFileSystem();
            auto outFileManager =
                Factories::CreateFileManager(outDir,
                                             outDir,
                                             outDir,
                                             *fileSystem);

            AnalyzeRowsInOneShard(shardId,
                                  termToText,
                                  *outFileManager->RowDensities(shardId).OpenForWrite());
        }
    }

    void RowTableAnalyzer::AnalyzeRowsInOneShard(
        ShardId const & shardId,
        ITermToText const & termToText,
        std::ostream& out) const
    {
        auto & fileManager = m_index.GetFileManager();
        auto terms(Factories::CreateDocumentFrequencyTable(
            *fileManager.DocFreqTable(shardId).OpenForRead()));

        std::array<std::vector<double>, c_maxRankValue> densities;

        for (Rank rank = 0; rank < c_maxRankValue; ++rank)
        {
            auto & shard = m_index.GetIngestor().GetShard(shardId);
            densities[rank] = shard.GetDensities(rank);
        }

        // Use CsvTableFormatter to escape terms that contain commas and quotes.
        CsvTsv::CsvTableFormatter formatter(out);

        for (auto dfEntry : *terms)
        {
            Term term = dfEntry.GetTerm();
            RowIdSequence rows(term, m_index.GetTermTable());

            formatter.WriteField(termToText.Lookup(term.GetRawHash()));
            formatter.WriteField(dfEntry.GetFrequency());

            std::stack<RowId> rowsReversed;
            for (auto row : rows)
            {
                rowsReversed.push(row);
            }

            while (!rowsReversed.empty())
            {
                auto row = rowsReversed.top();
                formatter.WriteField("r");
                out << row.GetRank();
                formatter.WriteField(row.GetIndex());
                formatter.WriteField(densities[row.GetRank()][row.GetIndex()]);

                rowsReversed.pop();
            }
            formatter.WriteRowEnd();
        }
    }

    //*************************************************************************
    //
    // Analyze columns
    //
    //*************************************************************************
    void RowTableAnalyzer::AnalyzeColumns(char const * outDir) const
    {
        auto & ingestor = m_index.GetIngestor();
        auto & cache = ingestor.GetDocumentCache();

        std::vector<Column> columns;

        for (auto doc : cache)
        {
            const DocumentHandleInternal
                handle(ingestor.GetHandle(doc.second));

            Slice const & slice = handle.GetSlice();
            const ShardId shard = slice.GetShard().GetId();

            columns.emplace_back(doc.second,
                                 shard,
                                 doc.first.GetPostingCount());

            void const * buffer = slice.GetSliceBuffer();
            const DocIndex column = handle.GetIndex();

            for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
            {
                RowTableDescriptor rowTable = slice.GetRowTable(rank);

                size_t bitCount = 0;
                const size_t rowCount = rowTable.GetRowCount();
                for (RowIndex row = 0; row < rowCount; ++row)
                {
                    if (rowTable.GetBit(buffer, row, column) != 0)
                    {
                        ++bitCount;
                    }
                }

                columns.back().SetCount(rank, bitCount);

                double density =
                    (rowCount == 0) ? 0.0 : static_cast<double>(bitCount) / rowCount;
                columns.back().SetDensity(rank, density);
            }
        }

        auto fileSystem = Factories::CreateFileSystem();
        auto outFileManager =
            Factories::CreateFileManager(outDir,
                                         outDir,
                                         outDir,
                                         *fileSystem);

        //
        // Write out raw column data.
        //
        {
            // No need to use CsvTableFormatter for escaping because all values
            // are numbers.
            auto out = outFileManager->ColumnDensities().OpenForWrite();
            Column::WriteHeader(*out);
            for (auto column : columns)
            {
                column.Write(*out);
            }
        }

        //
        // Generate summary.
        //
        {
            auto out = outFileManager->ColumnDensitySummary().OpenForWrite();

            *out << "Summary" << std::endl;

            for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
            {
                Accumulator accumulator;
                for (auto column : columns)
                {
                    accumulator.Record(column.m_densities[rank]);
                }

                *out << "Rank " << rank << std::endl
                    << "  column density: " << std::endl
                    << "      min: " << accumulator.GetMin() << std::endl
                    << "      max: " << accumulator.GetMax() << std::endl
                    << "     mean: " << accumulator.GetMean() << std::endl
                    << "      var: " << accumulator.GetVariance() << std::endl
                    << "    count: " << accumulator.GetCount() << std::endl;
            }
        }

    }

    RowTableAnalyzer::Column::Column(DocId id, ShardId shard, size_t postings)
      : m_id(id),
        m_postings(postings),
        m_shard(shard),
        m_bits{}
    {
    }

    void RowTableAnalyzer::Column::SetCount(Rank rank, size_t count)
    {
        m_bits[rank] = count;
    }

    void RowTableAnalyzer::Column::SetDensity(Rank rank, double density)
    {
        m_densities[rank] = density;
    }

    void RowTableAnalyzer::Column::WriteHeader(std::ostream& out)
    {
        out << "id,postings,shard";

        for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
        {
            out << ",rank" << rank;
        }

        out << std::endl;
    }

    void RowTableAnalyzer::Column::Write(std::ostream& out)
    {
        out << m_id
            << "," << m_postings
            << "," << m_shard;

        for (Rank rank = 0; rank <= c_maxRankValue; ++rank)
        {
            // TODO: Consider writing out or eliminating m_bits.
            out << "," << m_densities[rank];
        }

        out << std::endl;
    }
}
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/diff_context.h"
#include "libmesh/diff_system.h"

namespace libMesh
{

DiffContext::DiffContext (const System& sys) :
  time(sys.time),
  system_time(sys.time),
  elem_solution_derivative(1.),
  fixed_solution_derivative(0.),
  dof_indices_var(sys.n_vars()),
  _deltat(NULL)
{
  // Finally initialize solution/residual/jacobian data structures
  unsigned int n_vars = sys.n_vars();

  elem_subsolutions.reserve(n_vars);
  elem_subresiduals.reserve(n_vars);
  elem_subjacobians.resize(n_vars);
  if (sys.use_fixed_solution)
    elem_fixed_subsolutions.reserve(n_vars);

  // If the user resizes sys.qoi, it will invalidate us
  unsigned int n_qoi = sys.qoi.size();
  elem_qoi.resize(n_qoi);
  elem_qoi_derivative.resize(n_qoi);
  elem_qoi_subderivatives.resize(n_qoi);
  for (unsigned int q=0; q != n_qoi; ++q)
    elem_qoi_subderivatives[q].reserve(n_vars);

  for (unsigned int i=0; i != n_vars; ++i)
    {
      elem_subsolutions.push_back(new DenseSubVector<Number>(elem_solution));
      elem_subresiduals.push_back(new DenseSubVector<Number>(elem_residual));
      for (unsigned int q=0; q != n_qoi; ++q)
        elem_qoi_subderivatives[q].push_back(new DenseSubVector<Number>(elem_qoi_derivative[q]));
      elem_subjacobians[i].reserve(n_vars);

      if (sys.use_fixed_solution)
        elem_fixed_subsolutions.push_back
	  (new DenseSubVector<Number>(elem_fixed_solution));

      for (unsigned int j=0; j != n_vars; ++j)
        {
          elem_subjacobians[i].push_back
            (new DenseSubMatrix<Number>(elem_jacobian));
        }
    }
}

DiffContext::~DiffContext ()
{
  for (unsigned int i=0; i != elem_subsolutions.size(); ++i)
    {
      delete elem_subsolutions[i];
      delete elem_subresiduals[i];
      for (unsigned int q=0; q != elem_qoi_subderivatives.size(); ++q)
        delete elem_qoi_subderivatives[q][i];
      if (!elem_fixed_subsolutions.empty())
        delete elem_fixed_subsolutions[i];

      for (unsigned int j=0; j != elem_subjacobians[i].size(); ++j)
        delete elem_subjacobians[i][j];
    }
}

  void DiffContext::set_deltat_pointer(Real* dt)
  {
    // We may actually want to be able to set this pointer to NULL, so
    // don't report an error for that.
    _deltat = dt;
  }

  Real DiffContext::get_deltat_value()
  {
    libmesh_assert(_deltat);

    return *_deltat;
  }

} // namespace libMesh

<commit_msg>DiffContext should save (and have an accessor to) the System it was created for.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/diff_context.h"
#include "libmesh/diff_system.h"

namespace libMesh
{

DiffContext::DiffContext (const System& sys) :
  time(sys.time),
  system_time(sys.time),
  elem_solution_derivative(1.),
  fixed_solution_derivative(0.),
  dof_indices_var(sys.n_vars()),
  _deltat(NULL),
  _system(sys)
{
  // Finally initialize solution/residual/jacobian data structures
  unsigned int n_vars = sys.n_vars();

  elem_subsolutions.reserve(n_vars);
  elem_subresiduals.reserve(n_vars);
  elem_subjacobians.resize(n_vars);
  if (sys.use_fixed_solution)
    elem_fixed_subsolutions.reserve(n_vars);

  // If the user resizes sys.qoi, it will invalidate us
  unsigned int n_qoi = sys.qoi.size();
  elem_qoi.resize(n_qoi);
  elem_qoi_derivative.resize(n_qoi);
  elem_qoi_subderivatives.resize(n_qoi);
  for (unsigned int q=0; q != n_qoi; ++q)
    elem_qoi_subderivatives[q].reserve(n_vars);

  for (unsigned int i=0; i != n_vars; ++i)
    {
      elem_subsolutions.push_back(new DenseSubVector<Number>(elem_solution));
      elem_subresiduals.push_back(new DenseSubVector<Number>(elem_residual));
      for (unsigned int q=0; q != n_qoi; ++q)
        elem_qoi_subderivatives[q].push_back(new DenseSubVector<Number>(elem_qoi_derivative[q]));
      elem_subjacobians[i].reserve(n_vars);

      if (sys.use_fixed_solution)
        elem_fixed_subsolutions.push_back
	  (new DenseSubVector<Number>(elem_fixed_solution));

      for (unsigned int j=0; j != n_vars; ++j)
        {
          elem_subjacobians[i].push_back
            (new DenseSubMatrix<Number>(elem_jacobian));
        }
    }
}

DiffContext::~DiffContext ()
{
  for (unsigned int i=0; i != elem_subsolutions.size(); ++i)
    {
      delete elem_subsolutions[i];
      delete elem_subresiduals[i];
      for (unsigned int q=0; q != elem_qoi_subderivatives.size(); ++q)
        delete elem_qoi_subderivatives[q][i];
      if (!elem_fixed_subsolutions.empty())
        delete elem_fixed_subsolutions[i];

      for (unsigned int j=0; j != elem_subjacobians[i].size(); ++j)
        delete elem_subjacobians[i][j];
    }
}

  void DiffContext::set_deltat_pointer(Real* dt)
  {
    // We may actually want to be able to set this pointer to NULL, so
    // don't report an error for that.
    _deltat = dt;
  }

  Real DiffContext::get_deltat_value()
  {
    libmesh_assert(_deltat);

    return *_deltat;
  }

} // namespace libMesh

<|endoftext|>


<commit_before>// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Posix/FileImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <cstdio>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	FileImpl::FileImpl(const File* parent) :
	m_endOfFile(false),
	m_endOfFileUpdated(true)
	{
		NazaraUnused(parent);
	}

	void FileImpl::Close()
	{
		if (m_fileDescriptor != -1)
			close(m_fileDescriptor);
	}

	bool FileImpl::EndOfFile() const
	{
		if (!m_endOfFileUpdated)
		{
			struct stat64 fileSize;
			if (fstat64(m_fileDescriptor, &fileSize) == -1)
				fileSize.st_size = 0;

			m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
			m_endOfFileUpdated = true;
		}

		return m_endOfFile;
	}

	void FileImpl::Flush()
	{
		if (fsync(m_fileDescriptor) == -1)
			NazaraError("Unable to flush file: " + Error::GetLastSystemError());
	}

	UInt64 FileImpl::GetCursorPos() const
	{
		off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
		return static_cast<UInt64>(position);
	}

	bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
	{
		int flags;
		mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

		if ((mode & OpenMode_ReadWrite) == OpenMode_ReadWrite)
			flags = O_CREAT | O_RDWR;
		else if ((mode & OpenMode_ReadOnly) == OpenMode_ReadOnly)
			flags = O_RDONLY;
		else if ((mode & OpenMode_WriteOnly) == OpenMode_WriteOnly)
			flags = O_CREAT | O_WRONLY;
		else
			return false;

		if (mode & OpenMode_Append)
			flags |= O_APPEND;

		if (mode & OpenMode_MustExist)
			flags &= ~O_CREAT;

		if (mode & OpenMode_Truncate)
			flags |= O_TRUNC;

		///TODO: lock
		//if ((mode & OpenMode_Lock) == 0)
		//	shareMode |= FILE_SHARE_WRITE;

		m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
		return m_fileDescriptor != -1;
	}

	std::size_t FileImpl::Read(void* buffer, std::size_t size)
	{
		ssize_t bytes;
		if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
		{
			m_endOfFile = (static_cast<std::size_t>(bytes) != size);
			m_endOfFileUpdated = true;

			return static_cast<std::size_t>(bytes);
		}
		else
			return 0;
	}

	bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
	{
		int moveMethod;
		switch (pos)
		{
			case CursorPosition_AtBegin:
				moveMethod = SEEK_SET;
				break;

			case CursorPosition_AtCurrent:
				moveMethod = SEEK_CUR;
				break;

			case CursorPosition_AtEnd:
				moveMethod = SEEK_END;
				break;

			default:
				NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
				return false;
		}

		m_endOfFileUpdated = false;

		return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
	}

	bool FileImpl::SetSize(UInt64 size)
	{
		return ftruncate64(m_fileDescriptor, size) != 0;
	}

	std::size_t FileImpl::Write(const void* buffer, std::size_t size)
	{
		lockf64(m_fileDescriptor, F_LOCK, size);
		ssize_t written = write(m_fileDescriptor, buffer, size);
		lockf64(m_fileDescriptor, F_ULOCK, size);

		m_endOfFileUpdated = false;

		return written;
	}

	bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
	{
		int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
		if (fd1 == -1)
		{
			NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
			return false;
		}

		mode_t permissions;
		struct stat sb;
		if (fstat(fd1, &sb) == -1) // get permission from first file
		{
			NazaraWarning("Could not get permissions of source file");
			permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
		}
		else
		{
			permissions = sb.st_mode & ~S_IFMT; // S_IFMT: bit mask for the file type bit field -> ~S_IFMT: general permissions
		}

		int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
		if (fd2 == -1)
		{
			NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
			close(fd1);
			return false;
		}

		char buffer[512];
		ssize_t bytes;
		do
		{
			bytes = read(fd1,buffer,512);
			if (bytes == -1)
			{
				close(fd1);
				close(fd2);
				NazaraError("An error occured from copy : " + Error::GetLastSystemError());
				return false;
			}
			write(fd2,buffer,bytes);
		}
		while (bytes == 512);

		close(fd1);
		close(fd2);
		return true;
	}

	bool FileImpl::Delete(const String& filePath)
	{
		bool success = unlink(filePath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
			return false;
		}
	}

	bool FileImpl::Exists(const String& filePath)
	{
		const char* path = filePath.GetConstBuffer();
		if (access(path, F_OK) != -1)
			return true;

		return false;
	}

	time_t FileImpl::GetCreationTime(const String& filePath)
	{
		NazaraUnused(filePath);

		NazaraWarning("Posix has no creation time information");
		return 0;
	}

	time_t FileImpl::GetLastAccessTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_atime;
	}

	time_t FileImpl::GetLastWriteTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_mtime;
	}

	UInt64 FileImpl::GetSize(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return static_cast<UInt64>(stats.st_size);
	}

	bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
	{
		bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Unable to rename file: " + Error::GetLastSystemError());
			return false;
		}
	}
}
<commit_msg>Add lock file on Linux and the possibility to have two processes writing to the same one<commit_after>// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Posix/FileImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <cstdio>
#include <sys/file.h>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	FileImpl::FileImpl(const File* parent) :
	m_endOfFile(false),
	m_endOfFileUpdated(true)
	{
		NazaraUnused(parent);
	}

	void FileImpl::Close()
	{
		if (m_fileDescriptor != -1)
			close(m_fileDescriptor);
	}

	bool FileImpl::EndOfFile() const
	{
		if (!m_endOfFileUpdated)
		{
			struct stat64 fileSize;
			if (fstat64(m_fileDescriptor, &fileSize) == -1)
				fileSize.st_size = 0;

			m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
			m_endOfFileUpdated = true;
		}

		return m_endOfFile;
	}

	void FileImpl::Flush()
	{
		if (fsync(m_fileDescriptor) == -1)
			NazaraError("Unable to flush file: " + Error::GetLastSystemError());
	}

	UInt64 FileImpl::GetCursorPos() const
	{
		off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
		return static_cast<UInt64>(position);
	}

	bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
	{
		int flags;
		mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

		if ((mode & OpenMode_ReadWrite) == OpenMode_ReadWrite)
			flags = O_CREAT | O_RDWR;
		else if ((mode & OpenMode_ReadOnly) == OpenMode_ReadOnly)
			flags = O_RDONLY;
		else if ((mode & OpenMode_WriteOnly) == OpenMode_WriteOnly)
			flags = O_CREAT | O_WRONLY;
		else
			return false;

		if (mode & OpenMode_Append)
			flags |= O_APPEND;

		if (mode & OpenMode_MustExist)
			flags &= ~O_CREAT;

		if (mode & OpenMode_Truncate)
			flags |= O_TRUNC;

		m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);

		static struct flock lock;

		auto initialize_flock = [](struct flock& fileLock)
		{
			fileLock.l_type = F_WRLCK;
			fileLock.l_start = 0;
			fileLock.l_whence = SEEK_SET;
			fileLock.l_len = 0;
			fileLock.l_pid = getpid();
		};

		initialize_flock(lock);

		if (fcntl(m_fileDescriptor, F_GETLK, &lock) == -1)
		{
			Close();
			NazaraError("Unable to detect presence of lock on the file");
			return false;
		}

		if (lock.l_type != F_UNLCK)
		{
			Close();
			NazaraError("A lock is present on the file");
			return false;
		}

		if (mode & OpenMode_Lock)
		{
			initialize_flock(lock);

			if (fcntl(m_fileDescriptor, F_SETLK, &lock) == -1)
			{
				Close();
				NazaraError("Unable to place a lock on the file");
				return false;
			}
		}

		return m_fileDescriptor != -1;
	}

	std::size_t FileImpl::Read(void* buffer, std::size_t size)
	{
		ssize_t bytes;
		if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
		{
			m_endOfFile = (static_cast<std::size_t>(bytes) != size);
			m_endOfFileUpdated = true;

			return static_cast<std::size_t>(bytes);
		}
		else
			return 0;
	}

	bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
	{
		int moveMethod;
		switch (pos)
		{
			case CursorPosition_AtBegin:
				moveMethod = SEEK_SET;
				break;

			case CursorPosition_AtCurrent:
				moveMethod = SEEK_CUR;
				break;

			case CursorPosition_AtEnd:
				moveMethod = SEEK_END;
				break;

			default:
				NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
				return false;
		}

		m_endOfFileUpdated = false;

		return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
	}

	bool FileImpl::SetSize(UInt64 size)
	{
		return ftruncate64(m_fileDescriptor, size) != 0;
	}

	std::size_t FileImpl::Write(const void* buffer, std::size_t size)
	{
		ssize_t written = write(m_fileDescriptor, buffer, size);
		m_endOfFileUpdated = false;

		return written;
	}

	bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
	{
		int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
		if (fd1 == -1)
		{
			NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
			return false;
		}

		mode_t permissions;
		struct stat sb;
		if (fstat(fd1, &sb) == -1) // get permission from first file
		{
			NazaraWarning("Could not get permissions of source file");
			permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
		}
		else
		{
			permissions = sb.st_mode & ~S_IFMT; // S_IFMT: bit mask for the file type bit field -> ~S_IFMT: general permissions
		}

		int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
		if (fd2 == -1)
		{
			NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
			close(fd1);
			return false;
		}

		char buffer[512];
		ssize_t bytes;
		do
		{
			bytes = read(fd1,buffer,512);
			if (bytes == -1)
			{
				close(fd1);
				close(fd2);
				NazaraError("An error occured from copy : " + Error::GetLastSystemError());
				return false;
			}
			write(fd2,buffer,bytes);
		}
		while (bytes == 512);

		close(fd1);
		close(fd2);
		return true;
	}

	bool FileImpl::Delete(const String& filePath)
	{
		bool success = unlink(filePath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
			return false;
		}
	}

	bool FileImpl::Exists(const String& filePath)
	{
		const char* path = filePath.GetConstBuffer();
		if (access(path, F_OK) != -1)
			return true;

		return false;
	}

	time_t FileImpl::GetCreationTime(const String& filePath)
	{
		NazaraUnused(filePath);

		NazaraWarning("Posix has no creation time information");
		return 0;
	}

	time_t FileImpl::GetLastAccessTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_atime;
	}

	time_t FileImpl::GetLastWriteTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_mtime;
	}

	UInt64 FileImpl::GetSize(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return static_cast<UInt64>(stats.st_size);
	}

	bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
	{
		bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Unable to rename file: " + Error::GetLastSystemError());
			return false;
		}
	}
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>

#include "integrators/symplectic_integrator.hpp"

namespace principia {
namespace integrators {

class SPRKIntegrator : public SymplecticIntegrator {
 public:
  SPRKIntegrator();
  ~SPRKIntegrator() override = default;

  std::vector<std::vector<double>> const& Order5Optimal() const;

  void Initialize(Coefficients const& coefficients) override;

  void Solve(RightHandSideComputation const compute_force,
             AutonomousRightHandSideComputation const compute_velocity,
             Parameters const& parameters,
             Solution* solution) override;

 private:
  // The tableau.
  int stages_;
  std::vector<double> a_;
  std::vector<double> b_;
  std::vector<double> c_;
};

}  // namespace integrators
}  // namespace principia

#include "integrators/symplectic_partitioned_runge_kutta_integrator_body.hpp"
<commit_msg>After eggrobin's review.<commit_after>#pragma once

#include <vector>

#include "integrators/symplectic_integrator.hpp"

namespace principia {
namespace integrators {

class SPRKIntegrator : public SymplecticIntegrator {
 public:
  SPRKIntegrator();
  ~SPRKIntegrator() override = default;

  std::vector<std::vector<double>> const& Order5Optimal() const;

  void Initialize(Coefficients const& coefficients) override;

  void Solve(RightHandSideComputation const compute_force,
             AutonomousRightHandSideComputation const compute_velocity,
             Parameters const& parameters,
             Solution* solution) override;

 private:
  int stages_;

  // The position and momentum nodes.
  std::vector<double> a_;
  std::vector<double> b_;

  // The weights.
  std::vector<double> c_;
};

}  // namespace integrators
}  // namespace principia

#include "integrators/symplectic_partitioned_runge_kutta_integrator_body.hpp"
<|endoftext|>


<commit_before>/*
 * jcom.receive
 * External for Jamoma: receive messages from remote
 * By Trond Lossius & Tim Place, Copyright � 2006
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "Jamoma.h"

/** Receive Object */
typedef struct _receive{
	t_object					ob;					///< REQUIRED: Our object
	void						*outlet;			///< Need one for each outlet
	t_symbol					*attr_name;			///< ATTRIBUTE: name
	TTListPtr					lk_nodes;			///< a pointer to a selection of nodes of the tree
	TTListPtr					lk_attr_observer;	///< a pointer to each created attribute observers
	TTListPtr					lk_life_observer;	///< a pointer to each created life cycle observers
	t_receive_obex_callback		callback;			///< Function pointer to call if we instantiated inside of another extern
	void						*baton;				///< Baton to hand back to the callee of the callback when it is called
} t_receive;

// Prototypes
void		*receive_new(t_symbol *s, long argc, t_atom *argv);
void		receive_free(t_receive *x);
void		receive_assist(t_receive *x, void *b, long msg, long arg, char *dst);
t_max_err 	receive_setname(t_receive *x, void *attr, long argc, t_atom *argv);
void 		receive_setcallback(t_receive *x, void *callback, void *arg);
void 		receive_dispatch(t_receive *x, t_symbol *msg, long argc, t_atom *argv);
void		receive_bind(t_receive *x);
void 		receive_remove(t_receive *x);
void		receive_node_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv);
void		receive_node_attribute_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv);

// experimental method to test the getter mecanism on a node
void		receive_get(t_receive *x);

// Globals
static t_class		*s_receive_class;					// Required: Global pointer the jcom.receive class
//t_object			*g_receivemaster_object = NULL;		// An instance of the jcom.receivemaster class

/************************************************************************************/

void receive_initclass()
{
	long attrflags = 0;
	t_class *c;
	t_object *attr;

	// Define our class
	c = class_new(	"jcom.receive",
					(method)receive_new,
					(method)receive_free,
					sizeof(t_receive),
					(method)0L,
					A_GIMME,
					0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)receive_dispatch,		"dispatch",			A_CANT, 0);
	class_addmethod(c, (method)receive_node_callback,	"receive_node_attribute_callback",	A_CANT, 0);
	class_addmethod(c, (method)receive_node_attribute_callback,	"receive_node_attribute_callback",	A_CANT, 0);
	class_addmethod(c, (method)receive_setcallback,		"setcallback",		A_CANT, 0);
    class_addmethod(c, (method)receive_assist,			"assist", 			A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout, 	"dumpout", 			A_CANT, 0);

	// experimental method to test the getter mecanism on a node
	class_addmethod(c, (method)receive_get,				"bang", 			0);

	// ATTRIBUTE: name
	attr = attr_offset_new("name", _sym_symbol, attrflags,
		(method)0, (method)receive_setname, calcoffset(t_receive, attr_name));
	class_addattr(c, attr);

	// Finalize our class
	class_register(CLASS_BOX, c);
	s_receive_class = c;
}

/************************************************************************************/
// Object Life

// Create
void *receive_new(t_symbol *s, long argc, t_atom *argv)
{
	long		attrstart = attr_args_offset(argc, argv);		// support normal arguments
	t_receive	*x = (t_receive *)object_alloc(s_receive_class);

	if(x){
		object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x, NULL));
		x->outlet = outlet_new(x, NULL);

		//if(!g_receivemaster_object)
		//	g_receivemaster_object = (t_object *)object_new_typed(CLASS_NOBOX, SymbolGen("jcom.receivemaster"), 0, NULL);

		x->callback = NULL;
		x->attr_name = NULL;
		x->lk_nodes = new TTList();
		x->lk_attr_observer = new TTList();
		x->lk_life_observer = new TTList();
		// attr_args_process(x, argc, argv);					// handle attribute args

		// If no name was specified as an attribute
		if(x->attr_name == NULL){
			if(attrstart > 0)
				x->attr_name = atom_getsym(argv);
			else
				x->attr_name = SymbolGen("jcom.receive no arg specified");
			receive_bind(x);
		}
	}
	return x;
}

// Destroy
void receive_free(t_receive *x)
{
	;
}

/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void receive_assist(t_receive *x, void *b, long msg, long arg, char *dst)
{
	if(msg==1) 	// Inlets
		strcpy(dst, "(signal) input to the module");
	else if(msg==2){ // Outlets
		if(arg == 0)
			strcpy(dst, "output from remote");
		else
			strcpy(dst, "dumpout");
	}
}

// ATTRIBUTE: name
t_max_err receive_setname(t_receive *x, void *attr, long argc, t_atom *argv)
{
	t_symbol *arg = atom_getsym(argv);

	if(x->attr_name != arg){
		receive_remove(x);
		x->attr_name = arg;
		x->lk_nodes = new TTList();
		x->lk_attr_observer = new TTList();
		x->lk_life_observer = new TTList();
		receive_bind(x);
	}
	return MAX_ERR_NONE;
}

void receive_bind(t_receive *x)
{
	TTObjectPtr newLifeCallback;
	TTObjectPtr newAttrCallback;
	TTList		lk_selection;
	TTNodePtr	p_node;
	TTErr		err = kTTErrGeneric;

	//if(!NOGOOD(g_receivemaster_object))
	//	object_method(g_receivemaster_object, jps_add, x->attr_name, x);

	// if there isn't selection
	if(x->lk_nodes->isEmpty()){

		// look for the node(s) into the directory
		if(x->attr_name->s_name[0] == C_SEPARATOR){
			if(jamoma_directory){
				err = jamoma_directory->Lookup(TT(x->attr_name->s_name), lk_selection, &p_node);
				x->lk_nodes->merge(lk_selection);
			}

			if(err != kTTErrNone)
				object_error((t_object*)x,"jcom.receive : %s doesn't exist", x->attr_name->s_name);
		}
	}

	if(!x->lk_nodes->isEmpty()){

		// for each node of the selection
		for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next()){

			// get a node from the selection
			x->lk_nodes->current().get(0,(TTPtr*)&p_node);

			// prepare the callback mecanism to
			// be notified about changing value attribute
			// TODO : observe other attribute (default value)
			jamoma_node_attribute_observer_add(p_node, jps_value, (t_object*)x, gensym("receive_node_attribute_callback"), &newAttrCallback);

			// prepare the callback mecanism to
			// be notified about the destruction of the node
			jamoma_node_observer_add(p_node, (t_object*)x, gensym("receive_node_callback"), &newLifeCallback);

			x->lk_attr_observer->append(newAttrCallback);
			x->lk_life_observer->append(newLifeCallback);
		}
	}
}

// experimental method to test the getter mecanism on a node
void receive_get(t_receive *x)
{
	TTNodePtr	p_node;
	long		argc;
	t_atom		*argv;

	if(!x->lk_nodes->isEmpty()){

		// for each node of the selection
		for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next()){

			// get a node from the selection
			x->lk_nodes->current().get(0,(TTPtr*)&p_node);

			// get the value of the node
			jamoma_node_attribute_get(p_node, jps_value, &argc, &argv);

			// get the OSCAddress of the node (in case we use * inside the x->attrname)
			// and output data
			outlet_anything(x->outlet, jamoma_node_OSC_address(p_node), argc, argv);

			// free memory allocated inside the get property method
			free(argv);
		}
	}
}

// This method his called by each observer attached to a node.
// Read the TTNode file to get info about life cycle observers mecanism
void receive_node_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv)
{
	long flag = atom_getlong(&argv[0]);

	post("node destruction : %s %d", mess->s_name, flag);

	/*TTValue	c(observingObject);
	TTValue	v;
	TTErr	err;

	err = x->lk_nodes->findEquals(c, v);
	 */
}

// This method his called by each observer attached to an attibute of the node.
// Read the TTNode file to get info about attribute observers mecanism
void receive_node_attribute_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv)
{
	//object_post((t_object *)x, "jcom.receive : %s", mess->s_name);

	if(!x->callback){
		//object_post((t_object *)x, "external : %d", x);
		outlet_anything(x->outlet, (t_symbol *)mess, argc, argv);
	}
	else
		;//object_post((t_object *)x, "internal : %d", x);
}

void receive_remove(t_receive *x)
{
	TTObjectPtr oldAttrCallback;
	TTObjectPtr oldLifeCallback;
	TTNodePtr p_node;

	// if there is a selection, remove Observers
	if(x->lk_nodes){

		x->lk_attr_observer->begin();
		x->lk_life_observer->begin();
		for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next()){

			// get a node of the selection
			x->lk_nodes->current().get(0,(TTPtr*)&p_node);

			// get the observer relative to this node
			x->lk_attr_observer->current().get(0,(TTPtr*)&oldAttrCallback);
			x->lk_life_observer->current().get(0,(TTPtr*)&oldLifeCallback);

			// remove all the observers
			// TODO : remove the other attribute observers
			jamoma_node_attribute_observer_remove(p_node, jps_value, oldAttrCallback);
			jamoma_node_observer_remove(p_node, oldLifeCallback);

			x->lk_attr_observer->next();
			x->lk_life_observer->next();
		}
	}

	delete x->lk_nodes;
	delete x->lk_attr_observer;
	delete x->lk_life_observer;

	//object_method(g_receivemaster_object, jps_remove, x->attr_name, x);
}

// This method is called by jcom.receivemaster
// In reponse, we figure out if we should send the data to our outlet
void receive_dispatch(t_receive *x, t_symbol *msg, long argc, t_atom *argv)
{
	if(x->callback)
		x->callback(x->baton,  msg, argc, argv);	// call the registered callback on the object that we're instantiated inside of
	else
		outlet_anything(x->outlet, msg, argc, argv);
}

//	When we are inside of another external, we need a way to transmit messages
//	to it. This function sets up another callback, which can call a function
//	in that external to transmit the message.
void receive_setcallback(t_receive *x, void *callback, void *arg)
{
	x->callback = (t_receive_obex_callback)callback;
	x->baton = arg;
}<commit_msg>{ Adding : jcom.receive can observe the global node directory for creation or destruction notification}<commit_after>/*
 * jcom.receive
 * External for Jamoma: receive messages from remote
 * By Trond Lossius & Tim Place, Copyright � 2006
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "Jamoma.h"

/** Receive Object */
typedef struct _receive{
	t_object					ob;					///< REQUIRED: Our object
	void						*address_out;		///< outlet used to output address of received data
	void						*data_out;			///< outlet used to output received data
	t_symbol					*attr_name;			///< ATTRIBUTE: the name of the jcom.receive (/address:attribute)
	t_symbol					*_address;			///< the address to bind
	t_symbol					*_attribute;			///< the attribute to bind (default : value)
	bool						enable;				///< if false, received data won't be output without unregistered attribute observers (default true).
	TTListPtr					lk_nodes;			///< a pointer to a selection of nodes of the tree
	TTListPtr					lk_attr_observer;	///< a pointer to each created attribute observers
	TTObjectPtr					life_observer;		///< a pointer to a life cycle observer
} t_receive;

// Prototypes
void		*receive_new(t_symbol *s, long argc, t_atom *argv);
void		receive_free(t_receive *x);
void		receive_assist(t_receive *x, void *b, long msg, long arg, char *dst);

t_max_err 	receive_setname(t_receive *x, void *attr, long argc, t_atom *argv);

void		receive_bind(t_receive *x);
void 		receive_remove(t_receive *x);
void		receive_directory_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv);
void		receive_node_attribute_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv);

// ask the value to the node
void		receive_get(t_receive *x);

// enable/disable outputs without unregistered attributes observers
void		receive_enable(t_receive *x, long e);

// Globals
static t_class		*s_receive_class;					// Required: Global pointer the jcom.receive class

/************************************************************************************/

void receive_initclass()
{
	long attrflags = 0;
	t_class *c;
	t_object *attr;

	// Define our class
	c = class_new(	"jcom.receive",
					(method)receive_new,
					(method)receive_free,
					sizeof(t_receive),
					(method)0L,
					A_GIMME,
					0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)receive_directory_callback,		"receive_directory_callback",		A_CANT, 0);
	class_addmethod(c, (method)receive_node_attribute_callback,	"receive_node_attribute_callback",	A_CANT, 0);
    class_addmethod(c, (method)receive_assist,					"assist",							A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout,				"dumpout",							A_CANT, 0);

	// ask the value to the node
	class_addmethod(c, (method)receive_get,						"bang",								0);

	// enable/disable outputs without unregistered attributes observers
	class_addmethod(c, (method)receive_enable,					"int",								A_LONG,	0);

	// ATTRIBUTE: name
	attr = attr_offset_new("name", _sym_symbol, attrflags,
		(method)0, (method)receive_setname, calcoffset(t_receive, attr_name));
	class_addattr(c, attr);

	// Finalize our class
	class_register(CLASS_BOX, c);
	s_receive_class = c;
}

/************************************************************************************/
// Object Life

// Create
void *receive_new(t_symbol *s, long argc, t_atom *argv)
{
	long		attrstart = attr_args_offset(argc, argv);		// support normal arguments
	t_receive	*x = (t_receive *)object_alloc(s_receive_class);

	if(x){
		x->address_out = outlet_new(x,NULL);		// anything outlet
		x->data_out = outlet_new(x, NULL);			// anything outlet

		x->attr_name = NULL;
		x->_address = NULL;
		x->_attribute = NULL;
		x->enable = true;

		x->lk_nodes = NULL;
		x->lk_attr_observer = NULL;

		//attr_args_process(x, argc, argv);			// handle attribute args

		// If no name was specified as an attribute
		if(x->attr_name == NULL){
			if(attrstart > 0)
				x->attr_name = atom_getsym(argv);
			else
				x->attr_name = SymbolGen("jcom.receive no arg specified");

			receive_bind(x);
		}
	}
	return x;
}

// Destroy
void receive_free(t_receive *x)
{
	;
}

/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void receive_assist(t_receive *x, void *b, long msg, long arg, char *dst)
{
	if(msg==1) 	// Inlets
		strcpy(dst, "(signal) input to the module");
	else if(msg==2){ // Outlets
		if(arg == 0)
			strcpy(dst, "output from remote");
		else
			strcpy(dst, "dumpout");
	}
}

// ATTRIBUTE: name
t_max_err receive_setname(t_receive *x, void *attr, long argc, t_atom *argv)
{
	t_symbol *arg = atom_getsym(argv);

	if(x->attr_name != arg){
		receive_remove(x);
		x->attr_name = arg;
		receive_bind(x);
	}
	return MAX_ERR_NONE;
}

void receive_bind(t_receive *x)
{
	TTSymbolPtr oscAddress_parent, oscAddress_name, oscAddress_instance, oscAddress_attribute, oscAddress_noAttribute;
	TTObjectPtr newAttrCallback;
	TTList		lk_selection;
	TTNodePtr	p_node;
	TTErr		err = kTTErrGeneric;

	x->lk_nodes = new TTList();
	x->lk_attr_observer = new TTList();

	if(x->attr_name->s_name[0] == C_SEPARATOR){
		if(jamoma_directory){

			// 0. split the name in address part and attribute
			splitOSCAddress(TT(x->attr_name->s_name), &oscAddress_parent, &oscAddress_name, &oscAddress_instance, &oscAddress_attribute);
			mergeOSCAddress(&oscAddress_noAttribute, oscAddress_parent, oscAddress_name, oscAddress_instance, NO_ATTRIBUTE);
			x->_address = SymbolGen((char*)oscAddress_noAttribute->getCString());

			if(oscAddress_attribute != NO_ATTRIBUTE)
				x->_attribute = SymbolGen((char*)oscAddress_attribute->getCString());
			else
				x->_attribute = jps_value;

			// observe for node creation or destruction
			if((x->_attribute == gensym("created")) || (x->_attribute == gensym("destroyed")))
			{
				jamoma_directory_observer_add(x->_address, (t_object*)x, gensym("receive_directory_callback"), &x->life_observer);
			}
			// observe for node attribute changes
			else
			{
				// 1. look for node(s) into the directory
				err = jamoma_directory->Lookup(TT(x->_address->s_name), lk_selection, &p_node);

				// 2. start attribute observation on each existing node of the selection
				if(!err){

					x->lk_nodes->merge(lk_selection);

					for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next())
					{
						// get a node from the selection
						x->lk_nodes->current().get(0,(TTPtr*)&p_node);

						// prepare the callback mecanism to
						// be notified about changing value attribute
						jamoma_node_attribute_observer_add(p_node, x->_attribute, (t_object*)x, gensym("receive_node_attribute_callback"), &newAttrCallback);
						x->lk_attr_observer->append(new TTValue((TTPtr)newAttrCallback));
					}
				}

				// 3. observe any creation or destruction below the attr_name address
				jamoma_directory_observer_add(x->_address, (t_object*)x, gensym("receive_directory_callback"), &x->life_observer);
			}
		}
	}
}

// ask the value to the node
void receive_get(t_receive *x)
{
	TTNodePtr	p_node;
	TTString	fullAddress;
	long		argc;
	t_atom		*argv;

	if(!x->lk_nodes->isEmpty()){

		// for each node of the selection
		for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next()){

			// get a node from the selection
			x->lk_nodes->current().get(0,(TTPtr*)&p_node);

			// get the value of the node
			jamoma_node_attribute_get(p_node, x->_attribute, &argc, &argv);

			// output the OSCAddress of the node (in case we use * inside the x->attrname)
			fullAddress = jamoma_node_OSC_address(p_node)->s_name;
			if(x->_attribute != jps_value){
				fullAddress += C_PROPERTY;
				fullAddress += x->_attribute->s_name;
			}
			outlet_anything(x->address_out, gensym((char*)fullAddress.data()), 0, NULL);

			// then output data
			outlet_anything(x->data_out, _sym_nothing, argc, argv);

			// free memory allocated inside the get property method
			sysmem_freeptr(argv);
		}
	}
}

// enable/disable outputs without unregistered attributes observers
void receive_enable(t_receive *x, long e)
{
	x->enable = e > 0;
}

// This method his called the jcom.receive observer attached to the directory.
// Read the TTNodeDirectory file to get info about life cycle observers mecanism
void receive_directory_callback(t_receive *x, t_symbol *oscAddress, long argc, t_atom *argv)
{
	TTObjectPtr newAttrCallback;
	TTList		lk_selection;
	TTNodePtr	p_node;
	TTErr		err = kTTErrGeneric;
	long		flag = atom_getlong(&argv[0]);

	if(flag == kAddressCreated){

		//post("jcom.receive %s observe a node creation at %s", x->attr_name->s_name, oscAddress->s_name);

		// check the oscAddress into the directory to be sure that this node exist
		if(oscAddress->s_name[0] == C_SEPARATOR)
			if(jamoma_directory)
				err = jamoma_directory->getTTNodeForOSC(TT(oscAddress->s_name), &p_node);

		if(!err){

			if(x->_attribute == gensym("created"))
			{
				// output the OSCAddress of the new node
				outlet_anything(x->address_out, oscAddress, 0, NULL);
			}
			else
			{
				// add the node to the selection
				x->lk_nodes->append(new TTValue((TTPtr)p_node));

				// start attribute observation on the node
				jamoma_node_attribute_observer_add(p_node, x->_attribute, (t_object*)x, gensym("receive_node_attribute_callback"), &newAttrCallback);
				x->lk_attr_observer->append(new TTValue((TTPtr)newAttrCallback));
			}
		}
	}
	else{

		//post("jcom.receive %s observe a node destruction at %s", x->attr_name->s_name, oscAddress->s_name);

		if(x->_attribute == gensym("destroyed"))
		{
			// output the OSCAddress of the old node
			outlet_anything(x->address_out, oscAddress, 0, NULL);
		}
		else
		{
			// remove the node from the selection
			x->lk_nodes->remove(p_node);
		}
	}
}

// This method his called by each observer attached to an attribute of the node.
// Read the TTNode file to get info about attribute observers mecanism
void receive_node_attribute_callback(t_receive *x, t_symbol *mess, long argc, t_atom *argv)
{
	if(x->enable){
		// output the OSCAddress of the node (in case we use * inside the x->attrname)
		outlet_anything(x->address_out, (t_symbol *)mess, 0, NULL);

		// then output data
		outlet_anything(x->data_out, _sym_nothing, argc, argv);
	}
}

void receive_remove(t_receive *x)
{
	TTObjectPtr oldAttrCallback;
	TTNodePtr p_node;

	// if there is a selection, remove Observers
	if(x->lk_nodes){

		x->lk_attr_observer->begin();
		for(x->lk_nodes->begin(); x->lk_nodes->end(); x->lk_nodes->next()){

			// get a node of the selection
			x->lk_nodes->current().get(0,(TTPtr*)&p_node);

			// get the observer relative to this node
			x->lk_attr_observer->current().get(0,(TTPtr*)&oldAttrCallback);

			// remove all the observers
			jamoma_node_attribute_observer_remove(p_node, x->_attribute, oldAttrCallback);

			x->lk_attr_observer->next();
		}
	}

	delete x->lk_nodes;
	delete x->lk_attr_observer;

	jamoma_directory_observer_remove(x->attr_name, x->life_observer);
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 SeNDA
 *
 * 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.
 *
 */
/**
 * FILE Bundle.cpp
 * AUTHOR Blackcatn13
 * DATE Jun 15, 2015
 * VERSION 1
 * This file contains the Bundle class implementation.
 */

#include "Bundle/Bundle.h"
#include <string>
#include <vector>
#include <utility>
#include <sstream>
#include "Bundle/PrimaryBlock.h"
#include "Bundle/CanonicalBlock.h"
#include "Bundle/MetadataExtensionBlock.h"
#include "Bundle/Block.h"
#include "Bundle/PayloadBlock.h"
#include "Utils/TimestampManager.h"
#include "Utils/SDNV.h"
#include "Utils/Logger.h"

Bundle::Bundle(const std::string &rawData)
    : m_raw(rawData),
      m_primaryBlock(nullptr),
      m_payloadBlock(nullptr) {
  /**
   * A bundle is formed by a PrimaryBlock, and other blocks.
   * In this other blocks one of it must be a PayloadBlock.
   */
  LOG(35) << "New Bundle from raw Data";
  // First generate a PrimaryBlock with the data.
  LOG(35) << "Generating Primary Block";
  try {
    m_primaryBlock = std::shared_ptr<PrimaryBlock>(new PrimaryBlock(rawData));
    m_blocks.push_back(m_primaryBlock);
    // Skip the PrimaryBlock
    std::string data = rawData.substr(m_primaryBlock->getLength());
    // We now can start to generate the known blocks.
    std::shared_ptr<Block> b;
    while (data.size() != 0) {
      switch (static_cast<BlockTypes>(data[0])) {
        case BlockTypes::PAYLOAD_BLOCK: {
          // Check if another payload block is present
          if (m_payloadBlock == nullptr) {
            LOG(35) << "Generating Payload Block";
            b = std::shared_ptr<PayloadBlock>(new PayloadBlock(data, true));
            m_payloadBlock = std::static_pointer_cast<PayloadBlock>(b);
          } else {
            throw BundleCreationException(
                "[Bundle] More than one payload found");
          }
          break;
        }
        case BlockTypes::METADATA_EXTENSION_BLOCK: {
          // This is an abstraction of the metadata block, so we need to create
          // a derived block of it.
          LOG(35) << "Generating Metadata Extension Block";
          b = std::shared_ptr<MetadataExtensionBlock>(
              new MetadataExtensionBlock(data));
          break;
        }
        default: {
          LOG(35) << "Generating Canonical Block";
          b = std::shared_ptr<CanonicalBlock>(new CanonicalBlock(data));
          break;
        }
      }
      m_blocks.push_back(b);
      size_t blockSize = b->getLength();
      if (blockSize <= 0)
        throw BundleCreationException("[Bundle] Bad raw format");
      data = data.substr(blockSize);
    }
    std::vector<std::shared_ptr<Block>>::reverse_iterator finalBlock = m_blocks
        .rbegin();
    if (!std::static_pointer_cast<CanonicalBlock>(*finalBlock)->checkProcFlag(
        BlockControlFlags::LAST_BLOCK)) {
      throw BundleCreationException("[Bundle] Last block not marked as such");
    }
  } catch (const BlockConstructionException &e) {
    throw BundleCreationException(e.what());
  } catch (const std::exception &e) {
    throw BundleCreationException("[Bundle] Bad raw format");
  }
}

Bundle::Bundle(std::string origin, std::string destination, std::string payload)
    : m_raw() {
  LOG(34) << "Generating new bundle with parameters [Source: " << origin
          << "][Destination: " << destination << "][Payload: " << payload
          << "]";
  TimestampManager *tm = TimestampManager::getInstance();
  std::pair<uint64_t, uint64_t> timestampValue = tm->getTimestamp();
  m_primaryBlock = std::shared_ptr<PrimaryBlock>(
      new PrimaryBlock(origin, destination, timestampValue.first,
                       timestampValue.second));
  m_payloadBlock = std::shared_ptr<PayloadBlock>(new PayloadBlock(payload));
  m_blocks.push_back(m_primaryBlock);
  m_blocks.push_back(m_payloadBlock);
}

Bundle::~Bundle() {
  LOG(36) << "Deleting Bundle";
}

std::string Bundle::getRaw() {
  return m_raw;
}

std::string Bundle::toRaw() {
  LOG(36) << "Generating bundle in raw format";
  std::string raw = m_raw;
  if (raw == "") {
    std::stringstream ss;
    LOG(36) << "Getting the primary block in raw";
    std::vector<std::shared_ptr<Block>>::reverse_iterator finalBlock = m_blocks
        .rbegin();
    std::static_pointer_cast<CanonicalBlock>(*finalBlock)->setProcFlag(
        BlockControlFlags::LAST_BLOCK);
    for (std::vector<std::shared_ptr<Block>>::iterator it = m_blocks.begin();
        it != m_blocks.end(); ++it) {
      LOG(36) << "Getting the next block in raw";
      ss << (*it)->toRaw();
    }
    raw = ss.str();
  }
  return raw;
}

std::shared_ptr<PrimaryBlock> Bundle::getPrimaryBlock() {
  return m_primaryBlock;
}

std::shared_ptr<PayloadBlock> Bundle::getPayloadBlock() {
  return m_payloadBlock;
}

std::vector<std::shared_ptr<Block>> Bundle::getBlocks() {
  return m_blocks;
}

void Bundle::addBlock(std::shared_ptr<CanonicalBlock> newBlock) {
// Check if the block type is a PayloadBlock
// only one can be present into a bundle.
  LOG(37) << "Adding new Block to the bundle";
  if (newBlock->getBlockType()
      != static_cast<uint8_t>(BlockTypes::PAYLOAD_BLOCK)) {
    m_blocks.push_back(newBlock);
  } else {
    LOG(3) << "Some one is trying to add another Payload block";
    throw BundleException("[Bundle] a paylod block is present");
  }
}

std::string Bundle::getId() {
  return m_primaryBlock->getSource() + m_primaryBlock->getCreationTimestamp()
      + m_primaryBlock->getCreationTimestampSeqNumber();
}
<commit_msg>Fixes Bundle getId implementation.<commit_after>/*
 * Copyright (c) 2015 SeNDA
 *
 * 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.
 *
 */
/**
 * FILE Bundle.cpp
 * AUTHOR Blackcatn13
 * DATE Jun 15, 2015
 * VERSION 1
 * This file contains the Bundle class implementation.
 */

#include "Bundle/Bundle.h"
#include <string>
#include <vector>
#include <utility>
#include <sstream>
#include "Bundle/PrimaryBlock.h"
#include "Bundle/CanonicalBlock.h"
#include "Bundle/MetadataExtensionBlock.h"
#include "Bundle/Block.h"
#include "Bundle/PayloadBlock.h"
#include "Utils/TimestampManager.h"
#include "Utils/SDNV.h"
#include "Utils/Logger.h"

Bundle::Bundle(const std::string &rawData)
    : m_raw(rawData),
      m_primaryBlock(nullptr),
      m_payloadBlock(nullptr) {
  /**
   * A bundle is formed by a PrimaryBlock, and other blocks.
   * In this other blocks one of it must be a PayloadBlock.
   */
  LOG(35) << "New Bundle from raw Data";
  // First generate a PrimaryBlock with the data.
  LOG(35) << "Generating Primary Block";
  try {
    m_primaryBlock = std::shared_ptr<PrimaryBlock>(new PrimaryBlock(rawData));
    m_blocks.push_back(m_primaryBlock);
    // Skip the PrimaryBlock
    std::string data = rawData.substr(m_primaryBlock->getLength());
    // We now can start to generate the known blocks.
    std::shared_ptr<Block> b;
    while (data.size() != 0) {
      switch (static_cast<BlockTypes>(data[0])) {
        case BlockTypes::PAYLOAD_BLOCK: {
          // Check if another payload block is present
          if (m_payloadBlock == nullptr) {
            LOG(35) << "Generating Payload Block";
            b = std::shared_ptr<PayloadBlock>(new PayloadBlock(data, true));
            m_payloadBlock = std::static_pointer_cast<PayloadBlock>(b);
          } else {
            throw BundleCreationException(
                "[Bundle] More than one payload found");
          }
          break;
        }
        case BlockTypes::METADATA_EXTENSION_BLOCK: {
          // This is an abstraction of the metadata block, so we need to create
          // a derived block of it.
          LOG(35) << "Generating Metadata Extension Block";
          b = std::shared_ptr<MetadataExtensionBlock>(
              new MetadataExtensionBlock(data));
          break;
        }
        default: {
          LOG(35) << "Generating Canonical Block";
          b = std::shared_ptr<CanonicalBlock>(new CanonicalBlock(data));
          break;
        }
      }
      m_blocks.push_back(b);
      size_t blockSize = b->getLength();
      if (blockSize <= 0)
        throw BundleCreationException("[Bundle] Bad raw format");
      data = data.substr(blockSize);
    }
    std::vector<std::shared_ptr<Block>>::reverse_iterator finalBlock = m_blocks
        .rbegin();
    if (!std::static_pointer_cast<CanonicalBlock>(*finalBlock)->checkProcFlag(
        BlockControlFlags::LAST_BLOCK)) {
      throw BundleCreationException("[Bundle] Last block not marked as such");
    }
  } catch (const BlockConstructionException &e) {
    throw BundleCreationException(e.what());
  } catch (const std::exception &e) {
    throw BundleCreationException("[Bundle] Bad raw format");
  }
}

Bundle::Bundle(std::string origin, std::string destination, std::string payload)
    : m_raw() {
  LOG(34) << "Generating new bundle with parameters [Source: " << origin
          << "][Destination: " << destination << "][Payload: " << payload
          << "]";
  TimestampManager *tm = TimestampManager::getInstance();
  std::pair<uint64_t, uint64_t> timestampValue = tm->getTimestamp();
  m_primaryBlock = std::shared_ptr<PrimaryBlock>(
      new PrimaryBlock(origin, destination, timestampValue.first,
                       timestampValue.second));
  m_payloadBlock = std::shared_ptr<PayloadBlock>(new PayloadBlock(payload));
  m_blocks.push_back(m_primaryBlock);
  m_blocks.push_back(m_payloadBlock);
}

Bundle::~Bundle() {
  LOG(36) << "Deleting Bundle";
}

std::string Bundle::getRaw() {
  return m_raw;
}

std::string Bundle::toRaw() {
  LOG(36) << "Generating bundle in raw format";
  std::string raw = m_raw;
  if (raw == "") {
    std::stringstream ss;
    LOG(36) << "Getting the primary block in raw";
    std::vector<std::shared_ptr<Block>>::reverse_iterator finalBlock = m_blocks
        .rbegin();
    std::static_pointer_cast<CanonicalBlock>(*finalBlock)->setProcFlag(
        BlockControlFlags::LAST_BLOCK);
    for (std::vector<std::shared_ptr<Block>>::iterator it = m_blocks.begin();
        it != m_blocks.end(); ++it) {
      LOG(36) << "Getting the next block in raw";
      ss << (*it)->toRaw();
    }
    raw = ss.str();
  }
  return raw;
}

std::shared_ptr<PrimaryBlock> Bundle::getPrimaryBlock() {
  return m_primaryBlock;
}

std::shared_ptr<PayloadBlock> Bundle::getPayloadBlock() {
  return m_payloadBlock;
}

std::vector<std::shared_ptr<Block>> Bundle::getBlocks() {
  return m_blocks;
}

void Bundle::addBlock(std::shared_ptr<CanonicalBlock> newBlock) {
// Check if the block type is a PayloadBlock
// only one can be present into a bundle.
  LOG(37) << "Adding new Block to the bundle";
  if (newBlock->getBlockType()
      != static_cast<uint8_t>(BlockTypes::PAYLOAD_BLOCK)) {
    m_blocks.push_back(newBlock);
  } else {
    LOG(3) << "Some one is trying to add another Payload block";
    throw BundleException("[Bundle] a paylod block is present");
  }
}

std::string Bundle::getId() {
  std::stringstream ss;
  ss << m_primaryBlock->getSource() << m_primaryBlock->getCreationTimestamp()
     << m_primaryBlock->getCreationTimestampSeqNumber();
  return ss.str();
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param expression: a vector of strings;
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        if (expression.empty()) {
            return 0;
        }
        vector<string> postfix;
        infixToPostfix(expression, postfix);
        return evalPostfixExpression(postfix);
    }

    // Convert Infix to Postfix Expression.
    void infixToPostfix(vector<string>& infix, vector<string>& postfix) {
        stack<string> s;
        for (auto tok : infix) {
            if (atoi(tok.c_str())) {
                postfix.push_back(tok);
            }
            else if (tok == "(") {
                s.push(tok);
            }
            else if (tok == ")") {
                while (!s.empty()) {
                    tok = s.top();
                    s.pop();
                    if (tok == "(")
                        break;
                    postfix.push_back(tok);
                }
            } else {
                while(!s.empty() && precedence(tok) <= precedence(s.top())) {
                    postfix.push_back(s.top());
                    s.pop();
                }
                s.push(tok);
            }
        }
        while (!s.empty()) {
            postfix.push_back(s.top());
            s.pop();
        }
    }

    int precedence(string x) {
        if(x == "(") {
            return 0;
        }
        else if(x == "+" || x == "-") {
            return 1;
        }
        else if(x == "*" || x== "/") {
            return 2;
        }
        return 3;
    }

    // Evaluate Postfix Expression.
    int evalPostfixExpression(vector<string> &postfix) {
        if (postfix.empty()) {
            return 0;
        }
        stack<string> s;
        for(auto& tok : postfix) {
            if(!is_operator(tok)) {
                s.push(tok);
            }
            else {
                int y = stoi(s.top());
                s.pop();
                int x = stoi(s.top());
                s.pop();
                if(tok[0] == '+') {
                    x += y;
                }
                else if (tok[0] == '-') {
                    x -= y;
                }
                else if (tok[0] == '*') {
                    x *= y;
                }
                else {
                    x /= y;
                }
                s.push(to_string(x));
            }
        }
        return stoi(s.top());
    }

    bool is_operator(const string &op) {
        return op.length() == 1 && string("+-*/").find(op) != string::npos;
    }
};<commit_msg>update<commit_after>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param expression: a vector of strings;
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        if (expression.empty()) {
            return 0;
        }
        vector<string> postfix;
        infixToPostfix(expression, postfix);
        return evaluatePostfixExpression(postfix);
    }

    // Convert Infix to Postfix Expression.
    void infixToPostfix(vector<string>& infix, vector<string>& postfix) {
        stack<string> s;
        for (auto tok : infix) {
            if (atoi(tok.c_str())) {
                postfix.push_back(tok);
            }
            else if (tok == "(") {
                s.push(tok);
            }
            else if (tok == ")") {
                while (!s.empty()) {
                    tok = s.top();
                    s.pop();
                    if (tok == "(")
                        break;
                    postfix.push_back(tok);
                }
            } else {
                while(!s.empty() && precedence(tok) <= precedence(s.top())) {
                    postfix.push_back(s.top());
                    s.pop();
                }
                s.push(tok);
            }
        }
        while (!s.empty()) {
            postfix.push_back(s.top());
            s.pop();
        }
    }

    int precedence(string x) {
        if(x == "(") {
            return 0;
        }
        else if(x == "+" || x == "-") {
            return 1;
        }
        else if(x == "*" || x== "/") {
            return 2;
        }
        return 3;
    }

    // Evaluate Postfix Expression.
    int evaluatePostfixExpression(vector<string> &postfix) {
        if (postfix.empty()) {
            return 0;
        }
        stack<string> s;
        for(auto& tok : postfix) {
            if(!is_operator(tok)) {
                s.push(tok);
            }
            else {
                int y = stoi(s.top());
                s.pop();
                int x = stoi(s.top());
                s.pop();
                if(tok[0] == '+') {
                    x += y;
                }
                else if (tok[0] == '-') {
                    x -= y;
                }
                else if (tok[0] == '*') {
                    x *= y;
                }
                else {
                    x /= y;
                }
                s.push(to_string(x));
            }
        }
        return stoi(s.top());
    }

    bool is_operator(const string &op) {
        return op.length() == 1 && string("+-*/").find(op) != string::npos;
    }
};<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param expression: a vector of strings;
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        if (expression.empty()) {
            return 0;
        }
        vector<string> postfix;
        infixToPostfix(expression, postfix);
        return evaluatePostfixExpression(postfix);
    }

    // Convert Infix to Postfix Expression.
    void infixToPostfix(vector<string>& infix, vector<string>& postfix) {
        stack<string> s;
        for (auto tok : infix) {
            if (atoi(tok.c_str())) {
                postfix.push_back(tok);
            }
            else if (tok == "(") {
                s.push(tok);
            }
            else if (tok == ")") {
                while (!s.empty()) {
                    tok = s.top();
                    s.pop();
                    if (tok == "(")
                        break;
                    postfix.push_back(tok);
                }
            } else {
                while(!s.empty() && precedence(tok) <= precedence(s.top())) {
                    postfix.push_back(s.top());
                    s.pop();
                }
                s.push(tok);
            }
        }
        while (!s.empty()) {
            postfix.push_back(s.top());
            s.pop();
        }
    }

    int precedence(string x) {
        if(x == "(") {
            return 0;
        }
        else if(x == "+" || x == "-") {
            return 1;
        }
        else if(x == "*" || x== "/") {
            return 2;
        }
        return 3;
    }

    // Evaluate Postfix Expression.
    int evaluatePostfixExpression(vector<string> &postfix) {
        if (postfix.empty()) {
            return 0;
        }
        stack<string> s;
        for(auto& tok : postfix) {
            if(!is_operator(tok)) {
                s.push(tok);
            }
            else {
                int y = stoi(s.top());
                s.pop();
                int x = stoi(s.top());
                s.pop();
                if(tok[0] == '+') {
                    x += y;
                }
                else if (tok[0] == '-') {
                    x -= y;
                }
                else if (tok[0] == '*') {
                    x *= y;
                }
                else {
                    x /= y;
                }
                s.push(to_string(x));
            }
        }
        return stoi(s.top());
    }

    bool is_operator(const string &op) {
        return op.length() == 1 && string("+-*/").find(op) != string::npos;
    }
};<commit_msg>update<commit_after>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param expression: a vector of strings;
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        if (expression.empty()) {
            return 0;
        }
        vector<string> postfix;
        infixToPostfix(expression, postfix);
        return evaluatePostfixExpression(postfix);
    }

    // Convert Infix to Postfix Expression.
    void infixToPostfix(vector<string>& infix, vector<string>& postfix) {
        stack<string> s;
        for (auto tok : infix) {
            if (atoi(tok.c_str())) {
                postfix.push_back(tok);
            }
            else if (tok == "(") {
                s.push(tok);
            }
            else if (tok == ")") {
                while (!s.empty()) {
                    tok = s.top();
                    s.pop();
                    if (tok == "(") {
                        break;
                    }
                    postfix.push_back(tok);
                }
            } else {
                while(!s.empty() && precedence(tok) <= precedence(s.top())) {
                    postfix.push_back(s.top());
                    s.pop();
                }
                s.push(tok);
            }
        }
        while (!s.empty()) {
            postfix.push_back(s.top());
            s.pop();
        }
    }

    int precedence(string x) {
        if(x == "(") {
            return 0;
        }
        else if(x == "+" || x == "-") {
            return 1;
        }
        else if(x == "*" || x== "/") {
            return 2;
        }
        return 3;
    }

    // Evaluate Postfix Expression.
    int evaluatePostfixExpression(vector<string> &postfix) {
        if (postfix.empty()) {
            return 0;
        }
        stack<string> s;
        for(auto& tok : postfix) {
            if(!is_operator(tok)) {
                s.push(tok);
            }
            else {
                int y = stoi(s.top());
                s.pop();
                int x = stoi(s.top());
                s.pop();
                if(tok[0] == '+') {
                    x += y;
                }
                else if (tok[0] == '-') {
                    x -= y;
                }
                else if (tok[0] == '*') {
                    x *= y;
                }
                else {
                    x /= y;
                }
                s.push(to_string(x));
            }
        }
        return stoi(s.top());
    }

    bool is_operator(const string &op) {
        return op.length() == 1 && string("+-*/").find(op) != string::npos;
    }
};<|endoftext|>