text:
////////////////////////////////////////////////////////////////////////////////
//  Copyright (c) 2015 Bryce Adelstein Lelbach aka wash
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
////////////////////////////////////////////////////////////////////////////////

#include "detail/integer_sequence.hpp"

#include <boost/core/lightweight_test.hpp>

using std::true_type;
using std::false_type;
using std::is_same;

using std::experimental::detail::integer_sequence;

using std::experimental::detail::make_integer_sequence;
using std::experimental::detail::make_reversed_integer_sequence;

int main()
{
    ///////////////////////////////////////////////////////////////////////////
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 0>
      , integer_sequence<int>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 1>
      , integer_sequence<int, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 2>
      , integer_sequence<int, 0, 1>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 3>
      , integer_sequence<int, 0, 1, 2>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 4>
      , integer_sequence<int, 0, 1, 2, 3>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 5>
      , integer_sequence<int, 0, 1, 2, 3, 4>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 6>
      , integer_sequence<int, 0, 1, 2, 3, 4, 5>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 7>
      , integer_sequence<int, 0, 1, 2, 3, 4, 5, 6>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 8>
      , integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 9>
      , integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7, 8>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_integer_sequence<int, 10>
      , integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9>
    >::value), true);

    ///////////////////////////////////////////////////////////////////////////
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 0>
      , integer_sequence<int>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 1>
      , integer_sequence<int, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 2>
      , integer_sequence<int, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 3>
      , integer_sequence<int, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 4>
      , integer_sequence<int, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 5>
      , integer_sequence<int, 4, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 6>
      , integer_sequence<int, 5, 4, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 7>
      , integer_sequence<int, 6, 5, 4, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 8>
      , integer_sequence<int, 7, 6, 5, 4, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 9>
      , integer_sequence<int, 8, 7, 6, 5, 4, 3, 2, 1, 0>
    >::value), true);
    BOOST_TEST_EQ((is_same<
        make_reversed_integer_sequence<int, 10>
      , integer_sequence<int, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0>
    >::value), true);

    return boost::report_errors();
}

ext: cpp


text:
// Copyright (c) YugaByte, Inc.
//
// 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 "yb/tserver/metrics_snapshotter.h"

#include <memory>
#include <vector>
#include <mutex>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "yb/common/jsonb.h"
#include "yb/common/wire_protocol.h"
#include "yb/gutil/strings/escaping.h"
#include "yb/util/bytes_formatter.h"
#include "yb/util/date_time.h"
#include "yb/util/decimal.h"
#include "yb/util/varint.h"
#include "yb/util/enums.h"

#include "yb/client/client.h"
#include "yb/client/client-test-util.h"
#include "yb/client/error.h"
#include "yb/client/schema.h"
#include "yb/client/session.h"
#include "yb/client/table.h"
#include "yb/client/table_handle.h"
#include "yb/client/yb_op.h"

#include "yb/gutil/ref_counted.h"
#include "yb/gutil/strings/substitute.h"
#include "yb/tablet/tablet.h"
#include "yb/tablet/tablet_peer.h"
#include "yb/tserver/tablet_server.h"
#include "yb/tserver/tablet_server_options.h"
#include "yb/tserver/ts_tablet_manager.h"
#include "yb/util/capabilities.h"
#include "yb/util/flag_tags.h"
#include "yb/util/monotime.h"
#include "yb/util/net/net_util.h"
#include "yb/util/status.h"
#include "yb/util/thread.h"
#include "yb/util/mem_tracker.h"

#include "yb/client/client_fwd.h"
#include "yb/gutil/macros.h"
#include "yb/util/tsan_util.h"

#include <boost/algorithm/string.hpp>

using namespace std::literals;

DEFINE_int32(metrics_snapshotter_interval_ms, 30 * 1000,
             "Interval at which the metrics are snapshotted.");
TAG_FLAG(metrics_snapshotter_interval_ms, advanced);

DEFINE_string(metrics_snapshotter_tserver_metrics_whitelist,
    "handler_latency_yb_client_read_local_sum,handler_latency_yb_client_read_local_count",
    "Tserver metrics to record in native metrics storage.");
TAG_FLAG(metrics_snapshotter_tserver_metrics_whitelist, advanced);

DEFINE_string(metrics_snapshotter_table_metrics_whitelist,
    "rocksdb_sst_read_micros_sum,rocksdb_sst_read_micros_count",
    "Table metrics to record in native metrics storage.");
TAG_FLAG(metrics_snapshotter_table_metrics_whitelist, advanced);

constexpr int kTServerMetricsSnapshotterYbClientDefaultTimeoutMs =
  yb::RegularBuildVsSanitizers(5, 60) * 1000;

DEFINE_int32(tserver_metrics_snapshotter_yb_client_default_timeout_ms,
    kTServerMetricsSnapshotterYbClientDefaultTimeoutMs,
    "Default timeout for the YBClient embedded into the tablet server that is used "
    "by metrics snapshotter.");
TAG_FLAG(tserver_metrics_snapshotter_yb_client_default_timeout_ms, advanced);

DEFINE_uint64(metrics_snapshotter_ttl_ms, 7 * 24 * 60 * 60 * 1000 /* 1 week */,
             "Ttl for snapshotted metrics.");
TAG_FLAG(metrics_snapshotter_ttl_ms, advanced);

using std::shared_ptr;
using std::vector;
using strings::Substitute;

namespace yb {

using client::YBSession;
using client::YBTableName;
using client::YBqlOp;

namespace tserver {

// Most of the actual logic of the metrics snapshotter is inside this inner class,
// to avoid having too many dependencies from the header itself.
//
// This is basically the "PIMPL" pattern.
class MetricsSnapshotter::Thread {
 public:
  Thread(const TabletServerOptions& opts, TabletServer* server);

  Status Start();
  Status Stop();

 private:
  void RunThread();
  int GetMillisUntilNextMetricsSnapshot() const;

  CHECKED_STATUS DoPrometheusMetricsSnapshot(const client::TableHandle& table,
    shared_ptr<YBSession> session, const std::string& entity_type, const std::string& entity_id,
    const std::string& metric_name, int64_t metric_val);
  CHECKED_STATUS DoMetricsSnapshot();

  void FlushSession(const std::shared_ptr<YBSession>& session,
      const std::vector<std::shared_ptr<YBqlOp>>& ops = {});
  void LogSessionErrors(const std::shared_ptr<YBSession>& session, const Status& s);
  bool IsCurrentThread() const;

  const std::string& LogPrefix() const {
    return log_prefix_;
  }

  // The server for which we are collecting metrics.
  TabletServer* const server_;

  // The actual running thread (NULL before it is started)
  scoped_refptr<yb::Thread> thread_;

  boost::optional<yb::client::AsyncClientInitialiser> async_client_init_;

  // True once at least one attempt to record a snapshot has been made.
  bool has_metricssnapshotted_ = false;

  // Mutex/condition pair to trigger the metrics snapshotter thread
  // to either snapshot early or exit.
  Mutex mutex_;
  ConditionVariable cond_;

  // Protected by mutex_.
  bool should_run_ = false;

  const std::string log_prefix_;

  // Tokens from FLAGS_metrics_snapshotter_tserver_metrics_whitelist.
  std::unordered_set<std::string> tserver_metrics_whitelist_;

  // Tokens from FLAGS_metrics_snapshotter_table_metrics_whitelist.
  std::unordered_set<std::string> table_metrics_whitelist_;

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

////////////////////////////////////////////////////////////
// MetricsSnapshotter
////////////////////////////////////////////////////////////

MetricsSnapshotter::MetricsSnapshotter(const TabletServerOptions& opts, TabletServer* server)
  : thread_(new Thread(opts, server)) {

}
MetricsSnapshotter::~MetricsSnapshotter() {
  WARN_NOT_OK(Stop(), "Unable to stop metrics snapshotter thread");
}

Status MetricsSnapshotter::Start() {
  return thread_->Start();
}
Status MetricsSnapshotter::Stop() {
  return thread_->Stop();
}

////////////////////////////////////////////////////////////
// MetricsSnapshotter::Thread
////////////////////////////////////////////////////////////

static std::unordered_set<std::string> CSVToSet(const std::string& s) {
  std::unordered_set<std::string> t;
  boost::split(t, s, boost::is_any_of(","));
  return t;
}

MetricsSnapshotter::Thread::Thread(const TabletServerOptions& opts, TabletServer* server)
  : server_(server),
    cond_(&mutex_),
    log_prefix_(Format("P $0: ", server_->permanent_uuid())) {
  VLOG_WITH_PREFIX(1) << "Initializing metrics snapshotter thread";

  // Parse whitelist elements out of flag.
  tserver_metrics_whitelist_ = CSVToSet(FLAGS_metrics_snapshotter_tserver_metrics_whitelist);
  table_metrics_whitelist_ = CSVToSet(FLAGS_metrics_snapshotter_table_metrics_whitelist);

  async_client_init_.emplace(
      "tserver_metrics_snapshotter_client", 0 /* num_reactors */,
      FLAGS_tserver_metrics_snapshotter_yb_client_default_timeout_ms / 1000, "" /* tserver_uuid */,
      &server->options(), server->metric_entity(), server->mem_tracker(),
      server->messenger());
}

int MetricsSnapshotter::Thread::GetMillisUntilNextMetricsSnapshot() const {
  // When we first start up, snapshot immediately.
  if (!has_metricssnapshotted_) {
    return 0;
  }

  return FLAGS_metrics_snapshotter_interval_ms;
}

void MetricsSnapshotter::Thread::LogSessionErrors(const std::shared_ptr<YBSession>& session,
                            const Status& s) {
  auto errors = session->GetPendingErrors();

  int num_errors_to_log = 10;

  // Log only the first 10 errors.
  LOG_WITH_PREFIX(INFO) << errors.size() << " failed ops. First few errors follow";
  int i = 0;
  for (const auto& e : errors) {
    if (i == num_errors_to_log) {
      break;
    }
    LOG_WITH_PREFIX(INFO) << "Op " << e->failed_op().ToString()
              << " had status " << e->status().ToString();
    i++;
  }

  if (errors.size() > num_errors_to_log) {
    LOG_WITH_PREFIX(INFO) << (errors.size() - num_errors_to_log) << " failed ops skipped.";
  }
}

void MetricsSnapshotter::Thread::FlushSession(const std::shared_ptr<YBSession>& session,
                       const std::vector<std::shared_ptr<YBqlOp>>& ops) {
  Status s = session->Flush();
  if (PREDICT_FALSE(!s.ok())) {
    LogSessionErrors(session, s);
    return;
  }

  for (auto& op : ops) {
    if (QLResponsePB::YQL_STATUS_OK != op->response().status()) {
      LOG_WITH_PREFIX(WARNING) << "Status: " <<
        QLResponsePB::QLStatus_Name(op->response().status());
    }
  }
}

Status MetricsSnapshotter::Thread::DoPrometheusMetricsSnapshot(const client::TableHandle& table,
    shared_ptr<YBSession> session, const std::string& entity_type, const std::string& entity_id,
    const std::string& metric_name, int64_t metric_val) {
  auto op = table.NewWriteOp(QLWriteRequestPB::QL_STMT_INSERT);
  auto req = op->mutable_request();

  QLAddStringHashValue(req, server_->permanent_uuid());
  QLAddStringRangeValue(req, entity_type);
  QLAddStringRangeValue(req, entity_id);
  QLAddStringRangeValue(req, metric_name);
  QLAddTimestampRangeValue(req, DateTime::TimestampNow().ToInt64());
  table.AddInt32ColumnValue(req, "value", metric_val);

  req->set_ttl(FLAGS_metrics_snapshotter_ttl_ms);
  return session->Apply(op);
}

Status MetricsSnapshotter::Thread::DoMetricsSnapshot() {
  CHECK(IsCurrentThread());

  auto client_ = async_client_init_->client();
  shared_ptr<YBSession> session = client_->NewSession();
  session->SetTimeout(15s);

  const YBTableName kTableName(master::kSystemNamespaceName, kMetricsSnapshotsTableName);

  client::TableHandle table;
  RETURN_NOT_OK(table.Open(kTableName, client_));

  NMSWriter::EntityMetricsMap table_metrics;
  NMSWriter::MetricsMap server_metrics;
  NMSWriter nmswriter{&table_metrics, &server_metrics};
  WARN_NOT_OK(server_->metric_registry()->WriteForPrometheus(&nmswriter),
      "Couldn't write metrics for native metrics storage");

  for (const auto& kv : server_metrics) {
    if (tserver_metrics_whitelist_.find(kv.first) != tserver_metrics_whitelist_.end()) {
      RETURN_NOT_OK(DoPrometheusMetricsSnapshot(table, session, "tserver",
            server_->permanent_uuid(), kv.first, kv.second));
    }
  }

  for (const auto& kv : table_metrics) {
    for (const auto& vkv : kv.second) {
      if (table_metrics_whitelist_.find(vkv.first) != table_metrics_whitelist_.end()) {
        RETURN_NOT_OK(DoPrometheusMetricsSnapshot(table, session, "table", kv.first, vkv.first,
              vkv.second));
      }
    }
  }

  FlushSession(session);
  return Status::OK();
}

void MetricsSnapshotter::Thread::RunThread() {
  CHECK(IsCurrentThread());
  VLOG_WITH_PREFIX(1) << "Metrics snapshot thread starting";

  while (true) {
    MonoTime next_metrics_snapshot = MonoTime::Now();
    next_metrics_snapshot.AddDelta(
        MonoDelta::FromMilliseconds(GetMillisUntilNextMetricsSnapshot()));

    // Wait for either the snapshot interval to elapse, or for the signal to shut down.
    {
      MutexLock l(mutex_);
      while (true) {
        MonoDelta remaining = next_metrics_snapshot.GetDeltaSince(MonoTime::Now());
        if (remaining.ToMilliseconds() <= 0 ||
            !should_run_) {
          break;
        }
        cond_.TimedWait(remaining);
      }

      if (!should_run_) {
        VLOG_WITH_PREFIX(1) << "Metris snapshot thread finished";
        return;
      }
    }

    Status s = DoMetricsSnapshot();
    if (!s.ok()) {
      LOG_WITH_PREFIX(WARNING) << "Failed to snapshot metrics, code=" << s;
    }
    has_metricssnapshotted_ = true;
  }
}

bool MetricsSnapshotter::Thread::IsCurrentThread() const {
  return thread_.get() == yb::Thread::current_thread();
}

Status MetricsSnapshotter::Thread::Start() {
  CHECK(thread_ == nullptr);

  async_client_init_->Start();

  should_run_ = true;
  return yb::Thread::Create("metrics_snapshotter", "metrics_snapshot",
      &MetricsSnapshotter::Thread::RunThread, this, &thread_);
}

Status MetricsSnapshotter::Thread::Stop() {
  if (!thread_) {
    return Status::OK();
  }

  async_client_init_->Shutdown();

  {
    MutexLock l(mutex_);
    should_run_ = false;
    cond_.Signal();
  }
  RETURN_NOT_OK(ThreadJoiner(thread_.get()).Join());
  thread_ = nullptr;
  return Status::OK();
}

} // namespace tserver
} // namespace yb

ext: cc

max_stars_repo_name: JackDavidson/yugabyte-db

max_issues_repo_name: JackDavidson/yugabyte-db

max_forks_repo_name: JackDavidson/yugabyte-db


text:
/*
@copyright Louis Dionne 2014
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#include <boost/hana/detail/assert.hpp>
#include <boost/hana/list/instance.hpp>
using namespace boost::hana;

int main() {
    //! [main]
    BOOST_HANA_CONSTEXPR_ASSERT(not_equal(list(1, 2), list(3)));
    BOOST_HANA_CONSTEXPR_ASSERT(not_equal('x', 'y'));
    BOOST_HANA_CONSTANT_ASSERT(not_equal(list(1, 2), 'y'));
    //! [main]
}

max_stars_repo_name: rbock/hana

max_issues_repo_name: rbock/hana

max_forks_repo_name: rbock/hana


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

// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.

// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.

// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle

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

#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP

#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>

// BSG 2012-02-06: we use this currently only for distance.
// For other scalar results area,length,perimeter it is commented on purpose.
// Reason is that for distance there is no other choice. distance of two
// empty geometries (or one empty) should NOT return any value.
// But for area it is no problem to be 0.
// Suppose: area(intersection(a,b)). We (probably) don't want a throw there...

// So decided that at least for Boost 1.49 this is commented for
// scalar results, except distance.

#if defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
#include <boost/core/ignore_unused.hpp>
#endif

namespace geofeatures_boost {} namespace boost = geofeatures_boost; namespace geofeatures_boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail
{

template <typename Geometry>
inline void throw_on_empty_input(Geometry const& geometry)
{
#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
    if (geometry::is_empty(geometry))
    {
        throw empty_input_exception();
    }
#else
    geofeatures_boost::ignore_unused(geometry);
#endif
}

} // namespace detail
#endif // DOXYGEN_NO_DETAIL

}} // namespace geofeatures_boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP

ext: hpp

max_stars_repo_name: xarvey/Yuuuuuge

max_issues_repo_name: xarvey/Yuuuuuge

max_forks_repo_name: xarvey/Yuuuuuge


text:
#include "mess/networking/Server.h"

#include "mess/WeakPointerList.h"
#include "mess/networking/Session.h"

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/make_shared.hpp>

#include <iostream>

namespace mess {
namespace networking {

  using boost::asio::ip::tcp;

  Server::Server(boost::asio::io_service &io_service, const uint32_t port)
    : _io_service(io_service),
      _acceptor(io_service, tcp::endpoint(tcp::v4(), port)) {}

  void Server::Close()  {
    if (_acceptor.is_open())
      _acceptor.close();
  }

  void Server::Listen(CallbackFunction callback) {
    std::cout << "Starting server at " << _acceptor.local_endpoint() << "...\n";
    boost::asio::spawn(_io_service,
        [=](boost::asio::yield_context yield)
        {
          weak_ptr_list<Session> active_sessions;
          try {
            while (_acceptor.is_open()) {
              boost::system::error_code ec;
              tcp::socket socket(_io_service);
              _acceptor.async_accept(socket, yield[ec]);
              if (!ec) {
                auto ptr = boost::make_shared<Session>(std::move(socket));
                active_sessions.push_back(ptr);
                ptr->Go(callback);
              }
            }
          } catch (const std::exception &e) {
            std::cerr << "Server: Exception: " << e.what() << "\n";
          }
          active_sessions.for_each([](auto &session){ session.Close(); });
        });
  }

} // namespace networking
} // namespace mess

max_stars_repo_name: nsubiron/mess-engine

max_issues_repo_name: nsubiron/mess-engine

max_forks_repo_name: nsubiron/mess-engine


text:
/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <eosio/chain/abi_serializer.hpp>
#include <eosio/testing/tester.hpp>

#include <Runtime/Runtime.h>

#include <fc/variant_object.hpp>

#include <boost/test/unit_test.hpp>

#include <contracts.hpp>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif

using namespace eosio;
using namespace eosio::chain;
using namespace eosio::testing;
using namespace fc;

using mvo = fc::mutable_variant_object;

namespace
{
struct rem_genesis_account {
   account_name name;
   uint64_t     initial_balance;
};

std::vector<rem_genesis_account> rem_test_genesis( {
  {N(b1),        100'000'000'0000ll}, // TODO investigate why `b1` should be at least this value?
  {N(whale1),     40'000'000'0000ll},
  {N(whale2),     30'000'000'0000ll},
  {N(whale3),     20'000'000'0000ll},
  {N(proda),         500'000'0000ll},
  {N(prodb),         500'000'0000ll},
  {N(prodc),         500'000'0000ll},
  {N(prodd),         500'000'0000ll},
  {N(prode),         500'000'0000ll},
  {N(prodf),         500'000'0000ll},
  {N(prodg),         500'000'0000ll},
  {N(prodh),         500'000'0000ll},
  {N(prodi),         500'000'0000ll},
  {N(prodj),         500'000'0000ll},
  {N(prodk),         500'000'0000ll},
  {N(prodl),         500'000'0000ll},
  {N(prodm),         500'000'0000ll},
  {N(prodn),         500'000'0000ll},
  {N(prodo),         500'000'0000ll},
  {N(prodp),         500'000'0000ll},
  {N(prodq),         500'000'0000ll},
  {N(prodr),         500'000'0000ll},
  {N(prods),         500'000'0000ll},
  {N(prodt),         500'000'0000ll},
  {N(produ),         500'000'0000ll},
  {N(runnerup1),     280'000'0000ll},
  {N(runnerup2),     270'000'0000ll},
  {N(runnerup3),     260'000'0000ll},
  {N(runnerup4),     250'000'0000ll},
  {N(runnerup5),     240'000'0000ll},
  {N(test),          10'000'0000ll },
});

class punish_tester : public TESTER {
public:
   punish_tester();

   void deploy_contract( bool call_init = true ) {
      set_code( config::system_account_name, contracts::rem_system_wasm() );
      set_abi( config::system_account_name, contracts::rem_system_abi().data() );
      if( call_init ) {
         base_tester::push_action(config::system_account_name, N(init),
                                  config::system_account_name,  mutable_variant_object()
                                  ("version", 0)
                                  ("core", CORE_SYM_STR)
            );
      }
      const auto& accnt = control->db().get<account_object,by_name>( config::system_account_name );
      abi_def abi;
      BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
      abi_ser.set_abi(abi, abi_serializer_max_time);
   }

   fc::variant get_global_state() {
      vector<char> data = get_row_by_account( config::system_account_name, config::system_account_name, N(global), N(global) );
      if (data.empty()) std::cout << "\nData is empty\n" << std::endl;
      return data.empty() ? fc::variant() : abi_ser.binary_to_variant( "eosio_global_state", data, abi_serializer_max_time );
   }

   fc::variant get_global_rem_state() {
      vector<char> data = get_row_by_account( config::system_account_name, config::system_account_name, N(globalrem), N(globalrem) );
      if (data.empty()) std::cout << "\nData is empty\n" << std::endl;
      return data.empty() ? fc::variant() : abi_ser.binary_to_variant( "eosio_global_rem_state", data, abi_serializer_max_time );
   }

   uint32_t produce_blocks_until_schedule_is_changed(const uint32_t max_blocks) {
       const auto current_version = control->active_producers().version;
       uint32_t blocks_produced = 0;
       while (control->active_producers().version == current_version && blocks_produced < max_blocks) {
           produce_block();
           blocks_produced++;
       }
       return blocks_produced;
   }

    auto punish_producer( name producer) {
        auto r = base_tester::push_action(config::system_account_name, N(punishprod), producer, mvo()
                     ("producer", producer )
                     );
        produce_block();
        return r;
    }

    auto delegate_bandwidth( name from, name receiver, asset stake_quantity, uint8_t transfer = 1) {
       auto r = base_tester::push_action(config::system_account_name, N(delegatebw), from, mvo()
                    ("from", from )
                    ("receiver", receiver)
                    ("stake_quantity", stake_quantity)
                    ("transfer", transfer)
                    );
       produce_block();
       return r;
    }

   auto undelegate_bandwidth( name from, name receiver, asset unstake_quantity ) {
       auto r = base_tester::push_action(config::system_account_name, N(undelegatebw), from, mvo()
                    ("from", from )
                    ("receiver", receiver)
                    ("unstake_quantity", unstake_quantity)
                    );
       produce_block();
       return r;
    }

    void create_currency( name contract, name manager, asset maxsupply, const private_key_type* signer = nullptr ) {
        auto act =  mutable_variant_object()
                ("issuer",       manager )
                ("maximum_supply", maxsupply );

        base_tester::push_action(contract, N(create), contract, act );
    }

    auto issue( name contract, name manager, name to, asset amount ) {
       auto r = base_tester::push_action( contract, N(issue), manager, mutable_variant_object()
                ("to",      to )
                ("quantity", amount )
                ("memo", "")
        );
        produce_block();
        return r;
    }

    auto transfer( name from, name to, asset quantity ) {
       auto r = push_action( N(rem.token), N(transfer), config::system_account_name,
                             mutable_variant_object()
                             ("from", from)
                             ("to", to)
                             ("quantity", quantity)
                             ("memo", "")
       );
       produce_block();

       return r;
    }

    auto torewards( name caller, name payer, asset amount ) {
        auto r = base_tester::push_action(config::system_account_name, N(torewards), caller, mvo()
                ("payer", payer)
                ("amount", amount)
        );
        produce_block();
        return r;
    }

    auto claim_rewards( name owner ) {
       auto r = base_tester::push_action( config::system_account_name, N(claimrewards), owner, mvo()("owner",  owner ));
       produce_block();
       return r;
    }

    auto set_privileged( name account ) {
       auto r = base_tester::push_action(config::system_account_name, N(setpriv), config::system_account_name,  mvo()("account", account)("is_priv", 1));
       produce_block();
       return r;
    }

    auto register_producer(name producer) {
       auto r = base_tester::push_action(config::system_account_name, N(regproducer), producer, mvo()
                       ("producer",  name(producer))
                       ("producer_key", get_public_key( producer, "active" ) )
                       ("url", "" )
                       ("location", 0 )
                    );
       produce_block();
       return r;
    }

    asset get_balance( const account_name& act ) {
         return get_currency_balance(N(rem.token), symbol(CORE_SYMBOL), act);
    }

    void set_code_abi(const account_name& account, const vector<uint8_t>& wasm, const char* abi, const private_key_type* signer = nullptr) {
       wdump((account));
        set_code(account, wasm, signer);
        set_abi(account, abi, signer);
        if (account == config::system_account_name) {
           const auto& accnt = control->db().get<account_object,by_name>( account );
           abi_def abi_definition;
           BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi_definition), true);
           abi_ser.set_abi(abi_definition, abi_serializer_max_time);
        }
        produce_blocks();
    }

    fc::variant get_producer_info( const account_name& act ) {
       vector<char> data = get_row_by_account( config::system_account_name, config::system_account_name, N(producers), act );
       return abi_ser.binary_to_variant( "producer_info", data, abi_serializer_max_time );
    }

    fc::variant get_voter_info( const account_name& act ) {
       vector<char> data = get_row_by_account( config::system_account_name, config::system_account_name, N(voters), act );
       return data.empty() ? fc::variant() : abi_ser.binary_to_variant( "voter_info", data, abi_serializer_max_time );
    }

    // Vote for producers
    void votepro( account_name voter, vector<account_name> producers ) {
       std::sort( producers.begin(), producers.end() );
       base_tester::push_action(config::system_account_name, N(voteproducer), voter, mvo()
                            ("voter", name(voter))
                            ("proxy", name(0) )
                            ("producers", producers)
                );
       produce_blocks();
    };

   auto unregister_producer(name producer) {
       auto r = base_tester::push_action(config::system_account_name, N(unregprod), producer, mvo()
               ("producer",  name(producer))
               ("producer_key", get_public_key( producer, "active" ) )
               ("url", "" )
               ("location", 0 )
       );
       produce_block();
       return r;
   }

   auto refund_to_stake( const name& to ) {
      auto r = base_tester::push_action(
         config::system_account_name, N(refundtostake), to,
         mvo()("owner", to)
      );

      produce_block();
      return r;
   }

    fc::microseconds microseconds_since_epoch_of_iso_string( const fc::variant& v ) {
        return time_point::from_iso_string( v.as_string() ).time_since_epoch();
    }

    abi_serializer abi_ser;
};

punish_tester::punish_tester() {
   // Create rem.msig and rem.token
   create_accounts({N(rem.msig), N(rem.token), N(rem.rex), N(rem.ram), N(rem.ramfee), N(rem.stake), N(rem.bpay), N(rem.spay), N(rem.vpay), N(rem.saving) });

   // Set code for the following accounts:
   //  - rem (code: rem.bios) (already set by tester constructor)
   //  - rem.msig (code: rem.msig)
   //  - rem.token (code: rem.token)
   set_code_abi(N(rem.msig),
               contracts::rem_msig_wasm(),
               contracts::rem_msig_abi().data());//, &rem_active_pk);
   set_code_abi(N(rem.token),
               contracts::rem_token_wasm(),
               contracts::rem_token_abi().data()); //, &rem_active_pk);

   // Set privileged for rem.msig and rem.token
   set_privileged(N(rem.msig));
   set_privileged(N(rem.token));

   // Verify rem.msig and rem.token is privileged
   const auto& rem_msig_acc = get<account_metadata_object, by_name>(N(rem.msig));
   BOOST_TEST(rem_msig_acc.is_privileged() == true);
   const auto& rem_token_acc = get<account_metadata_object, by_name>(N(rem.token));
   BOOST_TEST(rem_token_acc.is_privileged() == true);

   // Create SYS tokens in rem.token, set its manager as rem
   const auto max_supply     = core_from_string("1000000000.0000"); /// 10x larger than 1B initial tokens
   const auto initial_supply = core_from_string("100000000.0000");  /// 10x larger than 1B initial tokens

   create_currency(N(rem.token), config::system_account_name, max_supply);
   // Issue the genesis supply of 1 billion SYS tokens to rem.system
   issue(N(rem.token), config::system_account_name, config::system_account_name, initial_supply);

   auto actual = get_balance(config::system_account_name);
   BOOST_REQUIRE_EQUAL(initial_supply, actual);

   // Create genesis accounts
   for( const auto& account : rem_test_genesis ) {
      create_account( account.name, config::system_account_name );
   }

   deploy_contract();

   // Buy ram and stake cpu and net for each genesis accounts
   for( const auto& account : rem_test_genesis ) {
      const auto stake_quantity = account.initial_balance - 1000;

      const auto r = delegate_bandwidth(N(rem.stake), account.name, asset(stake_quantity));
      BOOST_REQUIRE( !r->except_ptr );
   }
   auto producer_candidates = std::vector< account_name >{
       N(proda), N(prodb), N(prodc), N(prodd), N(prode), N(prodf), N(prodg),
       N(prodh), N(prodi), N(prodj), N(prodk), N(prodl), N(prodm), N(prodn),
       N(prodo), N(prodp), N(prodq), N(prodr), N(prods), N(prodt), N(produ)
   };
   for( auto pro : producer_candidates ) {
       register_producer(pro);
       votepro( pro, {pro} );
   }
   auto runnerups = std::vector< account_name >{
       N(runnerup1), N(runnerup2), N(runnerup3),  N(runnerup4),  N(runnerup5)
   };
   for( auto pro : runnerups ) {
       register_producer(pro);
       votepro( pro, {pro} );
   }

   // vote for prods to activate 15% of stake
   const auto whales = std::vector< name >{ N(b1), N(whale1), N(whale2) };
   for( const auto& whale : whales ) {
       votepro( whale, producer_candidates );
   }
   produce_blocks_for_n_rounds(3);
}

BOOST_AUTO_TEST_SUITE(punish_prod_tests)
BOOST_FIXTURE_TEST_CASE( punish_prod_not_enough_inactivity_test, punish_tester ) {
    try {
        {
            const auto active_schedule = control->head_block_state()->active_schedule;
            name prod_name_to_punish = active_schedule.producers.at(0).producer_name;

            BOOST_REQUIRE_THROW(
               punish_producer(prod_name_to_punish), eosio_assert_message_exception);

            produce_block();
            BOOST_TEST_REQUIRE(  get_producer_info( prod_name_to_punish )["is_active"].as_bool() );
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_prod_enough_inactivity_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
            const auto active_schedule = control->head_block_state()->active_schedule;
            name prod_name_to_punish = active_schedule.producers.at(0).producer_name;

            punish_producer(prod_name_to_punish);

            BOOST_TEST_REQUIRE(  !get_producer_info( prod_name_to_punish )["is_active"].as_bool() );
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_punished_prod_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
            const auto active_schedule = control->head_block_state()->active_schedule;
            name prod_name_to_punish = active_schedule.producers.at(0).producer_name;

            punish_producer(prod_name_to_punish);
            BOOST_REQUIRE_THROW(
               punish_producer(prod_name_to_punish), eosio_assert_message_exception);

        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( regprod_during_punishment_period_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
            const auto active_schedule = control->head_block_state()->active_schedule;
            name prod_name_to_punish = active_schedule.producers.at(0).producer_name;

            punish_producer(prod_name_to_punish);
            BOOST_REQUIRE_THROW(
               register_producer(prod_name_to_punish), eosio_assert_message_exception);
            BOOST_TEST_REQUIRE( !get_producer_info( prod_name_to_punish )["is_active"].as_bool() );
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( regprod_after_punishment_period_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
            const auto active_schedule = control->head_block_state()->active_schedule;
            name prod_name_to_punish = active_schedule.producers.at(0).producer_name;

            punish_producer(prod_name_to_punish);
            produce_empty_block(fc::days(32));
            register_producer(prod_name_to_punish);
            BOOST_TEST_REQUIRE( get_producer_info( prod_name_to_punish )["is_active"].as_bool() );
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_non_existing_producer_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
            name prod_name_to_punish = N(test);
            BOOST_REQUIRE_THROW(
               punish_producer(prod_name_to_punish), eosio_assert_message_exception);
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_not_active_producer_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
          const auto active_schedule = control->head_block_state()->active_schedule;
          name prod_name_to_punish = active_schedule.producers.at(0).producer_name;
          unregister_producer(prod_name_to_punish);

          BOOST_REQUIRE_THROW(
             punish_producer(prod_name_to_punish), eosio_assert_message_exception);
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_not_top21_producer_test, punish_tester ) {
    try {
        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));
        {
          const auto active_schedule = control->head_block_state()->active_schedule;
          name prod_name_to_punish = N(runnerup5);

          BOOST_REQUIRE_THROW(
             punish_producer(prod_name_to_punish), eosio_assert_message_exception);
        }
    } FC_LOG_AND_RETHROW()
}

BOOST_FIXTURE_TEST_CASE( punish_prod_right_after_top21_test, punish_tester ) {
    try {
        const auto whales = std::vector< name >{ N(b1) };
        auto producer_candidates = std::vector< account_name >{
            N(proda), N(prodb), N(prodc), N(prodd), N(prode), N(prodf), N(prodg),
            N(prodh), N(prodi), N(prodj), N(prodk), N(prodl), N(prodm), N(prodn),
            N(prodo), N(prodp), N(prodq), N(prodr), N(prods), N(prodt), N(produ)
        };
        const name prod_name_to_punish = N(runnerup5);

        for( const auto& whale : whales ) {
            votepro( whale, std::vector<name>{prod_name_to_punish} );
        }
        produce_blocks_for_n_rounds(3);

        for( const auto& whale : whales ) {
            votepro( whale, producer_candidates );
        }

        produce_blocks_for_n_rounds(3);

        produce_empty_block(fc::microseconds(get_global_rem_state()["producer_max_inactivity_time"]["_count"].as_int64()));

        for( const auto& whale : whales ) {
            votepro( whale, std::vector<name>{prod_name_to_punish} );
        }

        produce_blocks_until_schedule_is_changed(1000);

        BOOST_REQUIRE_THROW(
           punish_producer(prod_name_to_punish), eosio_assert_message_exception);

    } FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_SUITE_END()
} // namespace anonymous

max_stars_repo_name: kushnirenko/remprotocol

max_issues_repo_name: kushnirenko/remprotocol

max_forks_repo_name: kushnirenko/remprotocol


text:
//
//  name-components.cpp
//  libndnrtc
//
//  Copyright 2013 Regents of the University of California
//  For licensing details see the LICENSE file.
//
//  Author:  Peter Gusev
//

#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string.hpp>

#include "name-components.hpp"

using namespace std;
using namespace ndnrtc;
using namespace ndn;

const string NameComponents::NameComponentApp = "ndnrtc";
const string NameComponents::NameComponentAudio = "audio";
const string NameComponents::NameComponentVideo = "video";
const string NameComponents::NameComponentMeta = "_meta";
const string NameComponents::NameComponentDelta = "d";
const string NameComponents::NameComponentKey = "k";
const string NameComponents::NameComponentParity = "_parity";
const string NameComponents::NameComponentManifest = "_manifest";

#include <bitset>

Name
NamespaceInfo::getPrefix(int filter) const
{
    using namespace prefix_filter;
    Name prefix(basePrefix_);

    if (filter)
    {
        if (filter&(Library^Base))
            prefix.append(Name(NameComponents::NameComponentApp)).appendVersion(apiVersion_);
        if (filter&(Stream^Library))
            prefix.append((streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeAudio ?
                NameComponents::NameComponentAudio : NameComponents::NameComponentVideo)).append(streamName_);
        if (filter&(StreamTS^Stream) && threadName_ != "")
            prefix.appendTimestamp(streamTimestamp_);
        if (threadName_ != "" &&
            (filter&(Thread^StreamTS)  ||
            filter&(ThreadNT^StreamTS) & streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeVideo))
        {
            prefix.append(threadName_);
        }

        if (isMeta_)
        {
            if (filter&(Segment^Thread))
                prefix.append(NameComponents::NameComponentMeta);

            if (filter&(Segment^Sample))
            {
                prefix.appendVersion(metaVersion_).appendSegment(segNo_);
            }
        }
        else
        {
            if (filter&(Thread^ThreadNT) && threadName_ != "" &&
                streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeVideo)
                    prefix.append((isDelta_ ? NameComponents::NameComponentDelta : NameComponents::NameComponentKey));
            if (filter&(Sample^Thread))
                prefix.appendSequenceNumber(sampleNo_);

            if (filter&(Segment^Sample))
            {
                if (isParity_)
                    prefix.append(NameComponents::NameComponentParity);
                prefix.appendSegment(segNo_);
            }
        }
    }

    return prefix;
}

Name
NamespaceInfo::getSuffix(int filter) const
{
    using namespace suffix_filter;
    Name suffix;

    if (filter)
    {
        if (filter&(Library^Stream))
            suffix.append(Name(NameComponents::NameComponentApp)).appendVersion(apiVersion_);
        if (filter&(Stream^Thread))
        {
            suffix.append((streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeAudio ?
                NameComponents::NameComponentAudio : NameComponents::NameComponentVideo)).append(streamName_);
            if (threadName_ != "")
                suffix.appendTimestamp(streamTimestamp_);
        }
        if (filter&(Thread^Sample) && threadName_ != "")
            suffix.append(threadName_);

        if (isMeta_)
        {
            if ((filter&(Thread^Sample) && threadName_ != "") ||
                filter&(Stream^Thread))
                suffix.append(NameComponents::NameComponentMeta);
        }

        if (filter&(Thread^Sample) && threadName_ != "" &&
            streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeVideo &&
            !isMeta_)
            suffix.append((isDelta_ ? NameComponents::NameComponentDelta : NameComponents::NameComponentKey));
        if (filter&(Sample^Segment))
        {
            if (isMeta_)
                suffix.appendVersion(metaVersion_);
            else
                suffix.appendSequenceNumber(sampleNo_);
        }
        if (filter&(Segment) && hasSegNo_)
        {
            if (isParity_)
                suffix.append(NameComponents::NameComponentParity);
            suffix.appendSegment(segNo_);
        }
    }
    return suffix;
}

//******************************************************************************
vector<string> ndnrtcVersionComponents()
{
    string version = NameComponents::fullVersion();
    std::vector<string> components;

    boost::erase_all(version, "v");
    boost::split(components, version, boost::is_any_of("."), boost::token_compress_on);
    return components;
}

std::string
NameComponents::fullVersion()
{
    return std::string(PACKAGE_VERSION);
}

unsigned int
NameComponents::nameApiVersion()
{
    return (unsigned int)atoi(ndnrtcVersionComponents().front().c_str());
}

Name
NameComponents::ndnrtcSuffix()
{
    return Name(NameComponentApp).appendVersion(nameApiVersion());
}

Name
NameComponents::streamPrefix(MediaStreamParams::MediaStreamType type, std::string basePrefix)
{
    Name n = Name(basePrefix);
    n.append(ndnrtcSuffix());
    return ((type == MediaStreamParams::MediaStreamType::MediaStreamTypeAudio) ?
        n.append(NameComponentAudio) : n.append(NameComponentVideo));
}

Name
NameComponents::audioStreamPrefix(string basePrefix)
{
    return streamPrefix(MediaStreamParams::MediaStreamType::MediaStreamTypeAudio, basePrefix);
}

Name
NameComponents::videoStreamPrefix(string basePrefix)
{
    return streamPrefix(MediaStreamParams::MediaStreamType::MediaStreamTypeVideo, basePrefix);
}

//******************************************************************************
bool extractMeta(const ndn::Name& name, NamespaceInfo& info)
{
    // example: name == %FD%05/%00%00
    if (name.size() >= 1 && name[0].isVersion())
    {
        info.metaVersion_ = name[0].toVersion();
        if (name.size() >= 2)
        {
            info.segNo_ = name[1].toSegment();
            info.hasSegNo_ = true;
        }
        else
            info.hasSegNo_ = false;
        return true;
    }

    return false;
}

bool extractVideoStreamInfo(const ndn::Name& name, NamespaceInfo& info)
{
    if (name.size() < 3)
        return false;

    int idx = 0;
    info.streamName_ = name[idx++].toEscapedString();
    info.isMeta_ = (name[idx++] == Name::Component(NameComponents::NameComponentMeta));

    if (info.isMeta_)
    {   // example: name == camera/_meta/%FD%05/%00%00
        info.segmentClass_ = SegmentClass::Meta;
        info.threadName_ = "";
        return extractMeta(name.getSubName(idx), info);
    }
    else
    {   // example: name == camera/%FC%00%00%01c_%27%DE%D6/hi/d/%FE%07/%00%00

        info.class_ = SampleClass::Unknown;
        info.segmentClass_ = SegmentClass::Unknown;
        info.streamTimestamp_ = name[idx-1].toTimestamp();
        info.threadName_ = name[idx++].toEscapedString();

        if (name.size() <= idx)
            return false;

        info.isMeta_ = (name[idx++] == Name::Component(NameComponents::NameComponentMeta));

        if (info.isMeta_)
        {   // example: camera/%FC%00%00%01c_%27%DE%D6/hi/_meta/%FD%05/%00%00
            info.segmentClass_ = SegmentClass::Meta;
            if(name.size() > idx-1 && extractMeta(name.getSubName(idx), info))
                return true;
            return false;
        }

        if (name[idx-1] == Name::Component(NameComponents::NameComponentDelta) ||
            name[idx-1] == Name::Component(NameComponents::NameComponentKey))
        {
            info.isDelta_ = (name[idx-1] == Name::Component(NameComponents::NameComponentDelta));
            info.class_ = (info.isDelta_ ? SampleClass::Delta : SampleClass::Key);

            try{
                if (name.size() > idx)
                    info.sampleNo_ = (PacketNumber)name[idx++].toSequenceNumber();
                else
                {
                    info.hasSeqNo_ = false;
                    return true;
                }

                info.hasSeqNo_ = true;
                if (name.size() > idx)
                {
                    info.isParity_ = (name[idx] == Name::Component(NameComponents::NameComponentParity));
                    info.hasSegNo_ = true;

                    if (info.isParity_ && name.size() > idx+1)
                    {
                        info.segmentClass_ = SegmentClass::Parity;
                        info.segNo_ = name[idx+1].toSegment();
                        return true;
                    }
                    else
                    {
                        if (info.isParity_)
                            return false;
                        else
                        {
                            if (name[idx] == Name::Component(NameComponents::NameComponentManifest))
                                info.segmentClass_ = SegmentClass::Manifest;
                            else
                            {
                                info.segmentClass_ = SegmentClass::Data;
                                info.segNo_ = name[idx].toSegment();
                            }
                        }
                        return true;
                    }
                }
                else
                {
                    info.segmentClass_ = SegmentClass::Unknown;
                    info.hasSegNo_ = false;
                    return true;
                }
            }
            catch (std::runtime_error& e)
            {
                return false;
            }
        }
    }

    return false;
}

bool extractAudioStreamInfo(const ndn::Name& name, NamespaceInfo& info)
{
    if (name.size() < 2)
        return false;

    int idx = 0;
    info.streamName_ = name[idx++].toEscapedString();
    info.isMeta_ = (name[idx++] == Name::Component(NameComponents::NameComponentMeta));

    if (info.isMeta_)
    {
        info.segmentClass_ = SegmentClass::Meta;
        if (name.size() < idx+1)
            return false;

        info.threadName_ = "";
        return extractMeta(name.getSubName(idx), info);;
    }
    else
    {
        info.class_ = SampleClass::Unknown;
        info.segmentClass_ = SegmentClass::Unknown;
        info.streamTimestamp_ = name[idx-1].toTimestamp();
        info.threadName_ = name[idx++].toEscapedString();

        if (name.size() == 3)
        {
            info.hasSeqNo_ = false;
            return true;
        }

        info.isMeta_ = (name[idx] == Name::Component(NameComponents::NameComponentMeta));

        if (info.isMeta_)
        {
            info.segmentClass_ = SegmentClass::Meta;
            if (name.size() > idx+1 && extractMeta(name.getSubName(idx+1), info))
                return true;
            return false;
        }

        info.isDelta_ = true;
        info.class_ = SampleClass::Delta;

        try
        {
            if (name.size() > 3)
                info.sampleNo_ = (PacketNumber)name[idx++].toSequenceNumber();

            info.hasSeqNo_ = true;
            if (name.size() > idx)
            {
                if (name[idx] == Name::Component(NameComponents::NameComponentManifest))
                    info.segmentClass_ = SegmentClass::Manifest;
                else
                {
                    info.hasSegNo_ = true;
                    info.segmentClass_ = SegmentClass::Data;
                    info.segNo_ = name[idx].toSegment();
                }
                return true;
            }
            else
            {
                info.hasSegNo_ = false;
                return true;
            }
        }
        catch (std::runtime_error& e)
        {
            return false;
        }
    }

    return false;
}

bool
NameComponents::extractInfo(const ndn::Name& name, NamespaceInfo& info)
{
    bool goodName = false;
    static Name ndnrtcSubName(NameComponents::NameComponentApp);
    Name subName;
    int i;

    for (i = name.size()-2; i > 0 && !goodName; --i)
    {
        subName = name.getSubName(i);
        goodName = ndnrtcSubName.match(subName);
    }

    if (goodName)
    {
        info.basePrefix_ = name.getSubName(0, i+1);

        if ((goodName = subName[1].isVersion()))
        {
            info.apiVersion_ = subName[1].toVersion();

            if (subName.size() > 2 &&
                (goodName = (subName[2] == Name::Component(NameComponents::NameComponentAudio) ||
                            subName[2] == Name::Component(NameComponents::NameComponentVideo)))  )
            {
                info.streamType_ = (subName[2] == Name::Component(NameComponents::NameComponentAudio) ?
                                MediaStreamParams::MediaStreamType::MediaStreamTypeAudio :
                                MediaStreamParams::MediaStreamType::MediaStreamTypeVideo );

                if (info.streamType_ == MediaStreamParams::MediaStreamType::MediaStreamTypeAudio)
                    return extractAudioStreamInfo(subName.getSubName(3), info);
                else
                    return extractVideoStreamInfo(subName.getSubName(3), info);
            }
        }
    }

    return false;
}

max_stars_repo_name: peurpdapeurp/ndnrtc

max_issues_repo_name: peurpdapeurp/ndnrtc

max_forks_repo_name: peurpdapeurp/ndnrtc


text:
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-

// -- BEGIN LICENSE BLOCK ----------------------------------------------
// This file is part of the SCHUNK Canopen Driver suite.
//
// This program is free software licensed under the LGPL
// (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
// You can find a copy of this license in LICENSE folder in the top
// directory of the source code.
//
// © Copyright 2016 SCHUNK GmbH, Lauffen/Neckar Germany
// © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
// -- END LICENSE BLOCK ------------------------------------------------

//----------------------------------------------------------------------
/*!\file
 *
 * \author  Georg Heppner <heppner@fzi.de>
 * \author  Felix Mauch <mauch@fzi.de>
 * \date    2015-10-1
 *
 */
//----------------------------------------------------------------------

#include "CanOpenController.h"
#include <icl_hardware_can/tCanDeviceDummy.h>
#include "Logging.h"
#include "ds301.h"
#include "sync.h"
#include "exceptions.h"

#include <cstdlib> // getenv
#include <boost/filesystem.hpp>

namespace icl_hardware {
namespace canopen_schunk {

CanOpenController::CanOpenController(const std::string can_device_identifier,
                                     const uint32_t baud_rate,
                                     const std::string& resource_folder_location
                                    )
  : m_can_device_name(can_device_identifier),
    m_can_device_flags(O_RDWR|O_NONBLOCK),
    m_can_device_acceptance_code(0xff),
    m_can_device_acceptance_mask(0xff),
    m_can_device_send_fifo_size(300),
    m_can_device_receive_fifo_size(2000),
    m_can_device_baud_rate(baud_rate),
    m_heartbeat_monitor(new HeartBeatMonitor()),
    m_polling_period_ms(1),
    m_resource_folder_location(resource_folder_location),
    m_ws_broadcast_counter(0),
    m_ws_broadcast_rate(5)
{
    init();
}

CanOpenController::~CanOpenController ()
{
  // Stop receiving thread
  if (m_receive_thread)
  {
    m_receive_thread->stop();
  }
}

void CanOpenController::initNodes (const int16_t node_id)
{
  for (std::map<uint8_t, DS301Node::Ptr>::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  {
    if (it->first == node_id || node_id < 0)
    {
      it->second->initNode();
    }
  }
}

void CanOpenController::processCanMsgCallback ( const can::tCanMessage& msg )
{
  if (msg.id == ds301::ID_NMT)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "NMT MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Message length: " << msg.dlc << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id == ds301::ID_SYNC)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "SYNC MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_EMCY_MIN && msg.id <= ds301::ID_EMCY_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "EMCY MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_EMCY_MIN+1);
    if (node)
    {
      try
      {
        node->m_emcy->update(msg);
      }
      catch (const std::exception& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in EMCY update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id == ds301::ID_TIME)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TIME MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_TPDO1_MIN && msg.id <= ds301::ID_TPDO1_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TPDO1 MESSAGE for node " << msg.id - ds301::ID_TPDO1_MIN+1 << " RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_TPDO1_MIN+1);
    if (node)
    {
      try
      {
        node->m_tpdos.at(0)->update(msg);
      }
      catch (const std::exception& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in PDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_RPDO1_MIN && msg.id <= ds301::ID_RPDO1_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "RPDO1 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_TPDO2_MIN && msg.id <= ds301::ID_TPDO2_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TPDO2 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_TPDO2_MIN+1);
    if (node)
    {
      try
      {
        node->m_tpdos.at(1)->update(msg);
      }
      catch (const std::exception& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in PDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_RPDO2_MIN && msg.id <= ds301::ID_RPDO2_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "RPDO2 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_TPDO3_MIN && msg.id <= ds301::ID_TPDO3_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TPDO3 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_TPDO3_MIN+1);
    if (node)
    {
      try
      {
        node->m_tpdos.at(2)->update(msg);
      }
      catch (const std::exception& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in PDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_RPDO3_MIN && msg.id <= ds301::ID_RPDO3_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "RPDO3 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_TPDO4_MIN && msg.id <= ds301::ID_TPDO4_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TPDO4 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_TPDO4_MIN+1);
    if (node)
    {
      try
      {
        node->m_tpdos.at(3)->update(msg);
      }
      catch (const std::exception& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in PDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_RPDO4_MIN && msg.id <= ds301::ID_RPDO4_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "RPDO4 MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
  }
  else if (msg.id >= ds301::ID_TSDO_MIN && msg.id <= ds301::ID_TSDO_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "TSDO MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_TSDO_MIN+1);
    if (node)
    {
      try
      {
        node->m_sdo.update(msg);
      }
      catch (const ResponseException& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in SDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_RSDO_MIN && msg.id <= ds301::ID_RSDO_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "RSDO MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    DS301Node::Ptr node = getNodeById(msg.id - ds301::ID_RSDO_MIN+1);
    if (node)
    {
      try
      {
        node->m_sdo.update(msg);
      }
      catch (const ResponseException& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in SDO update function: " << e.what() << endl);
      }
    }
  }
  else if (msg.id >= ds301::ID_NMT_ERROR_MIN && msg.id <= ds301::ID_NMT_ERROR_MAX)
  {
    LOGGING_DEBUG_C (CanOpen, CanOpenController, "NMT_ERROR MESSAGE RECEIVED" << endl);
    LOGGING_TRACE_C (CanOpen, CanOpenController,
                     "Message id: " << msg.id << endl
                     << "Data: " << hexArrayToString(msg.data, msg.dlc) << endl);
    uint8_t node_id = msg.id - ds301::ID_NMT_ERROR_MIN+1;
    DS301Node::Ptr node = getNodeById(node_id);

    if (node)
    {
      try
      {
        node->m_nmt.update(msg);
      }
      catch (const ResponseException& e)
      {
        LOGGING_ERROR (CanOpen, "Exception thrown in NMT update function: " << e.what() << endl);
      }
      if (msg.data[0] != 0x0)
      {
        m_heartbeat_monitor->addHeartbeat(node_id);
      }
    }
    else if ( msg.dlc == 1 && msg.data[0] == 0x0)
    {
      // TODO (optional): If byte 0: add new node (autodiscovery)
      LOGGING_INFO_C (CanOpen, CanOpenController, "NMT bootup of node " << msg.id - ds301::ID_NMT_ERROR_MIN+1 << endl);
    }
  }
}

void CanOpenController::reconnectCanDevice(const std::string& can_identifier, const uint32_t baud_rate)
{
  if (baud_rate != 0)
  {
    m_can_device_baud_rate = baud_rate;
  }
  m_can_device_name = can_identifier;

  if (m_receive_thread)
  {
    m_receive_thread->stop();
  }

  try
  {
    init();
  }
  catch (const DeviceException& e)
  {
    LOGGING_ERROR_C (CanOpen, CanOpenController, "Initializing device failed. Reason: " << e.what());
  }
}

void CanOpenController::init()
{
  #ifdef _IC_BUILDER_ICL_COMM_WEBSOCKET_
  m_ws_broadcaster = boost::shared_ptr<icl_comm::websocket::WsBroadcaster>(new icl_comm::websocket::WsBroadcaster(icl_comm::websocket::WsBroadcaster::eRT_LWA4P));
  #endif // _IC_BUILDER_ICL_COMM_WEBSOCKET_

  getResources();

  if (m_can_device_name == "Dummy")
  {
    m_can_device.reset(new icl_hardware::can::tCanDeviceDummy( m_can_device_name.c_str(),
                                                            m_can_device_flags,
                                                            m_can_device_acceptance_code,
                                                            m_can_device_acceptance_mask,
                                                            m_can_device_baud_rate,
                                                            m_can_device_send_fifo_size,
                                                            m_can_device_receive_fifo_size
                                                          ));
  }
  else if (m_can_device_name == "auto")
  {
    const boost::array<const std::string, 4> names = {"/dev/pcanusb0","/dev/pcanusb1","/dev/pcanusb2","/dev/pcanusb3"};
    bool can_found = false;
    LOGGING_INFO (CanOpen, "CAN Device was set to auto. " << endl);

    for (size_t num = 0; num < names.size() ; ++num)
    {
        m_can_device_name = names[num];
        LOGGING_INFO(CanOpen, "Trying CAN device: " << m_can_device_name << "... " << endl);
        try
        {
            m_can_device.reset(icl_hardware::can::tCanDevice::Create( m_can_device_name.c_str(),
                                                                      m_can_device_flags,
                                                                      m_can_device_acceptance_code,
                                                                      m_can_device_acceptance_mask,
                                                                      m_can_device_baud_rate,
                                                                      m_can_device_send_fifo_size,
                                                                      m_can_device_receive_fifo_size
                                                                    ));

            if (m_can_device)
            {
              if (!m_can_device->IsInitialized())
              {
                std::stringstream ss;
                continue;
              }
            }
            can_found = true;

            break;

        }
        catch (DeviceException const& e)
        {
            LOGGING_INFO(CanOpen, e.what() << endl);
            can_found = false;
        }
    }
    if (!can_found)
    {
        LOGGING_ERROR(CanOpen, " CAN DEVICE COULD NOT BE OPENED. \n >> Giving up.");
        exit(-123);
        return;
    }
  }
  else
  {
    m_can_device.reset(icl_hardware::can::tCanDevice::Create( m_can_device_name.c_str(),
                                                            m_can_device_flags,
                                                            m_can_device_acceptance_code,
                                                            m_can_device_acceptance_mask,
                                                            m_can_device_baud_rate,
                                                            m_can_device_send_fifo_size,
                                                            m_can_device_receive_fifo_size
                                                          ));
  }

  if (m_can_device)
  {
    if (!m_can_device->IsInitialized())
    {
      std::stringstream ss;
      ss << "FATAL: COULD NOT INITIALIZE CAN DEVICE in " << m_can_device_name;

      throw DeviceException(ss.str());
    }
  }
  else
  {
    std::stringstream ss;
    ss << "FATAL: COULD NOT GET VALID CAN DEVICE in " << m_can_device_name;

    throw DeviceException(ss.str());
  }

  m_receive_thread.reset(new CanOpenReceiveThread(icl_core::TimeSpan::createFromMSec(m_polling_period_ms),
                                                  m_can_device,
                                                  boost::bind(&CanOpenController::processCanMsgCallback, this, _1)
                                                 ));

  if (!m_receive_thread)
  {
    throw DeviceException("FATAL: Could not start listener thread for CAN bus.");
  }

  // add default DS402Group
  addGroup<DS402Group>("default");
  m_heartbeat_monitor->registerErrorCallback(boost::bind(&CanOpenController::stopAll, this));
}

void CanOpenController::deleteGroup(const std::string& identifier)
{
  std::string sanitized_identifier = sanitizeString(identifier);

  std::map<std::string, DS301Group::Ptr>::iterator group_it;
  group_it = m_groups.find(sanitized_identifier);
  if (group_it != m_groups.end())
  {
    std::vector<uint8_t> deleted_node_ids;
    group_it->second->deleteNodes(deleted_node_ids); // This will return the IDs of deleted nodes

    // Now also delete shared pointers in controller
    for (std::vector<uint8_t>::iterator it = deleted_node_ids.begin();
         it != deleted_node_ids.end();
         ++it)
    {
      // Find the node with given Id
      std::map<uint8_t, DS301Node::Ptr>::iterator node_it = m_nodes.find(*it);
      assert(node_it->second.use_count() == 1);
      m_nodes.erase(node_it);
    }

    m_groups.erase(group_it);
  }
  else
  {
    LOGGING_ERROR_C(CanOpen, CanOpenController, "No group with the given identifer " << sanitized_identifier
      << " exists. Not deleting anything." << endl);
  }
}

void CanOpenController::deleteNode(const uint8_t node_id)
{
  // Delete node in group
  for (std::map<std::string, DS301Group::Ptr>::iterator it = m_groups.begin();
       it != m_groups.end();
       ++it)
  {
    if (it->second->deleteNodeFromId(node_id))
    {
      // group for node_id was found and node was deleted.
      break;
    }
  }

  // Delete node in controller's list
  std::map<uint8_t, DS301Node::Ptr>::iterator node_it = m_nodes.find(node_id);
  assert(node_it->second.use_count() == 1);
  m_nodes.erase(node_it);
}

DS301Node::Ptr CanOpenController::getNodeById(const uint8_t node_id)
{
  std::map<uint8_t, DS301Node::Ptr>::iterator node_it = m_nodes.find(node_id);
  if (node_it == m_nodes.end())
  {
    LOGGING_ERROR_C(CanOpen, CanOpenController, "A node with the given ID " << node_id <<
                                                " does not exist. Therefore this CAN message will be ignored." << endl);
    // Return a NULL pointer
    return DS301Node::Ptr();
  }
  return node_it->second;
}

void CanOpenController::getResources()
{
  boost::filesystem::path resources_path(m_resource_folder_location);

  if (m_resource_folder_location == "")
  {
    char const* tmp = std::getenv("CANOPEN_RESOURCE_PATH");
    if (tmp == NULL)
    {
      LOGGING_WARNING_C(
          CanOpen,
          CanOpenController,
          "The environment variable 'CANOPEN_RESOURCE_PATH' could not be read. Using relative path 'resources/'" << endl);
      resources_path = boost::filesystem::path("resources");
    }
    else
    {
      resources_path = boost::filesystem::path(tmp);
    }
  }

  std::string sdo_errors_filename = (resources_path / boost::filesystem::path("SDO.ini")).string();
  SDO::addErrorMapFromFile( sdo_errors_filename );

  std::string emcy_emergency_errors_filename = (resources_path / boost::filesystem::path("EMCY.ini")).string();
  EMCY::addEmergencyErrorMap( emcy_emergency_errors_filename, "emergency_errors");
  EMCY::addErrorRegisterMap( emcy_emergency_errors_filename, "error_registers");

  emcy_emergency_errors_filename = (resources_path / boost::filesystem::path("EMCY_DS402.ini")).string();
  EMCY::addEmergencyErrorMap( emcy_emergency_errors_filename, "emergency_errors");
}

void CanOpenController::syncAll()
{
  for (std::map<uint8_t, DS301Node::Ptr>::iterator it = m_nodes.begin();
       it != m_nodes.end();
  ++it)
  {
    it->second->downloadPDOs();
  }

  sendSync (m_can_device);

  for (std::map<uint8_t, DS301Node::Ptr>::iterator it = m_nodes.begin();
       it != m_nodes.end();
  ++it)
  {
    it->second->uploadPDOs();
  }

  #ifdef _IC_BUILDER_ICL_COMM_WEBSOCKET_
  if(m_ws_broadcast_counter % m_ws_broadcast_rate == 0)
  {
    if (!m_ws_broadcaster->sendState())
    {
    //    LOGGING_WARNING_C(
    //        CanOpen,
    //        CanOpenController, "Can't send ws_broadcaster state - reconnect pending..." << endl);
    }
    m_ws_broadcast_counter = 0;
  }
  ++m_ws_broadcast_counter;
  #endif // _IC_BUILDER_ICL_COMM_WEBSOCKET_

}

void CanOpenController::stopAll()
{
  LOGGING_INFO (CanOpen, "Stop of all nodes requested!" << endl);
  for (std::map<uint8_t, DS301Node::Ptr>::iterator it = m_nodes.begin();
       it != m_nodes.end();
  ++it)
  {
    it->second->stopNode();
  }
}

std::vector< uint8_t > CanOpenController::getNodeList()
{
  std::vector <uint8_t> node_list;

  size_t i=0;
  for (std::map<uint8_t, DS301Node::Ptr>::iterator it = m_nodes.begin();
       it != m_nodes.end();
  ++it)
  {
    it->second->downloadPDOs();
    node_list.push_back(it->second->getNodeId());
    ++i;
  }

  return node_list;
}

void CanOpenController::enablePPMotion(const int16_t node_id)
{
  syncAll();
  usleep(5000); // sleep 5 ms

  LOGGING_TRACE_C (CanOpen, CanOpenController, "in function " << __FUNCTION__ << endl);

  for (std::map<std::string, DS301Group::Ptr>::iterator it = m_groups.begin();
       it != m_groups.end();
       ++it)
  {
    DS402Group::Ptr group_ds402 = boost::dynamic_pointer_cast<DS402Group>(it->second);
    if (group_ds402)
    {
      group_ds402->startPPMovement(node_id);
    }
  }

  syncAll();
  usleep(5000); // sleep 5 ms

  for (std::map<std::string, DS301Group::Ptr>::iterator it = m_groups.begin();
       it != m_groups.end();
       ++it)
  {
    DS402Group::Ptr group_ds402 = boost::dynamic_pointer_cast<DS402Group>(it->second);
    if (group_ds402)
    {
      group_ds402->acceptPPTargets(node_id);
    }
  }
  syncAll();
  usleep(5000); // sleep 5 ms

}

}}//end of NS

max_stars_repo_name: khairulislam/phys

max_issues_repo_name: khairulislam/phys

max_forks_repo_name: khairulislam/phys


text:
/*!
 * @file
 * This file defines `boost::mpl::is_eplaceholder`.
 */

#ifndef BOOST_MPL_IS_EPLACEHOLDER_HPP
#define BOOST_MPL_IS_EPLACEHOLDER_HPP

#include <boost/mpl/any_of.hpp>
#include <boost/mpl/equote.hpp>
#include <boost/mpl/is_placeholder.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/vector.hpp>

namespace boost { namespace mpl {
    template <typename T>
    struct is_eplaceholder
        : is_placeholder<T>
    { };

    template <typename F>
    struct is_eplaceholder_expression
        : is_eplaceholder<F>
    { };

    template <template <typename ...> class F, typename ...T>
    struct is_eplaceholder_expression<F<T...>>
        : or_<
            is_eplaceholder<F<T...>>,
            any_of<
                typename vector<T...>::type,
                equote<is_eplaceholder_expression>
            >
        >
    { };
}} // end namespace boost::mpl

#endif // !BOOST_MPL_IS_EPLACEHOLDER_HPP