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

#include "csgapplication.h"
#include "trajectorywriter.h"
#include "trajectoryreader.h"
#include "topologyreader.h"
#include "topologymap.h"
#include "cgengine.h"
#include "version.h"
#include "votca/tools/easylock.h"

namespace votca {
    namespace csg {

        CsgApplication::CsgApplication(void) {
        }

        CsgApplication::~CsgApplication(void) {
        }

        void CsgApplication::Initialize(void) {
            // register all io plugins
            TrajectoryWriter::RegisterPlugins();
            TrajectoryReader::RegisterPlugins();
            TopologyReader::RegisterPlugins();

            AddProgramOptions()
                    ("top", boost::program_options::value<string > (), "  atomistic topology file");
            if (DoMapping()) {
                if (DoMappingDefault()) {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  coarse graining mapping definitions (xml-file)")
                            ("no-map", "  disable mapping and act on original trajectory");
                } else {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  [OPTIONAL] coarse graining mapping definitions\n"
                            "  (xml-file). If no file is given, program acts on original trajectory");
                }
            }

            if (DoTrajectory())
                AddProgramOptions("Trajectory options")
                ("trj", boost::program_options::value<string > (), "  atomistic trajectory file")
                ("begin", boost::program_options::value<double>()->default_value(0.0), "  skip frames before this time")
                ("first-frame", boost::program_options::value<int>()->default_value(0), "  start with this frame")
                ("nframes", boost::program_options::value<int>(), "  process so many frames")
                ;

            if (DoThreaded())
                AddProgramOptions("Threading options")
                ("nt", boost::program_options::value<int>()->default_value(1), "  number of threads")
                ;

        }

        bool CsgApplication::EvaluateOptions(void) {
            _do_mapping = false;
            CheckRequired("top", "no topology file specified");

            // check for mapping options
            if (DoMapping()) {
                // default mapping is on
                if (DoMappingDefault()) {
                    // if the user does not explicitly ask to turn it off, cg is needed
                    if (OptionsMap().count("no-map") == 0) {
                        CheckRequired("cg", "no coarse graining definition specified");
                        _do_mapping = true;
                    }
                }// default mapping is off, if user gives cg, then do mapping
                else if (OptionsMap().count("cg")) {
                    _do_mapping = true;
                }
            }

            /* check threading options */
            if (DoThreaded()) {
                /* TODO
                 * does the number of threads make sense?
                 * which criteria should be used? smaller than system's cores?
                 */
            }

            return true;
        }

        void CsgApplication::ShowHelpText(std::ostream &out) {
            string name = ProgramName();
            if (VersionString() != "")
                name = name + ", version " + VersionString();

            HelpTextHeader(name);
            HelpText(out);
            out << "\n\n" << OptionsDesc() << endl;
        }

        void CsgApplication::Run(void) {
            if (DoThreaded()) {
                RunThreaded();
                return;
            }
            // first read in the topology
            TopologyReader *reader;
            Topology top;

            Topology top_cg;
            TopologyMap *map = 0;
            CGEngine cg;

            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            // read in the topology
            reader->ReadTopology(_op_vm["top"].as<string > (), top);
            cout << "I have " << top.BeadCount() << " beads in " << top.MoleculeCount() << " molecules" << endl;
            top.CheckMoleculeNaming();

            if (_do_mapping) {
                // read in the coarse graining definitions (xml files)
                cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
                // create the mapping + cg topology
                map = cg.CreateCGTopology(top, top_cg);

                cout << "I have " << top_cg.BeadCount() << " beads in " << top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                map->Apply();
                if (!EvaluateTopology(&top_cg, &top))
                    return;
            } else
                if (!EvaluateTopology(&top))
                return;

            // do we need to read a trajectory?
            if (DoTrajectory()) {
                TrajectoryReader *traj_reader;

                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                int nframes = -1;
                if (_op_vm.count("nframes")) {
                    nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                traj_reader->Open(_op_vm["trj"].as<string > ());

                // read in first frame
                traj_reader->FirstFrame(top);

                // notify all observer that coarse graining has begun

                if (_do_mapping) {
                    map->Apply();
                    BeginEvaluate(&top_cg, &top);
                } else
                    BeginEvaluate(&top);

                for (bool bok = true; bok == true; bok = traj_reader->NextFrame(top)) {
                    if (((top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    if (nframes == 0) break;
                    if (_do_mapping) {
                        map->Apply();
                        EvalConfiguration(&top_cg, &top);

                    } else
                        EvalConfiguration(&top);
                    nframes--;
                }
                EndEvaluate();
                traj_reader->Close();

                delete traj_reader;
            }
            if (map)
                delete map;
            delete reader;

        }

        void CsgApplication::Worker::Run(void) {
            while (_app->ProcessData(this));
        }

        bool CsgApplication::ProcessData(Worker * worker) {
            //easyLock
            //EasyLock locker(_traj_readerMutex);
            //return traj_reader->NextFrame(*top);

            //not so easy lock
            _nframesMutex.Lock();
            if (_nframes > 0 || _nframes <= -99) {
                _nframes--;
                _nframesMutex.Unlock();
                bool tmpRes;
                _traj_readerMutex.Lock();

                tmpRes = _traj_reader->NextFrame(worker->_top);

                _traj_readerMutex.Unlock();
                if (_do_mapping) {
                    worker->_map->Apply();
                    worker->EvalConfiguration(&worker->_top_cg, &worker->_top);
                } else
                    worker->EvalConfiguration(&worker->_top);
                return tmpRes;
            } else {
                _nframesMutex.Unlock();
                return false;
            }
        }

        void CsgApplication::RunThreaded(void) {
            CGEngine cg;
            TopologyReader *reader;

            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            if (DoTrajectory()) {
                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                _nframes = -1;
                if (_op_vm.count("nframes")) {
                    _nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                _traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (_traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                _traj_reader->Open(_op_vm["trj"].as<string > ());

/////////////////////////////////////////////////////////////////////////

                if (_do_mapping)
                    cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
//////////////////////////////////////////////////////////////////////////

                for (int thread = 0; thread < _op_vm["nt"].as<int > (); thread++) {
                    Worker *myWorker = ForkWorker();
                    myWorker->setApplication(this);
                    myWorker->setId(thread);
                    _myWorkers.push_back(myWorker);

                    // read in the topology
                    reader->ReadTopology(_op_vm["top"].as<string > (), myWorker->_top);
                    myWorker->_top.CheckMoleculeNaming();

                    if (_do_mapping) {
                        // create the mapping + cg topology
                        myWorker->_map = cg.CreateCGTopology(myWorker->_top, myWorker->_top_cg);
                        myWorker->_map->Apply();

                        if (!EvaluateTopology(&myWorker->_top_cg, &myWorker->_top))
                            return;
                    } else
                        if (!EvaluateTopology(&myWorker->_top))
                        return;
                }

                cout << "I have " << _myWorkers[0]->_top.BeadCount() << " beads in " << _myWorkers[0]->_top.MoleculeCount() << " molecules" << endl;

/////////////////////////////////////////////////////////////////////////

                if (_do_mapping) {
                    cout << "I have " << _myWorkers[0]->_top_cg.BeadCount() << " beads in " << _myWorkers[0]->_top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                    // create the mapping + cg topology
                    if (!EvaluateTopology(&_myWorkers[0]->_top_cg, &_myWorkers[0]->_top))
                        return;
                } else
                    if (!EvaluateTopology(&_myWorkers[0]->_top))
                        return;

                _traj_reader->FirstFrame(_myWorkers[0]->_top);

                //seek to first frame, let thread0 do that
                for (bool bok = true; bok == true; bok = _traj_reader->NextFrame(_myWorkers[0]->_top)) {
                    if (((_myWorkers[0]->_top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    break;
                }

                // notify all observer that coarse graining has begun
                if (_do_mapping) {
                    _myWorkers[0]->_map->Apply();
                    BeginEvaluate(&_myWorkers[0]->_top_cg, &_myWorkers[0]->_top);
                } else
                    BeginEvaluate(&_myWorkers[0]->_top);

/////////////////////////////////////////////////////////////////////////

                //start threads
                for (long thread = 0; thread < _myWorkers.size(); thread++) {
                    _myWorkers[thread]->Start();
                }
                // hier noch nen block rein
                for (long thread = 0; thread < _myWorkers.size(); thread++) {
                    _myWorkers[thread]->WaitDone();
                    MergeWorker(_myWorkers[thread]);
                    delete _myWorkers[thread];
                }
                EndEvaluate();

                _traj_reader->Close();
                delete _traj_reader;
            }

            delete reader;

        }

        CsgApplication::Worker::~Worker() {
            if (_map)
                delete _map;

        }

        void CsgApplication::BeginEvaluate(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->BeginCG(top, top_ref);
        }

        void CsgApplication::EndEvaluate() {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EndCG();
        }

        void CsgApplication::EvalConfiguration(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EvalConfiguration(top, top_ref);
        }

        CsgApplication::Worker *CsgApplication::ForkWorker(void) {
            throw std::runtime_error("ForkWorker not implemented in application");
            return NULL;
        }

        void CsgApplication::MergeWorker(CsgApplication::Worker *worker) {
            throw std::runtime_error("MergeWorker not implemented in application");
        }

    }
}
<commit_msg>some more changes, one still have to think how best handle different instances of topology<commit_after>/*
 * Copyright 2009 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "csgapplication.h"
#include "trajectorywriter.h"
#include "trajectoryreader.h"
#include "topologyreader.h"
#include "topologymap.h"
#include "cgengine.h"
#include "version.h"
#include "votca/tools/easylock.h"

namespace votca {
    namespace csg {

        CsgApplication::CsgApplication(void) {
        }

        CsgApplication::~CsgApplication(void) {
        }

        void CsgApplication::Initialize(void) {
            // register all io plugins
            TrajectoryWriter::RegisterPlugins();
            TrajectoryReader::RegisterPlugins();
            TopologyReader::RegisterPlugins();

            AddProgramOptions()
                    ("top", boost::program_options::value<string > (), "  atomistic topology file");
            if (DoMapping()) {
                if (DoMappingDefault()) {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  coarse graining mapping definitions (xml-file)")
                            ("no-map", "  disable mapping and act on original trajectory");
                } else {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  [OPTIONAL] coarse graining mapping definitions\n"
                            "  (xml-file). If no file is given, program acts on original trajectory");
                }
            }

            if (DoTrajectory())
                AddProgramOptions("Trajectory options")
                ("trj", boost::program_options::value<string > (), "  atomistic trajectory file")
                ("begin", boost::program_options::value<double>()->default_value(0.0), "  skip frames before this time")
                ("first-frame", boost::program_options::value<int>()->default_value(0), "  start with this frame")
                ("nframes", boost::program_options::value<int>(), "  process so many frames")
                ;

            if (DoThreaded())
                AddProgramOptions("Threading options")
                ("nt", boost::program_options::value<int>()->default_value(1), "  number of threads")
                ;

        }

        bool CsgApplication::EvaluateOptions(void) {
            _do_mapping = false;
            CheckRequired("top", "no topology file specified");

            // check for mapping options
            if (DoMapping()) {
                // default mapping is on
                if (DoMappingDefault()) {
                    // if the user does not explicitly ask to turn it off, cg is needed
                    if (OptionsMap().count("no-map") == 0) {
                        CheckRequired("cg", "no coarse graining definition specified");
                        _do_mapping = true;
                    }
                }// default mapping is off, if user gives cg, then do mapping
                else if (OptionsMap().count("cg")) {
                    _do_mapping = true;
                }
            }

            /* check threading options */
            if (DoThreaded()) {
                /* TODO
                 * does the number of threads make sense?
                 * which criteria should be used? smaller than system's cores?
                 */
            }

            return true;
        }

        void CsgApplication::ShowHelpText(std::ostream &out) {
            string name = ProgramName();
            if (VersionString() != "")
                name = name + ", version " + VersionString();

            HelpTextHeader(name);
            HelpText(out);
            out << "\n\n" << OptionsDesc() << endl;
        }

        void CsgApplication::Run(void) {
            if (DoThreaded()) {
                RunThreaded();
                return;
            }
            // first read in the topology
            TopologyReader *reader;
            Topology top;

            Topology top_cg;
            TopologyMap *map = 0;
            CGEngine cg;

            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            // read in the topology
            reader->ReadTopology(_op_vm["top"].as<string > (), top);
            cout << "I have " << top.BeadCount() << " beads in " << top.MoleculeCount() << " molecules" << endl;
            top.CheckMoleculeNaming();

            if (_do_mapping) {
                // read in the coarse graining definitions (xml files)
                cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
                // create the mapping + cg topology
                map = cg.CreateCGTopology(top, top_cg);

                cout << "I have " << top_cg.BeadCount() << " beads in " << top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                map->Apply();
                if (!EvaluateTopology(&top_cg, &top))
                    return;
            } else
                if (!EvaluateTopology(&top))
                return;

            // do we need to read a trajectory?
            if (DoTrajectory()) {
                TrajectoryReader *traj_reader;

                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                int nframes = -1;
                if (_op_vm.count("nframes")) {
                    nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                traj_reader->Open(_op_vm["trj"].as<string > ());

                // read in first frame
                traj_reader->FirstFrame(top);

                // notify all observer that coarse graining has begun

                if (_do_mapping) {
                    map->Apply();
                    BeginEvaluate(&top_cg, &top);
                } else
                    BeginEvaluate(&top);

                for (bool bok = true; bok == true; bok = traj_reader->NextFrame(top)) {
                    if (((top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    if (nframes == 0) break;
                    if (_do_mapping) {
                        map->Apply();
                        EvalConfiguration(&top_cg, &top);

                    } else
                        EvalConfiguration(&top);
                    nframes--;
                }
                EndEvaluate();
                traj_reader->Close();

                delete traj_reader;
            }
            if (map)
                delete map;
            delete reader;

        }

        void CsgApplication::Worker::Run(void) {
            while (_app->ProcessData(this));
        }

        bool CsgApplication::ProcessData(Worker * worker) {
            //easyLock
            //EasyLock locker(_traj_readerMutex);
            //return traj_reader->NextFrame(*top);

            //not so easy lock
            _nframesMutex.Lock();
            if (_nframes > 0 || _nframes <= -99) {
                _nframes--;
                _nframesMutex.Unlock();
                bool tmpRes;
                _traj_readerMutex.Lock();

                tmpRes = _traj_reader->NextFrame(worker->_top);

                _traj_readerMutex.Unlock();
                if (_do_mapping) {
                    worker->_map->Apply();
                    worker->EvalConfiguration(&worker->_top_cg, &worker->_top);
                } else
                    worker->EvalConfiguration(&worker->_top);
                return tmpRes;
            } else {
                _nframesMutex.Unlock();
                return false;
            }
        }

        void CsgApplication::RunThreaded(void) {
            TopologyReader *reader;
            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            Topology top;
            Topology top_cg;
            CGEngine cg;
            TopologyMap *map;

            //////////////////////////////////////////////////
            // read in the topology for application
            //////////////////////////////////////////////////
            reader->ReadTopology(_op_vm["top"].as<string > (), top);
            cout << "I have " << top.BeadCount() << " beads in " << top.MoleculeCount() << " molecules" << endl;
            top.CheckMoleculeNaming();

            if (_do_mapping) {
                // read in the coarse graining definitions (xml files)
                cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
                // create the mapping + cg topology
                map = cg.CreateCGTopology(top, top_cg);

                cout << "I have " << top_cg.BeadCount() << " beads in " << top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                map->Apply();
                if (!EvaluateTopology(&top_cg, &top))
                    return;
            } else
                if (!EvaluateTopology(&top))
                return;

            //////////////////////////////////////////////////
            // Here trajectory parsing starts
            //////////////////////////////////////////////////
            if (DoTrajectory()) {
                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                _nframes = -1;
                if (_op_vm.count("nframes")) {
                    _nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                _traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (_traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                _traj_reader->Open(_op_vm["trj"].as<string > ());

            //////////////////////////////////////////////////
            // Create all the workers
            //////////////////////////////////////////////////
                for (int thread = 0; thread < _op_vm["nt"].as<int > (); thread++) {
                    Worker *myWorker = ForkWorker();
                    myWorker->setApplication(this);
                    myWorker->setId(thread);
                    _myWorkers.push_back(myWorker);

                    // this will me changed to CopyTopologyData
                    // read in the topology
                    reader->ReadTopology(_op_vm["top"].as<string > (), myWorker->_top);
                    myWorker->_top.CheckMoleculeNaming();

                    if (_do_mapping) {
                        // create the mapping + cg topology
                        myWorker->_map = cg.CreateCGTopology(myWorker->_top, myWorker->_top_cg);
                    }
                }

            //////////////////////////////////////////////////
            // Proceed to first frame of interest
            //////////////////////////////////////////////////

                _traj_reader->FirstFrame(_myWorkers[0]->_top);
                //seek to first frame, let thread0 do that
                for (bool bok = true; bok == true; bok = _traj_reader->NextFrame(_myWorkers[0]->_top)) {
                    if (((_myWorkers[0]->_top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    break;
                }

                // notify all observer that coarse graining has begun
                if (_do_mapping) {
                    _myWorkers[0]->_map->Apply();
                    BeginEvaluate(&_myWorkers[0]->_top_cg, &_myWorkers[0]->_top);
                } else
                    BeginEvaluate(&_myWorkers[0]->_top);

/////////////////////////////////////////////////////////////////////////

                //start threads
                for (long thread = 0; thread < _myWorkers.size(); thread++) {
                    _myWorkers[thread]->Start();
                }
                // hier noch nen block rein
                for (long thread = 0; thread < _myWorkers.size(); thread++) {
                    _myWorkers[thread]->WaitDone();
                    MergeWorker(_myWorkers[thread]);
                    delete _myWorkers[thread];
                }
                EndEvaluate();

                _traj_reader->Close();
                delete _traj_reader;
            }

            delete reader;

        }

        CsgApplication::Worker::~Worker() {
            if (_map)
                delete _map;

        }

        void CsgApplication::BeginEvaluate(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->BeginCG(top, top_ref);
        }

        void CsgApplication::EndEvaluate() {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EndCG();
        }

        void CsgApplication::EvalConfiguration(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EvalConfiguration(top, top_ref);
        }

        CsgApplication::Worker *CsgApplication::ForkWorker(void) {
            throw std::runtime_error("ForkWorker not implemented in application");
            return NULL;
        }

        void CsgApplication::MergeWorker(CsgApplication::Worker *worker) {
            throw std::runtime_error("MergeWorker not implemented in application");
        }

    }
}
<|endoftext|>


<commit_before>#pragma once

#include "types.hh"
#include "lock.hh"
#include "local-store.hh"
#include "goal.hh"

namespace nix {

/* Forward definition. */
class DerivationGoal;
class SubstitutionGoal;

/* Workaround for not being able to declare a something like

     class SubstitutionGoal : public Goal;

   even when Goal is a complete type; */
GoalPtr upcast_goal(std::shared_ptr<SubstitutionGoal> subGoal);

typedef std::chrono::time_point<std::chrono::steady_clock> steady_time_point;

/* A mapping used to remember for each child process to what goal it
   belongs, and file descriptors for receiving log data and output
   path creation commands. */
struct Child
{
    WeakGoalPtr goal;
    Goal * goal2; // ugly hackery
    set<int> fds;
    bool respectTimeouts;
    bool inBuildSlot;
    steady_time_point lastOutput; /* time we last got output on stdout/stderr */
    steady_time_point timeStarted;
};

/* Forward definition. */
struct HookInstance;

/* The worker class. */
class Worker
{
private:

    /* Note: the worker should only have strong pointers to the
       top-level goals. */

    /* The top-level goals of the worker. */
    Goals topGoals;

    /* Goals that are ready to do some work. */
    WeakGoals awake;

    /* Goals waiting for a build slot. */
    WeakGoals wantingToBuild;

    /* Child processes currently running. */
    std::list<Child> children;

    /* Number of build slots occupied.  This includes local builds and
       substitutions but not remote builds via the build hook. */
    unsigned int nrLocalBuilds;

    /* Maps used to prevent multiple instantiations of a goal for the
       same derivation / path. */
    std::map<StorePath, std::weak_ptr<DerivationGoal>> derivationGoals;
    std::map<StorePath, std::weak_ptr<SubstitutionGoal>> substitutionGoals;

    /* Goals waiting for busy paths to be unlocked. */
    WeakGoals waitingForAnyGoal;

    /* Goals sleeping for a few seconds (polling a lock). */
    WeakGoals waitingForAWhile;

    /* Last time the goals in `waitingForAWhile' where woken up. */
    steady_time_point lastWokenUp;

    /* Cache for pathContentsGood(). */
    std::map<StorePath, bool> pathContentsGoodCache;

public:

    const Activity act;
    const Activity actDerivations;
    const Activity actSubstitutions;

    /* Set if at least one derivation had a BuildError (i.e. permanent
       failure). */
    bool permanentFailure;

    /* Set if at least one derivation had a timeout. */
    bool timedOut;

    /* Set if at least one derivation fails with a hash mismatch. */
    bool hashMismatch;

    /* Set if at least one derivation is not deterministic in check mode. */
    bool checkMismatch;

    LocalStore & store;

    std::unique_ptr<HookInstance> hook;

    uint64_t expectedBuilds = 0;
    uint64_t doneBuilds = 0;
    uint64_t failedBuilds = 0;
    uint64_t runningBuilds = 0;

    uint64_t expectedSubstitutions = 0;
    uint64_t doneSubstitutions = 0;
    uint64_t failedSubstitutions = 0;
    uint64_t runningSubstitutions = 0;
    uint64_t expectedDownloadSize = 0;
    uint64_t doneDownloadSize = 0;
    uint64_t expectedNarSize = 0;
    uint64_t doneNarSize = 0;

    /* Whether to ask the build hook if it can build a derivation. If
       it answers with "decline-permanently", we don't try again. */
    bool tryBuildHook = true;

    Worker(LocalStore & store);
    ~Worker();

    /* Make a goal (with caching). */

    /* derivation goal */
private:
    std::shared_ptr<DerivationGoal> makeDerivationGoalCommon(
        const StorePath & drvPath, const StringSet & wantedOutputs,
        std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);
public:
    std::shared_ptr<DerivationGoal> makeDerivationGoal(
        const StorePath & drvPath,
        const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
    std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(
        const StorePath & drvPath, const BasicDerivation & drv,
        const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);

    /* substitution goal */
    std::shared_ptr<SubstitutionGoal> makeSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt);

    /* Remove a dead goal. */
    void removeGoal(GoalPtr goal);

    /* Wake up a goal (i.e., there is something for it to do). */
    void wakeUp(GoalPtr goal);

    /* Return the number of local build and substitution processes
       currently running (but not remote builds via the build
       hook). */
    unsigned int getNrLocalBuilds();

    /* Registers a running child process.  `inBuildSlot' means that
       the process counts towards the jobs limit. */
    void childStarted(GoalPtr goal, const set<int> & fds,
        bool inBuildSlot, bool respectTimeouts);

    /* Unregisters a running child process.  `wakeSleepers' should be
       false if there is no sense in waking up goals that are sleeping
       because they can't run yet (e.g., there is no free build slot,
       or the hook would still say `postpone'). */
    void childTerminated(Goal * goal, bool wakeSleepers = true);

    /* Put `goal' to sleep until a build slot becomes available (which
       might be right away). */
    void waitForBuildSlot(GoalPtr goal);

    /* Wait for any goal to finish.  Pretty indiscriminate way to
       wait for some resource that some other goal is holding. */
    void waitForAnyGoal(GoalPtr goal);

    /* Wait for a few seconds and then retry this goal.  Used when
       waiting for a lock held by another process.  This kind of
       polling is inefficient, but POSIX doesn't really provide a way
       to wait for multiple locks in the main select() loop. */
    void waitForAWhile(GoalPtr goal);

    /* Loop until the specified top-level goals have finished. */
    void run(const Goals & topGoals);

    /* Wait for input to become available. */
    void waitForInput();

    unsigned int exitStatus();

    /* Check whether the given valid path exists and has the right
       contents. */
    bool pathContentsGood(const StorePath & path);

    void markContentsGood(const StorePath & path);

    void updateProgress()
    {
        actDerivations.progress(doneBuilds, expectedBuilds + doneBuilds, runningBuilds, failedBuilds);
        actSubstitutions.progress(doneSubstitutions, expectedSubstitutions + doneSubstitutions, runningSubstitutions, failedSubstitutions);
        act.setExpected(actFileTransfer, expectedDownloadSize + doneDownloadSize);
        act.setExpected(actCopyPath, expectedNarSize + doneNarSize);
    }
};

}
<commit_msg>Explain that `upcast_goal` is still a static cast<commit_after>#pragma once

#include "types.hh"
#include "lock.hh"
#include "local-store.hh"
#include "goal.hh"

namespace nix {

/* Forward definition. */
class DerivationGoal;
class SubstitutionGoal;

/* Workaround for not being able to declare a something like

     class SubstitutionGoal : public Goal;

   even when Goal is a complete type.

   This is still a static cast. The purpose of exporting it is to define it in
   a place where `SubstitutionGoal` is concrete, and use it in a place where it
   is opaque. */
GoalPtr upcast_goal(std::shared_ptr<SubstitutionGoal> subGoal);

typedef std::chrono::time_point<std::chrono::steady_clock> steady_time_point;

/* A mapping used to remember for each child process to what goal it
   belongs, and file descriptors for receiving log data and output
   path creation commands. */
struct Child
{
    WeakGoalPtr goal;
    Goal * goal2; // ugly hackery
    set<int> fds;
    bool respectTimeouts;
    bool inBuildSlot;
    steady_time_point lastOutput; /* time we last got output on stdout/stderr */
    steady_time_point timeStarted;
};

/* Forward definition. */
struct HookInstance;

/* The worker class. */
class Worker
{
private:

    /* Note: the worker should only have strong pointers to the
       top-level goals. */

    /* The top-level goals of the worker. */
    Goals topGoals;

    /* Goals that are ready to do some work. */
    WeakGoals awake;

    /* Goals waiting for a build slot. */
    WeakGoals wantingToBuild;

    /* Child processes currently running. */
    std::list<Child> children;

    /* Number of build slots occupied.  This includes local builds and
       substitutions but not remote builds via the build hook. */
    unsigned int nrLocalBuilds;

    /* Maps used to prevent multiple instantiations of a goal for the
       same derivation / path. */
    std::map<StorePath, std::weak_ptr<DerivationGoal>> derivationGoals;
    std::map<StorePath, std::weak_ptr<SubstitutionGoal>> substitutionGoals;

    /* Goals waiting for busy paths to be unlocked. */
    WeakGoals waitingForAnyGoal;

    /* Goals sleeping for a few seconds (polling a lock). */
    WeakGoals waitingForAWhile;

    /* Last time the goals in `waitingForAWhile' where woken up. */
    steady_time_point lastWokenUp;

    /* Cache for pathContentsGood(). */
    std::map<StorePath, bool> pathContentsGoodCache;

public:

    const Activity act;
    const Activity actDerivations;
    const Activity actSubstitutions;

    /* Set if at least one derivation had a BuildError (i.e. permanent
       failure). */
    bool permanentFailure;

    /* Set if at least one derivation had a timeout. */
    bool timedOut;

    /* Set if at least one derivation fails with a hash mismatch. */
    bool hashMismatch;

    /* Set if at least one derivation is not deterministic in check mode. */
    bool checkMismatch;

    LocalStore & store;

    std::unique_ptr<HookInstance> hook;

    uint64_t expectedBuilds = 0;
    uint64_t doneBuilds = 0;
    uint64_t failedBuilds = 0;
    uint64_t runningBuilds = 0;

    uint64_t expectedSubstitutions = 0;
    uint64_t doneSubstitutions = 0;
    uint64_t failedSubstitutions = 0;
    uint64_t runningSubstitutions = 0;
    uint64_t expectedDownloadSize = 0;
    uint64_t doneDownloadSize = 0;
    uint64_t expectedNarSize = 0;
    uint64_t doneNarSize = 0;

    /* Whether to ask the build hook if it can build a derivation. If
       it answers with "decline-permanently", we don't try again. */
    bool tryBuildHook = true;

    Worker(LocalStore & store);
    ~Worker();

    /* Make a goal (with caching). */

    /* derivation goal */
private:
    std::shared_ptr<DerivationGoal> makeDerivationGoalCommon(
        const StorePath & drvPath, const StringSet & wantedOutputs,
        std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);
public:
    std::shared_ptr<DerivationGoal> makeDerivationGoal(
        const StorePath & drvPath,
        const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
    std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(
        const StorePath & drvPath, const BasicDerivation & drv,
        const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);

    /* substitution goal */
    std::shared_ptr<SubstitutionGoal> makeSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt);

    /* Remove a dead goal. */
    void removeGoal(GoalPtr goal);

    /* Wake up a goal (i.e., there is something for it to do). */
    void wakeUp(GoalPtr goal);

    /* Return the number of local build and substitution processes
       currently running (but not remote builds via the build
       hook). */
    unsigned int getNrLocalBuilds();

    /* Registers a running child process.  `inBuildSlot' means that
       the process counts towards the jobs limit. */
    void childStarted(GoalPtr goal, const set<int> & fds,
        bool inBuildSlot, bool respectTimeouts);

    /* Unregisters a running child process.  `wakeSleepers' should be
       false if there is no sense in waking up goals that are sleeping
       because they can't run yet (e.g., there is no free build slot,
       or the hook would still say `postpone'). */
    void childTerminated(Goal * goal, bool wakeSleepers = true);

    /* Put `goal' to sleep until a build slot becomes available (which
       might be right away). */
    void waitForBuildSlot(GoalPtr goal);

    /* Wait for any goal to finish.  Pretty indiscriminate way to
       wait for some resource that some other goal is holding. */
    void waitForAnyGoal(GoalPtr goal);

    /* Wait for a few seconds and then retry this goal.  Used when
       waiting for a lock held by another process.  This kind of
       polling is inefficient, but POSIX doesn't really provide a way
       to wait for multiple locks in the main select() loop. */
    void waitForAWhile(GoalPtr goal);

    /* Loop until the specified top-level goals have finished. */
    void run(const Goals & topGoals);

    /* Wait for input to become available. */
    void waitForInput();

    unsigned int exitStatus();

    /* Check whether the given valid path exists and has the right
       contents. */
    bool pathContentsGood(const StorePath & path);

    void markContentsGood(const StorePath & path);

    void updateProgress()
    {
        actDerivations.progress(doneBuilds, expectedBuilds + doneBuilds, runningBuilds, failedBuilds);
        actSubstitutions.progress(doneSubstitutions, expectedSubstitutions + doneSubstitutions, runningSubstitutions, failedSubstitutions);
        act.setExpected(actFileTransfer, expectedDownloadSize + doneDownloadSize);
        act.setExpected(actCopyPath, expectedNarSize + doneNarSize);
    }
};

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <iostream>

#include <llamaos/api/sleep.h>
#include <llamaos/memory/Memory.h>
#include <llamaos/net/llamaNET.h>
#include <llamaos/xen/Hypervisor.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::memory;
using namespace llamaos::net;
using namespace llamaos::xen;

const unsigned int llamaNET::HEADER_LENGTH = sizeof(llamaNET::Protocol_header);

llamaNET::llamaNET (int domd_id, int index)
   :  domd_id(domd_id),
      index(index),
      control(domd_id, 510 - index),    // hardcoded 510 for now, eventually use the xenstore
      rx_buffers(),
      tx_buffers()
{
   for (unsigned int i = 0; i < control->tx_buffer_size; i++)
   {
      tx_buffers.push_back (new Grant_map<Protocol_header>(domd_id, control->app [index].tx_refs [i]));
   }

   for (unsigned int i = 0; i < control->rx_buffer_size; i++)
   {
      rx_buffers.push_back (new Grant_map<Protocol_header>(domd_id, control->app [index].rx_refs [i], true));
   }
}

llamaNET::~llamaNET ()
{
   control->close_driver = 1;

   // pause to make sure driver gets this message
   api::sleep (2);

   for (unsigned int i = 0; i < tx_buffers.size (); i++)
   {
      delete tx_buffers [i];
   }

   for (unsigned int i = 0; i < rx_buffers.size (); i++)
   {
      delete rx_buffers [i];
   }
}

bool llamaNET::recv_poll ()
{
   // only check for message arrival
   return (   (control->driver.rx_head != control->app [index].rx_tail)
           || (control->driver.tx_head != control->app [index].tx_tail));
}

llamaNET::Protocol_header *llamaNET::recv ()
{
   // spin until message arrives
   for (;;)
   {
      if (control->driver.rx_head != control->app [index].rx_tail)
      {
         return rx_buffers [control->app [index].rx_tail]->get_pointer ();
      }

      if (control->driver.tx_head != control->app [index].tx_tail)
      {
         return tx_buffers [control->app [index].tx_tail]->get_pointer ();
      }
   }
//      while (!recv_poll ());

//   return rx_buffers [control->app [index].rx_tail]->get_pointer ();
}

llamaNET::Protocol_header *llamaNET::recv (uint32_t node)
{
   llamaNET::Protocol_header *header;

   for (;;)
   {
      header = recv ();

      if (header->dest == node)
      {
         return header;
      }

      release_recv_buffer (header);
   }
}

void llamaNET::release_recv_buffer (Protocol_header *header)
{
   if (header == rx_buffers [control->app [index].rx_tail]->get_pointer ())
   {
      unsigned int tail = control->app [index].rx_tail;
      tail++;
      tail %= control->rx_buffer_size;
      control->app [index].rx_tail = tail;
   }
   else if (header == tx_buffers [control->app [index].tx_tail]->get_pointer ())
   {
      unsigned int tail = control->app [index].tx_tail;
      tail++;
      tail %= control->tx_buffer_size;
      control->app [index].tx_tail = tail;
   }
}

llamaNET::Protocol_header *llamaNET::get_send_buffer ()
{
   // wait for last buffer to send
   while (control->app [index].tx_request);

   // get next index
   control->app [index].tx_index = __sync_fetch_and_add (&control->driver.next_tx_index, 1) & 7;

   // need atomic increment before this works with multiple llamaNET instances
   return tx_buffers [control->app [index].tx_index]->get_pointer ();
}

void llamaNET::send (Protocol_header *header)
{
//   Protocol_header *header = reinterpret_cast<Protocol_header *>(get_send_buffer ());

   // !BAM get these in a config soon
   // dalai node 0 mac 00-1b-21-d5-66-ef
   // redpj node 1 mac 68-05-ca-01-f7-db
/*
#if 0
   if (   (header->dest >= 0)
       && (header->dest < 6))
   {
      // sending to redpj
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x01;
      header->eth_dest [4] = 0xf7;
      header->eth_dest [5] = 0xdb;
   }
   else if (   (header->dest >= 6)
            && (header->dest < 12))
   {
      // sending to dalai
      header->eth_dest [0] = 0x00;
      header->eth_dest [1] = 0x1b;
      header->eth_dest [2] = 0x21;
      header->eth_dest [3] = 0xd5;
      header->eth_dest [4] = 0x66;
      header->eth_dest [5] = 0xef;
   }
   else
   {
      // throw exception?
   }

   if (   (header->src >= 0)
       && (header->src < 6))
   {
      // sending from dalai
      header->eth_src [0] = 0x00;
      header->eth_src [1] = 0x1b;
      header->eth_src [2] = 0x21;
      header->eth_src [3] = 0xd5;
      header->eth_src [4] = 0x66;
      header->eth_src [5] = 0xef;
   }
   else if (   (header->src >= 6)
            && (header->src < 12))
   {
      // sending from redpj
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x01;
      header->eth_src [4] = 0xf7;
      header->eth_src [5] = 0xdb;
   }
   else
   {
      // throw exception?
   }
#else
   // !BAM get these in a config soon
   // dalai node 0 (even) mac 00-1b-21-d5-66-ef
   // redpj node 1 (odd)  mac 68-05-ca-01-f7-db

   if ((header->dest % 2) == 0)
   {
      // sending to thor
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x06;
      header->eth_dest [4] = 0xde;
      header->eth_dest [5] = 0xc0;
   }
   else
   {
      // sending to wiley
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x06;
      header->eth_dest [4] = 0xf7;
      header->eth_dest [5] = 0x72;
   }

   if ((header->src % 2) == 0)
   {
      // sending from thor
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x06;
      header->eth_src [4] = 0xde;
      header->eth_src [5] = 0xc0;
   }
   else
   {
      // sending from wiley
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x06;
      header->eth_src [4] = 0xf7;
      header->eth_src [5] = 0x72;
   }

#endif
*/
   header->eth_type = 0x0C09;

//   unsigned int head = control->app [0].tx_head;
//   control->app [0].tx_length [head] = HEADER_LENGTH + header->len;
   control->app [index].tx_length = HEADER_LENGTH + header->len;

   // ensure write is processed
   wmb();

   control->app [index].tx_request = true;

//   head++;
//   head %= control->tx_buffer_size;
//   control->app [0].tx_head = head;
}
<commit_msg>check for eth type in recv message<commit_after>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <iostream>

#include <llamaos/api/sleep.h>
#include <llamaos/memory/Memory.h>
#include <llamaos/net/llamaNET.h>
#include <llamaos/xen/Hypervisor.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::memory;
using namespace llamaos::net;
using namespace llamaos::xen;

const unsigned int llamaNET::HEADER_LENGTH = sizeof(llamaNET::Protocol_header);

llamaNET::llamaNET (int domd_id, int index)
   :  domd_id(domd_id),
      index(index),
      control(domd_id, 510 - index),    // hardcoded 510 for now, eventually use the xenstore
      rx_buffers(),
      tx_buffers()
{
   for (unsigned int i = 0; i < control->tx_buffer_size; i++)
   {
      tx_buffers.push_back (new Grant_map<Protocol_header>(domd_id, control->app [index].tx_refs [i]));
   }

   for (unsigned int i = 0; i < control->rx_buffer_size; i++)
   {
      rx_buffers.push_back (new Grant_map<Protocol_header>(domd_id, control->app [index].rx_refs [i], true));
   }
}

llamaNET::~llamaNET ()
{
   control->close_driver = 1;

   // pause to make sure driver gets this message
   api::sleep (2);

   for (unsigned int i = 0; i < tx_buffers.size (); i++)
   {
      delete tx_buffers [i];
   }

   for (unsigned int i = 0; i < rx_buffers.size (); i++)
   {
      delete rx_buffers [i];
   }
}

bool llamaNET::recv_poll ()
{
   // only check for message arrival
   return (   (control->driver.rx_head != control->app [index].rx_tail)
           || (control->driver.tx_head != control->app [index].tx_tail));
}

llamaNET::Protocol_header *llamaNET::recv ()
{
   // spin until message arrives
   for (;;)
   {
      if (control->driver.rx_head != control->app [index].rx_tail)
      {
         return rx_buffers [control->app [index].rx_tail]->get_pointer ();
      }

      if (control->driver.tx_head != control->app [index].tx_tail)
      {
         return tx_buffers [control->app [index].tx_tail]->get_pointer ();
      }
   }
//      while (!recv_poll ());

//   return rx_buffers [control->app [index].rx_tail]->get_pointer ();
}

llamaNET::Protocol_header *llamaNET::recv (uint32_t node)
{
   llamaNET::Protocol_header *header;

   for (;;)
   {
      header = recv ();

      if (   (header->eth_type == 0x0C09)
          && (header->dest == node))
      {
         return header;
      }

      release_recv_buffer (header);
   }
}

void llamaNET::release_recv_buffer (Protocol_header *header)
{
   if (header == rx_buffers [control->app [index].rx_tail]->get_pointer ())
   {
      unsigned int tail = control->app [index].rx_tail;
      tail++;
      tail %= control->rx_buffer_size;
      control->app [index].rx_tail = tail;
   }
   else if (header == tx_buffers [control->app [index].tx_tail]->get_pointer ())
   {
      unsigned int tail = control->app [index].tx_tail;
      tail++;
      tail %= control->tx_buffer_size;
      control->app [index].tx_tail = tail;
   }
}

llamaNET::Protocol_header *llamaNET::get_send_buffer ()
{
   // wait for last buffer to send
   while (control->app [index].tx_request);

   // get next index
   control->app [index].tx_index = __sync_fetch_and_add (&control->driver.next_tx_index, 1) & 7;

   // need atomic increment before this works with multiple llamaNET instances
   return tx_buffers [control->app [index].tx_index]->get_pointer ();
}

void llamaNET::send (Protocol_header *header)
{
//   Protocol_header *header = reinterpret_cast<Protocol_header *>(get_send_buffer ());

   // !BAM get these in a config soon
   // dalai node 0 mac 00-1b-21-d5-66-ef
   // redpj node 1 mac 68-05-ca-01-f7-db
/*
#if 0
   if (   (header->dest >= 0)
       && (header->dest < 6))
   {
      // sending to redpj
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x01;
      header->eth_dest [4] = 0xf7;
      header->eth_dest [5] = 0xdb;
   }
   else if (   (header->dest >= 6)
            && (header->dest < 12))
   {
      // sending to dalai
      header->eth_dest [0] = 0x00;
      header->eth_dest [1] = 0x1b;
      header->eth_dest [2] = 0x21;
      header->eth_dest [3] = 0xd5;
      header->eth_dest [4] = 0x66;
      header->eth_dest [5] = 0xef;
   }
   else
   {
      // throw exception?
   }

   if (   (header->src >= 0)
       && (header->src < 6))
   {
      // sending from dalai
      header->eth_src [0] = 0x00;
      header->eth_src [1] = 0x1b;
      header->eth_src [2] = 0x21;
      header->eth_src [3] = 0xd5;
      header->eth_src [4] = 0x66;
      header->eth_src [5] = 0xef;
   }
   else if (   (header->src >= 6)
            && (header->src < 12))
   {
      // sending from redpj
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x01;
      header->eth_src [4] = 0xf7;
      header->eth_src [5] = 0xdb;
   }
   else
   {
      // throw exception?
   }
#else
   // !BAM get these in a config soon
   // dalai node 0 (even) mac 00-1b-21-d5-66-ef
   // redpj node 1 (odd)  mac 68-05-ca-01-f7-db

   if ((header->dest % 2) == 0)
   {
      // sending to thor
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x06;
      header->eth_dest [4] = 0xde;
      header->eth_dest [5] = 0xc0;
   }
   else
   {
      // sending to wiley
      header->eth_dest [0] = 0x68;
      header->eth_dest [1] = 0x05;
      header->eth_dest [2] = 0xca;
      header->eth_dest [3] = 0x06;
      header->eth_dest [4] = 0xf7;
      header->eth_dest [5] = 0x72;
   }

   if ((header->src % 2) == 0)
   {
      // sending from thor
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x06;
      header->eth_src [4] = 0xde;
      header->eth_src [5] = 0xc0;
   }
   else
   {
      // sending from wiley
      header->eth_src [0] = 0x68;
      header->eth_src [1] = 0x05;
      header->eth_src [2] = 0xca;
      header->eth_src [3] = 0x06;
      header->eth_src [4] = 0xf7;
      header->eth_src [5] = 0x72;
   }

#endif
*/
   header->eth_type = 0x0C09;

//   unsigned int head = control->app [0].tx_head;
//   control->app [0].tx_length [head] = HEADER_LENGTH + header->len;
   control->app [index].tx_length = HEADER_LENGTH + header->len;

   // ensure write is processed
   wmb();

   control->app [index].tx_request = true;

//   head++;
//   head %= control->tx_buffer_size;
//   control->app [0].tx_head = head;
}
<|endoftext|>


<commit_before>//
// Created by Jannis Hoppe on 29.01.16.
//
const double c = 340.42;    // speed of sound constant
const double PI = 3.141592653589793238460;
#include "srpphat.h"
#include "../utils/fft_lib.h"
namespace taylortrack {
    namespace localization {
        SrpPhat::SrpPhat(const int samplerate,const RArray &xDimMics,const RArray &yDimMics,const double xLength, const double yLength, double stepSize, int steps, double beta) {
            samplerate_ = samplerate;
            xDimMics_ = xDimMics;
            yDimMics_ = yDimMics;
            xLength_ = xLength;
            yLength_ = yLength;
            stepSize_ = stepSize;
            steps_ = steps;
            beta_ = beta;
        }

        double SrpPhat::imtdf(RArray &point, RArray &mic1, RArray &mic2) {
            return (std::sqrt(std::pow(point - mic1, 2).sum()) - std::sqrt(std::pow(point - mic2, 2).sum())) / c;
        }

        int SrpPhat::pointToAngle(double x_coordinate, double y_coordinate) {
            return (int) round(fmod(((atan2(y_coordinate,x_coordinate) * 180 / PI)+360) ,360.0));
        }

        std::vector< std::tuple<int,int>> SrpPhat::getMicPairs(){
            std::vector< std::tuple<int,int>> pairs;
            // iterating over microphones
            for (int i=0; i <xDimMics_.size(); i++){
                for (int j=0;j<xDimMics_.size();j++){
                    // only append pairs once and don't consider pairs of the same microphone
                    if (j>i){
                        pairs.push_back(std::make_tuple(i,j));
                    }
                }
            }
            return pairs;
        }

        RArray SrpPhat::gcc(RArray &signal1, RArray &signal2){
            size_t corr_length = signal1.size()+signal2.size() -1;
            // bringing the signals into the right shape to work with the fftlib
            // first making them complex and pad with necessary zeros
            taylortrack::utils::FftLib fft_obj = taylortrack::utils::FftLib();
            CArray tempsignal1 = fft_obj.converttocomp(signal1);
            CArray tempsignal2 = fft_obj.converttocomp(signal2);
            CArray csignal1 = fft_obj.zeropadding(tempsignal1,(int) (corr_length-signal1.size()));
            CArray csignal2 = fft_obj.zeropadding(tempsignal2,(int) (corr_length-signal2.size()));

            // perform FFT on the converted signals
            fft_obj.fft(csignal1);
            fft_obj.fft(csignal2);

            // computing nominator and denominator of the generalized cross correlation
            CArray nominator = csignal1 * csignal2.apply(std::conj);
            CArray denominator = std::pow(abs(nominator),(float) beta_);

            // reverse transfering to time domain
            CArray temp = nominator / denominator;

            fft_obj.ifft(temp);

            RArray result(temp.size());
            RArray temp3 = fft_obj.converttoreal(temp);

            fft_obj.fftshift(result, temp3);

            return result;
        }

        std::vector<double> SrpPhat::getAxisvalues(bool xaxis){
            std::vector<double> axisValues;
            int vectorSize = (int) (xaxis ? xLength_/stepSize_ +1  : yLength_/stepSize_ +1);
            double axStart = xaxis ? xLength_/2 * -1 : yLength_/2;
            while(axisValues.size()<vectorSize){
                axisValues.push_back(axStart);
                axStart = xaxis ? axStart + stepSize_ : axStart - stepSize_;
            }
            return axisValues;
        }

        RArray SrpPhat::getPositionDistribution(std::vector<std::vector<double>> &gccGrid){
            RArray degreevals(360);
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);

            for (int i=0;i<xAxisValues.size();i++){
                for(int j=0;j<yAxisValues.size();j++){
                    int deg = pointToAngle(xAxisValues[i], yAxisValues[j]);
                    if (deg == 360)
                        deg = 0;
                    degreevals[deg] += gccGrid[i][j];
                }
            }
            // get maximum for normalization of values
            double res = degreevals.sum();
            return degreevals / res;
        };

        int SrpPhat::getPosition(std::vector<std::vector<double>> &gccGrid) {
            RArray degreevals(360);
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);
            for (int i=0;i<360;i++){
                degreevals[i] = 0;
            }
            int vectorSize = (int) (xLength_/stepSize_ +1);
            for (int i=0;i<vectorSize;i++){
                for(int j=0;j<vectorSize;j++){
                    int deg = pointToAngle(xAxisValues[j],(double) yAxisValues[i]);
                    if (deg == 360)
                        deg = 0;
                    degreevals[deg] += gccGrid[j][i];
                }
            }
            double res = degreevals.max();
            return findVal(degreevals,res);
        };

        int SrpPhat::findVal(RArray &ra,double val){
            for(int i=0;i<ra.size();i++){
                if (std::abs(ra[i] - val) < 0.0001){
                    return i;
                }
            }
            return -1;
        }

        std::vector<std::vector<double>> SrpPhat::getGccGrid(std::vector<RArray> &signals){
            std::vector< std::tuple<int,int>> pairs = getMicPairs();
            std::vector<std::vector<double>> gccValues;
            unsigned long vectorSize = (unsigned long) (xLength_ / stepSize_ + 1);
            // initializing the gcc grid
            gccValues.resize(vectorSize);
            for (int i = 0; i < vectorSize; ++i) {
                gccValues[i].resize(vectorSize);
            }

            size_t signalLength = signals[0].size();
            long steps = signalLength / steps_ +1 ;
            std::vector<std::vector<std::vector<double>>> micDelays = getDelayTensor();
            // iterating over all microphone pairs
            for(int i=0;i<pairs.size();i++) {
                    RArray mic1(2);
                    RArray mic2(2);
                    int index1 = std::get<0>(pairs[i]);
                    int index2 = std::get<1>(pairs[i]);
                    // getting the coordinates of the mic pair
                    mic1[0] = xDimMics_[index1];
                    mic1[1] = yDimMics_[index1];
                    mic2[0] = xDimMics_[index2];
                    mic2[1] = yDimMics_[index2];
                    // assigning the corresponding signals
                    RArray signal1 = signals[index1];
                    RArray signal2 = signals[index2];
                        // get the current frame from the complete signal
                    RArray signalSlice1 = signal1[std::slice(0, steps_+1, 1)];
                    RArray signalSlice2 = signal2[std::slice(0, steps_, 1)];
                    // computing the cross correlation of both frames
                    int temp = signalSlice1.size();
                    int temp2 = signalSlice2.size();
                    RArray gccTemp = gcc(signalSlice1,signalSlice2);
                    // iterating over the whole x-y grid
                    for(int x=0;x<vectorSize;x++){
                        for(int y=0;y<vectorSize;y++){
                            double del = micDelays[x][y][i];
                            // adding the corresponding cross correlation value to the grid
                            gccValues[x][y] += gccTemp[(steps_-1)+round(del/(1.0/samplerate_))];
                        }
                    }
                }
            return gccValues;
        }

        std::vector<std::vector<std::vector<double>>> SrpPhat::getDelayTensor() {
            std::vector<std::vector<std::vector<double>>> delayTensor;
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);
            std::vector< std::tuple<int,int>> pairs = getMicPairs();
            int vectorSize = xLength_/stepSize_+1;

            int depth = pairs.size();
            delayTensor.resize(vectorSize);
            for (int i = 0; i < vectorSize; ++i) {
                delayTensor[i].resize(vectorSize);
                for (int j = 0; j < vectorSize; ++j)
                    delayTensor[i][j].resize(depth);
            }

            // iterating over the grid
            for(int x=0;x<vectorSize;x++){
                for(int y=0;y<vectorSize;y++){
                    // iterating over microphone pairs
                    for(int i=0;i<pairs.size();i++) {
                                //
                        RArray point(2);
                        RArray mic1(2);
                        RArray mic2(2);
                        // assigning the current point in the grid
                        point[0] = xAxisValues[x];
                        point[1] = yAxisValues[y];
                        // assigning the microphone values
                        int index1 = std::get<0>(pairs[i]);
                        int index2 = std::get<1>(pairs[i]);
                        mic1[0] = xDimMics_[index1];
                        mic1[1] = yDimMics_[index1];
                        mic2[0] = xDimMics_[index2];
                        mic2[1] = yDimMics_[index2];
                        double delay = imtdf(point,mic1,mic2);
                        delayTensor[x][y][i] = delay;
                    }
                }
            }
            // iterating over all microphone pairs
            return delayTensor;
        }

        RArray SrpPhat::getMicSignal(const std::string &s) {
            std::vector<double> tmp;
            std::ifstream infile(s);
            std::string line;
            while(std::getline(infile,line)) {
                std::istringstream ss(line);

                double a;
                if(!(ss >> a))
                    break;

                tmp.push_back(a);
            }
            infile.close();
            RArray signal(tmp.size());
            for (int i=0;i<tmp.size();i++){
                signal[i] = tmp[i];
            }
            return signal;
        }
    }
}<commit_msg>fixed Jannis' mistake. Tuple has to be included<commit_after>//
// Created by Jannis Hoppe on 29.01.16.
//
const double c = 340.42;    // speed of sound constant
const double PI = 3.141592653589793238460;

#include <tuple>
#include "srpphat.h"
#include "../utils/fft_lib.h"
namespace taylortrack {
    namespace localization {
        SrpPhat::SrpPhat(const int samplerate,const RArray &xDimMics,const RArray &yDimMics,const double xLength, const double yLength, double stepSize, int steps, double beta) {
            samplerate_ = samplerate;
            xDimMics_ = xDimMics;
            yDimMics_ = yDimMics;
            xLength_ = xLength;
            yLength_ = yLength;
            stepSize_ = stepSize;
            steps_ = steps;
            beta_ = beta;
        }

        double SrpPhat::imtdf(RArray &point, RArray &mic1, RArray &mic2) {
            return (std::sqrt(std::pow(point - mic1, 2).sum()) - std::sqrt(std::pow(point - mic2, 2).sum())) / c;
        }

        int SrpPhat::pointToAngle(double x_coordinate, double y_coordinate) {
            return (int) round(fmod(((atan2(y_coordinate,x_coordinate) * 180 / PI)+360) ,360.0));
        }

        std::vector< std::tuple<int,int>> SrpPhat::getMicPairs(){
            std::vector< std::tuple<int,int>> pairs;
            // iterating over microphones
            for (int i=0; i <xDimMics_.size(); i++){
                for (int j=0;j<xDimMics_.size();j++){
                    // only append pairs once and don't consider pairs of the same microphone
                    if (j>i){
                        pairs.push_back(std::make_tuple(i,j));
                    }
                }
            }
            return pairs;
        }

        RArray SrpPhat::gcc(RArray &signal1, RArray &signal2){
            size_t corr_length = signal1.size()+signal2.size() -1;
            // bringing the signals into the right shape to work with the fftlib
            // first making them complex and pad with necessary zeros
            taylortrack::utils::FftLib fft_obj = taylortrack::utils::FftLib();
            CArray tempsignal1 = fft_obj.converttocomp(signal1);
            CArray tempsignal2 = fft_obj.converttocomp(signal2);
            CArray csignal1 = fft_obj.zeropadding(tempsignal1,(int) (corr_length-signal1.size()));
            CArray csignal2 = fft_obj.zeropadding(tempsignal2,(int) (corr_length-signal2.size()));

            // perform FFT on the converted signals
            fft_obj.fft(csignal1);
            fft_obj.fft(csignal2);

            // computing nominator and denominator of the generalized cross correlation
            CArray nominator = csignal1 * csignal2.apply(std::conj);
            CArray denominator = std::pow(abs(nominator),(float) beta_);

            // reverse transfering to time domain
            CArray temp = nominator / denominator;

            fft_obj.ifft(temp);

            RArray result(temp.size());
            RArray temp3 = fft_obj.converttoreal(temp);

            fft_obj.fftshift(result, temp3);

            return result;
        }

        std::vector<double> SrpPhat::getAxisvalues(bool xaxis){
            std::vector<double> axisValues;
            int vectorSize = (int) (xaxis ? xLength_/stepSize_ +1  : yLength_/stepSize_ +1);
            double axStart = xaxis ? xLength_/2 * -1 : yLength_/2;
            while(axisValues.size()<vectorSize){
                axisValues.push_back(axStart);
                axStart = xaxis ? axStart + stepSize_ : axStart - stepSize_;
            }
            return axisValues;
        }

        RArray SrpPhat::getPositionDistribution(std::vector<std::vector<double>> &gccGrid){
            RArray degreevals(360);
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);

            for (int i=0;i<xAxisValues.size();i++){
                for(int j=0;j<yAxisValues.size();j++){
                    int deg = pointToAngle(xAxisValues[i], yAxisValues[j]);
                    if (deg == 360)
                        deg = 0;
                    degreevals[deg] += gccGrid[i][j];
                }
            }
            // get maximum for normalization of values
            double res = degreevals.sum();
            return degreevals / res;
        };

        int SrpPhat::getPosition(std::vector<std::vector<double>> &gccGrid) {
            RArray degreevals(360);
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);
            for (int i=0;i<360;i++){
                degreevals[i] = 0;
            }
            int vectorSize = (int) (xLength_/stepSize_ +1);
            for (int i=0;i<vectorSize;i++){
                for(int j=0;j<vectorSize;j++){
                    int deg = pointToAngle(xAxisValues[j],(double) yAxisValues[i]);
                    if (deg == 360)
                        deg = 0;
                    degreevals[deg] += gccGrid[j][i];
                }
            }
            double res = degreevals.max();
            return findVal(degreevals,res);
        };

        int SrpPhat::findVal(RArray &ra,double val){
            for(int i=0;i<ra.size();i++){
                if (std::abs(ra[i] - val) < 0.0001){
                    return i;
                }
            }
            return -1;
        }

        std::vector<std::vector<double>> SrpPhat::getGccGrid(std::vector<RArray> &signals){
            std::vector< std::tuple<int,int>> pairs = getMicPairs();
            std::vector<std::vector<double>> gccValues;
            unsigned long vectorSize = (unsigned long) (xLength_ / stepSize_ + 1);
            // initializing the gcc grid
            gccValues.resize(vectorSize);
            for (int i = 0; i < vectorSize; ++i) {
                gccValues[i].resize(vectorSize);
            }

            size_t signalLength = signals[0].size();
            long steps = signalLength / steps_ +1 ;
            std::vector<std::vector<std::vector<double>>> micDelays = getDelayTensor();
            // iterating over all microphone pairs
            for(int i=0;i<pairs.size();i++) {
                    RArray mic1(2);
                    RArray mic2(2);
                    int index1 = std::get<0>(pairs[i]);
                    int index2 = std::get<1>(pairs[i]);
                    // getting the coordinates of the mic pair
                    mic1[0] = xDimMics_[index1];
                    mic1[1] = yDimMics_[index1];
                    mic2[0] = xDimMics_[index2];
                    mic2[1] = yDimMics_[index2];
                    // assigning the corresponding signals
                    RArray signal1 = signals[index1];
                    RArray signal2 = signals[index2];
                        // get the current frame from the complete signal
                    RArray signalSlice1 = signal1[std::slice(0, steps_+1, 1)];
                    RArray signalSlice2 = signal2[std::slice(0, steps_, 1)];
                    // computing the cross correlation of both frames
                    int temp = signalSlice1.size();
                    int temp2 = signalSlice2.size();
                    RArray gccTemp = gcc(signalSlice1,signalSlice2);
                    // iterating over the whole x-y grid
                    for(int x=0;x<vectorSize;x++){
                        for(int y=0;y<vectorSize;y++){
                            double del = micDelays[x][y][i];
                            // adding the corresponding cross correlation value to the grid
                            gccValues[x][y] += gccTemp[(steps_-1)+round(del/(1.0/samplerate_))];
                        }
                    }
                }
            return gccValues;
        }

        std::vector<std::vector<std::vector<double>>> SrpPhat::getDelayTensor() {
            std::vector<std::vector<std::vector<double>>> delayTensor;
            std::vector<double> xAxisValues = getAxisvalues(true);
            std::vector<double> yAxisValues = getAxisvalues(false);
            std::vector< std::tuple<int,int>> pairs = getMicPairs();
            int vectorSize = xLength_/stepSize_+1;

            int depth = pairs.size();
            delayTensor.resize(vectorSize);
            for (int i = 0; i < vectorSize; ++i) {
                delayTensor[i].resize(vectorSize);
                for (int j = 0; j < vectorSize; ++j)
                    delayTensor[i][j].resize(depth);
            }

            // iterating over the grid
            for(int x=0;x<vectorSize;x++){
                for(int y=0;y<vectorSize;y++){
                    // iterating over microphone pairs
                    for(int i=0;i<pairs.size();i++) {
                                //
                        RArray point(2);
                        RArray mic1(2);
                        RArray mic2(2);
                        // assigning the current point in the grid
                        point[0] = xAxisValues[x];
                        point[1] = yAxisValues[y];
                        // assigning the microphone values
                        int index1 = std::get<0>(pairs[i]);
                        int index2 = std::get<1>(pairs[i]);
                        mic1[0] = xDimMics_[index1];
                        mic1[1] = yDimMics_[index1];
                        mic2[0] = xDimMics_[index2];
                        mic2[1] = yDimMics_[index2];
                        double delay = imtdf(point,mic1,mic2);
                        delayTensor[x][y][i] = delay;
                    }
                }
            }
            // iterating over all microphone pairs
            return delayTensor;
        }

        RArray SrpPhat::getMicSignal(const std::string &s) {
            std::vector<double> tmp;
            std::ifstream infile(s);
            std::string line;
            while(std::getline(infile,line)) {
                std::istringstream ss(line);

                double a;
                if(!(ss >> a))
                    break;

                tmp.push_back(a);
            }
            infile.close();
            RArray signal(tmp.size());
            for (int i=0;i<tmp.size();i++){
                signal[i] = tmp[i];
            }
            return signal;
        }
    }
}<|endoftext|>