text:
//
// $Id$
//
//
// Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
//
// Copyright 2009 Vanderbilt University - Nashville, TN 37232
//
// 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.
//

#define PWIZ_SOURCE

#include "ChromatogramList_Waters.hpp"

#ifdef PWIZ_READER_WATERS
#include "Reader_Waters_Detail.hpp"
#include "pwiz/utility/misc/SHA1Calculator.hpp"
#include "pwiz/utility/misc/Filesystem.hpp"
#include "pwiz/utility/misc/Std.hpp"
#include <boost/bind.hpp>

namespace pwiz {
namespace msdata {
namespace detail {

using namespace Waters;

PWIZ_API_DECL ChromatogramList_Waters::ChromatogramList_Waters(RawDataPtr rawdata, const Reader::Config& config)
:   rawdata_(rawdata),
    size_(0),
    config_(config),
    indexInitialized_(util::init_once_flag_proxy)
{
}

PWIZ_API_DECL size_t ChromatogramList_Waters::size() const
{
    boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this));
    return size_;
}

PWIZ_API_DECL const ChromatogramIdentity& ChromatogramList_Waters::chromatogramIdentity(size_t index) const
{
    boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this));
    if (index>size_)
        throw runtime_error(("[ChromatogramList_Waters::chromatogramIdentity()] Bad index: "
                            + lexical_cast<string>(index)).c_str());
    return index_[index];
}

PWIZ_API_DECL size_t ChromatogramList_Waters::find(const string& id) const
{
    boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this));

    map<string, size_t>::const_iterator scanItr = idToIndexMap_.find(id);
    if (scanItr == idToIndexMap_.end())
        return size_;
    return scanItr->second;
}

PWIZ_API_DECL ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, bool getBinaryData) const
{
    return chromatogram(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata);
}

PWIZ_API_DECL ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, DetailLevel detailLevel) const
{
    return chromatogram(index, detailLevel, 0.0, 0.0, 0.0);
}

PWIZ_API_DECL ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, DetailLevel detailLevel, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const
{
    boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this));
    if (index>size_)
        throw runtime_error(("[ChromatogramList_Waters::chromatogram()] Bad index: "
                            + lexical_cast<string>(index)).c_str());

    // allocate a new Chromatogram
    IndexEntry& ie = index_[index];
    ChromatogramPtr result = ChromatogramPtr(new Chromatogram);
    if (!result.get())
        throw std::runtime_error("[ChromatogramList_Waters::chromatogram()] Allocation error.");

    result->index = index;
    result->id = ie.id;
    result->set(ie.chromatogramType);

    if (ie.function >= 0)
    {
        PwizPolarityType polarityType = WatersToPwizPolarityType(rawdata_->Info.GetIonMode(ie.function));
        if (polarityType != PolarityType_Unknown)
            result->set(translate(polarityType));
    }

    bool getBinaryData = detailLevel == DetailLevel_FullData;

    switch (ie.chromatogramType)
    {
        case MS_TIC_chromatogram:
        {
            if (detailLevel < DetailLevel_FullMetadata)
                return result;

            map<double, double> fullFileTIC;

            for(int function : rawdata_->FunctionIndexList())
            {
                if (config_.globalChromatogramsAreMs1Only)
                {
                    int msLevel;
                    CVID spectrumType;
                    try { translateFunctionType(WatersToPwizFunctionType(rawdata_->Info.GetFunctionType(function)), msLevel, spectrumType); }
                    catch (...) // unable to translate function type
                    {
                        cerr << "[ChromatogramList_Waters::createIndex] Unable to translate function type \"" + rawdata_->Info.GetFunctionTypeString(rawdata_->Info.GetFunctionType(function)) + "\"" << endl;
                        continue;
                    }

                    if (spectrumType != MS_MS1_spectrum)
                        continue;

                    // heuristic to detect high-energy MSe function
                    if (function == 1)
                    {
                        double collisionEnergy = 0;
                        string collisionEnergyStr = rawdata_->GetScanStat(1, 0, MassLynxScanItem::COLLISION_ENERGY);
                        if (!collisionEnergyStr.empty())
                            collisionEnergy = lexical_cast<double>(collisionEnergyStr);

                        double collisionEnergyFunction1 = 0;
                        string collisionEnergyStrFunction1 = rawdata_->GetScanStat(0, 0, MassLynxScanItem::COLLISION_ENERGY);
                        if (collisionEnergy > collisionEnergyFunction1)
                        {
                            // MSe high energy is pseudo-MS2, exclude from MS1-only TIC
                            continue;
                        }
                    }
                }

                // add current function TIC to full file TIC
                const vector<float>& times = rawdata_->TimesByFunctionIndex()[function];
                const vector<float>& intensities = rawdata_->TicByFunctionIndex()[function];
                for (int i = 0, end = intensities.size(); i < end; ++i)
                    fullFileTIC[times[i]] += intensities[i];
            }

            result->setTimeIntensityArrays(std::vector<double>(), std::vector<double>(), UO_minute, MS_number_of_detector_counts);

            if (getBinaryData)
            {
                BinaryDataArrayPtr timeArray = result->getTimeArray();
                BinaryDataArrayPtr intensityArray = result->getIntensityArray();

                timeArray->data.reserve(fullFileTIC.size());
                intensityArray->data.reserve(fullFileTIC.size());
                for (map<double, double>::iterator itr = fullFileTIC.begin();
                     itr != fullFileTIC.end();
                     ++itr)
                {
                    timeArray->data.push_back(itr->first);
                    intensityArray->data.push_back(itr->second);
                }
            }

            result->defaultArrayLength = fullFileTIC.size();
        }
        break;

        case MS_SRM_chromatogram:
        {
            result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q1, MS_m_z);
            //result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ie.q1, MS_m_z);
            //result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ie.q1, MS_m_z);
            result->precursor.activation.set(MS_CID);

            result->product.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q3, MS_m_z);
            //result->product.isolationWindow.set(MS_isolation_window_lower_offset, ie.q3, MS_m_z);
            //result->product.isolationWindow.set(MS_isolation_window_upper_offset, ie.q3, MS_m_z);

            if (detailLevel < DetailLevel_FullMetadata)
                return result;

            result->setTimeIntensityArrays(std::vector<double>(), std::vector<double>(), UO_minute, MS_number_of_detector_counts);

            vector<float> times;
            vector<float> intensities;
            rawdata_->ChromatogramReader.ReadMRMChromatogram(ie.function, ie.offset, times, intensities);
            result->defaultArrayLength = times.size();

            if (getBinaryData)
            {
                result->getTimeArray()->data.assign(times.begin(), times.end());
                result->getIntensityArray()->data.assign(intensities.begin(), intensities.end());
            }
        }
        break;

        case MS_SIM_chromatogram:
        {
            result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q1, MS_m_z);
            //result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ie.q1, MS_m_z);
            //result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ie.q1, MS_m_z);
            result->precursor.activation.set(MS_CID);

            if (detailLevel < DetailLevel_FullMetadata)
                return result;

            result->setTimeIntensityArrays(std::vector<double>(), std::vector<double>(), UO_minute, MS_number_of_detector_counts);

            vector<float> times;
            vector<float> intensities;
            rawdata_->ChromatogramReader.ReadMRMChromatogram(ie.function, ie.offset, times, intensities);
            result->defaultArrayLength = times.size();

            if (getBinaryData)
            {
                result->getTimeArray()->data.assign(times.begin(), times.end());
                result->getIntensityArray()->data.assign(intensities.begin(), intensities.end());
            }
        }
        break;
    }

    return result;
}

PWIZ_API_DECL void ChromatogramList_Waters::createIndex() const
{
    index_.push_back(IndexEntry());
    IndexEntry& ie = index_.back();
    ie.index = index_.size()-1;
    ie.id = "TIC";
    ie.function = -1;
    ie.chromatogramType = MS_TIC_chromatogram;
    idToIndexMap_[ie.id] = ie.index;

    for(int function : rawdata_->FunctionIndexList())
    {
        int msLevel;
        CVID spectrumType;

        try { translateFunctionType(WatersToPwizFunctionType(rawdata_->Info.GetFunctionType(function)), msLevel, spectrumType); }
        catch(...) // unable to translate function type
        {
            cerr << "[ChromatogramList_Waters::createIndex] Unable to translate function type \"" + rawdata_->Info.GetFunctionTypeString(rawdata_->Info.GetFunctionType(function)) + "\"" << endl;
            continue;
        }

        if (spectrumType != MS_SRM_spectrum && spectrumType != MS_SIM_spectrum)
            continue;

        //rawdata_->Info.GetAcquisitionTimeRange(function, f1, f2);
        //cout << "Time range: " << f1 << " - " << f2 << endl;

        vector<float> precursorMZs, productMZs, intensities;
        rawdata_->Reader.ReadScan(function, 1, precursorMZs, intensities, productMZs);

        if (spectrumType == MS_SRM_spectrum && productMZs.size() != precursorMZs.size())
            throw runtime_error("[ChromatogramList_Waters::createIndex] MRM function " + lexical_cast<string>(function+1) + " has mismatch between product m/z count (" + lexical_cast<string>(productMZs.size()) + ") and precursor m/z count (" + lexical_cast<string>(precursorMZs.size()) + ")");

        for (size_t i=0; i < precursorMZs.size(); ++i)
        {
            index_.push_back(IndexEntry());
            IndexEntry& ie = index_.back();
            ie.index = index_.size()-1;
            ie.function = function;
            ie.offset = i;
            ie.Q1 = precursorMZs[i];

            std::ostringstream oss;

            if (spectrumType == MS_SRM_spectrum)
            {
                ie.Q3 = productMZs[i];
                ie.chromatogramType = MS_SRM_chromatogram;
                oss << polarityStringForFilter((WatersToPwizPolarityType(rawdata_->Info.GetIonMode(ie.function)) == PolarityType_Negative) ? MS_negative_scan : MS_positive_scan) <<
                       "SRM SIC Q1=" << ie.Q1 <<
                       " Q3=" << ie.Q3 <<
                       " function=" << (function + 1) <<
                       " offset=" << ie.offset;
            }
            else
            {
                ie.Q3 = 0;
                ie.chromatogramType = MS_SIM_chromatogram;
                oss << "SIM SIC Q1=" << ie.Q1 <<
                       " function=" << (function + 1) <<
                       " offset=" << ie.offset;
            }

            ie.id = oss.str();
            idToIndexMap_[ie.id] = ie.index;
        }
    }

    size_ = index_.size();
}

} // detail
} // msdata
} // pwiz

#else // PWIZ_READER_WATERS

//
// non-MSVC implementation
//

namespace pwiz {
namespace msdata {
namespace detail {

namespace {const ChromatogramIdentity emptyIdentity;}

size_t ChromatogramList_Waters::size() const {return 0;}
const ChromatogramIdentity& ChromatogramList_Waters::chromatogramIdentity(size_t index) const {return emptyIdentity;}
size_t ChromatogramList_Waters::find(const std::string& id) const {return 0;}
ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, bool getBinaryData) const {return ChromatogramPtr();}
ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, DetailLevel detailLevel) const {return ChromatogramPtr();}
ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, DetailLevel detailLevel, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const {return ChromatogramPtr();}

} // detail
} // msdata
} // pwiz

#endif // PWIZ_READER_WATERS

max_stars_repo_name: poshul/pwiz

max_issues_repo_name: poshul/pwiz

max_forks_repo_name: poshul/pwiz


text:
#ifndef EDIT_HPP_
#define EDIT_HPP_
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// Name        :
// Author      : Avi
// Revision    : $Revision: #18 $
//
// Copyright 2009- ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//
// Description :
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

#include <boost/python.hpp>
#include "Variable.hpp"

class Edit {
public:
   explicit Edit(const boost::python::dict& dict);
   Edit(const boost::python::dict& dict,const boost::python::dict& dict2);
   const std::vector<Variable>& variables() const { return vec_;}
   static std::string to_string() { return "edit";}
   static boost::python::object init(boost::python::tuple args, boost::python::dict kw);
private:
   std::vector<Variable> vec_;
};

#endif

ext: hpp

max_stars_repo_name: mpartio/ecflow

max_issues_repo_name: mpartio/ecflow

max_forks_repo_name: mpartio/ecflow


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.

// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP
#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP

// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
// boost::polygon::point_data -> boost::geometry::point

#include <type_traits>

#include <boost/polygon/polygon.hpp>

#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
namespace traits
{

template <typename CoordinateType>
struct tag<boost::polygon::point_data<CoordinateType> >
{
    typedef point_tag type;
};

template <typename CoordinateType>
struct coordinate_type<boost::polygon::point_data<CoordinateType> >
{
    typedef CoordinateType type;
};

template <typename CoordinateType>
struct coordinate_system<boost::polygon::point_data<CoordinateType> >
{
    typedef cs::cartesian type;
};

template <typename CoordinateType>
struct dimension<boost::polygon::point_data<CoordinateType> >
    : std::integral_constant<std::size_t, 2>
{};

template <typename CoordinateType>
struct access<boost::polygon::point_data<CoordinateType>, 0>
{
    typedef boost::polygon::point_data<CoordinateType> point_type;

    static inline CoordinateType get(point_type const& p)
    {
        return p.x();
    }

    static inline void set(point_type& p, CoordinateType const& value)
    {
        p.x(value);
    }
};

template <typename CoordinateType>
struct access<boost::polygon::point_data<CoordinateType>, 1>
{
    typedef boost::polygon::point_data<CoordinateType> point_type;

    static inline CoordinateType get(point_type const& p)
    {
        return p.y();
    }

    static inline void set(point_type& p, CoordinateType const& value)
    {
        p.y(value);
    }
};

} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP


text:
//
// $Id: Modification.hpp 2453 2011-01-07 21:29:27Z chambm $
//
//
// Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
//
// Copyright 2006 Louis Warschaw Prostate Cancer Center
//   Cedars Sinai Medical Center, Los Angeles, California  90048
// Copyright 2008 Vanderbilt University - Nashville, TN 37232
//
// 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.
//

#ifndef _MODIFICATION_HPP_
#define _MODIFICATION_HPP_

#include "pwiz/utility/misc/Export.hpp"
#include "Peptide.hpp"
#include <string>
#include "pwiz/utility/misc/virtual_map.hpp"
#include <boost/shared_ptr.hpp>

namespace pwiz {
namespace proteome {

/// represents a post-translational modification (PTM)
/// modification formula or masses must be provided at instantiation
class PWIZ_API_DECL Modification
{
    public:

    /// constructs a zero-mass modification (provided for MSVC compatibility)
    Modification();

    Modification(const chemistry::Formula& formula);
    Modification(double monoisotopicDeltaMass,
                 double averageDeltaMass);
    Modification(const Modification&);
    Modification& operator=(const Modification&);
    ~Modification();

    /// returns true iff the mod was constructed with formula
    bool hasFormula() const;

    /// returns the difference formula;
    /// throws runtime_error if hasFormula() = false
    const chemistry::Formula& formula() const;

    double monoisotopicDeltaMass() const;
    double averageDeltaMass() const;

    /// returns true iff delta masses are equal
    bool operator==(const Modification& rhs) const;

    /// returns true iff this mod has smaller delta masses
    bool operator<(const Modification& rhs) const;

    private:
    class Impl;
    boost::shared_ptr<Impl> impl_;
};

/// represents a list of modifications on a single amino acid
class PWIZ_API_DECL ModificationList
    : public std::vector<Modification> // TODO: make virtual wrapper
{
    public:

    ModificationList();
    ModificationList(const Modification& mod);
    ModificationList(const std::vector<Modification>& mods);

    /// returns the sum of the monoisotopic delta masses of all modifications in the list
    double monoisotopicDeltaMass() const;

    /// returns the sum of the average delta masses of all modifications in the list
    double averageDeltaMass() const;

    /// returns true iff the list has equal modifications
    bool operator==(const ModificationList& rhs) const;

    /// returns true iff the list has fewer modifications or one that's lesser than in the rhs list
    bool operator<(const ModificationList& rhs) const;
};

/// maps peptide/protein sequence indexes (0-based) to a modification list
/// * ModificationMap::NTerminus() returns the index for specifying N terminal mods
/// * ModificationMap::CTerminus() returns the index for specifying C terminal mods
class PWIZ_API_DECL ModificationMap
    : public pwiz::util::virtual_map<int, ModificationList>
{
    public:

    ~ModificationMap();

    // bring the const overloads into scope
    using pwiz::util::virtual_map<int, ModificationList>::begin;
    using pwiz::util::virtual_map<int, ModificationList>::end;
    using pwiz::util::virtual_map<int, ModificationList>::rbegin;
    using pwiz::util::virtual_map<int, ModificationList>::rend;
    using pwiz::util::virtual_map<int, ModificationList>::operator[];
    using pwiz::util::virtual_map<int, ModificationList>::equal_range;
    using pwiz::util::virtual_map<int, ModificationList>::find;
    using pwiz::util::virtual_map<int, ModificationList>::lower_bound;
    using pwiz::util::virtual_map<int, ModificationList>::upper_bound;

    static int NTerminus();
    static int CTerminus();

    /// returns the sum of the monoisotopic delta masses of all modifications in the map
    double monoisotopicDeltaMass() const;

    /// returns the sum of the average delta masses of all modifications in the map
    double averageDeltaMass() const;

    /// Returns an iterator pointing to the first element stored in the map. First is defined by the map's comparison operator, Compare.
    virtual iterator begin();

    /// Returns an iterator pointing to the last element stored in the map; in other words, to the off-the-end value.
    virtual iterator end();

    /// Returns a reverse_iterator pointing to the first element stored in the map. First is defined by the map's comparison operator, Compare.
    virtual reverse_iterator rbegin();

    /// Returns a reverse_iterator pointing to the last element stored in the map; in other words, to the off-the-end value).
    virtual reverse_iterator rend();

    /// If an element with the key x exists in the map, then a reference to its associated value is returned. Otherwise the pair x,T() is inserted into the map and a reference to the default object T() is returned.
    virtual mapped_type& operator[](const key_type& x);

    /// Returns the pair (lower_bound(x), upper_bound(x)).
    virtual std::pair<iterator, iterator> equal_range(const key_type& x);

    /// Searches the map for a pair with the key value x and returns an iterator to that pair if it is found. If such a pair is not found the value end() is returned.
    virtual iterator find(const key_type& x);

    /// Returns a reference to the first entry with a key greater than or equal to x.
    virtual iterator lower_bound(const key_type& x);

    /// Returns an iterator for the first entry with a key greater than x.
    virtual iterator upper_bound(const key_type& x);

    /// Erases all elements from the self.
    virtual void clear();

    /// Deletes the map element pointed to by the iterator position.
    virtual void erase(iterator position);

    /// If the iterators start and finish point to the same map and last is reachable from first, all elements in the range [start, finish) are deleted from the map.
    virtual void erase(iterator start, iterator finish);

    /// Deletes the element with the key value x from the map, if one exists. Returns 1 if x existed in the map, 0 otherwise.
    virtual size_type erase(const key_type& x);

    /// If a value_type with the same key as x is not present in the map, then x is inserted into the map. Otherwise, the pair is not inserted.
    virtual std::pair<iterator, bool> insert(const value_type& x);

    /// If a value_type with the same key as x is not present in the map, then x is inserted into the map. Otherwise, the pair is not inserted. A position may be supplied as a hint regarding where to do the insertion. If the insertion is done right after position, then it takes amortized constant time. Otherwise it takes O(log N) time.
    virtual iterator insert(iterator position, const value_type& x);

    /// returns true iff the map has the same modifications
    virtual bool operator==(const ModificationMap& rhs) const;

    /// returns true iff the map has fewer modified positions or one of the positions is less than in the rhs map
    virtual bool operator<(const ModificationMap& rhs) const;

    private:

    ModificationMap();
    ModificationMap(const ModificationMap& other);
    ModificationMap& operator=(const ModificationMap&);
    class Impl;
    boost::shared_ptr<Impl> impl_;
    virtual void swap(ModificationMap&);
    friend class Peptide::Impl; // allow only Peptide::Impl to construct a ModificationMap
};

} // namespace proteome
} // namespace pwiz

#endif // _MODIFICATION_HPP_

max_stars_repo_name: edyp-lab/pwiz-mzdb

max_issues_repo_name: shze/pwizard-deb

max_forks_repo_name: shze/pwizard-deb


text:
#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>
#include <opencv2/opencv.hpp>

#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/exception/all.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <stdlib.h>
#include <amqp.h>

#include "messages.h"

using namespace AmqpClient;
using namespace akkapatterns::daemon;
using namespace boost;
using namespace cv;

void worker() {
  // create the channel and then...
  while (true) {
    // create a channel and bind it to a queue
    Channel::ptr_t channel = Channel::Create();
    channel->BindQueue("image", "amq.direct", "image.key");
    std::string tag = channel->BasicConsume("image", "", true, true, false, 1);

    // consume the request message
    std::cout << "Waiting..." << std::endl;
    Envelope::ptr_t env = channel->BasicConsumeMessage(tag);
    BasicMessage::ptr_t request = env->Message();
    std::string fileName = request->Body();
    std::string replyTo = request->ReplyTo();

    // do the processing
    Mat srcHost = cv::imread(fileName, CV_LOAD_IMAGE_GRAYSCALE);
    gpu::GpuMat *srcGpu = NULL;
    if (gpu::getCudaEnabledDeviceCount() > 0) {
      srcGpu = new gpu::GpuMat();
      srcGpu->upload(srcHost);
      std::cout << "CUDA" << std::endl;
//      srcGpu = NULL;
    }
    while (true) {
      try {
        Mat dstHost;
        Mat kernel;
        Size thumbnail;

        thumbnail.height = 32;
        thumbnail.width = 32;

        if (srcGpu != NULL) {
          // we're CUDA
          gpu::GpuMat dst;
          cv::gpu::threshold(*srcGpu, dst, 128.0, 255.0, CV_THRESH_BINARY);
          cv::gpu::resize(dst, dst, thumbnail);
          dst.download(dstHost);
        } else {
          // we're on CPU
          cv::threshold(srcHost, dstHost, 128.0, 255.0, CV_THRESH_BINARY);
          cv::resize(dstHost, dstHost, thumbnail);
        }

        vector<uchar> buf;
        cv::imencode(".jpeg", dstHost, buf);

        amqp_bytes_t body;
        amqp_basic_properties_t properties;
        body.len = buf.size();
        body.bytes = new uchar[body.len];
        memcpy(body.bytes, buf.data(), body.len);

        BasicMessage::ptr_t response = BasicMessage::Create(body, &properties);
        channel->BasicPublish("", replyTo, response, true);
      } catch (const std::runtime_error&) {
        // The reply queue is gone.
        // The server has disconnected. We stop sending and go back to waiting for a new request.
        std::cout << "Disconnected" << std::endl;
        break;
      } catch (const cv::Exception &e) {
        std::cerr << e.what() << std::endl;
        break;
      }
    }
  }
}

int main() {
  int count = 96;
  try {
    thread_group group;
    for (int i = 0; i < count; i++) group.create_thread(worker);

    std::cout << "Ready..." << std::endl;
    group.join_all();
  } catch (std::runtime_error &e) {
    std::cout << "Error " << e.what() << std::endl;
  }

}

ext: cpp

max_stars_repo_name: rssrujan/akka-patterns

max_issues_repo_name: rssrujan/akka-patterns

max_forks_repo_name: rssrujan/akka-patterns


text:
#pragma once

#include "../base/type.h"
#include "../base/check.h"
#include "../utils/type_traits.hpp"

#include <boost/callable_traits.hpp>
#include "../brigand.hpp"

#ifdef AUTOCXXPY_INCLUDED_PYBIND11
#include <pybind11/stl.h>
#endif

#include <iostream>
#include <type_traits>

#include "./utils.hpp"
#include <functional>

namespace autocxxpy
{
    template <class method_constant, class ret_t, class base_t, class ... Ls, class ... Rs>
    inline constexpr auto wrap_pointer_argument_as_inout_impl(brigand::list<Ls...>, brigand::list <Rs...>)
    {
        namespace ct = boost::callable_traits;
        return [](Ls ... ls, base_t &arg, Rs ... rs)
        {
            constexpr auto method = method_constant::value;
            //using func_t = ct::function_type_t<decltype(method)>;
            //using args_t = wrap<ct::args_t<func_t>, list>;
            //using ret_t = ct::return_type_t<func_t>;
            auto stdmethod = std::function<ct::function_type_t<decltype(method)>>(method);
            if constexpr (std::is_void_v<ret_t>)
            {
                stdmethod(std::forward<Ls>(ls)..., &arg, std::forward<Rs>(rs)...);
                return std::move(arg);
            }
            else
            {
                return append_as_tuple(stdmethod(
                    std::forward<Ls>(ls)...,
                    &arg,
                    std::forward<Rs>(rs)...
                ), std::move(arg));
            }
        };
    }
    template <class method_constant, class ret_t, class base_t, class ... Ls, class ... Rs>
    inline constexpr auto wrap_reference_argument_as_inout_impl(brigand::list<Ls...>, brigand::list <Rs...>)
    {
        namespace ct = boost::callable_traits;
        return [](Ls ... ls, base_t arg, Rs ... rs)
        {
            constexpr auto method = method_constant::value;
            auto stdmethod = std::function<ct::function_type_t<decltype(method)>>(method);
            if constexpr (std::is_void_v<ret_t>)
            {
                stdmethod(std::forward<Ls>(ls)..., arg, std::forward<Rs>(rs)...);
                return arg;
            }
            else
            {
                return append_as_tuple(stdmethod(
                    std::forward<Ls>(ls)...,
                    arg,
                    std::forward<Rs>(rs)...
                ), arg);

            }
        };
    }

    template <class method_constant, size_t index>
    inline constexpr auto wrap_argument_as_inout()
    {
        using namespace brigand;
        namespace ct = boost::callable_traits;

        constexpr auto method = method_constant::value;
        using func_t = ct::function_type_t<decltype(method)>;
        using args_t = wrap<ct::args_t<func_t>, list>;

        if constexpr (check_not_out_of_bound<index, size<args_t>::value>())
        {
            using s = split_at<args_t, std::integral_constant<int, index>>;
            using ls = front<s>;
            using rs = pop_front<back<s>>;
            using arg_t = at<args_t, std::integral_constant<int, index>>;
            using ret_t = ct::return_type_t<func_t>;
            if constexpr (std::is_pointer_v<arg_t>)
            {
                using base_t = std::remove_pointer_t<arg_t>;
                return wrap_pointer_argument_as_inout_impl<method_constant, ret_t, base_t>(ls{}, rs{});
            }
            else
            {
                using base_t = std::remove_reference_t<arg_t>;
                return wrap_reference_argument_as_inout_impl<method_constant, ret_t, base_t>(ls{}, rs{});
            }
        }
    }

    template <class method_constant, class integral_constant>
    struct inout_argument_transform
    {
        using type = inout_argument_transform;
        using value_type = decltype(wrap_argument_as_inout<method_constant, integral_constant::value>());
        static constexpr value_type value = wrap_argument_as_inout<method_constant, integral_constant::value>();
    };
}

max_stars_repo_name: andrewchenshx/vnpy

max_issues_repo_name: andrewchenshx/vnpy

max_forks_repo_name: andrewchenshx/vnpy


text:
#include <common/app/log/LogContext.h>
#include <common/components/worker/queue/UserWorkContainer.h>
#include <common/components/worker/DummyWork.h>
#include <common/components/ComponentInitException.h>
#include <common/components/RegistrationDatagramListener.h>
#include <common/net/message/nodes/RegisterNodeMsg.h>
#include <common/net/message/nodes/RegisterNodeRespMsg.h>
#include <common/net/sock/RDMASocket.h>
#include <common/nodes/LocalNode.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <common/toolkit/NodesTk.h>
#include <components/FileEventLogger.h>
#include <components/ModificationEventFlusher.h>
#include <components/DisposalGarbageCollector.h>
#include <program/Program.h>
#include <session/SessionStore.h>
#include <storage/MetadataEx.h>
#include <toolkit/BuddyCommTk.h>
#include <toolkit/StorageTkEx.h>
#include <boost/format.hpp>
#include "App.h"

#include <array>
#include <mntent.h>
#include <csignal>
#include <fstream>
#include <sstream>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/statfs.h>
#include <blkid/blkid.h>
#include <uuid/uuid.h>

// this magic number is not available on all supported platforms. specifically, rhel5 does not have
// linux/magic.h (which is where this constant is found).
#ifndef EXT3_SUPER_MAGIC
 #define EXT3_SUPER_MAGIC  0xEF53
#endif

#define APP_WORKERS_DIRECT_NUM      1
#define APP_SYSLOG_IDENTIFIER       "congfs-meta"

App::App(int argc, char** argv)
{
   this->argc = argc;
   this->argv = argv;

   this->appResult = APPCODE_NO_ERROR;

   this->cfg = NULL;
   this->netFilter = NULL;
   this->tcpOnlyFilter = NULL;
   this->log = NULL;
   this->mgmtNodes = NULL;
   this->metaNodes = NULL;
   this->storageNodes = NULL;
   this->clientNodes = NULL;
   this->metaCapacityPools = NULL;
   this->targetMapper = NULL;
   this->storageBuddyGroupMapper = NULL;
   this->metaBuddyGroupMapper = NULL;
   this->targetStateStore = NULL;
   this->metaStateStore = NULL;
   this->metaBuddyCapacityPools = NULL;
   this->workQueue = NULL;
   this->commSlaveQueue = NULL;
   this->disposalDir = NULL;
   this->buddyMirrorDisposalDir = NULL;
   this->rootDir = NULL;
   this->metaStore = NULL;
   this->ackStore = NULL;
   this->sessions = NULL;
   this->mirroredSessions = NULL;
   this->nodeOperationStats = NULL;
   this->netMessageFactory = NULL;
   this->inodesPath = NULL;
   this->dentriesPath = NULL;
   this->buddyMirrorInodesPath = NULL;
   this->buddyMirrorDentriesPath = NULL;
   this->dgramListener = NULL;
   this->connAcceptor = NULL;
   this->statsCollector = NULL;
   this->internodeSyncer = NULL;
   this->modificationEventFlusher = NULL;
   this->timerQueue = new TimerQueue(1, 1);
   this->gcQueue = new TimerQueue(1, 1);
   this->buddyResyncer = NULL;

   this->nextNumaBindTarget = 0;
}

App::~App()
{
   // Note: Logging of the common lib classes is not working here, because this is called
   // from class Program (so the thread-specific app-pointer isn't set in this context).

   commSlavesDelete();
   workersDelete();

   SAFE_DELETE(this->buddyResyncer);
   SAFE_DELETE(this->timerQueue);
   SAFE_DELETE(this->modificationEventFlusher);
   SAFE_DELETE(this->internodeSyncer);
   SAFE_DELETE(this->statsCollector);
   SAFE_DELETE(this->connAcceptor);

   streamListenersDelete();

   SAFE_DELETE(this->dgramListener);
   SAFE_DELETE(this->dentriesPath);
   SAFE_DELETE(this->inodesPath);
   SAFE_DELETE(this->buddyMirrorDentriesPath);
   SAFE_DELETE(this->buddyMirrorInodesPath);
   SAFE_DELETE(this->netMessageFactory);
   SAFE_DELETE(this->nodeOperationStats);
   SAFE_DELETE(this->sessions);
   SAFE_DELETE(this->mirroredSessions);
   SAFE_DELETE(this->ackStore);
   if(this->disposalDir && this->metaStore)
      this->metaStore->releaseDir(this->disposalDir->getID() );
   if(this->buddyMirrorDisposalDir && this->metaStore)
      this->metaStore->releaseDir(this->buddyMirrorDisposalDir->getID() );
   if(this->rootDir && this->metaStore)
      this->metaStore->releaseDir(this->rootDir->getID() );
   SAFE_DELETE(this->metaStore);
   SAFE_DELETE(this->commSlaveQueue);
   SAFE_DELETE(this->workQueue);
   SAFE_DELETE(this->clientNodes);
   SAFE_DELETE(this->storageNodes);
   SAFE_DELETE(this->metaNodes);
   SAFE_DELETE(this->mgmtNodes);
   this->localNode.reset();
   SAFE_DELETE(this->metaBuddyCapacityPools);
   SAFE_DELETE(this->storageBuddyGroupMapper);
   SAFE_DELETE(this->metaBuddyGroupMapper);
   SAFE_DELETE(this->targetMapper);
   SAFE_DELETE(this->metaStateStore);
   SAFE_DELETE(this->targetStateStore);
   SAFE_DELETE(this->metaCapacityPools);
   SAFE_DELETE(this->log);
   SAFE_DELETE(this->tcpOnlyFilter);
   SAFE_DELETE(this->netFilter);

   SAFE_DELETE(this->cfg);

   delete timerQueue;

   Logger::destroyLogger();
   closelog();
}

/**
 * Initialize config and run app either in normal mode or in special unit tests mode.
 */
void App::run()
{
   try
   {
      openlog(APP_SYSLOG_IDENTIFIER, LOG_NDELAY | LOG_PID | LOG_CONS, LOG_DAEMON);

      this->cfg = new Config(argc, argv);

      runNormal();
   }
   catch (InvalidConfigException& e)
   {
      std::cerr << std::endl;
      std::cerr << "Error: " << e.what() << std::endl;
      std::cerr << std::endl;
      std::cerr << "[ConGFS Metadata Node Version: " << CONGFS_VERSION << std::endl;
      std::cerr << "Refer to the default config file (/etc/congfs/congfs-meta.conf)" << std::endl;
      std::cerr << "or visit http://www.congfs.com to find out about configuration options.]"
         << std::endl;
      std::cerr << std::endl;

      if(this->log)
         log->logErr(e.what() );

      appResult = APPCODE_INVALID_CONFIG;
      return;
   }
   catch (std::exception& e)
   {
      std::cerr << std::endl;
      std::cerr << "Unrecoverable error: " << e.what() << std::endl;
      std::cerr << std::endl;

      if(this->log)
         log->logErr(e.what() );

      appResult = APPCODE_RUNTIME_ERROR;
      return;
   }
}

/**
 * @throw InvalidConfigException on error
 */
void App::runNormal()
{
   // numa binding (as early as possible)

   if(cfg->getTuneBindToNumaZone() != -1) // -1 means disable binding
   {
      bool bindRes = System::bindToNumaNode(cfg->getTuneBindToNumaZone() );
      if(!bindRes)
         throw InvalidConfigException("Unable to bind to this NUMA zone: " +
            StringTk::intToStr(cfg->getTuneBindToNumaZone() ) );
   }

   // init basic data objects & storage
   NumNodeID localNodeNumID;
   std::string localNodeID;

   // locks working dir => call before anything else that accesses the disk
   const bool targetNew = preinitStorage();

   initLogging();
   checkTargetUUID();
   initLocalNodeIDs(localNodeID, localNodeNumID);
   initDataObjects();
   initBasicNetwork();

   initStorage();
   initXAttrLimit();
   initRootDir(localNodeNumID);
   initDisposalDir();

   registerSignalHandler();

   // prepare ibverbs for forking
   RDMASocket::rdmaForkInitOnce();

   // ACLs need enabled client side XAttrs in order to work.
   if (cfg->getStoreClientACLs() && !cfg->getStoreClientXAttrs() )
      throw InvalidConfigException(
            "Client ACLs are enabled in config file, but extended attributes are not. "
            "ACLs cannot be stored without extended attributes.");

   // detach process
   if(cfg->getRunDaemonized() )
      daemonize();

   // find RDMA interfaces (based on TCP/IP interfaces)

   // note: we do this here, because when we first create an RDMASocket (and this is done in this
   // check), the process opens the verbs device. Recent OFED versions have a check if the
   // credentials of the opening process match those of the calling process (not only the values
   // are compared, but the pointer is checked for equality). Thus, the first open needs to happen
   // after the fork, because we need to access the device in the child process.
   if(cfg->getConnUseRDMA() && RDMASocket::rdmaDevicesExist() )
   {
      bool foundRdmaInterfaces = NetworkInterfaceCard::checkAndAddRdmaCapability(localNicList);
      if (foundRdmaInterfaces)
         localNicList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces}); // re-sort the niclist
   }

   // Find MgmtNode
   bool mgmtWaitRes = waitForMgmtNode();
   if(!mgmtWaitRes)
   { // typically user just pressed ctrl+c in this case
      log->logErr("Waiting for congfs-mgmtd canceled");
      appResult = APPCODE_RUNTIME_ERROR;
      return;
   }

   // retrieve localNodeNumID from management node (if we don't have it yet)
   if(!localNodeNumID)
   { // no local num ID yet => try to retrieve one from mgmt

      bool preregisterRes = preregisterNode(localNodeID, localNodeNumID);
      if(!preregisterRes)
         throw InvalidConfigException("Pre-registration at management node canceled");
   }

   if (!localNodeNumID) // just a sanity check that should never fail
      throw InvalidConfigException("Failed to retrieve numeric local node ID from mgmt");

   // we have all local node data now => init localNode

   initLocalNode(localNodeID, localNodeNumID);
   initLocalNodeNumIDFile(localNodeNumID);

   // Keeps the local node state from the static call to the InternodeSyncer method so we can pass
   // it when we construct the actual object.
   TargetConsistencyState initialConsistencyState;

   bool downloadRes = downloadMgmtInfo(initialConsistencyState);
   if (!downloadRes)
   {
      log->log(1, "Downloading target states from management node failed. Shutting down...");
      appResult = APPCODE_INITIALIZATION_ERROR;
      return;
   }

   // Check for the sessions file. If there is none, it's either the first run, or we crashed so we
   // need a resync.
   bool sessionFilePresent = StorageTk::checkSessionFileExists(metaPathStr);
   if (!targetNew && !sessionFilePresent)
      initialConsistencyState = TargetConsistencyState_NEEDS_RESYNC;

   // init components

   BuddyCommTk::prepareBuddyNeedsResyncState(*mgmtNodes->referenceFirstNode(),
         *metaBuddyGroupMapper, *timerQueue, localNode->getNumID());

   try
   {
      initComponents(initialConsistencyState);
   }
   catch(ComponentInitException& e)
   {
      log->logErr(e.what() );
      log->log(Log_CRITICAL, "A hard error occurred. Shutting down...");
      appResult = APPCODE_INITIALIZATION_ERROR;
      return;
   }

   // restore sessions from last clean shut down
   restoreSessions();

   // log system and configuration info

   logInfos();

   // start component threads and join them

   startComponents();

   // session restore is finished so delete old session files
   // clean shutdown will generate a new session file
   deleteSessionFiles();

   // wait for termination

   joinComponents();

   // clean shutdown (at least no cache loss) => generate a new session file
   if(sessions)
      storeSessions();

   // close all client sessions
   InternodeSyncer::syncClients({}, false);

   log->log(Log_CRITICAL, "All components stopped. Exiting now!");
}

void App::initLogging()
{
   // check absolute log path to avoid chdir() problems
   Path logStdPath(cfg->getLogStdFile() );

   if(!logStdPath.empty() && !logStdPath.absolute())
   {
      throw InvalidConfigException("Path to log file must be absolute");
   }

   Logger::createLogger(cfg->getLogLevel(), cfg->getLogType(), cfg->getLogNoDate(),
         cfg->getLogStdFile(), cfg->getLogNumLines(), cfg->getLogNumRotatedFiles());
   this->log = new LogContext("App");

   if (!cfg->getFileEventLogTarget().empty())
      fileEventLogger.reset(new FileEventLogger(cfg->getFileEventLogTarget()));
}

/**
 * Init basic shared objects like work queues, node stores etc.
 */
void App::initDataObjects()
{
   this->mgmtNodes = new NodeStoreServers(NODETYPE_Mgmt, true);
   this->metaNodes = new NodeStoreServers(NODETYPE_Meta, true);
   this->storageNodes = new NodeStoreServers(NODETYPE_Storage, false);
   this->clientNodes = new NodeStoreClients();

   NicAddressList nicList;

   this->targetMapper = new TargetMapper();
   this->storageNodes->attachTargetMapper(targetMapper);

   this->storageBuddyGroupMapper = new MirrorBuddyGroupMapper(targetMapper);
   this->metaBuddyGroupMapper = new MirrorBuddyGroupMapper();

   this->metaCapacityPools = new NodeCapacityPools(
         false, DynamicPoolLimits(0, 0, 0, 0, 0, 0), DynamicPoolLimits(0, 0, 0, 0, 0, 0) );
   this->metaNodes->attachCapacityPools(metaCapacityPools);

   this->metaBuddyCapacityPools = new NodeCapacityPools(
      false, DynamicPoolLimits(0, 0, 0, 0, 0, 0), DynamicPoolLimits(0, 0, 0, 0, 0, 0) );
   this->metaBuddyGroupMapper->attachMetaCapacityPools(metaBuddyCapacityPools);

   this->targetStateStore = new TargetStateStore(NODETYPE_Storage);
   this->targetMapper->attachStateStore(targetStateStore);

   this->metaStateStore = new TargetStateStore(NODETYPE_Meta);
   this->metaNodes->attachStateStore(metaStateStore);

   this->storagePoolStore = boost::make_unique<StoragePoolStore>(storageBuddyGroupMapper,
                                                                 targetMapper);
   // add newly mapped targets and buddy groups to storage pool store
   this->targetMapper->attachStoragePoolStore(storagePoolStore.get());
   this->storageBuddyGroupMapper->attachStoragePoolStore(storagePoolStore.get());

   this->targetMapper->attachExceededQuotaStores(&exceededQuotaStores);

   this->workQueue = new MultiWorkQueue();
   this->commSlaveQueue = new MultiWorkQueue();

   if(cfg->getTuneUsePerUserMsgQueues() )
      workQueue->setIndirectWorkList(new UserWorkContainer() );

   this->ackStore = new AcknowledgmentStore();

   this->sessions = new SessionStore();
   this->mirroredSessions = new SessionStore();

   this->nodeOperationStats = new MetaNodeOpStats();

   this->isRootBuddyMirrored = false;
}

/**
 * Init basic networking data structures.
 *
 * Note: no RDMA is detected here, because this needs to be done later
 */
void App::initBasicNetwork()
{
   // check if management host is defined
   if(!cfg->getSysMgmtdHost().length() )
      throw InvalidConfigException("Management host undefined");

   // prepare filter for outgoing packets/connections
   this->netFilter = new NetFilter(cfg->getConnNetFilterFile() );
   this->tcpOnlyFilter = new NetFilter(cfg->getConnTcpOnlyFilterFile() );

   // prepare filter for interfaces
   std::string interfacesList = cfg->getConnInterfacesList();
   if(!interfacesList.empty() )
   {
      log->log(Log_DEBUG, "Allowed interfaces: " + interfacesList);
      StringTk::explodeEx(interfacesList, ',', true, &allowedInterfaces);
   }

   // discover local NICs and filter them
   NetworkInterfaceCard::findAllInterfaces(allowedInterfaces, localNicList);

   if(localNicList.empty() )
      throw InvalidConfigException("Couldn't find any usable NIC");

   localNicList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces});

   // prepare factory for incoming messages
   this->netMessageFactory = new NetMessageFactory();
}

/**
 * Load node IDs from disk or generate string ID.
 */
void App::initLocalNodeIDs(std::string& outLocalID, NumNodeID& outLocalNumID)
{
   // load (or generate) nodeID and compare to original nodeID

   Path metaPath(metaPathStr);
   Path nodeIDPath = metaPath / STORAGETK_NODEID_FILENAME;
   StringList nodeIDList; // actually contains only a single line

   bool idPathExists = StorageTk::pathExists(nodeIDPath.str());
   if(idPathExists)
      ICommonConfig::loadStringListFile(nodeIDPath.str().c_str(), nodeIDList);

   if(!nodeIDList.empty() )
      outLocalID = *nodeIDList.begin();

   // auto-generate nodeID if it wasn't loaded

   if(outLocalID.empty() )
      outLocalID = System::getHostname();

   // check for nodeID changes

   StorageTk::checkOrCreateOrigNodeIDFile(metaPathStr, outLocalID);

   // load nodeNumID file
   StorageTk::readNumIDFile(metaPath.str(), STORAGETK_NODENUMID_FILENAME, &outLocalNumID);

   // note: localNodeNumID is still 0 here if it wasn't loaded from the file
}

/**
 * create and attach the localNode object, store numID in storage dir
 */
void App::initLocalNode(std::string& localNodeID, NumNodeID localNodeNumID)
{
   unsigned portUDP = cfg->getConnMetaPortUDP();
   unsigned portTCP = cfg->getConnMetaPortTCP();

   // create localNode object
   localNode = std::make_shared<LocalNode>(NODETYPE_Meta, localNodeID, localNodeNumID, portUDP,
         portTCP, localNicList);

   // attach to metaNodes store
   metaNodes->setLocalNode(this->localNode);
}

/**
 * Store numID file in storage directory
 */
void App::initLocalNodeNumIDFile(NumNodeID localNodeNumID)
{
   StorageTk::createNumIDFile(metaPathStr, STORAGETK_NODENUMID_FILENAME, localNodeNumID.val());
}

/**
 * this contains things that would actually live inside initStorage() but need to be
 * done at an earlier stage (like working dir locking before log file creation).
 *
 * note: keep in mind that we don't have the logger here yet, because logging can only be
 * initialized after the working dir has conn locked within this method.
 *
 * @returns true if there was no storageFormatFile before (target was uninitialized)
 */
bool App::preinitStorage()
{
   Path metaPath(cfg->getStoreMetaDirectory() );
   this->metaPathStr = metaPath.str(); // normalize

   if(metaPath.empty() )
      throw InvalidConfigException("No metadata storage directory specified");

   if(!metaPath.absolute() ) /* (check to avoid problems after chdir later) */
      throw InvalidConfigException("Path to storage directory must be absolute: " + metaPathStr);

   const bool formatFileExists = StorageTk::checkStorageFormatFileExists(metaPathStr);

   if(!cfg->getStoreAllowFirstRunInit() &&
      !formatFileExists)
      throw InvalidConfigException("Storage directory not initialized and "
         "initialization has conn disabled: " + metaPathStr);

   this->pidFileLockFD = createAndLockPIDFile(cfg->getPIDFile() ); // ignored if pidFile not defined

   if(!StorageTk::createPathOnDisk(metaPath, false) )
      throw InvalidConfigException("Unable to create metadata directory: " + metaPathStr +
         " (" + System::getErrString(errno) + ")" );

   this->workingDirLockFD = StorageTk::lockWorkingDirectory(cfg->getStoreMetaDirectory() );
   if (!workingDirLockFD.valid())
      throw InvalidConfigException("Unable to lock working directory: " + metaPathStr);

   return !formatFileExists;
}

void App::initStorage()
{
   // change working dir to meta directory
   int changeDirRes = chdir(metaPathStr.c_str() );
   if(changeDirRes)
   { // unable to change working directory
      throw InvalidConfigException("Unable to change working directory to: " + metaPathStr + " "
         "(SysErr: " + System::getErrString() + ")");
   }

   // storage format file
   if(!StorageTkEx::createStorageFormatFile(metaPathStr) )
      throw InvalidConfigException("Unable to create storage format file in: " +
         cfg->getStoreMetaDirectory() );

   StorageTkEx::checkStorageFormatFile(metaPathStr);

   // dentries directory
   dentriesPath = new Path(META_DENTRIES_SUBDIR_NAME);
   StorageTk::initHashPaths(*dentriesPath,
      META_DENTRIES_LEVEL1_SUBDIR_NUM, META_DENTRIES_LEVEL2_SUBDIR_NUM);

   // buddy mirrored dentries directory
   buddyMirrorDentriesPath = new Path(META_BUDDYMIRROR_SUBDIR_NAME "/" META_DENTRIES_SUBDIR_NAME);
   StorageTk::initHashPaths(*buddyMirrorDentriesPath,
      META_DENTRIES_LEVEL1_SUBDIR_NUM, META_DENTRIES_LEVEL2_SUBDIR_NUM);

   // inodes directory
   inodesPath = new Path(META_INODES_SUBDIR_NAME);
   if(!StorageTk::createPathOnDisk(*this->inodesPath, false) )
      throw InvalidConfigException("Unable to create directory: " +  inodesPath->str() );
   StorageTk::initHashPaths(*inodesPath,
      META_INODES_LEVEL1_SUBDIR_NUM, META_INODES_LEVEL2_SUBDIR_NUM);

   // buddy mirrored inodes directory
   buddyMirrorInodesPath = new Path(META_BUDDYMIRROR_SUBDIR_NAME "/" META_INODES_SUBDIR_NAME);
   if(!StorageTk::createPathOnDisk(*this->buddyMirrorInodesPath, false) )
      throw InvalidConfigException(
         "Unable to create directory: " + buddyMirrorInodesPath->str());
   StorageTk::initHashPaths(*buddyMirrorInodesPath,
      META_INODES_LEVEL1_SUBDIR_NUM, META_INODES_LEVEL2_SUBDIR_NUM);

   // raise file descriptor limit
   if(cfg->getTuneProcessFDLimit() )
   {
      uint64_t oldLimit;

      bool setFDLimitRes = System::incProcessFDLimit(cfg->getTuneProcessFDLimit(), &oldLimit);
      if(!setFDLimitRes)
         log->log(Log_CRITICAL, std::string("Unable to increase process resource limit for "
            "number of file handles. Proceeding with default limit: ") +
            StringTk::uintToStr(oldLimit) + " " +
            "(SysErr: " + System::getErrString() + ")");
   }
}

void App::initXAttrLimit()
{
   // check whether the filesystem supports overly many amounts of xattrs (>64kb list size).
   // of the filesystems we support, this is currently only xfs.
   // also check for filesystems mounted beneath the metadata root dir, if any are found, limit the
   // xattrs too (it's probably not worth it to check the fs types here, since the setup should be
   // rare.)
   if (!cfg->getStoreUseExtendedAttribs())
      return;

   cfg->setLimitXAttrListLength(true);

   struct statfs metaRootStat;

   if (::statfs(cfg->getStoreMetaDirectory().c_str(), &metaRootStat))
   {
      LOG(GENERAL, CRITICAL, "Could not statfs() meta root directory.", sysErr);
      throw InvalidConfigException("Could not statfs() meta root directory.");
   }

   // ext3 and ext4 have the same magic, and are currently the only "safe" filesystems officially
   // supported.
   if (metaRootStat.f_type == EXT3_SUPER_MAGIC)
      cfg->setLimitXAttrListLength(false);
   else
   {
      LOG(GENERAL, NOTICE, "Limiting number of xattrs per inode.");
      return;
   }

   // the metadata root directory does not support overly long xattrs. check for filesystems mounted
   // beneath the metadata root, and enable xattrs limiting if any are found.
   std::string metaRootPath(PATH_MAX, '\0');

   if (!realpath(cfg->getStoreMetaDirectory().c_str(), &metaRootPath[0]))
   {
      LOG(GENERAL, CRITICAL, "Could not check meta root dir for xattr compatibility.", sysErr);
      throw InvalidConfigException("Could not check meta root dir for xattr compatibility.");
   }

   metaRootPath.resize(strlen(metaRootPath.c_str()));
   metaRootPath += '/';

   FILE* mounts = setmntent("/etc/mtab", "r");
   if (!mounts)
   {
      LOG(GENERAL, CRITICAL, "Could not open mtab.", sysErr);
      throw InvalidConfigException("Could not open mtab.");
   }

   struct mntent mountBuf;
   char buf[PATH_MAX * 4];

   struct mntent* mount;

   errno = 0;
   while ((mount = getmntent_r(mounts, &mountBuf, buf, sizeof(buf))))
   {
      if (strstr(mount->mnt_dir, metaRootPath.c_str()) == mount->mnt_dir)
      {
         cfg->setLimitXAttrListLength(true);
         break;
      }
   }

   endmntent(mounts);

   if (errno)
   {
      LOG(GENERAL, ERR, "Could not read mtab.", sysErr);
      throw InvalidConfigException("Could not read mtab.");
   }

   if (cfg->getLimitXAttrListLength())
      LOG(GENERAL, NOTICE, "Limiting number of xattrs per inode.");
}

void App::initRootDir(NumNodeID localNodeNumID)
{
   // try to load root dir from disk (through metaStore) or create a new one

   this->metaStore = new MetaStore();

   // try to reference root directory with buddy mirroring
   rootDir = this->metaStore->referenceDir(META_ROOTDIR_ID_STR, true, true);

   // if that didn't work try to reference non-buddy-mirrored root dir
   if (!rootDir)
   {
      rootDir = this->metaStore->referenceDir(META_ROOTDIR_ID_STR, false, true);
   }

   if(rootDir)
   { // loading succeeded (either with or without mirroring => init rootNodeID
      this->log->log(Log_NOTICE, "Root directory loaded.");

      NumNodeID rootDirOwner = rootDir->getOwnerNodeID();
      bool rootIsBuddyMirrored = rootDir->getIsBuddyMirrored();

      // try to set rootDirOwner as root node
      if (rootDirOwner && metaRoot.setIfDefault(rootDirOwner, rootIsBuddyMirrored))
      { // new root node accepted (check if rootNode is localNode)
         NumNodeID primaryRootDirOwner;
         if (rootIsBuddyMirrored)
            primaryRootDirOwner = NumNodeID(
               metaBuddyGroupMapper->getPrimaryTargetID(rootDirOwner.val() ) );
         else
            primaryRootDirOwner = rootDirOwner;

         if(localNodeNumID == primaryRootDirOwner)
         {
            log->log(Log_CRITICAL, "I got root (by possession of root directory)");
            if (rootIsBuddyMirrored)
               log->log(Log_CRITICAL, "Root directory is mirrored");
         }
         else
            log->log(Log_CRITICAL,
               "Root metadata server (by possession of root directory): " + rootDirOwner.str());
      }
   }
   else
   { // failed to load root directory => create a new rootDir (not mirrored)
      this->log->log(Log_CRITICAL,
         "This appears to be a new storage directory. Creating a new root dir.");

      UInt16Vector stripeTargets;
      unsigned defaultChunkSize = this->cfg->getTuneDefaultChunkSize();
      unsigned defaultNumStripeTargets = this->cfg->getTuneDefaultNumStripeTargets();
      Raid0Pattern stripePattern(defaultChunkSize, stripeTargets, defaultNumStripeTargets);

      DirInode newRootDir(META_ROOTDIR_ID_STR,
         S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO, 0, 0, NumNodeID(), stripePattern, false);

      this->metaStore->makeDirInode(newRootDir);
      this->rootDir = this->metaStore->referenceDir(META_ROOTDIR_ID_STR, false, true);

      if(!this->rootDir)
      { // error
         this->log->logErr("Failed to store root directory. Unable to proceed.");
         throw InvalidConfigException("Failed to store root directory");
      }
   }

}

void App::initDisposalDir()
{
   // try to load disposal dir from disk (through metaStore) or create a new one

   this->disposalDir = this->metaStore->referenceDir(META_DISPOSALDIR_ID_STR, false, true);
   if(this->disposalDir)
   { // loading succeeded
      this->log->log(Log_DEBUG, "Disposal directory loaded.");
   }
   else
   { // failed to load disposal directory => create a new one
      this->log->log(Log_DEBUG, "Creating a new disposal directory.");

      UInt16Vector stripeTargets;
      unsigned defaultChunkSize = this->cfg->getTuneDefaultChunkSize();
      unsigned defaultNumStripeTargets = this->cfg->getTuneDefaultNumStripeTargets();
      Raid0Pattern stripePattern(defaultChunkSize, stripeTargets, defaultNumStripeTargets);

      DirInode newDisposalDir(META_DISPOSALDIR_ID_STR,
         S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO, 0, 0, NumNodeID(), stripePattern, false);

      this->metaStore->makeDirInode(newDisposalDir);
      this->disposalDir = this->metaStore->referenceDir(META_DISPOSALDIR_ID_STR, false, true);

      if(!this->disposalDir)
      { // error
         this->log->logErr("Failed to store disposal directory. Unable to proceed.");
         throw InvalidConfigException("Failed to store disposal directory");
      }

   }

   buddyMirrorDisposalDir = metaStore->referenceDir(META_MIRRORDISPOSALDIR_ID_STR, true, true);
   if(buddyMirrorDisposalDir)
   { // loading succeeded
      log->log(Log_DEBUG, "Mirrored disposal directory loaded.");
   }
   else
   { // failed to load disposal directory => create a new one
      log->log(Log_DEBUG, "Creating a new mirrored disposal directory.");

      UInt16Vector stripeTargets;
      unsigned defaultChunkSize = cfg->getTuneDefaultChunkSize();
      unsigned defaultNumStripeTargets = cfg->getTuneDefaultNumStripeTargets();
      Raid0Pattern stripePattern(defaultChunkSize, stripeTargets, defaultNumStripeTargets);

      DirInode newDisposalDir(META_MIRRORDISPOSALDIR_ID_STR,
         S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO, 0, 0, NumNodeID(), stripePattern, true);

      metaStore->makeDirInode(newDisposalDir);
      buddyMirrorDisposalDir = metaStore->referenceDir(META_MIRRORDISPOSALDIR_ID_STR, true, true);

      if(!buddyMirrorDisposalDir)
      { // error
         log->logErr("Failed to store mirrored disposal directory. Unable to proceed.");
         throw InvalidConfigException("Failed to store mirrored disposal directory");
      }

   }

}

void App::initComponents(TargetConsistencyState initialConsistencyState)
{
   this->log->log(Log_DEBUG, "Initializing components...");

   this->dgramListener = new DatagramListener(
      netFilter, localNicList, ackStore, cfg->getConnMetaPortUDP() );
   if(cfg->getTuneListenerPrioShift() )
      dgramListener->setPriorityShift(cfg->getTuneListenerPrioShift() );

   streamListenersInit();

   unsigned short listenPort = cfg->getConnMetaPortTCP();

   this->connAcceptor = new ConnAcceptor(this, localNicList, listenPort);

   this->statsCollector = new StatsCollector(workQueue, STATSCOLLECTOR_COLLECT_INTERVAL_MS,
      STATSCOLLECTOR_HISTORY_LENGTH);

   this->buddyResyncer = new BuddyResyncer();

   this->internodeSyncer = new InternodeSyncer(initialConsistencyState);

   this->modificationEventFlusher = new ModificationEventFlusher();

   workersInit();
   commSlavesInit();

   this->log->log(Log_DEBUG, "Components initialized.");
}

void App::startComponents()
{
   log->log(Log_DEBUG, "Starting up components...");

   // make sure child threads don't receive SIGINT/SIGTERM (blocked signals are inherited)
   PThread::blockInterruptSignals();

   timerQueue->start();
   gcQueue->start();

   this->dgramListener->start();

   // wait for nodes list download before we start handling client requests

   PThread::unblockInterruptSignals(); // temporarily unblock interrupt, so user can cancel waiting

   PThread::blockInterruptSignals(); // reblock signals for next child threads

   streamListenersStart();

   this->connAcceptor->start();

   this->statsCollector->start();

   this->internodeSyncer->start();

   timerQueue->enqueue(std::chrono::minutes(5),
         [] { InternodeSyncer::downloadAndSyncClients(true); });

   this->modificationEventFlusher->start();

   if(const auto wait = getConfig()->getTuneDisposalGCPeriod()) {
       this->gcQueue->enqueue(std::chrono::seconds(wait), disposalGarbageCollector);
   }

   workersStart();
   commSlavesStart();

   PThread::unblockInterruptSignals(); // main app thread may receive SIGINT/SIGTERM

   log->log(Log_DEBUG, "Components running.");
}

void App::stopComponents()
{

   SAFE_DELETE(this->gcQueue);

   // note: this method may not wait for termination of the components, because that could
   //    lead to a deadlock (when calling from signal handler)

   // note: no commslave stop here, because that would keep workers from terminating

   if(modificationEventFlusher) // The modificationEventFlusher has to be stopped before the
                                // workers, because it tries to notify all the workers about the
                                // changed modification state.
      modificationEventFlusher->selfTerminate();

   // resyncer wants to control the workers, so any running resync must be finished or aborted
   // before the workers are stopped.
   if(buddyResyncer)
      buddyResyncer->shutdown();

   workersStop();

   if(internodeSyncer)
      internodeSyncer->selfTerminate();

   if(statsCollector)
      statsCollector->selfTerminate();

   if(connAcceptor)
      connAcceptor->selfTerminate();

   streamListenersStop();

   if(dgramListener)
   {
      dgramListener->selfTerminate();
      dgramListener->sendDummyToSelfUDP(); // for faster termination
   }

   this->selfTerminate(); /* this flag can be noticed by thread-independent methods and is also
      required e.g. to let App::waitForMgmtNode() know that it should cancel */
}

/**
 * Handles expections that lead to the termination of a component.
 * Initiates an application shutdown.
 */
void App::handleComponentException(std::exception& e)
{
   const char* logContext = "App (component exception handler)";
   LogContext log(logContext);

   const auto componentName = PThread::getCurrentThreadName();

   log.logErr(
         "The component [" + componentName + "] encountered an unrecoverable error. " +
         std::string("[SysErr: ") + System::getErrString() + "] " +
         std::string("Exception message: ") + e.what() );

   log.log(Log_WARNING, "Shutting down...");

   stopComponents();
}

void App::joinComponents()
{
   log->log(Log_DEBUG, "Joining component threads...");

   /* (note: we need one thread for which we do an untimed join, so this should be a quite reliably
      terminating thread) */
   statsCollector->join();

   workersJoin();

   waitForComponentTermination(modificationEventFlusher);
   waitForComponentTermination(dgramListener);
   waitForComponentTermination(connAcceptor);

   streamListenersJoin();

   waitForComponentTermination(internodeSyncer);

   commSlavesStop(); // placed here because otherwise it would keep workers from terminating
   commSlavesJoin();
}

void App::streamListenersInit()
{
   this->numStreamListeners = cfg->getTuneNumStreamListeners();

   for(unsigned i=0; i < numStreamListeners; i++)
   {
      StreamListenerV2* listener = new StreamListenerV2(
         std::string("StreamLis") + StringTk::uintToStr(i+1), this, workQueue);

      if(cfg->getTuneListenerPrioShift() )
         listener->setPriorityShift(cfg->getTuneListenerPrioShift() );

      if(cfg->getTuneUseAggressiveStreamPoll() )
         listener->setUseAggressivePoll();

      streamLisVec.push_back(listener);
   }
}

void App::workersInit()
{
   unsigned numWorkers = cfg->getTuneNumWorkers();

   for(unsigned i=0; i < numWorkers; i++)
   {
      Worker* worker = new Worker(
         std::string("Worker") + StringTk::uintToStr(i+1), workQueue, QueueWorkType_INDIRECT);

      worker->setBufLens(cfg->getTuneWorkerBufSize(), cfg->getTuneWorkerBufSize() );

      workerList.push_back(worker);
   }

   for(unsigned i=0; i < APP_WORKERS_DIRECT_NUM; i++)
   {
      Worker* worker = new Worker(
         std::string("DirectWorker") + StringTk::uintToStr(i+1), workQueue, QueueWorkType_DIRECT);

      worker->setBufLens(cfg->getTuneWorkerBufSize(), cfg->getTuneWorkerBufSize() );

      workerList.push_back(worker);
   }
}

void App::commSlavesInit()
{
   unsigned numCommSlaves = cfg->getTuneNumCommSlaves();

   for(unsigned i=0; i < numCommSlaves; i++)
   {
      Worker* worker = new Worker(
         std::string("CommSlave") + StringTk::uintToStr(i+1), commSlaveQueue, QueueWorkType_DIRECT);

      worker->setBufLens(cfg->getTuneCommSlaveBufSize(), cfg->getTuneCommSlaveBufSize() );

      commSlaveList.push_back(worker);
   }
}

void App::streamListenersStart()
{
   unsigned numNumaNodes = System::getNumNumaNodes();

   for(StreamLisVecIter iter = streamLisVec.begin(); iter != streamLisVec.end(); iter++)
   {
      if(cfg->getTuneListenerNumaAffinity() )
         (*iter)->startOnNumaNode( (++nextNumaBindTarget) % numNumaNodes);
      else
         (*iter)->start();
   }
}

void App::workersStart()
{
   unsigned numNumaNodes = System::getNumNumaNodes();

   for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
   {
      if(cfg->getTuneWorkerNumaAffinity() )
         (*iter)->startOnNumaNode( (++nextNumaBindTarget) % numNumaNodes);
      else
         (*iter)->start();
   }
}

void App::commSlavesStart()
{
   unsigned numNumaNodes = System::getNumNumaNodes();

   for(WorkerListIter iter = commSlaveList.begin(); iter != commSlaveList.end(); iter++)
   {
      if(cfg->getTuneWorkerNumaAffinity() )
         (*iter)->startOnNumaNode( (++nextNumaBindTarget) % numNumaNodes);
      else
         (*iter)->start();
   }
}

void App::streamListenersStop()
{
   for(StreamLisVecIter iter = streamLisVec.begin(); iter != streamLisVec.end(); iter++)
   {
      (*iter)->selfTerminate();
   }
}

void App::workersStop()
{
   for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
   {
      (*iter)->selfTerminate();

      // add dummy work to wake up the worker immediately for faster self termination
      PersonalWorkQueue* personalQ = (*iter)->getPersonalWorkQueue();
      workQueue->addPersonalWork(new DummyWork(), personalQ);
   }
}

void App::commSlavesStop()
{
   // need two loops because we don't know if the worker that handles the work will be the same that
   // received the self-terminate-request
   for(WorkerListIter iter = commSlaveList.begin(); iter != commSlaveList.end(); iter++)
   {
      (*iter)->selfTerminate();
   }

   for(WorkerListIter iter = commSlaveList.begin(); iter != commSlaveList.end(); iter++)
   {
      commSlaveQueue->addDirectWork(new DummyWork() );
   }
}

void App::streamListenersDelete()
{
   for(StreamLisVecIter iter = streamLisVec.begin(); iter != streamLisVec.end(); iter++)
   {
      delete(*iter);
   }

   streamLisVec.clear();
}

void App::workersDelete()
{
   for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
   {
      delete(*iter);
   }

   workerList.clear();
}

void App::commSlavesDelete()
{
   for(WorkerListIter iter = commSlaveList.begin(); iter != commSlaveList.end(); iter++)
   {
      delete(*iter);
   }

   commSlaveList.clear();
}

void App::streamListenersJoin()
{
   for(StreamLisVecIter iter = streamLisVec.begin(); iter != streamLisVec.end(); iter++)
   {
      waitForComponentTermination(*iter);
   }
}

void App::workersJoin()
{
   for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
   {
      waitForComponentTermination(*iter);
   }
}

void App::commSlavesJoin()
{
   for(WorkerListIter iter = commSlaveList.begin(); iter != commSlaveList.end(); iter++)
   {
      waitForComponentTermination(*iter);
   }
}

void App::logInfos()
{
   // print software version (CONGFS_VERSION)
   log->log(Log_CRITICAL, std::string("Version: ") + CONGFS_VERSION);

   // print debug version info
   LOG_DEBUG_CONTEXT(*log, Log_CRITICAL, "--DEBUG VERSION--");

   // print local nodeIDs
   log->log(Log_WARNING, "LocalNode: " + localNode->getNodeIDWithTypeStr() );

   // list usable network interfaces
   NicAddressList nicList(localNode->getNicList() );

   std::string nicListStr;
   std::string extendedNicListStr;
   for (NicAddressListIter nicIter = nicList.begin(); nicIter != nicList.end(); nicIter++)
   {
      std::string nicTypeStr;

      if (nicIter->nicType == NICADDRTYPE_RDMA)
         nicTypeStr = "RDMA";
      else if (nicIter->nicType == NICADDRTYPE_SDP)
         nicTypeStr = "SDP";
      else if (nicIter->nicType == NICADDRTYPE_STANDARD)
         nicTypeStr = "TCP";
      else
         nicTypeStr = "Unknown";

      nicListStr += " " + std::string(nicIter->name) + "(" + nicTypeStr + ")";

      extendedNicListStr += "\n+ " + NetworkInterfaceCard::nicAddrToString(&(*nicIter) );
   }

   log->log(Log_WARNING, std::string("Usable NICs:") + nicListStr);
   log->log(Log_DEBUG, std::string("Extended list of usable NICs:") + extendedNicListStr);

   // print net filters
   if(netFilter->getNumFilterEntries() )
   {
      log->log(Log_WARNING, std::string("Net filters: ") +
         StringTk::uintToStr(netFilter->getNumFilterEntries() ) );
   }

   if(tcpOnlyFilter->getNumFilterEntries() )
   {
      this->log->log(Log_WARNING, std::string("TCP-only filters: ") +
         StringTk::uintToStr(tcpOnlyFilter->getNumFilterEntries() ) );
   }

   // print numa info
   // (getTuneBindToNumaZone==-1 means disable binding)
   if(cfg->getTuneListenerNumaAffinity() || cfg->getTuneWorkerNumaAffinity() ||
      (cfg->getTuneBindToNumaZone() != -1) )
   {
      unsigned numNumaNodes = System::getNumNumaNodes();

      /* note: we use the term "numa areas" instead of "numa nodes" in log messages to avoid
         confusion with cluster "nodes" */

      log->log(Log_NOTICE, std::string("NUMA areas: ") + StringTk::uintToStr(numNumaNodes) );

      for(unsigned nodeNum=0; nodeNum < numNumaNodes; nodeNum++)
      { // print core list for each numa node
         cpu_set_t cpuSet;

         System::getNumaCoresByNode(nodeNum, &cpuSet);

         // create core list for current numa node

         std::string coreListStr;
         for(unsigned coreNum = 0; coreNum < CPU_SETSIZE; coreNum++)
         {
            if(CPU_ISSET(coreNum, &cpuSet) )
               coreListStr += StringTk::uintToStr(coreNum) + " ";
         }

         log->log(Log_SPAM, "NUMA area " + StringTk::uintToStr(nodeNum) + " cores: " + coreListStr);
      }
   }
}

void App::daemonize()
{
   int nochdir = 1; // 1 to keep working directory
   int noclose = 0; // 1 to keep stdin/-out/-err open

   log->log(Log_DEBUG, std::string("Detaching process...") );

   int detachRes = daemon(nochdir, noclose);
   if(detachRes == -1)
      throw InvalidConfigException(std::string("Unable to detach process. SysErr: ") +
         System::getErrString() );

   updateLockedPIDFile(pidFileLockFD); // ignored if pidFileFD is -1
}

void App::registerSignalHandler()
{
   signal(SIGINT, App::signalHandler);
   signal(SIGTERM, App::signalHandler);
}

void App::signalHandler(int sig)
{
   App* app = Program::getApp();

   Logger* log = Logger::getLogger();
   const char* logContext = "App::signalHandler";

   // note: this might deadlock if the signal was thrown while the logger mutex is locked by the
   //    application thread (depending on whether the default mutex style is recursive). but
   //    even recursive mutexes are not acceptable in this case.
   //    we need something like a timed lock for the log mutex. if it succeeds within a
   //    few seconds, we know that we didn't hold the mutex lock. otherwise we simply skip the
   //    log message. this will only work if the mutex is non-recusive (which is unknown for
   //    the default mutex style).
   //    but it is very unlikely that the application thread holds the log mutex, because it
   //    joins the component threads and so it doesn't do anything else but sleeping!

   switch(sig)
   {
      case SIGINT:
      {
         signal(sig, SIG_DFL); // reset the handler to its default
         log->log(Log_CRITICAL, logContext, "Received a SIGINT. Shutting down...");
      } break;

      case SIGTERM:
      {
         signal(sig, SIG_DFL); // reset the handler to its default
         log->log(Log_CRITICAL, logContext, "Received a SIGTERM. Shutting down...");
      } break;

      default:
      {
         signal(sig, SIG_DFL); // reset the handler to its default
         log->log(Log_CRITICAL, logContext, "Received an unknown signal. Shutting down...");
      } break;
   }

   app->stopComponents();
}

/**
 * Request mgmt heartbeat and wait for the mgmt node to appear in nodestore.
 *
 * @return true if mgmt heartbeat received, false on error or thread selftermination order
 */
bool App::waitForMgmtNode()
{
   const unsigned waitTimeoutMS = 0; // infinite wait
   const unsigned nameResolutionRetries = 3;

   unsigned udpListenPort = cfg->getConnMetaPortUDP();
   unsigned udpMgmtdPort = cfg->getConnMgmtdPortUDP();
   std::string mgmtdHost = cfg->getSysMgmtdHost();

   RegistrationDatagramListener regDGramLis(netFilter, localNicList, ackStore, udpListenPort);

   regDGramLis.start();

   log->log(Log_CRITICAL, "Waiting for congfs-mgmtd@" +
      mgmtdHost + ":" + StringTk::uintToStr(udpMgmtdPort) + "...");

   bool gotMgmtd = NodesTk::waitForMgmtHeartbeat(
      this, &regDGramLis, mgmtNodes, mgmtdHost, udpMgmtdPort, waitTimeoutMS, nameResolutionRetries);

   regDGramLis.selfTerminate();
   regDGramLis.sendDummyToSelfUDP(); // for faster termination

   regDGramLis.join();

   return gotMgmtd;
}

/**
 * Pre-register node to get a numeric ID from mgmt.
 *
 * @return true if pre-registration successful and localNodeNumID set.
 */
bool App::preregisterNode(std::string& localNodeID, NumNodeID& outLocalNodeNumID)
{
   static bool registrationFailureLogged = false; // to avoid log spamming

   auto mgmtNode = mgmtNodes->referenceFirstNode();
   if(!mgmtNode)
   {
      log->logErr("Unexpected: No management node found in store during node pre-registration.");
      return false;
   }

   NumNodeID rootNodeID = metaRoot.getID();

   RegisterNodeMsg msg(localNodeID, outLocalNodeNumID, NODETYPE_Meta, &localNicList,
      cfg->getConnMetaPortUDP(), cfg->getConnMetaPortTCP() );
   msg.setRootNumID(rootNodeID);

   Time startTime;
   Time lastRetryTime;
   unsigned nextRetryDelayMS = 0;

   // wait for mgmt node to appear and periodically resend request
   /* note: we usually expect not to loop here, because we already waited for mgmtd in
      waitForMgmtNode(), so mgmt should respond immediately. */

   while(!outLocalNodeNumID && !getSelfTerminate() )
   {
      if(lastRetryTime.elapsedMS() < nextRetryDelayMS)
      { // wait some time between retries
         waitForSelfTerminateOrder(nextRetryDelayMS);
         if(getSelfTerminate() )
            break;
      }

      const auto respMsg = MessagingTk::requestResponse(*mgmtNode, msg,
            NETMSGTYPE_RegisterNodeResp);

      if (respMsg)
      { // communication successful
         RegisterNodeRespMsg* respMsgCast = (RegisterNodeRespMsg*)respMsg.get();

         outLocalNodeNumID = respMsgCast->getNodeNumID();

         if(!outLocalNodeNumID)
         { // mgmt rejected our registration
            log->logErr("ID reservation request was rejected by this mgmt node: " +
               mgmtNode->getTypedNodeID() );
         }
         else
            log->log(Log_WARNING, "Node ID reservation successful.");

         break;
      }

      // comm failed => log status message

      if(!registrationFailureLogged)
      {
         log->log(Log_CRITICAL, "Node ID reservation failed. Management node offline? "
            "Will keep on trying...");
         registrationFailureLogged = true;
      }

      // calculate next retry wait time

      lastRetryTime.setToNow();
      nextRetryDelayMS = NodesTk::getRetryDelayMS(startTime.elapsedMS() );
   }

   return bool(outLocalNodeNumID);
}

/**
 * Downloads the list of nodes, targets and buddy groups (for meta and storage servers) from the
 * mgmtd.
 *
 * @param outInitialConsistencyState The consistency state the local meta node has on the mgmtd
 *                                   before any state reports are sent.
 */
bool App::downloadMgmtInfo(TargetConsistencyState& outInitialConsistencyState)
{
   Config* cfg = this->getConfig();

   int retrySleepTimeMS = 10000; // 10sec
   unsigned udpListenPort = cfg->getConnMetaPortUDP();
   bool allSuccessful = false;

   // start temporary registration datagram listener
   RegistrationDatagramListener regDGramLis(netFilter, localNicList, ackStore, udpListenPort);
   regDGramLis.start();

   // loop until we're registered and everything is downloaded (or until we got interrupted)
   do
   {
      // register ourselves
      // (note: node registration needs to be done before downloads to get notified of updates)
      if (!InternodeSyncer::registerNode(&regDGramLis) )
         continue;

      // download all mgmt info the HBM cares for
      if (!InternodeSyncer::downloadAndSyncNodes() ||
          !InternodeSyncer::downloadAndSyncTargetMappings() ||
          !InternodeSyncer::downloadAndSyncStoragePools() ||
          !InternodeSyncer::downloadAndSyncTargetStatesAndBuddyGroups() ||
          !InternodeSyncer::updateMetaCapacityPools() ||
          !InternodeSyncer::updateMetaBuddyCapacityPools())
         continue;

      InternodeSyncer::downloadAndSyncClients(false);

      // ...and then the InternodeSyncer's part.
      if (!InternodeSyncer::updateMetaStatesAndBuddyGroups(outInitialConsistencyState, false) )
         continue;

      if(!InternodeSyncer::downloadAllExceededQuotaLists(storagePoolStore->getPoolsAsVec()))
         continue;

      allSuccessful = true;
      break;

   } while(!waitForSelfTerminateOrder(retrySleepTimeMS) );

   // stop temporary registration datagram listener
   regDGramLis.selfTerminate();
   regDGramLis.sendDummyToSelfUDP(); // for faster termination

   regDGramLis.join();

   if(allSuccessful)
      log->log(Log_NOTICE, "Registration and management info download complete.");

   return allSuccessful;
}

bool App::restoreSessions()
{
   bool retVal = true;

   std::string path = this->metaPathStr  + "/" + std::string(STORAGETK_SESSIONS_BACKUP_FILE_NAME);
   std::string mpath = this->metaPathStr  + "/" + std::string(STORAGETK_MSESSIONS_BACKUP_FILE_NAME);

   bool pathRes = StorageTk::pathExists(path);
   bool mpathRes = StorageTk::pathExists(mpath);
   if (!pathRes && !mpathRes)
      return false;

   if (pathRes)
   {
      bool loadRes = this->sessions->loadFromFile(path, *metaStore);
      if (!loadRes)
      {
         log->logErr("Could not restore all sessions");
         retVal = false;
      }
   }

   if (mpathRes)
   {
      bool loadRes = this->mirroredSessions->loadFromFile(mpath, *metaStore);
      if (!loadRes)
      {
         log->logErr("Could not restore all mirrored sessions");
         retVal = false;
      }
   }

   log->log(Log_NOTICE, "Restored "
         + StringTk::uintToStr(sessions->getSize()) + " sessions and "
         + StringTk::uintToStr(mirroredSessions->getSize()) + " mirrored sessions");

   return retVal;
}

bool App::storeSessions()
{
   bool retVal = true;

   std::string path = this->metaPathStr + "/" + std::string(STORAGETK_SESSIONS_BACKUP_FILE_NAME);
   std::string mpath = this->metaPathStr + "/" + std::string(STORAGETK_MSESSIONS_BACKUP_FILE_NAME);

   if (StorageTk::pathExists(path))
      log->log(Log_WARNING, "Overwriting existing session file");

   bool saveRes = this->sessions->saveToFile(path);
   if(!saveRes)
   {
      this->log->logErr("Could not store all sessions to file " + path);
      retVal = false;
   }

   if (StorageTk::pathExists(mpath))
      log->log(Log_WARNING, "Overwriting existing mirror session file");

   saveRes = this->mirroredSessions->saveToFile(mpath);
   if(!saveRes)
   {
      this->log->logErr("Could not store all mirror sessions to file " + mpath);
      retVal = false;
   }

   if (retVal)
      log->log(Log_NOTICE, "Stored "
            + StringTk::uintToStr(sessions->getSize()) + " sessions and "
            + StringTk::uintToStr(mirroredSessions->getSize()) + " mirrored sessions");

   return retVal;
}

bool App::deleteSessionFiles()
{
   bool retVal = true;

   std::string path = this->metaPathStr + "/" + std::string(STORAGETK_SESSIONS_BACKUP_FILE_NAME);
   std::string mpath = this->metaPathStr + "/" + std::string(STORAGETK_MSESSIONS_BACKUP_FILE_NAME);

   bool pathRes = StorageTk::pathExists(path);
   bool mpathRes = StorageTk::pathExists(mpath);
   if (!pathRes && !mpathRes)
      return retVal;

   if (pathRes && remove(path.c_str()))
   {
      log->logErr("Could not remove sessions file");
      retVal = false;
   }

   if (mpathRes && remove(mpath.c_str()))
   {
      log->logErr("Could not remove mirrored sessions file");
      retVal = false;
   }

   return retVal;
}

void App::checkTargetUUID()
{
   if (!cfg->getStoreFsUUID().empty())
   {
      Path metaPath(cfg->getStoreMetaDirectory() );

      // Find out device numbers of underlying device
      struct stat st;

      if (stat(metaPath.str().c_str(), &st)) {
         throw InvalidConfigException("Could not stat metadata directory: " + metaPathStr);
      }

      // look for the device path
      std::ifstream mountInfo("/proc/self/mountinfo");

      if (!mountInfo) {
         throw InvalidConfigException("Could not open /proc/self/mountinfo");
      }

      std::string line, device_path, device_majmin;
      while (std::getline(mountInfo, line)) {
         std::istringstream is(line);
	      std::string dummy;
         is >> dummy >> dummy >> device_majmin >> dummy >> dummy >> dummy >> dummy >> dummy >> dummy >> device_path;

	      auto majmin_f = boost::format("%1%:%2%") % (st.st_dev >> 8) % (st.st_dev & 0xFF);

         if (majmin_f.str() == device_majmin)
            break;

	      device_path = "";
      }

      if (device_path.empty()) {
         throw InvalidConfigException("Could not find a device path that belongs to device " + device_majmin);
      }

      // Lookup the fs UUID
      std::unique_ptr<blkid_struct_probe, void(*)(blkid_struct_probe*)>
            probe(blkid_new_probe_from_filename(device_path.data()), blkid_free_probe);

      if (!probe) {
	      throw InvalidConfigException("Failed to open device for probing: " + device_path);
      }

      if (blkid_probe_enable_superblocks(probe.get(), 1) < 0) {
	      throw InvalidConfigException("Failed to enable superblock probing");
      }

      if (blkid_do_fullprobe(probe.get()) < 0) {
	      throw InvalidConfigException("Failed to probe device");
      }

      const char* uuid = nullptr; // gets released automatically
      if (blkid_probe_lookup_value(probe.get(), "UUID", &uuid, nullptr) < 0) {
	      throw InvalidConfigException("Failed to lookup file system UUID");
      }

      std::string uuid_str(uuid);

      if (cfg->getStoreFsUUID() != uuid_str)
      {
         throw InvalidConfigException("UUID of the metadata file system (" + uuid_str
               + ") does not match the one configured (" + cfg->getStoreFsUUID() + ")");
      }
   }
   else
   {
      LOG(GENERAL, WARNING, "UUID of underlying file system has not conn configured and will "
            "therefore not be checked. To prevent starting the server accidentally with the wrong "
            "data, it is strongly recommended to set the storeFsUUID config parameter to "
            "the appropriate UUID.");
   }

}

max_stars_repo_name: congweitao/congfs

max_issues_repo_name: congweitao/congfs

max_forks_repo_name: congweitao/congfs


text:
#pragma once

#include "geocoder/name_dictionary.hpp"
#include "geocoder/types.hpp"

#include "base/assert.hpp"
#include "base/geo_object_id.hpp"

#include "coding/json.hpp"

#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include <boost/serialization/array.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/version.hpp>

namespace geocoder
{
class Hierarchy
{
public:
  struct ParsingStats
  {
    // Number of entries that the hierarchy was constructed from.
    uint64_t m_numLoaded = 0;

    // Number of corrupted json lines.
    uint64_t m_badJsons = 0;

    // Number of entries with unreadable base::GeoObjectIds.
    uint64_t m_badOsmIds = 0;

    // Number of base::GeoObjectsIds that occur as keys in at least two entries.
    uint64_t m_duplicateOsmIds = 0;

    // Number of entries with duplicate subfields in the address field.
    uint64_t m_duplicateAddresses = 0;

    // Number of entries whose address field either does
    // not exist or consists of empty lines.
    uint64_t m_emptyAddresses = 0;

    // Number of entries without the name field or with an empty one.
    uint64_t m_emptyNames = 0;

    // Number of street entries without a locality name.
    uint64_t m_noLocalityStreets = 0;

    // Number of building entries without a locality name.
    uint64_t m_noLocalityBuildings = 0;

    // Number of entries whose names do not match the most
    // specific parts of their addresses.
    // This is expected from POIs but not from regions or streets.
    uint64_t m_mismatchedNames = 0;
  };

  // A single entry in the hierarchy directed acyclic graph.
  // Currently, this is more or less the "properties"-"address"
  // part of the geojson entry.
  struct Entry
  {
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
      CHECK_EQUAL(version, kIndexFormatVersion, ());
      ar & m_osmId;
      ar & m_name;
      ar & m_type;
      ar & m_kind;
      ar & m_normalizedAddress;
    }

    bool DeserializeFromJSON(std::string const & jsonStr,
                             NameDictionaryBuilder & normalizedNameDictionaryBuilder,
                             ParsingStats & stats);
    bool DeserializeFromJSONImpl(coding::JsonDocument const & root, std::string const & jsonStr,
                                 NameDictionaryBuilder & normalizedNameDictionaryBuilder,
                                 ParsingStats & stats);
    bool DeserializeAddressFromJSON(coding::JsonDocument const & root,
                                    NameDictionaryBuilder & normalizedNameDictionaryBuilder,
                                    ParsingStats & stats);
    static bool FetchAddressFieldNames(coding::JsonValue const & locales, Type type,
                                       MultipleNames & multipleNames);
    bool HasFieldInAddress(Type type) const;
    // See generator::regions::LevelRegion::GetRank().
    static Type RankToType(uint8_t rank);

    MultipleNames const & GetNormalizedMultipleNames(
        Type type, NameDictionary const & normalizedNameDictionary) const;
    bool operator<(Entry const & rhs) const { return m_osmId < rhs.m_osmId; }

    base::GeoObjectId m_osmId = base::GeoObjectId(base::GeoObjectId::kInvalid);

    // Original name of the entry. Useful for debugging.
    std::string m_name;

    Type m_type = Type::Count;
    Kind m_kind{Kind::Unknown};

    // The positions of entry address fields in normalized name dictionary, one per Type.
    std::array<NameDictionary::Position, static_cast<size_t>(Type::Count)> m_normalizedAddress{};
  };

  Hierarchy() = default;
  Hierarchy(std::vector<Entry> && entries, NameDictionary && normalizeNameDictionary,
            std::string && dataVersion);

  template<class Archive>
  void serialize(Archive & ar, const unsigned int version)
  {
    CHECK_EQUAL(version, kIndexFormatVersion, ());
    ar & m_entries;
    ar & m_normalizedNameDictionary;
    ar & m_dataVersion;
  }

  std::vector<Entry> const & GetEntries() const;
  NameDictionary const & GetNormalizedNameDictionary() const;

  Entry const * GetEntryForOsmId(base::GeoObjectId const & osmId) const;
  bool IsParentTo(Hierarchy::Entry const & entry, Hierarchy::Entry const & toEntry) const;

  std::string const & GetDataVersion() const
  {
    return m_dataVersion;
  }

private:
  std::vector<Entry> m_entries;
  NameDictionary m_normalizedNameDictionary;
  std::string m_dataVersion;
};
}  // namespace geocoder

BOOST_CLASS_VERSION(geocoder::Hierarchy, geocoder::kIndexFormatVersion)
BOOST_CLASS_VERSION(geocoder::Hierarchy::Entry, geocoder::kIndexFormatVersion)

namespace boost
{
namespace serialization
{
template<class Archive>
inline void serialize(Archive & ar, base::GeoObjectId & t, const unsigned int version)
{
  split_free(ar, t, version);
}

template<class Archive>
inline void save(Archive & ar, base::GeoObjectId const & t, const unsigned int /*version*/)
{
  ar & t.GetEncodedId();
}

template<class Archive>
inline void load(Archive & ar, base::GeoObjectId & t, const unsigned int /*version*/)
{
  uint64_t encodedId = 0;
  ar & encodedId;
  t = base::GeoObjectId(encodedId);
}
}  // namespace serialization
}  // namespace boost

max_stars_repo_name: mapsme/geocore

max_issues_repo_name: mapsme/geocore

max_forks_repo_name: mapsme/geocore


text:
// Standard library:
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <dlfcn.h>

/// Third Party:
// - Boost:
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

// This project
#include <XY/config.hpp>
#include <XY/PluginSupport.hpp>

#if BSTCUD_WITH_EOS == 1
#include <eos/portable_iarchive.hpp>
#include <eos/portable_oarchive.hpp>
#endif // BSTCUD_WITH_EOS

int main(void)
{
  xy::plugin_deck & sysPlugDeck = xy::plugin_deck::instance();
  sysPlugDeck.print(std::clog);

  std::clog << "Loading libPlugin DLL..." << std::endl;
  void * libPluginHandle = dlopen("libPlugin.so", RTLD_NOW);
  if (libPluginHandle == nullptr) {
    std::cerr << "[error] Cannot load plugin '" << "libPlugin.so" << "'" << std::endl;
    exit(1);
  }
  sysPlugDeck.print(std::clog);

  xy::BasePlugin * plugFactory = nullptr;
  if (sysPlugDeck.has_current_plugin()) {
    plugFactory = &sysPlugDeck.current_plugin();
    std::clog << "Plugin factory @" << plugFactory << std::endl;
  }

  {
    std::string filename = "test_Plugin_2.xml";
    typedef std::shared_ptr<xy::A> xy_a_sp;
    {
      std::vector<xy_a_sp> coll;
      std::clog << "Serializing..." << std::endl;
      std::ofstream file(filename.c_str());
      boost::archive::xml_oarchive oa(file);
      for (std::size_t i = 0; i < 20; i++) {
        xy_a_sp ptr(plugFactory->create());
        coll.push_back(ptr);
        std::clog << "back = " << coll.back()->to_string() << std::endl;
      }
      oa & BOOST_SERIALIZATION_NVP(coll);
    }

    {
      std::vector<xy_a_sp> coll;
      std::clog << "Deserializing..." << std::endl;
      std::ifstream file(filename.c_str());
      boost::archive::xml_iarchive ia(file);
      ia & BOOST_SERIALIZATION_NVP(coll);
      for (std::size_t i = 0; i < coll.size(); i++) {
        std::clog << "loaded back = " << coll[i]->to_string() << std::endl;
      }
    }
  }

#if BSTCUD_WITH_EOS == 1
  {
    std::string filename = "test_Plugin_2.data";
    typedef std::shared_ptr<xy::A> xy_a_sp;
    {
      std::vector<xy_a_sp> coll;
      std::clog << "Serializing..." << std::endl;
      std::ofstream file(filename.c_str());
      eos::portable_oarchive oa(file);
      for (std::size_t i = 0; i < 20; i++) {
        xy_a_sp ptr(plugFactory->create());
        coll.push_back(ptr);
        std::clog << "back = " << coll.back()->to_string() << std::endl;
      }
      oa & BOOST_SERIALIZATION_NVP(coll);
    }

    {
      std::vector<xy_a_sp> coll;
      std::clog << "Deserializing..." << std::endl;
      std::ifstream file(filename.c_str());
      eos::portable_iarchive ia(file);
      ia & BOOST_SERIALIZATION_NVP(coll);
      for (std::size_t i = 0; i < coll.size(); i++) {
        std::clog << "loaded back = " << coll[i]->to_string() << std::endl;
      }
    }
  }
#endif // BSTCUD_WITH_EOS

  std::clog << "Closing libPlugin DLL..." << std::endl;
  dlclose(libPluginHandle);
  return 0;
}

ext: cxx


text:
/**
 * Fast map matching.
 *
 * Network configuration class
 *
 * @author Can Yang
 */

#ifndef FMM_NETWORK_CONFIG_HPP_
#define FMM_NETWORK_CONFIG_HPP_

#include <string>
#include "cxxopts/cxxopts.hpp"
#include <boost/predef.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

namespace FMM{

namespace CONFIG {
/**
 *  Network configuration class for reading network from a file.
 */
struct NetworkConfig{
  std::string file; /**< filename */
  std::string id; /**< id field/column name */
  std::string source; /**< source field/column name */
  std::string target; /**< target field/column name */

  /**
   * Check if the input is shapefile format
   */
  bool is_shapefile_format() const;
  /**
   * Validate the GPS configuration for file existence.
   * @return if file exists returns true, otherwise return false
   */
  bool validate() const;
  /**
   * Print informaiton
   */
  void print() const;
  /**
   * Load NetworkConfig from xml data
   * @param  xml_data XML data read from a file
   * @return NetworkConfig object containing information stored in the
   * xml file.
   */
  static NetworkConfig load_from_xml(
    const boost::property_tree::ptree &xml_data);
  /**
   * Load NetworkConfig from argument parsed data
   * @param  arg_data Argument data parsed from command line
   * @return NetworkConfig object containing information parsed from
   * command line argument.
   */
  static NetworkConfig load_from_arg(
    const cxxopts::ParseResult &arg_data);
  /**
   * Register arguments to an option object
   */
  static void register_arg(cxxopts::Options &options);
  /**
   * Register help information to a string stream
   */
  static void register_help(std::ostringstream &oss);
};

} // CONFIG

} // FMM

#endif //FMM_NETWORK_CONFIG_HPP_

max_stars_repo_name: pauljherring/fmm

max_issues_repo_name: pauljherring/fmm

max_forks_repo_name: pauljherring/fmm