<commit_before>
//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Dagoberto Salazar - gAGE. 2007
//
//============================================================================

#include "TypeID.hpp"

/**
 * @file TypeID.cpp
 * gpstk::TypeID - Identifies types of values
 */

namespace gpstk
{
   std::map< TypeID::ValueType, std::string > TypeID::tStrings;

   TypeID::Initializer TypeIDsingleton;

   TypeID::Initializer::Initializer()
   {
      tStrings[Unknown] = "UnknownType";
      tStrings[C1]      = "C1";
      tStrings[C2]      = "C2";
      tStrings[P1]      = "P1";
      tStrings[P2]      = "P2";
      tStrings[L1]      = "L1";
      tStrings[L2]      = "L2";
      tStrings[D1]      = "D1";
      tStrings[D2]      = "D2";
      tStrings[S1]      = "S1";
      tStrings[S2]      = "S2";
      tStrings[T1]      = "T1";
      tStrings[T2]      = "T2";
      tStrings[SSI1]     = "SSI1";
      tStrings[LLI1]     = "LLI1";
      tStrings[SSI2]     = "SSI2";
      tStrings[LLI2]     = "LLI2";
      tStrings[C5]      = "C5";
      tStrings[L5]      = "L5";
      tStrings[D5]      = "D5";
      tStrings[S5]      = "S5";
      tStrings[SSI5]    = "SSI5";
      tStrings[LLI5]    = "LLI5";
      tStrings[C6]      = "C6";
      tStrings[L6]      = "L6";
      tStrings[D6]      = "D6";
      tStrings[S6]      = "S6";
      tStrings[SSI6]    = "SSI6";
      tStrings[LLI6]    = "LLI6";
      tStrings[C7]      = "C7";
      tStrings[L7]      = "L7";
      tStrings[D7]      = "D7";
      tStrings[S7]      = "S7";
      tStrings[SSI7]    = "SSI7";
      tStrings[LLI7]    = "LLI7";
      tStrings[C8]      = "C8";
      tStrings[L8]      = "L8";
      tStrings[D8]      = "D8";
      tStrings[S8]      = "S8";
      tStrings[SSI8]    = "SSI8";
      tStrings[LLI8]    = "LLI8";
      tStrings[PC]      = "PC";
      tStrings[LC]      = "LC";
      tStrings[PI]      = "PI";
      tStrings[LI]      = "LI";
      tStrings[Pdelta]  = "Pdelta";
      tStrings[Ldelta]  = "Ldelta";
      tStrings[rho]     = "rho";
      tStrings[dtSat]   = "dtSat";
      tStrings[rel]     = "rel";
      tStrings[tropo]   = "tropo";
      tStrings[dryTropo] = "dry tropo";
      tStrings[wetTropo] = "wet tropo";
      tStrings[tropoSlant] = "slant tropo";
      tStrings[iono]    = "vertical iono";
      tStrings[ionoSlant] = "slant iono";
      tStrings[windUp]  = "windup";
      tStrings[satX]    = "satX";
      tStrings[satY]    = "satY";
      tStrings[satZ]    = "satZ";
      tStrings[elevation] = "elevation";
      tStrings[azimuth] = "azimuth";
      tStrings[BL1]     = "ambiguity L1";
      tStrings[BL2]     = "ambiguity L2";
      tStrings[BL5]     = "ambiguity L5";
      tStrings[BL6]     = "ambiguity L6";
      tStrings[BL7]     = "ambiguity L7";
      tStrings[BL8]     = "ambiguity L8";
      tStrings[mpC1]    = "multipath C1";
      tStrings[mpC2]    = "multipath C2";
      tStrings[mpC5]    = "multipath C5";
      tStrings[mpC6]    = "multipath C6";
      tStrings[mpC7]    = "multipath C7";
      tStrings[mpC8]    = "multipath C8";
      tStrings[mpL1]    = "multipath L1";
      tStrings[mpL2]    = "multipath L2";
      tStrings[mpL5]    = "multipath L5";
      tStrings[mpL6]    = "multipath L6";
      tStrings[mpL7]    = "multipath L7";
      tStrings[mpL8]    = "multipath L8";
      tStrings[instC1]  = "instrumental C1";
      tStrings[instC2]  = "instrumental C2";
      tStrings[instC5]  = "instrumental C5";
      tStrings[instC6]  = "instrumental C6";
      tStrings[instC7]  = "instrumental C7";
      tStrings[instC8]  = "instrumental C8";
      tStrings[instL1]  = "instrumental L1";
      tStrings[instL2]  = "instrumental L2";
      tStrings[instL5]  = "instrumental L5";
      tStrings[instL6]  = "instrumental L6";
      tStrings[instL7]  = "instrumental L7";
      tStrings[instL8]  = "instrumental L8";
      tStrings[prefitC] = "prefit residual code";
      tStrings[prefitL] = "prefit residual phase";
      tStrings[postfitC] = "posfit residual code";
      tStrings[postfitL] = "posfit residual phase";
      tStrings[rhoX]    = "unit vector X";
      tStrings[rhoY]    = "unit vector Y";
      tStrings[rhoZ]    = "unit vector Z";
      tStrings[dX]      = "dX";
      tStrings[dY]      = "dY";
      tStrings[dZ]      = "dZ";
      tStrings[dt]      = "Rx clock offset";
      tStrings[dLat]    = "dLat";
      tStrings[dLon]    = "dLon";
      tStrings[dH]      = "dH";
      tStrings[weight]  = "weight";
      tStrings[recX]    = "Rx position X";
      tStrings[recY]    = "Rx position Y";
      tStrings[recZ]    = "Rx position Z";
      tStrings[recLat]  = "Rx Lat";
      tStrings[recLon]  = "Rx Lon";
      tStrings[recH]    = "Rx H";
      tStrings[sigma]   = "sigma";
   }

   std::ostream& TypeID::dump(std::ostream& s) const
   {
      s << TypeID::tStrings[type];

      return s;
   } // TypeID::dump()

   bool TypeID::isValid() const
   {
      // At some time this needs to be implemented.
      return !(type==Unknown);
   }

   TypeID::ValueType TypeID::newValueType(const std::string& s)
   {
      ValueType newId =
         static_cast<ValueType>(TypeID::tStrings.rbegin()->first + 1);
      TypeID::tStrings[newId] = s;
      return newId;
   }

   namespace StringUtils
   {
      // convert this object to a string representation
      std::string asString(const TypeID& p)
      {
         std::ostringstream oss;
         p.dump(oss);
         return oss.str();
      }
   }

   // stream output for TypeID
   std::ostream& operator<<(std::ostream& s, const TypeID& p)
   {
      p.dump(s);
      return s;
   }

}
<commit_msg>More changes in TypeID description strings.<commit_after>
//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Dagoberto Salazar - gAGE. 2007
//
//============================================================================

#include "TypeID.hpp"

/**
 * @file TypeID.cpp
 * gpstk::TypeID - Identifies types of values
 */

namespace gpstk
{
   std::map< TypeID::ValueType, std::string > TypeID::tStrings;

   TypeID::Initializer TypeIDsingleton;

   TypeID::Initializer::Initializer()
   {
      tStrings[Unknown] = "UnknownType";
      tStrings[C1]      = "C1";
      tStrings[C2]      = "C2";
      tStrings[P1]      = "P1";
      tStrings[P2]      = "P2";
      tStrings[L1]      = "L1";
      tStrings[L2]      = "L2";
      tStrings[D1]      = "D1";
      tStrings[D2]      = "D2";
      tStrings[S1]      = "S1";
      tStrings[S2]      = "S2";
      tStrings[T1]      = "T1";
      tStrings[T2]      = "T2";
      tStrings[SSI1]    = "SSI1";
      tStrings[LLI1]    = "LLI1";
      tStrings[SSI2]    = "SSI2";
      tStrings[LLI2]    = "LLI2";
      tStrings[C5]      = "C5";
      tStrings[L5]      = "L5";
      tStrings[D5]      = "D5";
      tStrings[S5]      = "S5";
      tStrings[SSI5]    = "SSI5";
      tStrings[LLI5]    = "LLI5";
      tStrings[C6]      = "C6";
      tStrings[L6]      = "L6";
      tStrings[D6]      = "D6";
      tStrings[S6]      = "S6";
      tStrings[SSI6]    = "SSI6";
      tStrings[LLI6]    = "LLI6";
      tStrings[C7]      = "C7";
      tStrings[L7]      = "L7";
      tStrings[D7]      = "D7";
      tStrings[S7]      = "S7";
      tStrings[SSI7]    = "SSI7";
      tStrings[LLI7]    = "LLI7";
      tStrings[C8]      = "C8";
      tStrings[L8]      = "L8";
      tStrings[D8]      = "D8";
      tStrings[S8]      = "S8";
      tStrings[SSI8]    = "SSI8";
      tStrings[LLI8]    = "LLI8";
      tStrings[PC]      = "PC";
      tStrings[LC]      = "LC";
      tStrings[PI]      = "PI";
      tStrings[LI]      = "LI";
      tStrings[Pdelta]  = "Pdelta";
      tStrings[Ldelta]  = "Ldelta";
      tStrings[rho]     = "rho";
      tStrings[dtSat]   = "dtSat";
      tStrings[rel]     = "rel";
      tStrings[tropo]   = "tropo";
      tStrings[dryTropo] = "dryTropo";
      tStrings[wetTropo] = "wetTropo";
      tStrings[tropoSlant] = "slantTropo";
      tStrings[iono]    = "verticalIono";
      tStrings[ionoSlant] = "slantIono";
      tStrings[windUp]  = "windup";
      tStrings[satX]    = "satX";
      tStrings[satY]    = "satY";
      tStrings[satZ]    = "satZ";
      tStrings[elevation] = "elevation";
      tStrings[azimuth] = "azimuth";
      tStrings[BL1]     = "ambiguityL1";
      tStrings[BL2]     = "ambiguityL2";
      tStrings[BL5]     = "ambiguityL5";
      tStrings[BL6]     = "ambiguityL6";
      tStrings[BL7]     = "ambiguityL7";
      tStrings[BL8]     = "ambiguityL8";
      tStrings[mpC1]    = "multipathC1";
      tStrings[mpC2]    = "multipathC2";
      tStrings[mpC5]    = "multipathC5";
      tStrings[mpC6]    = "multipathC6";
      tStrings[mpC7]    = "multipathC7";
      tStrings[mpC8]    = "multipathC8";
      tStrings[mpL1]    = "multipathL1";
      tStrings[mpL2]    = "multipathL2";
      tStrings[mpL5]    = "multipathL5";
      tStrings[mpL6]    = "multipathL6";
      tStrings[mpL7]    = "multipathL7";
      tStrings[mpL8]    = "multipathL8";
      tStrings[instC1]  = "instrumentalC1";
      tStrings[instC2]  = "instrumentalC2";
      tStrings[instC5]  = "instrumentalC5";
      tStrings[instC6]  = "instrumentalC6";
      tStrings[instC7]  = "instrumentalC7";
      tStrings[instC8]  = "instrumentalC8";
      tStrings[instL1]  = "instrumentalL1";
      tStrings[instL2]  = "instrumentalL2";
      tStrings[instL5]  = "instrumentalL5";
      tStrings[instL6]  = "instrumentalL6";
      tStrings[instL7]  = "instrumentalL7";
      tStrings[instL8]  = "instrumentalL8";
      tStrings[prefitC] = "prefitResidualCode";
      tStrings[prefitL] = "prefitResidualPhase";
      tStrings[postfitC] = "posfitResidualCode";
      tStrings[postfitL] = "posfitResidualPhase";
      tStrings[rhoX]    = "unitVectorX";
      tStrings[rhoY]    = "unitVectorY";
      tStrings[rhoZ]    = "unitVectorZ";
      tStrings[dX]      = "dX";
      tStrings[dY]      = "dY";
      tStrings[dZ]      = "dZ";
      tStrings[dt]      = "RxClockOffset";
      tStrings[dLat]    = "dLat";
      tStrings[dLon]    = "dLon";
      tStrings[dH]      = "dH";
      tStrings[weight]  = "weight";
      tStrings[recX]    = "RxPositionX";
      tStrings[recY]    = "RxPositionY";
      tStrings[recZ]    = "RxPositionZ";
      tStrings[recLat]  = "RxLat";
      tStrings[recLon]  = "RxLon";
      tStrings[recH]    = "RxH";
      tStrings[sigma]   = "sigma";
   }

   std::ostream& TypeID::dump(std::ostream& s) const
   {
      s << TypeID::tStrings[type];

      return s;
   } // TypeID::dump()

   bool TypeID::isValid() const
   {
      // At some time this needs to be implemented.
      return !(type==Unknown);
   }

   TypeID::ValueType TypeID::newValueType(const std::string& s)
   {
      ValueType newId =
         static_cast<ValueType>(TypeID::tStrings.rbegin()->first + 1);
      TypeID::tStrings[newId] = s;
      return newId;
   }

   namespace StringUtils
   {
      // convert this object to a string representation
      std::string asString(const TypeID& p)
      {
         std::ostringstream oss;
         p.dump(oss);
         return oss.str();
      }
   }

   // stream output for TypeID
   std::ostream& operator<<(std::ostream& s, const TypeID& p)
   {
      p.dump(s);
      return s;
   }

}
<|endoftext|>


<commit_before><commit_msg>Convert NOTIMPLs into a bug.<commit_after><|endoftext|>


<commit_before>/** \file   log_rotate.cc
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include "FileUtil.h"
#include "MiscUtil.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "util.h"

const unsigned DEFAULT_MAX_ROTATIONS(5);

void Usage() {
    std::cerr << "Usage: " << ::progname
              << " [--verbose] [--max-rotations=max_rotations|--no-of-lines-to-keep=max_line_count] directory file_regex\n"
              << "       where the default for \"max_rotations\" is " << DEFAULT_MAX_ROTATIONS << '\n'
              << "       and \"file_regex\" must be a PCRE.  (There is no default for \"max_line_count\".)\n"
              << "       When using --no-of-lines-to-keep, the result will be either empty, if the original\n"
              << "       was empty, or the file will end in a newline even if it originally didn't.\n\n";
    std::exit(EXIT_FAILURE);
}

void SkipLines(File * const input, unsigned skip_count) {
    while (skip_count > 0) {
        std::string line;
        input->getline(&line);
        --skip_count;
    }
}

void CopyLines(File * const input, File * const output) {
    while (not input->eof()) {
        std::string line;
        input->getline(&line);
        if (unlikely(not output->write(line + "\n")))
            logger->error("in CopyLines: failed to write a line to \"" + output->getPath() + "\"!");
    }
}

// Keeps the last \"max_line_count\" number of lines in \"filename\".
void KeepLines(const std::string &filename, const unsigned &max_line_count) {
    const size_t original_line_count(FileUtil::CountLines(filename));
    if (original_line_count <= max_line_count)
        return;

    std::unique_ptr<File> input(FileUtil::OpenInputFileOrDie(filename));
    SkipLines(input.get(), original_line_count - max_line_count);

    FileUtil::AutoTempFile temp_file;
    std::unique_ptr<File> output(FileUtil::OpenOutputFileOrDie(temp_file.getFilePath()));
    CopyLines(input.get(), output.get());
    input->close(), output->close();
    if (not FileUtil::RenameFile(temp_file.getFilePath(), filename, /* remove_target = */ true))
        logger->error("in KeepLines: failed to rename \"" + temp_file.getFilePath() + "\" to \"" + filename + "\"!");
}

inline bool HasNumericExtension(const std::string &filename) {
    static RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory("\\.[0-9]+$"));
    return matcher->matched(filename);
}

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 3)
        Usage();

    bool verbose(false);
    if (std::strcmp(argv[1], "--verbose") == 0) {
        verbose = true;
        --argc, ++argv;
    }

    if (argc != 3 and argc != 4)
        Usage();

    unsigned max_rotations(DEFAULT_MAX_ROTATIONS), max_line_count(0);
    std::string directory_path, file_regex;
    if (argc == 3) {
        directory_path = argv[1];
        file_regex     = argv[2];
    } else { // argc == 4.
        if (StringUtil::StartsWith(argv[1], "--max-rotations=")) {
            if (not StringUtil::ToUnsigned(argv[1] + std::strlen("--max-rotations="), &max_rotations)
                or max_rotations == 0)
                logger->error("\"" + std::string(argv[1] + std::strlen("--max-rotations="))
                              + "\" is not a valid maximum rotation count!");
        } else if (StringUtil::StartsWith(argv[1], "--no-of-lines-to-keep=")) {
            if (not StringUtil::ToUnsigned(argv[1] + std::strlen("--no-of-lines-to-keep="), &max_line_count)
                or max_line_count == 0)
                logger->error("\"" + std::string(argv[1] + std::strlen("--no-of-lines-to-keep="))
                              + "\" is not a valid line count!");
        } else
            Usage();
        directory_path = argv[2];
        file_regex     = argv[3];
    }

    try {
        FileUtil::Directory directory(directory_path, file_regex);
        for (const auto &entry : directory) {
            if (not HasNumericExtension(entry.getName())) {
                if (verbose)
                    std::cout << "About to rotate \"" << entry.getName() << "\".\n";
                if (max_line_count > 0)
                    KeepLines(directory_path + "/" + entry.getName(), max_line_count);
                else
                    MiscUtil::LogRotate(directory_path + "/" + entry.getName(), max_rotations);
            }
        }
    } catch (const std::exception &x) {
        logger->error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>Moved all local functions into an unnamed namespace.<commit_after>/** \file   log_rotate.cc
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include "FileUtil.h"
#include "MiscUtil.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "util.h"

namespace {

const unsigned DEFAULT_MAX_ROTATIONS(5);

void Usage() {
    std::cerr << "Usage: " << ::progname
              << " [--verbose] [--max-rotations=max_rotations|--no-of-lines-to-keep=max_line_count] directory file_regex\n"
              << "       where the default for \"max_rotations\" is " << DEFAULT_MAX_ROTATIONS << '\n'
              << "       and \"file_regex\" must be a PCRE.  (There is no default for \"max_line_count\".)\n"
              << "       When using --no-of-lines-to-keep, the result will be either empty, if the original\n"
              << "       was empty, or the file will end in a newline even if it originally didn't.\n\n";
    std::exit(EXIT_FAILURE);
}

void SkipLines(File * const input, unsigned skip_count) {
    while (skip_count > 0) {
        std::string line;
        input->getline(&line);
        --skip_count;
    }
}

void CopyLines(File * const input, File * const output) {
    while (not input->eof()) {
        std::string line;
        input->getline(&line);
        if (unlikely(not output->write(line + "\n")))
            logger->error("in CopyLines: failed to write a line to \"" + output->getPath() + "\"!");
    }
}

// Keeps the last \"max_line_count\" number of lines in \"filename\".
void KeepLines(const std::string &filename, const unsigned &max_line_count) {
    const size_t original_line_count(FileUtil::CountLines(filename));
    if (original_line_count <= max_line_count)
        return;

    std::unique_ptr<File> input(FileUtil::OpenInputFileOrDie(filename));
    SkipLines(input.get(), original_line_count - max_line_count);

    FileUtil::AutoTempFile temp_file;
    std::unique_ptr<File> output(FileUtil::OpenOutputFileOrDie(temp_file.getFilePath()));
    CopyLines(input.get(), output.get());
    input->close(), output->close();
    if (not FileUtil::RenameFile(temp_file.getFilePath(), filename, /* remove_target = */ true))
        logger->error("in KeepLines: failed to rename \"" + temp_file.getFilePath() + "\" to \"" + filename + "\"!");
}

inline bool HasNumericExtension(const std::string &filename) {
    static RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory("\\.[0-9]+$"));
    return matcher->matched(filename);
}

} // unnamed namespace

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 3)
        Usage();

    bool verbose(false);
    if (std::strcmp(argv[1], "--verbose") == 0) {
        verbose = true;
        --argc, ++argv;
    }

    if (argc != 3 and argc != 4)
        Usage();

    unsigned max_rotations(DEFAULT_MAX_ROTATIONS), max_line_count(0);
    std::string directory_path, file_regex;
    if (argc == 3) {
        directory_path = argv[1];
        file_regex     = argv[2];
    } else { // argc == 4.
        if (StringUtil::StartsWith(argv[1], "--max-rotations=")) {
            if (not StringUtil::ToUnsigned(argv[1] + std::strlen("--max-rotations="), &max_rotations)
                or max_rotations == 0)
                logger->error("\"" + std::string(argv[1] + std::strlen("--max-rotations="))
                              + "\" is not a valid maximum rotation count!");
        } else if (StringUtil::StartsWith(argv[1], "--no-of-lines-to-keep=")) {
            if (not StringUtil::ToUnsigned(argv[1] + std::strlen("--no-of-lines-to-keep="), &max_line_count)
                or max_line_count == 0)
                logger->error("\"" + std::string(argv[1] + std::strlen("--no-of-lines-to-keep="))
                              + "\" is not a valid line count!");
        } else
            Usage();
        directory_path = argv[2];
        file_regex     = argv[3];
    }

    try {
        FileUtil::Directory directory(directory_path, file_regex);
        for (const auto &entry : directory) {
            if (not HasNumericExtension(entry.getName())) {
                if (verbose)
                    std::cout << "About to rotate \"" << entry.getName() << "\".\n";
                if (max_line_count > 0)
                    KeepLines(directory_path + "/" + entry.getName(), max_line_count);
                else
                    MiscUtil::LogRotate(directory_path + "/" + entry.getName(), max_rotations);
            }
        }
    } catch (const std::exception &x) {
        logger->error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>


<commit_before>/* Copyright 2016 Streampunk Media Ltd.

  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 <nan.h>
#include "UdpPort.h"
#include "MyWorker.h"
#include "Memory.h"
#include "RioNetwork.h"
#include "NetworkFactory.h"

using namespace v8;

namespace streampunk {

class UdpPortProcessData : public iProcessData {
public:
  UdpPortProcessData(std::string errStr, std::shared_ptr<Memory> buf)
    : mErrStr(errStr), mDstBuf(buf) {}
  ~UdpPortProcessData() {}

  std::string errStr() const { return mErrStr; }
  std::shared_ptr<Memory> dstBuf() const { return mDstBuf; }

private:
  std::string mErrStr;
  std::shared_ptr<Memory> mDstBuf;
};

class UdpPortBindProcessData : public iProcessData {
public:
  UdpPortBindProcessData(uint32_t port, std::string addrStr)
    : mPort(port), mAddrStr(addrStr) {}
  ~UdpPortBindProcessData() {}

  uint32_t mPort;
  std::string mAddrStr;
};

class UdpPortSendProcessData : public iProcessData {
public:
  UdpPortSendProcessData(const tBufVec &bufVec, uint32_t port, const std::string &addrStr)
    : mBufVec(bufVec), mPort(port), mAddrStr(addrStr) {}
  ~UdpPortSendProcessData() {}

  const tBufVec mBufVec;
  const uint32_t mPort;
  const std::string mAddrStr;
};

class UdpPortCloseProcessData : public iProcessData {
public:
  UdpPortCloseProcessData() {}
  ~UdpPortCloseProcessData() {}
};

UdpPort::UdpPort(std::string ipType, bool reuseAddr, uint32_t packetSize, uint32_t recvMinPackets, uint32_t sendMinPackets,
                 Nan::Callback *portCallback, Nan::Callback *callback)
  : mWorker(new MyWorker(callback, portCallback)), mIsBound(false),
    mNetwork(NetworkFactory::createNetwork(ipType, reuseAddr, packetSize, recvMinPackets, sendMinPackets)),
    mListenThread(std::thread(&UdpPort::listenLoop, this)) {
  AsyncQueueWorker(mWorker);
}
UdpPort::~UdpPort() {}

void UdpPort::listenLoop() {
  bool active = true;
  std::string errStr;
  std::shared_ptr<Memory> dstBuf;

  while (active) {
    active = !mNetwork->processCompletions(errStr, dstBuf);
    if (active && (!errStr.empty() || dstBuf))
      mWorker->doProcess(std::make_shared<UdpPortProcessData>(errStr, dstBuf), this, NULL);
    else
      mWorker->quit();
  }
}

// iProcess
void UdpPort::doProcess (std::shared_ptr<iProcessData> processData, std::string &errStr, std::shared_ptr<Memory> &dstBuf, uint32_t &port, std::string &addrStr) {
  try {
    std::shared_ptr<UdpPortProcessData> upd = std::dynamic_pointer_cast<UdpPortProcessData>(processData);
    if (upd) {
      errStr = upd->errStr();
      dstBuf = upd->dstBuf();
    }

    std::shared_ptr<UdpPortBindProcessData> ubpd = std::dynamic_pointer_cast<UdpPortBindProcessData>(processData);
    if (ubpd) {
      mNetwork->Bind(ubpd->mPort, ubpd->mAddrStr);
      port = ubpd->mPort;
      addrStr = ubpd->mAddrStr;
      mIsBound = true;
    }

    std::shared_ptr<UdpPortSendProcessData> uspd = std::dynamic_pointer_cast<UdpPortSendProcessData>(processData);
    if (uspd) {
      if (!mIsBound) {
        uint32_t port = 0;
        std::string addr;
        mNetwork->Bind(port, addr);
        printf ("Bind to %s:%d\n", addr.c_str(), port);
        mIsBound = true;
      }

      mNetwork->Send(uspd->mBufVec, uspd->mPort, uspd->mAddrStr);
      mNetwork->CommitSend();
    }

    std::shared_ptr<UdpPortCloseProcessData> ucpd = std::dynamic_pointer_cast<UdpPortCloseProcessData>(processData);
    if (ucpd) {
      mNetwork->Close();
    }
  } catch (std::runtime_error& err) {
    errStr = err.what();
  }
}

NAN_METHOD(UdpPort::AddMembership) {
  if (info.Length() != 2)
    return Nan::ThrowError("UdpPort AddMembership expects 2 arguments");
  String::Utf8Value mAddrStr(Nan::To<String>(info[0]).ToLocalChecked());
  String::Utf8Value uAddrStr(Nan::To<String>(info[1]).ToLocalChecked());

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->AddMembership(*mAddrStr, *uAddrStr);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::DropMembership) {
  if (info.Length() != 2)
    return Nan::ThrowError("UdpPort DropMembership expects 2 arguments");
  String::Utf8Value mAddrStr(Nan::To<String>(info[0]).ToLocalChecked());
  String::Utf8Value uAddrStr(Nan::To<String>(info[1]).ToLocalChecked());

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->DropMembership(*mAddrStr, *uAddrStr);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetTTL) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetTTL expects 1 argument");
  uint32_t ttl = Nan::To<uint32_t>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetTTL(ttl);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetMulticastTTL) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetMulticastTTL expects 1 argument");
  uint32_t ttl = Nan::To<uint32_t>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetMulticastTTL(ttl);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetBroadcast) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetBroadcast expects 1 argument");
  bool flag = Nan::To<bool>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetBroadcast(flag);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetMulticastLoopback) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetMulticastLoopback expects 1 argument");
  bool flag = Nan::To<bool>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetMulticastLoopback(flag);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Bind) {
  if (info.Length() != 3)
    return Nan::ThrowError("UdpPort Bind expects 4 arguments");
  if (!info[2]->IsFunction())
    return Nan::ThrowError("UdpPort Bind requires a valid callback as the third parameter");

  uint32_t port = Nan::To<uint32_t>(info[0]).FromJust();
  String::Utf8Value addrStr(Nan::To<String>(info[1]).ToLocalChecked());
  Local<Function> callback = Local<Function>::Cast(info[2]);

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortBindProcessData>(port, *addrStr), obj, new Nan::Callback(callback));
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }

  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Send) {
  if (info.Length() != 6)
    return Nan::ThrowError("UdpPort Send expects 6 arguments");
  if (!info[0]->IsArray())
    return Nan::ThrowError("UdpPort Send requires a valid buffer array as the first parameter");
  if (!info[5]->IsFunction())
    return Nan::ThrowError("UdpPort Send requires a valid callback as the sixth parameter");

  Local<Array> bufArray = Local<Array>::Cast(info[0]);
  uint32_t offset = Nan::To<uint32_t>(info[1]).FromJust();
  uint32_t length = Nan::To<uint32_t>(info[2]).FromJust();
  uint32_t port = Nan::To<uint32_t>(info[3]).FromJust();
  String::Utf8Value addrStr(Nan::To<String>(info[4]).ToLocalChecked());
  Nan::Callback *callback = new Nan::Callback(Local<Function>::Cast(info[5]));

  if (1 == bufArray->Length()) {
    uint32_t buffLen = (uint32_t)node::Buffer::Length(bufArray->Get(0));
    if (offset + length > buffLen)
      return Nan::ThrowError("UdpPort Send - out of range offset/length");
  }

  tBufVec bufVec;
  for (uint32_t i = 0; i < bufArray->Length(); ++i) {
    Local<Object> bufferObj = Local<Object>::Cast(bufArray->Get(i));
    uint8_t *sendBuf = (uint8_t *)node::Buffer::Data(bufferObj);
    uint32_t bufLen = (uint32_t)node::Buffer::Length(bufferObj);
    if (1 == bufArray->Length()) {
      sendBuf += offset;
      bufLen = length;
    }

    bufVec.push_back(Memory::makeNew(sendBuf, bufLen));
  }

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortSendProcessData>(bufVec, port, *addrStr), obj, callback);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }

  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Close) {
  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortCloseProcessData>(), obj, NULL);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_MODULE_INIT(UdpPort::Init) {
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("UdpPort").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  SetPrototypeMethod(tpl, "addMembership", AddMembership);
  SetPrototypeMethod(tpl, "dropMembership", DropMembership);
  SetPrototypeMethod(tpl, "setTTL", SetTTL);
  SetPrototypeMethod(tpl, "setMulticastTTL", SetMulticastTTL);
  SetPrototypeMethod(tpl, "setBroadcast", SetBroadcast);
  SetPrototypeMethod(tpl, "setMulticastLoopback", SetMulticastLoopback);
  SetPrototypeMethod(tpl, "bind", Bind);
  SetPrototypeMethod(tpl, "send", Send);
  SetPrototypeMethod(tpl, "close", Close);

  constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target, Nan::New("UdpPort").ToLocalChecked(),
    Nan::GetFunction(tpl).ToLocalChecked());
}

} // namespace streampunk
<commit_msg>Fix early exit case<commit_after>/* Copyright 2016 Streampunk Media Ltd.

  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 <nan.h>
#include "UdpPort.h"
#include "MyWorker.h"
#include "Memory.h"
#include "RioNetwork.h"
#include "NetworkFactory.h"

using namespace v8;

namespace streampunk {

class UdpPortProcessData : public iProcessData {
public:
  UdpPortProcessData(std::string errStr, std::shared_ptr<Memory> buf)
    : mErrStr(errStr), mDstBuf(buf) {}
  ~UdpPortProcessData() {}

  std::string errStr() const { return mErrStr; }
  std::shared_ptr<Memory> dstBuf() const { return mDstBuf; }

private:
  std::string mErrStr;
  std::shared_ptr<Memory> mDstBuf;
};

class UdpPortBindProcessData : public iProcessData {
public:
  UdpPortBindProcessData(uint32_t port, std::string addrStr)
    : mPort(port), mAddrStr(addrStr) {}
  ~UdpPortBindProcessData() {}

  uint32_t mPort;
  std::string mAddrStr;
};

class UdpPortSendProcessData : public iProcessData {
public:
  UdpPortSendProcessData(const tBufVec &bufVec, uint32_t port, const std::string &addrStr)
    : mBufVec(bufVec), mPort(port), mAddrStr(addrStr) {}
  ~UdpPortSendProcessData() {}

  const tBufVec mBufVec;
  const uint32_t mPort;
  const std::string mAddrStr;
};

class UdpPortCloseProcessData : public iProcessData {
public:
  UdpPortCloseProcessData() {}
  ~UdpPortCloseProcessData() {}
};

UdpPort::UdpPort(std::string ipType, bool reuseAddr, uint32_t packetSize, uint32_t recvMinPackets, uint32_t sendMinPackets,
                 Nan::Callback *portCallback, Nan::Callback *callback)
  : mWorker(new MyWorker(callback, portCallback)), mIsBound(false),
    mNetwork(NetworkFactory::createNetwork(ipType, reuseAddr, packetSize, recvMinPackets, sendMinPackets)),
    mListenThread(std::thread(&UdpPort::listenLoop, this)) {
  AsyncQueueWorker(mWorker);
}
UdpPort::~UdpPort() {}

void UdpPort::listenLoop() {
  bool active = true;
  std::string errStr;
  std::shared_ptr<Memory> dstBuf;

  while (active) {
    active = !mNetwork->processCompletions(errStr, dstBuf);
    if (active) {
      if (!errStr.empty() || dstBuf) {
        mWorker->doProcess(std::make_shared<UdpPortProcessData>(errStr, dstBuf), this, NULL);
      }
    }
    else
      mWorker->quit();
  }
}

// iProcess
void UdpPort::doProcess (std::shared_ptr<iProcessData> processData, std::string &errStr, std::shared_ptr<Memory> &dstBuf, uint32_t &port, std::string &addrStr) {
  try {
    std::shared_ptr<UdpPortProcessData> upd = std::dynamic_pointer_cast<UdpPortProcessData>(processData);
    if (upd) {
      errStr = upd->errStr();
      dstBuf = upd->dstBuf();
    }

    std::shared_ptr<UdpPortBindProcessData> ubpd = std::dynamic_pointer_cast<UdpPortBindProcessData>(processData);
    if (ubpd) {
      mNetwork->Bind(ubpd->mPort, ubpd->mAddrStr);
      port = ubpd->mPort;
      addrStr = ubpd->mAddrStr;
      mIsBound = true;
    }

    std::shared_ptr<UdpPortSendProcessData> uspd = std::dynamic_pointer_cast<UdpPortSendProcessData>(processData);
    if (uspd) {
      if (!mIsBound) {
        uint32_t port = 0;
        std::string addr;
        mNetwork->Bind(port, addr);
        printf ("Bind to %s:%d\n", addr.c_str(), port);
        mIsBound = true;
      }

      mNetwork->Send(uspd->mBufVec, uspd->mPort, uspd->mAddrStr);
      mNetwork->CommitSend();
    }

    std::shared_ptr<UdpPortCloseProcessData> ucpd = std::dynamic_pointer_cast<UdpPortCloseProcessData>(processData);
    if (ucpd) {
      mNetwork->Close();
    }
  } catch (std::runtime_error& err) {
    errStr = err.what();
  }
}

NAN_METHOD(UdpPort::AddMembership) {
  if (info.Length() != 2)
    return Nan::ThrowError("UdpPort AddMembership expects 2 arguments");
  String::Utf8Value mAddrStr(Nan::To<String>(info[0]).ToLocalChecked());
  String::Utf8Value uAddrStr(Nan::To<String>(info[1]).ToLocalChecked());

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->AddMembership(*mAddrStr, *uAddrStr);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::DropMembership) {
  if (info.Length() != 2)
    return Nan::ThrowError("UdpPort DropMembership expects 2 arguments");
  String::Utf8Value mAddrStr(Nan::To<String>(info[0]).ToLocalChecked());
  String::Utf8Value uAddrStr(Nan::To<String>(info[1]).ToLocalChecked());

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->DropMembership(*mAddrStr, *uAddrStr);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetTTL) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetTTL expects 1 argument");
  uint32_t ttl = Nan::To<uint32_t>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetTTL(ttl);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetMulticastTTL) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetMulticastTTL expects 1 argument");
  uint32_t ttl = Nan::To<uint32_t>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetMulticastTTL(ttl);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetBroadcast) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetBroadcast expects 1 argument");
  bool flag = Nan::To<bool>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetBroadcast(flag);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::SetMulticastLoopback) {
  if (info.Length() != 1)
    return Nan::ThrowError("UdpPort SetMulticastLoopback expects 1 argument");
  bool flag = Nan::To<bool>(info[0]).FromJust();

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mNetwork->SetMulticastLoopback(flag);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Bind) {
  if (info.Length() != 3)
    return Nan::ThrowError("UdpPort Bind expects 4 arguments");
  if (!info[2]->IsFunction())
    return Nan::ThrowError("UdpPort Bind requires a valid callback as the third parameter");

  uint32_t port = Nan::To<uint32_t>(info[0]).FromJust();
  String::Utf8Value addrStr(Nan::To<String>(info[1]).ToLocalChecked());
  Local<Function> callback = Local<Function>::Cast(info[2]);

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortBindProcessData>(port, *addrStr), obj, new Nan::Callback(callback));
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }

  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Send) {
  if (info.Length() != 6)
    return Nan::ThrowError("UdpPort Send expects 6 arguments");
  if (!info[0]->IsArray())
    return Nan::ThrowError("UdpPort Send requires a valid buffer array as the first parameter");
  if (!info[5]->IsFunction())
    return Nan::ThrowError("UdpPort Send requires a valid callback as the sixth parameter");

  Local<Array> bufArray = Local<Array>::Cast(info[0]);
  uint32_t offset = Nan::To<uint32_t>(info[1]).FromJust();
  uint32_t length = Nan::To<uint32_t>(info[2]).FromJust();
  uint32_t port = Nan::To<uint32_t>(info[3]).FromJust();
  String::Utf8Value addrStr(Nan::To<String>(info[4]).ToLocalChecked());
  Nan::Callback *callback = new Nan::Callback(Local<Function>::Cast(info[5]));

  if (1 == bufArray->Length()) {
    uint32_t buffLen = (uint32_t)node::Buffer::Length(bufArray->Get(0));
    if (offset + length > buffLen)
      return Nan::ThrowError("UdpPort Send - out of range offset/length");
  }

  tBufVec bufVec;
  for (uint32_t i = 0; i < bufArray->Length(); ++i) {
    Local<Object> bufferObj = Local<Object>::Cast(bufArray->Get(i));
    uint8_t *sendBuf = (uint8_t *)node::Buffer::Data(bufferObj);
    uint32_t bufLen = (uint32_t)node::Buffer::Length(bufferObj);
    if (1 == bufArray->Length()) {
      sendBuf += offset;
      bufLen = length;
    }

    bufVec.push_back(Memory::makeNew(sendBuf, bufLen));
  }

  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortSendProcessData>(bufVec, port, *addrStr), obj, callback);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }

  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(UdpPort::Close) {
  UdpPort *obj = Nan::ObjectWrap::Unwrap<UdpPort>(info.Holder());
  try {
    obj->mWorker->doProcess(std::make_shared<UdpPortCloseProcessData>(), obj, NULL);
  } catch (std::runtime_error& err) {
    return Nan::ThrowError(Nan::New(err.what()).ToLocalChecked());
  }
  info.GetReturnValue().SetUndefined();
}

NAN_MODULE_INIT(UdpPort::Init) {
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("UdpPort").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  SetPrototypeMethod(tpl, "addMembership", AddMembership);
  SetPrototypeMethod(tpl, "dropMembership", DropMembership);
  SetPrototypeMethod(tpl, "setTTL", SetTTL);
  SetPrototypeMethod(tpl, "setMulticastTTL", SetMulticastTTL);
  SetPrototypeMethod(tpl, "setBroadcast", SetBroadcast);
  SetPrototypeMethod(tpl, "setMulticastLoopback", SetMulticastLoopback);
  SetPrototypeMethod(tpl, "bind", Bind);
  SetPrototypeMethod(tpl, "send", Send);
  SetPrototypeMethod(tpl, "close", Close);

  constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target, Nan::New("UdpPort").ToLocalChecked(),
    Nan::GetFunction(tpl).ToLocalChecked());
}

} // namespace streampunk
<|endoftext|>


<commit_before><commit_msg>`UniverseStruct`: set default value of `speed` to `0.1f`.<commit_after><|endoftext|>


<commit_before>#include "TFile.h"
#include "TH1F.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"

#ifdef __CINT__
#pragma link C++ class TTreeReaderValue<Float_t>+;
#endif

void TreeReaderSimple() {
	TH1F *myHistogram = new TH1F ("h1","ntuple",100,-4,4);

	TFile *myFile = TFile::Open("hsimple.root");
	TTreeReader myHSimpleReader ("ntuple", myFile);

	TTreeReaderValue<Float_t> myPx (myHSimpleReader, "px");
	TTreeReaderValue<Float_t> myPy (myHSimpleReader, "py");

	while (myHSimpleReader.SetNextEntry()){
		myHistogram->Fill(*myPx + *myPy);
	}

	myHistogram->Draw();
}
<commit_msg>Removed now unnecessary pragma link<commit_after>#include "TFile.h"
#include "TH1F.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"

void TreeReaderSimple() {
	TH1F *myHistogram = new TH1F ("h1","ntuple",100,-4,4);

	TFile *myFile = TFile::Open("hsimple.root");
	TTreeReader myHSimpleReader ("ntuple", myFile);

	TTreeReaderValue<Float_t> myPx (myHSimpleReader, "px");
	TTreeReaderValue<Float_t> myPy (myHSimpleReader, "py");

	while (myHSimpleReader.SetNextEntry()){
		myHistogram->Fill(*myPx + *myPy);
	}

	myHistogram->Draw();
}
<|endoftext|>


<commit_before>/*===================================================================
APM_PLANNER Open Source Ground Control Station

(c) 2013 APM_PLANNER PROJECT <http://www.diydrones.com>

This file is part of the APM_PLANNER project

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

    APM_PLANNER is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with APM_PLANNER. If not, see <http://www.gnu.org/licenses/>.

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

#include "AccelCalibrationConfig.h"
#include "GAudioOutput.h"
#include "MainWindow.h"

const char* COUNTDOWN_STRING = "
Time remaining until timeout: %d
";

AccelCalibrationConfig::AccelCalibrationConfig(QWidget *parent) : AP2ConfigWidget(parent),
    m_muted(false),
    m_isCalibrating(false),
    m_countdownCount(CALIBRATION_TIMEOUT_SEC)
{
    ui.setupUi(this);
    connect(ui.calibrateAccelButton,SIGNAL(clicked()),this,SLOT(calibrateButtonClicked()));

    m_accelAckCount=0;
    initConnections();
    //coutdownLabel
    connect(&m_countdownTimer,SIGNAL(timeout()),this,SLOT(countdownTimerTick()));
}

AccelCalibrationConfig::~AccelCalibrationConfig()
{
}
void AccelCalibrationConfig::countdownTimerTick()
{
    ui.coutdownLabel->setText(QString().sprintf(COUNTDOWN_STRING, m_countdownCount--));
    if (m_countdownCount <= 0)
    {
        ui.coutdownLabel->setText("Command timed out, please try again");
        m_countdownTimer.stop();
        ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
        m_accelAckCount = 0;
    }
}

void AccelCalibrationConfig::activeUASSet(UASInterface *uas)
{
    if (m_uas)
    {
        disconnect(m_uas,SIGNAL(textMessageReceived(int,int,int,QString)),this,SLOT(uasTextMessageReceived(int,int,int,QString)));
        disconnect(m_uas,SIGNAL(connected()),this,SLOT(uasConnected()));
        disconnect(m_uas,SIGNAL(disconnected()),this,SLOT(uasDisconnected()));
    }
    AP2ConfigWidget::activeUASSet(uas);
    if (!uas)
    {
        return;
    }
    connect(m_uas,SIGNAL(textMessageReceived(int,int,int,QString)),this,SLOT(uasTextMessageReceived(int,int,int,QString)));
    connect(m_uas,SIGNAL(connected()),this,SLOT(uasConnected()));
    connect(m_uas,SIGNAL(disconnected()),this,SLOT(uasDisconnected()));
    uasConnected();

}
void AccelCalibrationConfig::uasConnected()
{

}

void AccelCalibrationConfig::uasDisconnected()
{

}

void AccelCalibrationConfig::calibrateButtonClicked()
{
    if (!m_uas)
    {
        showNullMAVErrorMessageBox();
        return;
    }

    ui.outputLabel->clear();

    m_isCalibrating = true; // this is to guard against showing unwanted GCS Text Messages.

    // Mute Audio until calibrated to avoid HeartBeat Warning message
    if (GAudioOutput::instance()->isMuted() == false) {
        GAudioOutput::instance()->mute(true);
        m_muted = true;
    }
    m_uas->getLinks()->at(0)->disableTimeouts();

    MainWindow::instance()->toolBar().stopAnimation();

    if (m_accelAckCount == 0)
    {
        MAV_CMD command = MAV_CMD_PREFLIGHT_CALIBRATION;
        int confirm = 0;
        float param1 = 0.0;
        float param2 = 0.0;
        float param3 = 0.0;
        float param4 = 0.0;
        float param5 = 1.0;
        float param6 = 0.0;
        float param7 = 0.0;
        int component = 1;
        m_uas->executeCommand(command, confirm, param1, param2, param3, param4, param5, param6, param7, component);
        m_countdownCount = CALIBRATION_TIMEOUT_SEC;
        ui.coutdownLabel->setText(QString().sprintf(COUNTDOWN_STRING, m_countdownCount--));
        m_countdownTimer.start(1000);
    }
    else if (m_accelAckCount <= 10)
    {
        m_uas->executeCommandAck(m_accelAckCount++,true);
        m_countdownCount = CALIBRATION_TIMEOUT_SEC;
    }
    else
    {
        m_uas->executeCommandAck(m_accelAckCount++,true);
        ui.coutdownLabel->setText("");
        m_countdownTimer.stop();
        ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
        if (m_accelAckCount > 8)
        {
            //We've clicked too many times! Reset.
            for (int i=0;i<8;i++)
            {
                m_uas->executeCommandAck(i,true);
            }
            m_accelAckCount = 0;
        }
    }

}

void AccelCalibrationConfig::hideEvent(QHideEvent *evt)
{
    Q_UNUSED(evt);

    if (m_muted) { // turns audio backon, when you leave the page
        GAudioOutput::instance()->mute(false);
        m_muted = false;
    }

    MainWindow::instance()->toolBar().startAnimation();

    if (!m_uas || !m_accelAckCount)
    {
        return;
    }
    for (int i=m_accelAckCount;i<8;i++)
    {
        m_uas->executeCommandAck(i,true); //Clear out extra commands.
    }
    m_uas->getLinks()->at(0)->enableTimeouts();
}
void AccelCalibrationConfig::uasTextMessageReceived(int uasid, int componentid, int severity, QString text)
{
    Q_UNUSED(uasid);
    Q_UNUSED(componentid);

    if ((severity == 5 /*SEVERITY_USER_RESPONSE*/)||(severity == 3 /*SEVERITY_HIGH*/))
    {
        //This is a calibration instruction
        if (!m_isCalibrating || text.startsWith("PreArm:") || text.startsWith("EKF") || text.startsWith("Arm"))
        {
            // Don't show these warning messages
            return;
        }

        if (text.contains("Place") && text.contains ("and press any key"))
        {
            //Instruction
            if (m_accelAckCount == 0)
            {
                //Calibration Sucessful\r"
                ui.calibrateAccelButton->setText("Continue\nPress SpaceBar");
                ui.calibrateAccelButton->setShortcut(QKeySequence(Qt::Key_Space));
            }
            ui.outputLabel->setText(text);
            m_accelAckCount++;
        }
        else if (text.contains("Calibration successful") || text.contains("FAILED"))
        {
            //Calibration complete success or failure
            if (m_muted) { // turns audio back on, when you complete fail or success
                GAudioOutput::instance()->mute(false);
                m_muted = false;
            }
            ui.outputLabel->setText(ui.outputLabel->text() + "\n" + text);
            ui.coutdownLabel->setText("");
            m_countdownTimer.stop();
            MainWindow::instance()->toolBar().startAnimation();
            m_accelAckCount = 0;
            ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
            ui.calibrateAccelButton->setShortcut(QKeySequence());
            m_isCalibrating = false;
        }
        else
        {
            ui.outputLabel->setText(ui.outputLabel->text() + "\n" + text);
        }
    }

}
<commit_msg>Accel Calibration: Add MAV ID ident to calibration message<commit_after>/*===================================================================
APM_PLANNER Open Source Ground Control Station

(c) 2013 APM_PLANNER PROJECT <http://www.diydrones.com>

This file is part of the APM_PLANNER project

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

    APM_PLANNER is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with APM_PLANNER. If not, see <http://www.gnu.org/licenses/>.

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

#include "AccelCalibrationConfig.h"
#include "GAudioOutput.h"
#include "MainWindow.h"

const char* COUNTDOWN_STRING = "
Calibrate MAV%03d
Time remaining until timeout: %d
";

AccelCalibrationConfig::AccelCalibrationConfig(QWidget *parent) : AP2ConfigWidget(parent),
    m_muted(false),
    m_isCalibrating(false),
    m_countdownCount(CALIBRATION_TIMEOUT_SEC)
{
    ui.setupUi(this);
    connect(ui.calibrateAccelButton,SIGNAL(clicked()),this,SLOT(calibrateButtonClicked()));

    m_accelAckCount=0;
    initConnections();
    //coutdownLabel
    connect(&m_countdownTimer,SIGNAL(timeout()),this,SLOT(countdownTimerTick()));
}

AccelCalibrationConfig::~AccelCalibrationConfig()
{
}
void AccelCalibrationConfig::countdownTimerTick()
{
    ui.coutdownLabel->setText(QString().sprintf(COUNTDOWN_STRING, m_uas->getUASID(), m_countdownCount--));
    if (m_countdownCount <= 0)
    {
        ui.coutdownLabel->setText("Command timed out, please try again");
        m_countdownTimer.stop();
        ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
        m_accelAckCount = 0;
    }
}

void AccelCalibrationConfig::activeUASSet(UASInterface *uas)
{
    if (m_uas)
    {
        disconnect(m_uas,SIGNAL(textMessageReceived(int,int,int,QString)),this,SLOT(uasTextMessageReceived(int,int,int,QString)));
        disconnect(m_uas,SIGNAL(connected()),this,SLOT(uasConnected()));
        disconnect(m_uas,SIGNAL(disconnected()),this,SLOT(uasDisconnected()));
    }
    AP2ConfigWidget::activeUASSet(uas);
    if (!uas)
    {
        return;
    }
    connect(m_uas,SIGNAL(textMessageReceived(int,int,int,QString)),this,SLOT(uasTextMessageReceived(int,int,int,QString)));
    connect(m_uas,SIGNAL(connected()),this,SLOT(uasConnected()));
    connect(m_uas,SIGNAL(disconnected()),this,SLOT(uasDisconnected()));
    uasConnected();

}
void AccelCalibrationConfig::uasConnected()
{

}

void AccelCalibrationConfig::uasDisconnected()
{

}

void AccelCalibrationConfig::calibrateButtonClicked()
{
    if (!m_uas)
    {
        showNullMAVErrorMessageBox();
        return;
    }

    ui.outputLabel->clear();

    m_isCalibrating = true; // this is to guard against showing unwanted GCS Text Messages.

    // Mute Audio until calibrated to avoid HeartBeat Warning message
    if (GAudioOutput::instance()->isMuted() == false) {
        GAudioOutput::instance()->mute(true);
        m_muted = true;
    }
    m_uas->getLinks()->at(0)->disableTimeouts();

    MainWindow::instance()->toolBar().stopAnimation();

    if (m_accelAckCount == 0)
    {
        MAV_CMD command = MAV_CMD_PREFLIGHT_CALIBRATION;
        int confirm = 0;
        float param1 = 0.0;
        float param2 = 0.0;
        float param3 = 0.0;
        float param4 = 0.0;
        float param5 = 1.0;
        float param6 = 0.0;
        float param7 = 0.0;
        int component = 1;
        m_uas->executeCommand(command, confirm, param1, param2, param3, param4, param5, param6, param7, component);
        m_countdownCount = CALIBRATION_TIMEOUT_SEC;
        ui.coutdownLabel->setText(QString().sprintf(COUNTDOWN_STRING, m_uas->getUASID(), m_countdownCount--));
        m_countdownTimer.start(1000);
    }
    else if (m_accelAckCount <= 10)
    {
        m_uas->executeCommandAck(m_accelAckCount++,true);
        m_countdownCount = CALIBRATION_TIMEOUT_SEC;
    }
    else
    {
        m_uas->executeCommandAck(m_accelAckCount++,true);
        ui.coutdownLabel->setText("");
        m_countdownTimer.stop();
        ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
        if (m_accelAckCount > 8)
        {
            //We've clicked too many times! Reset.
            for (int i=0;i<8;i++)
            {
                m_uas->executeCommandAck(i,true);
            }
            m_accelAckCount = 0;
        }
    }

}

void AccelCalibrationConfig::hideEvent(QHideEvent *evt)
{
    Q_UNUSED(evt);

    if (m_muted) { // turns audio backon, when you leave the page
        GAudioOutput::instance()->mute(false);
        m_muted = false;
    }

    MainWindow::instance()->toolBar().startAnimation();

    if (!m_uas || !m_accelAckCount)
    {
        return;
    }
    for (int i=m_accelAckCount;i<8;i++)
    {
        m_uas->executeCommandAck(i,true); //Clear out extra commands.
    }
    m_uas->getLinks()->at(0)->enableTimeouts();
}
void AccelCalibrationConfig::uasTextMessageReceived(int uasid, int componentid, int severity, QString text)
{
    Q_UNUSED(uasid);
    Q_UNUSED(componentid);

    if ((severity == 5 /*SEVERITY_USER_RESPONSE*/)||(severity == 3 /*SEVERITY_HIGH*/))
    {
        //This is a calibration instruction
        if (!m_isCalibrating || text.startsWith("PreArm:") || text.startsWith("EKF") || text.startsWith("Arm"))
        {
            // Don't show these warning messages
            return;
        }

        if (text.contains("Place") && text.contains ("and press any key"))
        {
            //Instruction
            if (m_accelAckCount == 0)
            {
                //Calibration Sucessful\r"
                ui.calibrateAccelButton->setText("Continue\nPress SpaceBar");
                ui.calibrateAccelButton->setShortcut(QKeySequence(Qt::Key_Space));
            }
            ui.outputLabel->setText(text);
            m_accelAckCount++;
        }
        else if (text.contains("Calibration successful") || text.contains("FAILED"))
        {
            //Calibration complete success or failure
            if (m_muted) { // turns audio back on, when you complete fail or success
                GAudioOutput::instance()->mute(false);
                m_muted = false;
            }
            ui.outputLabel->setText(ui.outputLabel->text() + "\n" + text);
            ui.coutdownLabel->setText("");
            m_countdownTimer.stop();
            MainWindow::instance()->toolBar().startAnimation();
            m_accelAckCount = 0;
            ui.calibrateAccelButton->setText("Calibrate\nAccelerometer");
            ui.calibrateAccelButton->setShortcut(QKeySequence());
            m_isCalibrating = false;
        }
        else
        {
            ui.outputLabel->setText(ui.outputLabel->text() + "\n" + text);
        }
    }

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
 * OWNER 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.
 */

#ifndef __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__

#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"

// forward declarations
#if FULL_SYSTEM
class Processor;
class AlphaITB;
class AlphaDTB;
class PhysicalMemory;

class RemoteGDB;
class GDBListener;

#else

class Process;

#endif // FULL_SYSTEM

class MemInterface;
class Checkpoint;

namespace Trace {
    class InstRecord;
}

class SimpleCPU : public BaseCPU
{
    class CpuPort : public Port
    {

        SimpleCPU *cpu;

      public:

        CpuPort(SimpleCPU *_cpu)
            : cpu(_cpu)
        { }

      protected:

        virtual bool recvTiming(Packet &pkt)
        { return cpu->processCacheCompletion(pkt); }

        virtual Tick recvAtomic(Packet &pkt)
        { return cpu->processCacheCompletion(pkt); }

        virtual void recvFunctional(Packet &pkt)
        { cpu->processCacheCompletion(pkt); }

        virtual void recvStatusChange(Status status)
        { cpu->recvStatusChange(status); }

    };

    CpuPort icache_port;
    CpuPort dcache_port;

    bool recvTiming(Packet &pkt);
    Tick recvAtomic(Packet &pkt);
    void recvFunctional(Packet &pkt);

  public:
    // main simulation loop (one cycle)
    void tick();

  private:
    struct TickEvent : public Event
    {
        SimpleCPU *cpu;
        int width;

        TickEvent(SimpleCPU *c, int w);
        void process();
        const char *description();
    };

    TickEvent tickEvent;

    /// Schedule tick event, regardless of its current state.
    void scheduleTickEvent(int numCycles)
    {
        if (tickEvent.squashed())
            tickEvent.reschedule(curTick + cycles(numCycles));
        else if (!tickEvent.scheduled())
            tickEvent.schedule(curTick + cycles(numCycles));
    }

    /// Unschedule tick event, regardless of its current state.
    void unscheduleTickEvent()
    {
        if (tickEvent.scheduled())
            tickEvent.squash();
    }

  private:
    Trace::InstRecord *traceData;

  public:
    //
    enum Status {
        Running,
        Idle,
        IcacheMissStall,
        IcacheMissComplete,
        DcacheMissStall,
        DcacheMissSwitch,
        SwitchedOut
    };

  private:
    Status _status;

  public:
    void post_interrupt(int int_num, int index);

    void zero_fill_64(Addr addr) {
      static int warned = 0;
      if (!warned) {
        warn ("WH64 is not implemented");
        warned = 1;
      }
    };

  public:
    struct Params : public BaseCPU::Params
    {
        MemInterface *icache_interface;
        MemInterface *dcache_interface;
        int width;
#if FULL_SYSTEM
        AlphaITB *itb;
        AlphaDTB *dtb;
        FunctionalMemory *mem;
#else
        Process *process;
#endif
    };
    SimpleCPU(Params *params);
    virtual ~SimpleCPU();

  public:
    // execution context
    ExecContext *xc;

    void switchOut(Sampler *s);
    void takeOverFrom(BaseCPU *oldCPU);

#if FULL_SYSTEM
    Addr dbg_vtophys(Addr addr);

    bool interval_stats;
#endif

    // current instruction
    MachInst inst;

    CpuRequest *req;
    Packet *pkt;

    // Pointer to the sampler that is telling us to switchover.
    // Used to signal the completion of the pipe drain and schedule
    // the next switchover
    Sampler *sampler;

    StaticInstPtr<TheISA> curStaticInst;

    class CacheCompletionEvent : public Event
    {
      private:
        SimpleCPU *cpu;

      public:
        CacheCompletionEvent(SimpleCPU *_cpu);

        virtual void process();
        virtual const char *description();
    };

    CacheCompletionEvent cacheCompletionEvent;

    Status status() const { return _status; }

    virtual void activateContext(int thread_num, int delay);
    virtual void suspendContext(int thread_num);
    virtual void deallocateContext(int thread_num);
    virtual void haltContext(int thread_num);

    // statistics
    virtual void regStats();
    virtual void resetStats();

    // number of simulated instructions
    Counter numInst;
    Counter startNumInst;
    Stats::Scalar<> numInsts;

    virtual Counter totalInstructions() const
    {
        return numInst - startNumInst;
    }

    // number of simulated memory references
    Stats::Scalar<> numMemRefs;

    // number of simulated loads
    Counter numLoad;
    Counter startNumLoad;

    // number of idle cycles
    Stats::Average<> notIdleFraction;
    Stats::Formula idleFraction;

    // number of cycles stalled for I-cache misses
    Stats::Scalar<> icacheStallCycles;
    Counter lastIcacheStall;

    // number of cycles stalled for D-cache misses
    Stats::Scalar<> dcacheStallCycles;
    Counter lastDcacheStall;

    void processCacheCompletion();

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    template <class T>
    Fault read(Addr addr, T &data, unsigned flags);

    template <class T>
    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);

    // These functions are only used in CPU models that split
    // effective address computation from the actual memory access.
    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }

    void prefetch(Addr addr, unsigned flags)
    {
        // need to do this...
    }

    void writeHint(Addr addr, int size, unsigned flags)
    {
        // need to do this...
    }

    Fault copySrcTranslate(Addr src);

    Fault copy(Addr dest);

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntReg(const StaticInst<TheISA> *si, int idx)
    {
        return xc->readIntReg(si->srcRegIdx(idx));
    }

    float readFloatRegSingle(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegSingle(reg_idx);
    }

    double readFloatRegDouble(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegDouble(reg_idx);
    }

    uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegInt(reg_idx);
    }

    void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val)
    {
        xc->setIntReg(si->destRegIdx(idx), val);
    }

    void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegSingle(reg_idx, val);
    }

    void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegDouble(reg_idx, val);
    }

    void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegInt(reg_idx, val);
    }

    uint64_t readPC() { return xc->readPC(); }
    void setNextPC(uint64_t val) { xc->setNextPC(val); }

    uint64_t readUniq() { return xc->readUniq(); }
    void setUniq(uint64_t val) { xc->setUniq(val); }

    uint64_t readFpcr() { return xc->readFpcr(); }
    void setFpcr(uint64_t val) { xc->setFpcr(val); }

#if FULL_SYSTEM
    uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
    Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
    Fault hwrei() { return xc->hwrei(); }
    int readIntrFlag() { return xc->readIntrFlag(); }
    void setIntrFlag(int val) { xc->setIntrFlag(val); }
    bool inPalMode() { return xc->inPalMode(); }
    void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
    bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
    void syscall() { xc->syscall(); }
#endif

    bool misspeculating() { return xc->misspeculating(); }
    ExecContext *xcBase() { return xc; }
};

#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
<commit_msg>Remove non-needed functions, fix return values of completion handler.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
 * OWNER 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.
 */

#ifndef __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__

#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"

// forward declarations
#if FULL_SYSTEM
class Processor;
class AlphaITB;
class AlphaDTB;
class PhysicalMemory;

class RemoteGDB;
class GDBListener;

#else

class Process;

#endif // FULL_SYSTEM

class MemInterface;
class Checkpoint;

namespace Trace {
    class InstRecord;
}

class SimpleCPU : public BaseCPU
{
    class CpuPort : public Port
    {

        SimpleCPU *cpu;

      public:

        CpuPort(SimpleCPU *_cpu)
            : cpu(_cpu)
        { }

      protected:

        virtual bool recvTiming(Packet &pkt)
        { cpu->processCacheCompletion(pkt); return true; }

        virtual Tick recvAtomic(Packet &pkt)
        { cpu->processCacheCompletion(pkt); return CurTick; }

        virtual void recvFunctional(Packet &pkt)
        { cpu->processCacheCompletion(pkt); }

        virtual void recvStatusChange(Status status)
        { cpu->recvStatusChange(status); }

    };

    CpuPort icache_port;
    CpuPort dcache_port;

  public:
    // main simulation loop (one cycle)
    void tick();

  private:
    struct TickEvent : public Event
    {
        SimpleCPU *cpu;
        int width;

        TickEvent(SimpleCPU *c, int w);
        void process();
        const char *description();
    };

    TickEvent tickEvent;

    /// Schedule tick event, regardless of its current state.
    void scheduleTickEvent(int numCycles)
    {
        if (tickEvent.squashed())
            tickEvent.reschedule(curTick + cycles(numCycles));
        else if (!tickEvent.scheduled())
            tickEvent.schedule(curTick + cycles(numCycles));
    }

    /// Unschedule tick event, regardless of its current state.
    void unscheduleTickEvent()
    {
        if (tickEvent.scheduled())
            tickEvent.squash();
    }

  private:
    Trace::InstRecord *traceData;

  public:
    //
    enum Status {
        Running,
        Idle,
        IcacheMissStall,
        IcacheMissComplete,
        DcacheMissStall,
        DcacheMissSwitch,
        SwitchedOut
    };

  private:
    Status _status;

  public:
    void post_interrupt(int int_num, int index);

    void zero_fill_64(Addr addr) {
      static int warned = 0;
      if (!warned) {
        warn ("WH64 is not implemented");
        warned = 1;
      }
    };

  public:
    struct Params : public BaseCPU::Params
    {
        MemInterface *icache_interface;
        MemInterface *dcache_interface;
        int width;
#if FULL_SYSTEM
        AlphaITB *itb;
        AlphaDTB *dtb;
        FunctionalMemory *mem;
#else
        Process *process;
#endif
    };
    SimpleCPU(Params *params);
    virtual ~SimpleCPU();

  public:
    // execution context
    ExecContext *xc;

    void switchOut(Sampler *s);
    void takeOverFrom(BaseCPU *oldCPU);

#if FULL_SYSTEM
    Addr dbg_vtophys(Addr addr);

    bool interval_stats;
#endif

    // current instruction
    MachInst inst;

    CpuRequest *req;
    Packet *pkt;

    // Pointer to the sampler that is telling us to switchover.
    // Used to signal the completion of the pipe drain and schedule
    // the next switchover
    Sampler *sampler;

    StaticInstPtr<TheISA> curStaticInst;

    class CacheCompletionEvent : public Event
    {
      private:
        SimpleCPU *cpu;

      public:
        CacheCompletionEvent(SimpleCPU *_cpu);

        virtual void process();
        virtual const char *description();
    };

    CacheCompletionEvent cacheCompletionEvent;

    Status status() const { return _status; }

    virtual void activateContext(int thread_num, int delay);
    virtual void suspendContext(int thread_num);
    virtual void deallocateContext(int thread_num);
    virtual void haltContext(int thread_num);

    // statistics
    virtual void regStats();
    virtual void resetStats();

    // number of simulated instructions
    Counter numInst;
    Counter startNumInst;
    Stats::Scalar<> numInsts;

    virtual Counter totalInstructions() const
    {
        return numInst - startNumInst;
    }

    // number of simulated memory references
    Stats::Scalar<> numMemRefs;

    // number of simulated loads
    Counter numLoad;
    Counter startNumLoad;

    // number of idle cycles
    Stats::Average<> notIdleFraction;
    Stats::Formula idleFraction;

    // number of cycles stalled for I-cache misses
    Stats::Scalar<> icacheStallCycles;
    Counter lastIcacheStall;

    // number of cycles stalled for D-cache misses
    Stats::Scalar<> dcacheStallCycles;
    Counter lastDcacheStall;

    void processCacheCompletion();

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    template <class T>
    Fault read(Addr addr, T &data, unsigned flags);

    template <class T>
    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);

    // These functions are only used in CPU models that split
    // effective address computation from the actual memory access.
    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }

    void prefetch(Addr addr, unsigned flags)
    {
        // need to do this...
    }

    void writeHint(Addr addr, int size, unsigned flags)
    {
        // need to do this...
    }

    Fault copySrcTranslate(Addr src);

    Fault copy(Addr dest);

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntReg(const StaticInst<TheISA> *si, int idx)
    {
        return xc->readIntReg(si->srcRegIdx(idx));
    }

    float readFloatRegSingle(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegSingle(reg_idx);
    }

    double readFloatRegDouble(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegDouble(reg_idx);
    }

    uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx)
    {
        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
        return xc->readFloatRegInt(reg_idx);
    }

    void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val)
    {
        xc->setIntReg(si->destRegIdx(idx), val);
    }

    void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegSingle(reg_idx, val);
    }

    void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegDouble(reg_idx, val);
    }

    void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val)
    {
        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
        xc->setFloatRegInt(reg_idx, val);
    }

    uint64_t readPC() { return xc->readPC(); }
    void setNextPC(uint64_t val) { xc->setNextPC(val); }

    uint64_t readUniq() { return xc->readUniq(); }
    void setUniq(uint64_t val) { xc->setUniq(val); }

    uint64_t readFpcr() { return xc->readFpcr(); }
    void setFpcr(uint64_t val) { xc->setFpcr(val); }

#if FULL_SYSTEM
    uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
    Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
    Fault hwrei() { return xc->hwrei(); }
    int readIntrFlag() { return xc->readIntrFlag(); }
    void setIntrFlag(int val) { xc->setIntrFlag(val); }
    bool inPalMode() { return xc->inPalMode(); }
    void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
    bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
    void syscall() { xc->syscall(); }
#endif

    bool misspeculating() { return xc->misspeculating(); }
    ExecContext *xcBase() { return xc; }
};

#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
<|endoftext|>


<commit_before><commit_msg>findKeywordを使用<commit_after><|endoftext|>