<commit_before>#include <process.hpp>

#include <vector>

#include <glog/logging.h>

#include <boost/lexical_cast.hpp>

#include "config/config.hpp"

#include "common/fatal.hpp"
#include "common/foreach.hpp"
#ifdef WITH_ZOOKEEPER
#include "common/zookeeper.hpp"
#endif

#include "messaging/messages.hpp"

#include "detector.hpp"
#include "url_processor.hpp"

using namespace mesos;
using namespace mesos::internal;

using boost::lexical_cast;

using process::Process;
using process::UPID;

using std::pair;
using std::string;
using std::vector;

#ifdef WITH_ZOOKEEPER
class ZooKeeperMasterDetector : public MasterDetector, public Watcher
{
public:
  /**
   * Uses ZooKeeper for both detecting masters and contending to be a
   * master.
   *
   * @param server comma separated list of server host:port pairs
   *
   * @param znode top-level "ZooKeeper node" (directory) to use
   * @param pid libprocess pid to send messages/updates to (and to
   * use for contending to be a master)
   * @param contend true if should contend to be master (not needed
   * for slaves and frameworks)
   * @param quiet verbosity logging level for undelying ZooKeeper library
   */
  ZooKeeperMasterDetector(const string& servers,
			  const string& znode,
			  const UPID& pid,
			  bool contend = false,
			  bool quiet = false);

  virtual ~ZooKeeperMasterDetector();

  /**
   * ZooKeeper watcher callback.
   */
  virtual void process(ZooKeeper *zk, int type, int state, const string &path);

private:
  void connected();
  void reconnecting();
  void reconnected();
  void expired();
  void updated(const string& path);

  /**
   * @param s sequence id
   */
  void setId(const string &s);

  /**
   * @return current sequence id if contending to be a master
   */
  string getId();

  /**
   * Attempts to detect a master.
   */
  void detectMaster();

  /**
   * @param seq sequence id of a master
   * @return PID corresponding to a master
   */
  UPID lookupMasterPID(const string &seq) const;

  const string servers;
  const string znode;
  const UPID pid;
  bool contend;
  bool reconnect;

  ZooKeeper *zk;

  // Our sequence string if contending to be a master.
  string mySeq;

  string currentMasterSeq;
  UPID currentMasterPID;
};
#endif // WITH_ZOOKEEPER

MasterDetector::~MasterDetector() {}

MasterDetector* MasterDetector::create(const string &url,
                                       const UPID &pid,
                                       bool contend,
                                       bool quiet)
{
  if (url == "")
    if (contend) {
      return new BasicMasterDetector(pid);
    } else {
      fatal("cannot use specified url to detect master");
    }

  MasterDetector *detector = NULL;

  // Parse the url.
  pair<UrlProcessor::URLType, string> urlPair = UrlProcessor::process(url);

  switch (urlPair.first) {
    // ZooKeeper URL.
    case UrlProcessor::ZOO: {
#ifdef WITH_ZOOKEEPER
      // TODO(benh): Consider actually using the chroot feature of
      // ZooKeeper, rather than just using it's syntax.
      size_t index = urlPair.second.find("/");
      if (index == string::npos) {
	fatal("expecting chroot path for ZooKeeper");
      }

      const string &servers = urlPair.second.substr(0, index);

      const string &znode = urlPair.second.substr(index);
      if (znode == "/") {
	fatal("expecting chroot path for ZooKeeper ('/' is not supported)");
      }

      detector = new ZooKeeperMasterDetector(servers, znode, pid, contend, quiet);
#else
      fatal("Cannot detect masters with 'zoo://', "
            "ZooKeeper is not supported in this build");
#endif // WITH_ZOOKEEPER
      break;
    }

    // Mesos URL or libprocess pid.
    case UrlProcessor::MESOS:
    case UrlProcessor::UNKNOWN: {
      if (contend) {
	// TODO(benh): Wierdnesses like this makes it seem like there
	// should be a separate elector and detector. In particular,
	// it doesn't make sense to pass a libprocess pid and attempt
	// to contend (at least not right now).
	fatal("cannot contend to be a master with specified url");
      } else {
	UPID master(urlPair.second);
	if (!master)
	  fatal("cannot use specified url to detect master");
	detector = new BasicMasterDetector(master, pid);
      }
      break;
    }
  }

  return detector;
}

void MasterDetector::destroy(MasterDetector *detector)
{
  if (detector != NULL)
    delete detector;
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master)
  : master(_master)
{
  // Send a master token.
  {
    MSG<GOT_MASTER_TOKEN> msg;
    msg.set_token("0");
    MesosProcess<class T>::post(master, msg);
  }

  // Elect the master.
  {
    MSG<NEW_MASTER_DETECTED> msg;
    msg.set_pid(master);
    MesosProcess<class T>::post(master, msg);
  }
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master,
					 const UPID& pid,
					 bool elect)
  : master(_master)
{
  if (elect) {
    // Send a master token.
    {
      MSG<GOT_MASTER_TOKEN> msg;
      msg.set_token("0");
      MesosProcess<class T>::post(master, msg);
    }

    // Elect the master.
    {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(master);
      MesosProcess<class T>::post(master, msg);
    }
  }

  // Tell the pid about the master.
  MSG<NEW_MASTER_DETECTED> msg;
  msg.set_pid(master);
  MesosProcess<class T>::post(pid, msg);
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master,
					 const vector<UPID>& pids,
					 bool elect)
  : master(_master)
{
  if (elect) {
    // Send a master token.
    {
      MSG<GOT_MASTER_TOKEN> msg;
      msg.set_token("0");
      MesosProcess<class T>::post(master, msg);
    }

    // Elect the master.
    {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(master);
      MesosProcess<class T>::post(master, msg);
    }
  }

  // Tell each pid about the master.
  foreach (const UPID& pid, pids) {
    MSG<NEW_MASTER_DETECTED> msg;
    msg.set_pid(master);
    MesosProcess<class T>::post(pid, msg);
  }
}

BasicMasterDetector::~BasicMasterDetector() {}

#ifdef WITH_ZOOKEEPER
ZooKeeperMasterDetector::ZooKeeperMasterDetector(const string& servers,
						 const string& znode,
						 const UPID& pid,
						 bool contend,
						 bool quiet)
  : servers(servers), znode(znode), pid(pid),
    contend(contend), reconnect(false)
{
  // Set verbosity level for underlying ZooKeeper library logging.
  // TODO(benh): Put this in the C++ API.
  zoo_set_debug_level(quiet ? ZOO_LOG_LEVEL_ERROR : ZOO_LOG_LEVEL_DEBUG);

  // Start up the ZooKeeper connection!
  zk = new ZooKeeper(servers, 10000, this);
}

ZooKeeperMasterDetector::~ZooKeeperMasterDetector()
{
  if (zk != NULL) {
    delete zk;
  }
}

void ZooKeeperMasterDetector::connected()
{
  LOG(INFO) << "Master detector connected to ZooKeeper ...";

  int ret;
  string result;

  static const string delimiter = "/";

  // Assume the znode that was created does not end with a "/".
  CHECK(znode.at(znode.length() - 1) != '/');

  // Create directory path znodes as necessary.
  size_t index = znode.find(delimiter, 0);

  while (index < string::npos) {
    // Get out the prefix to create.
    index = znode.find(delimiter, index + 1);
    string prefix = znode.substr(0, index);

    LOG(INFO) << "Trying to create znode '" << prefix << "' in ZooKeeper";

    // Create the node (even if it already exists).
    ret = zk->create(prefix, "", ZOO_OPEN_ACL_UNSAFE,
		     // ZOO_CREATOR_ALL_ACL, // needs authentication
		     0, &result);

    if (ret != ZOK && ret != ZNODEEXISTS) {
      fatal("failed to create ZooKeeper znode! (%s)", zk->error(ret));
    }
  }

  // Wierdness in ZooKeeper timing, let's check that everything is created.
  ret = zk->get(znode, false, &result, NULL);

  if (ret != ZOK) {
    fatal("ZooKeeper not responding correctly (%s). "
	  "Make sure ZooKeeper is running on: %s",
	  zk->error(ret), servers.c_str());
  }

  if (contend) {
    // We contend with the pid given in constructor.
    ret = zk->create(znode + "/", pid, ZOO_OPEN_ACL_UNSAFE,
		     // ZOO_CREATOR_ALL_ACL, // needs authentication
		     ZOO_SEQUENCE | ZOO_EPHEMERAL, &result);

    if (ret != ZOK) {
      fatal("ZooKeeper not responding correctly (%s). "
	    "Make sure ZooKeeper is running on: %s",
	    zk->error(ret), servers.c_str());
    }

    setId(result);
    LOG(INFO) << "Created ephemeral/sequence:" << getId();

    MSG<GOT_MASTER_TOKEN> msg;
    msg.set_token(getId());
    MesosProcess<class T>::post(pid, msg);
  }

  // Now determine who the master is (it may be us).
  detectMaster();
}

void ZooKeeperMasterDetector::reconnecting()
{
  LOG(INFO) << "Master detector lost connection to ZooKeeper, "
	    << "attempting to reconnect ...";
}

void ZooKeeperMasterDetector::reconnected()
{
  LOG(INFO) << "Master detector reconnected ...";

  int ret;
  string result;

  static const string delimiter = "/";

  if (contend) {
    // Contending for master, confirm our ephemeral sequence znode exists.
    ret = zk->get(znode + "/" + mySeq, false, &result, NULL);

    // We might no longer be the master! Commit suicide for now
    // (hoping another master is on standbye), but in the future
    // it would be nice if we could go back on standbye.
    if (ret == ZNONODE) {
      fatal("failed to reconnect to ZooKeeper quickly enough "
	    "(our ephemeral sequence znode is gone), commiting suicide!");
    }

    if (ret != ZOK) {
      fatal("ZooKeeper not responding correctly (%s). "
	    "Make sure ZooKeeper is running on: %s",
	    zk->error(ret), servers.c_str());
    }

    // We are still the master!
    LOG(INFO) << "Still acting as master";
  } else {
    // Reconnected, but maybe the master changed?
    detectMaster();
  }
}

void ZooKeeperMasterDetector::expired()
{
  LOG(WARNING) << "Master detector ZooKeeper session expired!";

  CHECK(zk != NULL);
  delete zk;

  zk = new ZooKeeper(servers, 10000, this);
}

void ZooKeeperMasterDetector::updated(const string& path)
{
  // A new master might have showed up and created a sequence
  // identifier or a master may have died, determine who the master is now!
  detectMaster();
}

void ZooKeeperMasterDetector::process(ZooKeeper* zk, int type, int state,
				      const string &path)
{
  if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_SESSION_EVENT)) {
    // Check if this is a reconnect.
    if (!reconnect) {
      // Initial connect.
      connected();
    } else {
      // Reconnected.
      reconnected();
    }
  } else if ((state == ZOO_CONNECTING_STATE) && (type == ZOO_SESSION_EVENT)) {
    // The client library automatically reconnects, taking into
    // account failed servers in the connection string,
    // appropriately handling the "herd effect", etc.
    reconnect = true;
    reconnecting();
  } else if ((state == ZOO_EXPIRED_SESSION_STATE) && (type == ZOO_SESSION_EVENT)) {
    // Session expiration. Let the manager take care of it.
    expired();

    // If this watcher is reused, the next connect won't be a reconnect.
    reconnect = false;
  } else if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_CHILD_EVENT)) {
    updated(path);
  } else if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_CHANGED_EVENT)) {
    updated(path);
  } else {
    LOG(WARNING) << "Unimplemented watch event: (state is "
		 << state << " and type is " << type << ")";
  }
}

void ZooKeeperMasterDetector::setId(const string& s)
{
  string seq = s;
  // Converts "/path/to/znode/000000131" to "000000131".
  int pos;
  if ((pos = seq.find_last_of('/')) != string::npos) {
    mySeq = seq.erase(0, pos + 1);
  } else
    mySeq = "";
}

string ZooKeeperMasterDetector::getId()
{
  return mySeq;
}

void ZooKeeperMasterDetector::detectMaster()
{
  vector<string> results;

  int ret = zk->getChildren(znode, true, &results);

  if (ret != ZOK) {
    LOG(ERROR) << "Master detector failed to get masters: "
	       << zk->error(ret);
  } else {
    LOG(INFO) << "Master detector found " << results.size()
	      << " registered masters";
  }

  string masterSeq;
  long min = LONG_MAX;
  foreach (const string& result, results) {
    int i = lexical_cast<int>(result);
    if (i < min) {
      min = i;
      masterSeq = result;
    }
  }

  // No master present (lost or possibly hasn't come up yet).
  if (masterSeq.empty()) {
    process::post(pid, NO_MASTER_DETECTED);
  } else if (masterSeq != currentMasterSeq) {
    currentMasterSeq = masterSeq;
    currentMasterPID = lookupMasterPID(masterSeq);

    // While trying to get the master PID, master might have crashed,
    // so PID might be empty.
    if (currentMasterPID == UPID()) {
      process::post(pid, NO_MASTER_DETECTED);
    } else {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(currentMasterPID);
      MesosProcess<class T>::post(pid, msg);
    }
  }
}

UPID ZooKeeperMasterDetector::lookupMasterPID(const string& seq) const
{
  CHECK(!seq.empty());

  int ret;
  string result;

  ret = zk->get(znode + "/" + seq, false, &result, NULL);

  if (ret != ZOK) {
    LOG(ERROR) << "Master detector failed to fetch new master pid: "
	       << zk->error(ret);
  } else {
    LOG(INFO) << "Master detector got new master pid: " << result;
  }

  return result;
}

#endif // WITH_ZOOKEEPER
<commit_msg>Minor formating tweak.<commit_after>#include <process.hpp>

#include <vector>

#include <glog/logging.h>

#include <boost/lexical_cast.hpp>

#include "config/config.hpp"

#include "common/fatal.hpp"
#include "common/foreach.hpp"
#ifdef WITH_ZOOKEEPER
#include "common/zookeeper.hpp"
#endif

#include "messaging/messages.hpp"

#include "detector.hpp"
#include "url_processor.hpp"

using namespace mesos;
using namespace mesos::internal;

using boost::lexical_cast;

using process::Process;
using process::UPID;

using std::pair;
using std::string;
using std::vector;

#ifdef WITH_ZOOKEEPER
class ZooKeeperMasterDetector : public MasterDetector, public Watcher
{
public:
  /**
   * Uses ZooKeeper for both detecting masters and contending to be a
   * master.
   *
   * @param server comma separated list of server host:port pairs
   *
   * @param znode top-level "ZooKeeper node" (directory) to use
   * @param pid libprocess pid to send messages/updates to (and to
   * use for contending to be a master)
   * @param contend true if should contend to be master (not needed
   * for slaves and frameworks)
   * @param quiet verbosity logging level for undelying ZooKeeper library
   */
  ZooKeeperMasterDetector(const string& servers,
			  const string& znode,
			  const UPID& pid,
			  bool contend = false,
			  bool quiet = false);

  virtual ~ZooKeeperMasterDetector();

  /**
   * ZooKeeper watcher callback.
   */
  virtual void process(ZooKeeper *zk, int type, int state, const string &path);

private:
  void connected();
  void reconnecting();
  void reconnected();
  void expired();
  void updated(const string& path);

  /**
   * @param s sequence id
   */
  void setId(const string &s);

  /**
   * @return current sequence id if contending to be a master
   */
  string getId();

  /**
   * Attempts to detect a master.
   */
  void detectMaster();

  /**
   * @param seq sequence id of a master
   * @return PID corresponding to a master
   */
  UPID lookupMasterPID(const string &seq) const;

  const string servers;
  const string znode;
  const UPID pid;
  bool contend;
  bool reconnect;

  ZooKeeper *zk;

  // Our sequence string if contending to be a master.
  string mySeq;

  string currentMasterSeq;
  UPID currentMasterPID;
};
#endif // WITH_ZOOKEEPER

MasterDetector::~MasterDetector() {}

MasterDetector* MasterDetector::create(const string &url,
                                       const UPID &pid,
                                       bool contend,
                                       bool quiet)
{
  if (url == "")
    if (contend) {
      return new BasicMasterDetector(pid);
    } else {
      fatal("cannot use specified url to detect master");
    }

  MasterDetector *detector = NULL;

  // Parse the url.
  pair<UrlProcessor::URLType, string> urlPair = UrlProcessor::process(url);

  switch (urlPair.first) {
    // ZooKeeper URL.
    case UrlProcessor::ZOO: {
#ifdef WITH_ZOOKEEPER
      // TODO(benh): Consider actually using the chroot feature of
      // ZooKeeper, rather than just using it's syntax.
      size_t index = urlPair.second.find("/");
      if (index == string::npos) {
	fatal("expecting chroot path for ZooKeeper");
      }

      const string &servers = urlPair.second.substr(0, index);

      const string &znode = urlPair.second.substr(index);
      if (znode == "/") {
	fatal("expecting chroot path for ZooKeeper ('/' is not supported)");
      }

      detector = new ZooKeeperMasterDetector(servers, znode, pid, contend, quiet);
#else
      fatal("Cannot detect masters with 'zoo://', "
            "ZooKeeper is not supported in this build");
#endif // WITH_ZOOKEEPER
      break;
    }

    // Mesos URL or libprocess pid.
    case UrlProcessor::MESOS:
    case UrlProcessor::UNKNOWN: {
      if (contend) {
	// TODO(benh): Wierdnesses like this makes it seem like there
	// should be a separate elector and detector. In particular,
	// it doesn't make sense to pass a libprocess pid and attempt
	// to contend (at least not right now).
	fatal("cannot contend to be a master with specified url");
      } else {
	UPID master(urlPair.second);
	if (!master)
	  fatal("cannot use specified url to detect master");
	detector = new BasicMasterDetector(master, pid);
      }
      break;
    }
  }

  return detector;
}

void MasterDetector::destroy(MasterDetector *detector)
{
  if (detector != NULL)
    delete detector;
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master)
  : master(_master)
{
  // Send a master token.
  {
    MSG<GOT_MASTER_TOKEN> msg;
    msg.set_token("0");
    MesosProcess<class T>::post(master, msg);
  }

  // Elect the master.
  {
    MSG<NEW_MASTER_DETECTED> msg;
    msg.set_pid(master);
    MesosProcess<class T>::post(master, msg);
  }
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master,
					 const UPID& pid,
					 bool elect)
  : master(_master)
{
  if (elect) {
    // Send a master token.
    {
      MSG<GOT_MASTER_TOKEN> msg;
      msg.set_token("0");
      MesosProcess<class T>::post(master, msg);
    }

    // Elect the master.
    {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(master);
      MesosProcess<class T>::post(master, msg);
    }
  }

  // Tell the pid about the master.
  MSG<NEW_MASTER_DETECTED> msg;
  msg.set_pid(master);
  MesosProcess<class T>::post(pid, msg);
}

BasicMasterDetector::BasicMasterDetector(const UPID& _master,
					 const vector<UPID>& pids,
					 bool elect)
  : master(_master)
{
  if (elect) {
    // Send a master token.
    {
      MSG<GOT_MASTER_TOKEN> msg;
      msg.set_token("0");
      MesosProcess<class T>::post(master, msg);
    }

    // Elect the master.
    {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(master);
      MesosProcess<class T>::post(master, msg);
    }
  }

  // Tell each pid about the master.
  foreach (const UPID& pid, pids) {
    MSG<NEW_MASTER_DETECTED> msg;
    msg.set_pid(master);
    MesosProcess<class T>::post(pid, msg);
  }
}

BasicMasterDetector::~BasicMasterDetector() {}

#ifdef WITH_ZOOKEEPER
ZooKeeperMasterDetector::ZooKeeperMasterDetector(const string& servers,
						 const string& znode,
						 const UPID& pid,
						 bool contend,
						 bool quiet)
  : servers(servers), znode(znode), pid(pid),
    contend(contend), reconnect(false)
{
  // Set verbosity level for underlying ZooKeeper library logging.
  // TODO(benh): Put this in the C++ API.
  zoo_set_debug_level(quiet ? ZOO_LOG_LEVEL_ERROR : ZOO_LOG_LEVEL_DEBUG);

  // Start up the ZooKeeper connection!
  zk = new ZooKeeper(servers, 10000, this);
}

ZooKeeperMasterDetector::~ZooKeeperMasterDetector()
{
  if (zk != NULL) {
    delete zk;
  }
}

void ZooKeeperMasterDetector::connected()
{
  LOG(INFO) << "Master detector connected to ZooKeeper ...";

  int ret;
  string result;

  static const string delimiter = "/";

  // Assume the znode that was created does not end with a "/".
  CHECK(znode.at(znode.length() - 1) != '/');

  // Create directory path znodes as necessary.
  size_t index = znode.find(delimiter, 0);

  while (index < string::npos) {
    // Get out the prefix to create.
    index = znode.find(delimiter, index + 1);
    string prefix = znode.substr(0, index);

    LOG(INFO) << "Trying to create znode '" << prefix << "' in ZooKeeper";

    // Create the node (even if it already exists).
    ret = zk->create(prefix, "", ZOO_OPEN_ACL_UNSAFE,
		     // ZOO_CREATOR_ALL_ACL, // needs authentication
		     0, &result);

    if (ret != ZOK && ret != ZNODEEXISTS) {
      fatal("failed to create ZooKeeper znode! (%s)", zk->error(ret));
    }
  }

  // Wierdness in ZooKeeper timing, let's check that everything is created.
  ret = zk->get(znode, false, &result, NULL);

  if (ret != ZOK) {
    fatal("ZooKeeper not responding correctly (%s). "
	  "Make sure ZooKeeper is running on: %s",
	  zk->error(ret), servers.c_str());
  }

  if (contend) {
    // We contend with the pid given in constructor.
    ret = zk->create(znode + "/", pid, ZOO_OPEN_ACL_UNSAFE,
		     // ZOO_CREATOR_ALL_ACL, // needs authentication
		     ZOO_SEQUENCE | ZOO_EPHEMERAL, &result);

    if (ret != ZOK) {
      fatal("ZooKeeper not responding correctly (%s). "
	    "Make sure ZooKeeper is running on: %s",
	    zk->error(ret), servers.c_str());
    }

    setId(result);
    LOG(INFO) << "Created ephemeral/sequence:" << getId();

    MSG<GOT_MASTER_TOKEN> msg;
    msg.set_token(getId());
    MesosProcess<class T>::post(pid, msg);
  }

  // Now determine who the master is (it may be us).
  detectMaster();
}

void ZooKeeperMasterDetector::reconnecting()
{
  LOG(INFO) << "Master detector lost connection to ZooKeeper, "
	    << "attempting to reconnect ...";
}

void ZooKeeperMasterDetector::reconnected()
{
  LOG(INFO) << "Master detector reconnected ...";

  int ret;
  string result;

  static const string delimiter = "/";

  if (contend) {
    // Contending for master, confirm our ephemeral sequence znode exists.
    ret = zk->get(znode + "/" + mySeq, false, &result, NULL);

    // We might no longer be the master! Commit suicide for now
    // (hoping another master is on standbye), but in the future
    // it would be nice if we could go back on standbye.
    if (ret == ZNONODE) {
      fatal("failed to reconnect to ZooKeeper quickly enough "
	    "(our ephemeral sequence znode is gone), commiting suicide!");
    }

    if (ret != ZOK) {
      fatal("ZooKeeper not responding correctly (%s). "
	    "Make sure ZooKeeper is running on: %s",
	    zk->error(ret), servers.c_str());
    }

    // We are still the master!
    LOG(INFO) << "Still acting as master";
  } else {
    // Reconnected, but maybe the master changed?
    detectMaster();
  }
}

void ZooKeeperMasterDetector::expired()
{
  LOG(WARNING) << "Master detector ZooKeeper session expired!";

  CHECK(zk != NULL);
  delete zk;

  zk = new ZooKeeper(servers, 10000, this);
}

void ZooKeeperMasterDetector::updated(const string& path)
{
  // A new master might have showed up and created a sequence
  // identifier or a master may have died, determine who the master is now!
  detectMaster();
}

void ZooKeeperMasterDetector::process(ZooKeeper* zk, int type, int state,
				      const string& path)
{
  if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_SESSION_EVENT)) {
    // Check if this is a reconnect.
    if (!reconnect) {
      // Initial connect.
      connected();
    } else {
      // Reconnected.
      reconnected();
    }
  } else if ((state == ZOO_CONNECTING_STATE) && (type == ZOO_SESSION_EVENT)) {
    // The client library automatically reconnects, taking into
    // account failed servers in the connection string,
    // appropriately handling the "herd effect", etc.
    reconnect = true;
    reconnecting();
  } else if ((state == ZOO_EXPIRED_SESSION_STATE) && (type == ZOO_SESSION_EVENT)) {
    // Session expiration. Let the manager take care of it.
    expired();

    // If this watcher is reused, the next connect won't be a reconnect.
    reconnect = false;
  } else if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_CHILD_EVENT)) {
    updated(path);
  } else if ((state == ZOO_CONNECTED_STATE) && (type == ZOO_CHANGED_EVENT)) {
    updated(path);
  } else {
    LOG(WARNING) << "Unimplemented watch event: (state is "
		 << state << " and type is " << type << ")";
  }
}

void ZooKeeperMasterDetector::setId(const string& s)
{
  string seq = s;
  // Converts "/path/to/znode/000000131" to "000000131".
  int pos;
  if ((pos = seq.find_last_of('/')) != string::npos) {
    mySeq = seq.erase(0, pos + 1);
  } else
    mySeq = "";
}

string ZooKeeperMasterDetector::getId()
{
  return mySeq;
}

void ZooKeeperMasterDetector::detectMaster()
{
  vector<string> results;

  int ret = zk->getChildren(znode, true, &results);

  if (ret != ZOK) {
    LOG(ERROR) << "Master detector failed to get masters: "
	       << zk->error(ret);
  } else {
    LOG(INFO) << "Master detector found " << results.size()
	      << " registered masters";
  }

  string masterSeq;
  long min = LONG_MAX;
  foreach (const string& result, results) {
    int i = lexical_cast<int>(result);
    if (i < min) {
      min = i;
      masterSeq = result;
    }
  }

  // No master present (lost or possibly hasn't come up yet).
  if (masterSeq.empty()) {
    process::post(pid, NO_MASTER_DETECTED);
  } else if (masterSeq != currentMasterSeq) {
    currentMasterSeq = masterSeq;
    currentMasterPID = lookupMasterPID(masterSeq);

    // While trying to get the master PID, master might have crashed,
    // so PID might be empty.
    if (currentMasterPID == UPID()) {
      process::post(pid, NO_MASTER_DETECTED);
    } else {
      MSG<NEW_MASTER_DETECTED> msg;
      msg.set_pid(currentMasterPID);
      MesosProcess<class T>::post(pid, msg);
    }
  }
}

UPID ZooKeeperMasterDetector::lookupMasterPID(const string& seq) const
{
  CHECK(!seq.empty());

  int ret;
  string result;

  ret = zk->get(znode + "/" + seq, false, &result, NULL);

  if (ret != ZOK) {
    LOG(ERROR) << "Master detector failed to fetch new master pid: "
	       << zk->error(ret);
  } else {
    LOG(INFO) << "Master detector got new master pid: " << result;
  }

  return result;
}

#endif // WITH_ZOOKEEPER
<|endoftext|>


<commit_before>#include <cstring>
#include <string>
#include "halley/bytes/byte_serializer.h"
#include "halley/text/halleystring.h"

using namespace Halley;

Serializer::Serializer(SerializerOptions options)
	: options(std::move(options))
	, dryRun(true)
{}

Serializer::Serializer(gsl::span<gsl::byte> dst, SerializerOptions options)
	: options(std::move(options))
	, dst(dst)
	, dryRun(false)
{}

Serializer& Serializer::operator<<(const std::string& str)
{
	return *this << String(str);
}

Serializer& Serializer::operator<<(const String& str)
{
	if (options.version == 0) {
		const uint32_t sz = static_cast<uint32_t>(str.size());
		*this << sz;
		*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
	} else {
		if (options.stringToIndex) {
			auto idx = options.stringToIndex(str);
			if (idx) {
				// Found, store index with bit 0 set to 1
				const uint64_t value = uint64_t(options.exhaustiveDictionary ? idx.value() : (size_t(1) | (idx.value() << 1)));
				*this << value;
			} else {
				if (options.exhaustiveDictionary) {
					throw Exception("String \"" + str + "\" not found in serialization dictionary, but it's marked as exhaustive.", HalleyExceptions::Utils);
				}

				// Not found, store it with bit 0 set to 0
				const auto sz = str.size();
				*this << (sz << 1);
				*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
			}
		} else {
			// No dictionary, just store it old style
			const auto sz = str.size();
			*this << sz;
			*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
		}
	}
	return *this;
}

Serializer& Serializer::operator<<(const Path& path)
{
	return (*this << path.string());
}

Serializer& Serializer::operator<<(gsl::span<const gsl::byte> span)
{
	if (!dryRun) {
		memcpy(dst.data() + size, span.data(), span.size_bytes());
	}
	size += span.size_bytes();
	return *this;
}

Serializer& Serializer::operator<<(const Bytes& bytes)
{
	const uint32_t byteSize = static_cast<uint32_t>(bytes.size());
	*this << byteSize;

	if (!dryRun) {
		memcpy(dst.data() + size, bytes.data(), bytes.size());
	}
	size += bytes.size();
	return *this;
}

void Serializer::serializeVariableInteger(uint64_t val, OptionalLite<bool> sign)
{
	// 7  0sxxxxxx
	// 14 10sxxxxx xxxxxxxx
	// 21 110sxxxx xxxxxxxx xxxxxxxx
	// 28 1110sxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 35 11110sxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 42 111110sx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 49 1111110s xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 56 11111110 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 64 11111111 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

	const size_t nBits = size_t(fastLog2Ceil(val)) + (sign ? 1 : 0);
	const size_t nBytes = std::min((nBits - 1) / 7, size_t(8)) + 1; // Total length of this sequence
	std::array<uint8_t, 9> buffer;
	buffer.fill(0);

	// Combine sign into value
	uint64_t toWrite = val;
	if (sign) {
		const size_t signPos = nBytes * 7 + (nBytes == 9 ? 0 : -1); // 9-byte version places it on pos 63, not 62
		toWrite |= uint64_t(sign.value() ? 1 : 0) << signPos;
	}

	// Write header
	// To generate the mask, we get 9 - nBytes to see how many zeroes we need (8 at 1 byte, 7 at 2 bytes, etc), generate that many "1"s, then xor that with 255 (0b11111111) to flip those bits
	const size_t headerBits = std::min(nBytes, size_t(7));
	buffer[0] = uint8_t(255) ^ (uint8_t((1 << (9 - headerBits)) - 1));

	// Write bits
	size_t bitsAvailableOnByte = 8 - headerBits;
	size_t bitsToWrite = nBits;
	size_t curPos = 0;

	while (bitsToWrite > 0) {
		const size_t nBits = std::min(bitsToWrite, bitsAvailableOnByte);
		const uint64_t mask = (uint64_t(1) << bitsAvailableOnByte) - 1;

		buffer[curPos] |= toWrite & mask;

		toWrite >>= nBits;
		bitsAvailableOnByte = 8;
		curPos++;
		bitsToWrite -= nBits;
	}

	*this << gsl::as_bytes(gsl::span<const uint8_t>(buffer.data(), curPos));
}

Deserializer::Deserializer(gsl::span<const gsl::byte> src, SerializerOptions options)
	: options(std::move(options))
	, src(src)
{
}

Deserializer::Deserializer(const Bytes& src, SerializerOptions options)
	: options(std::move(options))
	, src(gsl::as_bytes(gsl::span<const Halley::Byte>(src)))
{
}

Deserializer& Deserializer::operator>>(std::string& str)
{
	String s;
	*this >> s;
	str = s.cppStr();
	return *this;
}

Deserializer& Deserializer::operator>>(String& str)
{
	auto readRawString = [&] (size_t size)
	{
		ensureSufficientBytesRemaining(size);
		str = String(reinterpret_cast<const char*>(src.data() + pos), size);
		pos += size;
	};

	if (options.version == 0) {
		uint32_t size;
		*this >> size;
		readRawString(size);
	} else {
		uint64_t value;
		*this >> value;

		if (options.indexToString) {
			if (options.exhaustiveDictionary || (value & 0x1) != 0) {
				// Indexed string
				int shift = options.exhaustiveDictionary ? 0 : 1;
				str = options.indexToString(value >> shift);
			} else {
				// Not indexed
				readRawString(value >> 1);
			}
		} else {
			// No dictionary
			readRawString(value);
		}
	}

	return *this;
}

Deserializer& Deserializer::operator>>(Path& p)
{
	std::string s;
	*this >> s;
	p = s;
	return *this;
}

Deserializer& Deserializer::operator>>(gsl::span<gsl::byte> span)
{
	if (span.empty()) {
		return *this;
	}
	Expects(span.size_bytes() > 0);

	ensureSufficientBytesRemaining(size_t(span.size_bytes()));

	memcpy(span.data(), src.data() + pos, span.size_bytes());
	pos += span.size_bytes();
	return *this;
}

Deserializer& Deserializer::operator>>(Bytes& bytes)
{
	uint32_t sz;
	*this >> sz;
	ensureSufficientBytesRemaining(sz);
	bytes.resize(sz);

	auto dst = gsl::as_writable_bytes(gsl::span<Byte>(bytes));
	*this >> dst;
	return *this;
}

void Deserializer::setVersion(int v)
{
	version = v;
}

int Deserializer::getVersion() const
{
	return version;
}

void Deserializer::deserializeVariableInteger(uint64_t& val, bool& sign, bool isSigned)
{
	// 7  0sxxxxxx
	// 14 10sxxxxx xxxxxxxx
	// 21 110sxxxx xxxxxxxx xxxxxxxx
	// 28 1110sxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 35 11110sxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 42 111110sx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 49 1111110s xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 56 11111110 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 64 11111111 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

	// Read header
	uint8_t header;
	*this >> header;

	// Figure out which pattern we're dealing with
	size_t nBytes = 0;
	if ((header & 0x80) != 0x80) {
		nBytes = 1;
	} else if ((header & 0xC0) != 0xC0) {
		nBytes = 2;
	} else if ((header & 0xE0) != 0xE0) {
		nBytes = 3;
	} else if ((header & 0xF0) != 0xF0) {
		nBytes = 4;
	} else if ((header & 0xF8) != 0xF8) {
		nBytes = 5;
	} else if ((header & 0xFC) != 0xFC) {
		nBytes = 6;
	} else if ((header & 0xFE) != 0xFE) {
		nBytes = 7;
	} else if ((header & 0xFF) != 0xFF) {
		nBytes = 8;
	} else {
		nBytes = 9;
	}
	const size_t headerBits = std::min(nBytes, size_t(7));

	// Read rest of the data
	std::array<uint8_t, 9> buffer;
	buffer[0] = header;
	if (nBytes > 1) {
		*this >> gsl::as_writable_bytes(gsl::span<uint8_t>(buffer.data(), nBytes - 1));
	}

	// Convert to uint64_t
	size_t bitsAvailableOnByte = 8 - headerBits;
	size_t bitsRead = 0;
	uint64_t value = 0;
	for (size_t i = 0; i < nBytes; ++i) {
		const uint64_t byteMask = (uint64_t(1) << bitsAvailableOnByte) - 1;
		value |= (uint64_t(buffer[i]) & byteMask) << bitsRead;
		bitsRead += bitsAvailableOnByte;
		bitsAvailableOnByte = 8;
	}

	// Restore sign
	if (isSigned) {
		const size_t signPos = nBytes * 7 + (nBytes == 9 ? 0 : -1); // 9-byte version places it on pos 63, not 62
		const uint64_t signMask = uint64_t(1) << signPos;
		sign = (value & signMask) != 0;
		value &= ~signMask;
	} else {
		sign = false;
	}

	// Output value
	val = value;
}

void Deserializer::ensureSufficientBytesRemaining(size_t bytes)
{
	if (bytes > getBytesRemaining()) {
		throw Exception("Attempt to deserialize out of bounds", HalleyExceptions::File);
	}
}

size_t Deserializer::getBytesRemaining() const
{
	if (pos > size_t(src.size_bytes())) {
		return 0;
	} else {
		return size_t(src.size_bytes()) - pos;
	}
}
<commit_msg>Remove more ambiguity.<commit_after>#include <cstring>
#include <string>
#include "halley/bytes/byte_serializer.h"
#include "halley/text/halleystring.h"

using namespace Halley;

Serializer::Serializer(SerializerOptions options)
	: options(std::move(options))
	, dryRun(true)
{}

Serializer::Serializer(gsl::span<gsl::byte> dst, SerializerOptions options)
	: options(std::move(options))
	, dst(dst)
	, dryRun(false)
{}

Serializer& Serializer::operator<<(const std::string& str)
{
	return *this << String(str);
}

Serializer& Serializer::operator<<(const String& str)
{
	if (options.version == 0) {
		const uint32_t sz = static_cast<uint32_t>(str.size());
		*this << sz;
		*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
	} else {
		if (options.stringToIndex) {
			auto idx = options.stringToIndex(str);
			if (idx) {
				// Found, store index with bit 0 set to 1
				const uint64_t value = uint64_t(options.exhaustiveDictionary ? idx.value() : (size_t(1) | (idx.value() << 1)));
				*this << value;
			} else {
				if (options.exhaustiveDictionary) {
					throw Exception("String \"" + str + "\" not found in serialization dictionary, but it's marked as exhaustive.", HalleyExceptions::Utils);
				}

				// Not found, store it with bit 0 set to 0
				const uint64_t sz = uint64_t(str.size());
				*this << (sz << 1);
				*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
			}
		} else {
			// No dictionary, just store it old style
			const auto sz = str.size();
			*this << sz;
			*this << gsl::as_bytes(gsl::span<const char>(str.c_str(), sz));
		}
	}
	return *this;
}

Serializer& Serializer::operator<<(const Path& path)
{
	return (*this << path.string());
}

Serializer& Serializer::operator<<(gsl::span<const gsl::byte> span)
{
	if (!dryRun) {
		memcpy(dst.data() + size, span.data(), span.size_bytes());
	}
	size += span.size_bytes();
	return *this;
}

Serializer& Serializer::operator<<(const Bytes& bytes)
{
	const uint32_t byteSize = static_cast<uint32_t>(bytes.size());
	*this << byteSize;

	if (!dryRun) {
		memcpy(dst.data() + size, bytes.data(), bytes.size());
	}
	size += bytes.size();
	return *this;
}

void Serializer::serializeVariableInteger(uint64_t val, OptionalLite<bool> sign)
{
	// 7  0sxxxxxx
	// 14 10sxxxxx xxxxxxxx
	// 21 110sxxxx xxxxxxxx xxxxxxxx
	// 28 1110sxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 35 11110sxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 42 111110sx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 49 1111110s xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 56 11111110 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 64 11111111 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

	const size_t nBits = size_t(fastLog2Ceil(val)) + (sign ? 1 : 0);
	const size_t nBytes = std::min((nBits - 1) / 7, size_t(8)) + 1; // Total length of this sequence
	std::array<uint8_t, 9> buffer;
	buffer.fill(0);

	// Combine sign into value
	uint64_t toWrite = val;
	if (sign) {
		const size_t signPos = nBytes * 7 + (nBytes == 9 ? 0 : -1); // 9-byte version places it on pos 63, not 62
		toWrite |= uint64_t(sign.value() ? 1 : 0) << signPos;
	}

	// Write header
	// To generate the mask, we get 9 - nBytes to see how many zeroes we need (8 at 1 byte, 7 at 2 bytes, etc), generate that many "1"s, then xor that with 255 (0b11111111) to flip those bits
	const size_t headerBits = std::min(nBytes, size_t(7));
	buffer[0] = uint8_t(255) ^ (uint8_t((1 << (9 - headerBits)) - 1));

	// Write bits
	size_t bitsAvailableOnByte = 8 - headerBits;
	size_t bitsToWrite = nBits;
	size_t curPos = 0;

	while (bitsToWrite > 0) {
		const size_t nBits = std::min(bitsToWrite, bitsAvailableOnByte);
		const uint64_t mask = (uint64_t(1) << bitsAvailableOnByte) - 1;

		buffer[curPos] |= toWrite & mask;

		toWrite >>= nBits;
		bitsAvailableOnByte = 8;
		curPos++;
		bitsToWrite -= nBits;
	}

	*this << gsl::as_bytes(gsl::span<const uint8_t>(buffer.data(), curPos));
}

Deserializer::Deserializer(gsl::span<const gsl::byte> src, SerializerOptions options)
	: options(std::move(options))
	, src(src)
{
}

Deserializer::Deserializer(const Bytes& src, SerializerOptions options)
	: options(std::move(options))
	, src(gsl::as_bytes(gsl::span<const Halley::Byte>(src)))
{
}

Deserializer& Deserializer::operator>>(std::string& str)
{
	String s;
	*this >> s;
	str = s.cppStr();
	return *this;
}

Deserializer& Deserializer::operator>>(String& str)
{
	auto readRawString = [&] (size_t size)
	{
		ensureSufficientBytesRemaining(size);
		str = String(reinterpret_cast<const char*>(src.data() + pos), size);
		pos += size;
	};

	if (options.version == 0) {
		uint32_t size;
		*this >> size;
		readRawString(size);
	} else {
		uint64_t value;
		*this >> value;

		if (options.indexToString) {
			if (options.exhaustiveDictionary || (value & 0x1) != 0) {
				// Indexed string
				int shift = options.exhaustiveDictionary ? 0 : 1;
				str = options.indexToString(value >> shift);
			} else {
				// Not indexed
				readRawString(value >> 1);
			}
		} else {
			// No dictionary
			readRawString(value);
		}
	}

	return *this;
}

Deserializer& Deserializer::operator>>(Path& p)
{
	std::string s;
	*this >> s;
	p = s;
	return *this;
}

Deserializer& Deserializer::operator>>(gsl::span<gsl::byte> span)
{
	if (span.empty()) {
		return *this;
	}
	Expects(span.size_bytes() > 0);

	ensureSufficientBytesRemaining(size_t(span.size_bytes()));

	memcpy(span.data(), src.data() + pos, span.size_bytes());
	pos += span.size_bytes();
	return *this;
}

Deserializer& Deserializer::operator>>(Bytes& bytes)
{
	uint32_t sz;
	*this >> sz;
	ensureSufficientBytesRemaining(sz);
	bytes.resize(sz);

	auto dst = gsl::as_writable_bytes(gsl::span<Byte>(bytes));
	*this >> dst;
	return *this;
}

void Deserializer::setVersion(int v)
{
	version = v;
}

int Deserializer::getVersion() const
{
	return version;
}

void Deserializer::deserializeVariableInteger(uint64_t& val, bool& sign, bool isSigned)
{
	// 7  0sxxxxxx
	// 14 10sxxxxx xxxxxxxx
	// 21 110sxxxx xxxxxxxx xxxxxxxx
	// 28 1110sxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 35 11110sxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 42 111110sx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 49 1111110s xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 56 11111110 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
	// 64 11111111 sxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

	// Read header
	uint8_t header;
	*this >> header;

	// Figure out which pattern we're dealing with
	size_t nBytes = 0;
	if ((header & 0x80) != 0x80) {
		nBytes = 1;
	} else if ((header & 0xC0) != 0xC0) {
		nBytes = 2;
	} else if ((header & 0xE0) != 0xE0) {
		nBytes = 3;
	} else if ((header & 0xF0) != 0xF0) {
		nBytes = 4;
	} else if ((header & 0xF8) != 0xF8) {
		nBytes = 5;
	} else if ((header & 0xFC) != 0xFC) {
		nBytes = 6;
	} else if ((header & 0xFE) != 0xFE) {
		nBytes = 7;
	} else if ((header & 0xFF) != 0xFF) {
		nBytes = 8;
	} else {
		nBytes = 9;
	}
	const size_t headerBits = std::min(nBytes, size_t(7));

	// Read rest of the data
	std::array<uint8_t, 9> buffer;
	buffer[0] = header;
	if (nBytes > 1) {
		*this >> gsl::as_writable_bytes(gsl::span<uint8_t>(buffer.data(), nBytes - 1));
	}

	// Convert to uint64_t
	size_t bitsAvailableOnByte = 8 - headerBits;
	size_t bitsRead = 0;
	uint64_t value = 0;
	for (size_t i = 0; i < nBytes; ++i) {
		const uint64_t byteMask = (uint64_t(1) << bitsAvailableOnByte) - 1;
		value |= (uint64_t(buffer[i]) & byteMask) << bitsRead;
		bitsRead += bitsAvailableOnByte;
		bitsAvailableOnByte = 8;
	}

	// Restore sign
	if (isSigned) {
		const size_t signPos = nBytes * 7 + (nBytes == 9 ? 0 : -1); // 9-byte version places it on pos 63, not 62
		const uint64_t signMask = uint64_t(1) << signPos;
		sign = (value & signMask) != 0;
		value &= ~signMask;
	} else {
		sign = false;
	}

	// Output value
	val = value;
}

void Deserializer::ensureSufficientBytesRemaining(size_t bytes)
{
	if (bytes > getBytesRemaining()) {
		throw Exception("Attempt to deserialize out of bounds", HalleyExceptions::File);
	}
}

size_t Deserializer::getBytesRemaining() const
{
	if (pos > size_t(src.size_bytes())) {
		return 0;
	} else {
		return size_t(src.size_bytes()) - pos;
	}
}
<|endoftext|>


<commit_before>#ifndef COZMO_COZMO_HPP_
#define COZMO_COZMO_HPP_

#include "dart/dart.hpp"

using BodyNodePtr = dart::dynamics::BodyNodePtr;
using SkeletonPtr = dart::dynamics::SkeletonPtr;
using InverseKinematicsPtr = dart::dynamics::InverseKinematicsPtr;

class Cozmo
{
private:
  SkeletonPtr cozmo;
  BodyNodePtr head;
  BodyNodePtr base;
  BodyNodePtr forklift;
  BodyNodePtr ghost_strut;
  BodyNodePtr lower_forklift_strut_left;
  BodyNodePtr lower_forklift_strut_right;
  BodyNodePtr upper_forklift_strut_left;
  BodyNodePtr upper_forklift_strut_right;
  InverseKinematicsPtr ik;

  BodyNodePtr makeRootBody(const SkeletonPtr& cozmo, const std::string& name, const std::string& mesh_dir);
  BodyNodePtr addBody(const SkeletonPtr& cozmo, BodyNodePtr parent, const std::string& name, const std::string& mesh_dir,
	              Eigen::Vector3d transformFromParent, Eigen::Vector3d transformFromChild);
  SkeletonPtr createCozmo(const std::string& mesh_dir);
  void createIKModule();

public:
  Cozmo(const std::string& mesh_dir);
  void setPosition(double pos);
  SkeletonPtr getCozmoSkeleton() { return cozmo; };
};

#endif  // COZMO_COZMO_HPP_
<commit_msg>Fixed issues<commit_after>#ifndef COZMO_COZMO_HPP_
#define COZMO_COZMO_HPP_

#include "dart/dart.hpp"

namespace libcozmo {
using BodyNodePtr = dart::dynamics::BodyNodePtr;
using SkeletonPtr = dart::dynamics::SkeletonPtr;
using InverseKinematicsPtr = dart::dynamics::InverseKinematicsPtr;

class Cozmo
{
public:
  Cozmo(const std::string& mesh_dir);
  void setForkliftPosition(double pos);
  SkeletonPtr getCozmoSkeleton() { return cozmo; };

private:
  SkeletonPtr cozmo;
  BodyNodePtr head;
  BodyNodePtr base;
  BodyNodePtr forklift;
  BodyNodePtr ghost_strut;
  BodyNodePtr lower_forklift_strut_left;
  BodyNodePtr lower_forklift_strut_right;
  BodyNodePtr upper_forklift_strut_left;
  BodyNodePtr upper_forklift_strut_right;
  InverseKinematicsPtr ik;

  BodyNodePtr makeRootBody(const SkeletonPtr& cozmo, const std::string& name, const std::string& mesh_dir);
  BodyNodePtr addBody(const SkeletonPtr& cozmo, BodyNodePtr parent, const std::string& name, const std::string& mesh_dir,
	              Eigen::Vector3d transformFromParent, Eigen::Vector3d transformFromChild);
  SkeletonPtr createCozmo(const std::string& mesh_dir);
  void createIKModule();
};
}
#endif  // COZMO_COZMO_HPP_
<|endoftext|>


<commit_before>/*
 * expressions.hpp
 * Author: Radu Cotescu (rdc1g10@soton.ac.uk)
 *
 * Part 2: Expression Templates
 * Write C++ templates which allow you to use types to represent arithmetic
 * expressions over the four basic operations (addition, subtraction,
 * multiplication and division), a single variable, and integer exponentiation:
 * (e.g. x^2+(x-2)^3/5). For the purposes of this assignment we refer to the
 * single variable as x.
 *
 * The types representing the expressions should contain a function named "eval"
 * that provides code for evaluating the expression. This function should accept
 * a double parameter that will be used as the value for the single variable x.
 */
#ifndef EXPRESSIONS_HPP_
#define EXPRESSIONS_HPP_
#include <functional>
#include <typeinfo>
#include <math.h>
using namespace std;

/*
 * Class defining Literals (scalars).
 */
class Literal {
public:
	Literal(const double v) : value(v) {}

	/*
	 * Returns the expression evaluation for a Literal.
	 * @param dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double eval(double) const {
		return value;
	}

	/*
	 * Returns the derivative of a Literal.
	 * @param dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double der(double) const {
		return 0;
	}
private:
	const double value;
};

/*
 * Class defining double variables.
 */
class Variable {
public:
	/*
	 * Returns the expression evaluation for a Variable (its value).
	 * @param d the value for which the variable should be evaluated
	 */
	double eval(double d) const {
		return d;
	}

	/*
	 * Returns the derivative of a variable.
	 * @param d dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double der(double d) const {
		return 1;
	}
};

/*
 * Expression traits used to convert constants of numerical types to objects
 * of type Literal, without changing expressions.
 */
template <class Expression> struct expressionTrait {
	typedef Expression expressionType;
};

template <> struct expressionTrait<unsigned int> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<int> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<float> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<double> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<long> {
	typedef Literal expressionType;
};

/*
 * Exponentiation function object class.
 */
template <class T> struct exponentiation : binary_function <T, T, T> {
	T operator() (const T& m, const T& n) const {
		return pow(m, n);
	}
};

/*
 * Template defining a binary expression.
 */
template <class LHS, class RHS, class BinaryOperation> class BinaryExpression {
public:
	BinaryExpression(
			LHS _lhs,
			RHS _rhs,
			BinaryOperation _operation = BinaryOperation()
	) : lhs(_lhs), rhs(_rhs), operation(_operation) {}

	/*
	 * Returns the result of the expression's operation for a specified value.
	 * @param d the value for which the expression is evaluated
	 */
	double eval(double d) const {
		return operation(lhs.eval(d), rhs.eval(d));
	}

	/*
	 * Returns the derivative of the expression, evaluated for a certain value.
	 * @param d the value at which the derivative of the expression is evaluated
	 */
	double der(double d) const {
		if (typeid(operation) == typeid(plus<double>)) {
			return (lhs.der(d) + rhs.der(d));
		}
		else if (typeid(operation) == typeid(minus<double>)) {
			return (lhs.der(d) - rhs.der(d));
		}
		else if (typeid(operation) == typeid(multiplies<double>)) {
			return (lhs.eval(d) * rhs.der(d) + lhs.der(d) * rhs.eval(d));
		}
		else if (typeid(operation) == typeid(divides<double>)) {
			return ((rhs.eval(d) * lhs.der(d) - lhs.eval(d) * rhs.der(d)) / (rhs^2).eval(d));
		}
		else if (typeid(operation) == typeid(exponentiation<double>)) {
			return (rhs.eval(d) * (lhs^(rhs.eval(d) - 1)).eval(d) * lhs.der(d));
		}
		else {
			assert (false);
			return 0;
		}
	}
private:
	typename expressionTrait<LHS>::expressionType lhs;
	typename expressionTrait<RHS>::expressionType rhs;
	BinaryOperation operation;
};

/*
 * Operator + overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, plus<double> > operator+(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, plus<double> >(lhs, rhs);
}

/*
 * Operator - overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, minus<double> > operator-(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, minus<double> >(lhs, rhs);
}

/*
 * Operator * overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, multiplies<double> > operator*(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, multiplies<double> >(lhs, rhs);
}

/*
 * Operator / overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, divides<double> > operator/(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, divides<double> >(lhs, rhs);
}

/*
 * Template for defining the exponentiation operation.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, exponentiation<double> > operator^(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, exponentiation<double> >(lhs, rhs);
}
#endif /* EXPRESSIONS_HPP_ */
<commit_msg>added acknowledgements<commit_after>/*
 * expressions.hpp
 * Author: Radu Cotescu (rdc1g10@soton.ac.uk)
 *
 * The implementation is based on an article written by Angelika Langer and
 * published on her web site at the following address:
 *
 * http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm
 *
 * Part 2: Expression Templates
 * Write C++ templates which allow you to use types to represent arithmetic
 * expressions over the four basic operations (addition, subtraction,
 * multiplication and division), a single variable, and integer exponentiation:
 * (e.g. x^2+(x-2)^3/5). For the purposes of this assignment we refer to the
 * single variable as x.
 *
 * The types representing the expressions should contain a function named "eval"
 * that provides code for evaluating the expression. This function should accept
 * a double parameter that will be used as the value for the single variable x.
 */
#ifndef EXPRESSIONS_HPP_
#define EXPRESSIONS_HPP_
#include <functional>
#include <typeinfo>
#include <math.h>
using namespace std;

/*
 * Class defining Literals (scalars).
 */
class Literal {
public:
	Literal(const double v) : value(v) {}

	/*
	 * Returns the expression evaluation for a Literal.
	 * @param dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double eval(double) const {
		return value;
	}

	/*
	 * Returns the derivative of a Literal.
	 * @param dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double der(double) const {
		return 0;
	}
private:
	const double value;
};

/*
 * Class defining double variables.
 */
class Variable {
public:
	/*
	 * Returns the expression evaluation for a Variable (its value).
	 * @param d the value for which the variable should be evaluated
	 */
	double eval(double d) const {
		return d;
	}

	/*
	 * Returns the derivative of a variable.
	 * @param d dummy value to keep the function's consistency over the
	 * 		expressions' implementation
	 */
	double der(double d) const {
		return 1;
	}
};

/*
 * Expression traits used to convert constants of numerical types to objects
 * of type Literal, without changing expressions.
 */
template <class Expression> struct expressionTrait {
	typedef Expression expressionType;
};

template <> struct expressionTrait<unsigned int> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<int> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<float> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<double> {
	typedef Literal expressionType;
};

template <> struct expressionTrait<long> {
	typedef Literal expressionType;
};

/*
 * Exponentiation function object class.
 */
template <class T> struct exponentiation : binary_function <T, T, T> {
	T operator() (const T& m, const T& n) const {
		return pow(m, n);
	}
};

/*
 * Template defining a binary expression.
 */
template <class LHS, class RHS, class BinaryOperation> class BinaryExpression {
public:
	BinaryExpression(
			LHS _lhs,
			RHS _rhs,
			BinaryOperation _operation = BinaryOperation()
	) : lhs(_lhs), rhs(_rhs), operation(_operation) {}

	/*
	 * Returns the result of the expression's operation for a specified value.
	 * @param d the value for which the expression is evaluated
	 */
	double eval(double d) const {
		return operation(lhs.eval(d), rhs.eval(d));
	}

	/*
	 * Returns the derivative of the expression, evaluated for a certain value.
	 * @param d the value at which the derivative of the expression is evaluated
	 */
	double der(double d) const {
		if (typeid(operation) == typeid(plus<double>)) {
			return (lhs.der(d) + rhs.der(d));
		}
		else if (typeid(operation) == typeid(minus<double>)) {
			return (lhs.der(d) - rhs.der(d));
		}
		else if (typeid(operation) == typeid(multiplies<double>)) {
			return (lhs.eval(d) * rhs.der(d) + lhs.der(d) * rhs.eval(d));
		}
		else if (typeid(operation) == typeid(divides<double>)) {
			return ((rhs.eval(d) * lhs.der(d) - lhs.eval(d) * rhs.der(d)) / (rhs^2).eval(d));
		}
		else if (typeid(operation) == typeid(exponentiation<double>)) {
			return (rhs.eval(d) * (lhs^(rhs.eval(d) - 1)).eval(d) * lhs.der(d));
		}
		else {
			assert (false);
			return 0;
		}
	}
private:
	typename expressionTrait<LHS>::expressionType lhs;
	typename expressionTrait<RHS>::expressionType rhs;
	BinaryOperation operation;
};

/*
 * Operator + overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, plus<double> > operator+(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, plus<double> >(lhs, rhs);
}

/*
 * Operator - overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, minus<double> > operator-(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, minus<double> >(lhs, rhs);
}

/*
 * Operator * overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, multiplies<double> > operator*(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, multiplies<double> >(lhs, rhs);
}

/*
 * Operator / overloading.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, divides<double> > operator/(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, divides<double> >(lhs, rhs);
}

/*
 * Template for defining the exponentiation operation.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, exponentiation<double> > operator^(LHS lhs, RHS rhs) {
	return BinaryExpression<LHS, RHS, exponentiation<double> >(lhs, rhs);
}
#endif /* EXPRESSIONS_HPP_ */
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial applications,
 * as long as this copyright notice is maintained.
 *
 * This application 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.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

///////////////////////////////////////////////////////////////////////////
//
// osgProducer version (see osgViewer version in next section below)

#include <osgProducer/Viewer>
int main_osgProducer(osg::ArgumentParser& arguments)
{
    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters");
    arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available");
    arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available");

    arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings.");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    bool helpAll = arguments.read("--help-all");
    unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) |
                            ((helpAll ||  arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) |
                            ((helpAll ||  arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 );
    if (helpType)
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        return 1;
    }

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    osg::Timer_t start_tick = osg::Timer::instance()->tick();

    // read the scene from the list of file specified command line args.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);

    // if no model has been successfully loaded report failure.
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
    }

    osg::Timer_t end_tick = osg::Timer::instance()->tick();

    std::cout << "Time to load = "<<osg::Timer::instance()->delta_s(start_tick,end_tick)<<std::endl;

    // optimize the scene graph, remove redundant nodes and state etc.
    osgUtil::Optimizer optimizer;
    optimizer.optimize(loadedModel.get());

    // pass the loaded scene graph to the viewer.
    viewer.setSceneData(loadedModel.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete.
    viewer.sync();

    // run a clean up frame to delete all OpenGL objects.
    viewer.cleanup_frame();

    // wait for all the clean up frame to complete.
    viewer.sync();

    return 0;
}

///////////////////////////////////////////////////////////////////////////
//
// osgViewer version

#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>

int main_osgViewer(osg::ArgumentParser& arguments)
{
    osgViewer::Viewer viewer;

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    {
        osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
        statesetManipulator->setStateSet(viewer.getCamera()->getOrCreateStateSet());

        viewer.addEventHandler( statesetManipulator.get() );
    }

    viewer.setSceneData( osgDB::readNodeFiles(arguments) );

    return viewer.run();
}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    if (arguments.read("--osgProducer"))
    {
        return main_osgProducer(arguments);
    }
    else
    {
        return main_osgViewer(arguments);
    }

}

<commit_msg>Added support for animation path manipulator to osgViewer path<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial applications,
 * as long as this copyright notice is maintained.
 *
 * This application 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.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

///////////////////////////////////////////////////////////////////////////
//
// osgProducer version (see osgViewer version in next section below)

#include <osgProducer/Viewer>
int main_osgProducer(osg::ArgumentParser& arguments)
{
    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters");
    arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available");
    arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available");

    arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings.");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    bool helpAll = arguments.read("--help-all");
    unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) |
                            ((helpAll ||  arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) |
                            ((helpAll ||  arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 );
    if (helpType)
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        return 1;
    }

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    osg::Timer_t start_tick = osg::Timer::instance()->tick();

    // read the scene from the list of file specified command line args.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);

    // if no model has been successfully loaded report failure.
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
    }

    osg::Timer_t end_tick = osg::Timer::instance()->tick();

    std::cout << "Time to load = "<<osg::Timer::instance()->delta_s(start_tick,end_tick)<<std::endl;

    // optimize the scene graph, remove redundant nodes and state etc.
    osgUtil::Optimizer optimizer;
    optimizer.optimize(loadedModel.get());

    // pass the loaded scene graph to the viewer.
    viewer.setSceneData(loadedModel.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete.
    viewer.sync();

    // run a clean up frame to delete all OpenGL objects.
    viewer.cleanup_frame();

    // wait for all the clean up frame to complete.
    viewer.sync();

    return 0;
}

///////////////////////////////////////////////////////////////////////////
//
// osgViewer version

#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>

int main_osgViewer(osg::ArgumentParser& arguments)
{
    osgViewer::Viewer viewer;

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );

        std::string pathfile;
        osg::ref_ptr<osgGA::AnimationPathManipulator> apm = 0;
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( '4', "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    {
        osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
        statesetManipulator->setStateSet(viewer.getCamera()->getOrCreateStateSet());

        viewer.addEventHandler( statesetManipulator.get() );
    }

    viewer.setSceneData( osgDB::readNodeFiles(arguments) );

    return viewer.run();
}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    if (arguments.read("--osgProducer"))
    {
        return main_osgProducer(arguments);
    }
    else
    {
        return main_osgViewer(arguments);
    }

}

<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  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.txt
 *
 *  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 "rtkmedian_ggo.h"
#include "rtkGgoFunctions.h"

#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayEllipsoidIntersectionImageFilter.h"
#include "rtkMedianImageFilter.h"
#include "rtkProjectionsReader.h"
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkRegularExpressionSeriesFileNames.h>
#include <itkTimeProbe.h>

int main(int argc, char * argv[])
{
  GGO(rtkmedian, args_info);

  typedef unsigned short OutputPixelType;
  const unsigned int     Dimension = 2;
  unsigned int           medianWindow[2];

  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;

  // Input reader
  if(args_info.verbose_flag)
    std::cout << "Reading input volume "
              << args_info.input_arg
              << "..."
              << std::flush;
  itk::TimeProbe readerProbe;
  typedef itk::ImageFileReader< OutputImageType > ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( args_info.input_arg );
  readerProbe.Start();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( reader->Update() )
  readerProbe.Stop();
  if(args_info.verbose_flag)
    std::cout << " done in "
              << readerProbe.GetMean() << ' ' << readerProbe.GetUnit()
              << '.' << std::endl;

  // Reading median Window
  if(args_info.median_given<Dimension)
  {
    for(unsigned int i=0; i<Dimension; i++)
      medianWindow[i] = args_info.median_arg[0];
  }
  else
    for(unsigned int i=0; i<Dimension; i++)
      medianWindow[i] = args_info.median_arg[i];

  // Median filter
  typedef rtk::MedianImageFilter MEDFilterType;
  MEDFilterType::Pointer median=MEDFilterType::New();
  median->SetInput(reader->GetOutput());
  median->SetMedianWindow(medianWindow);
  median->Update();
  // Write
  typedef itk::ImageFileWriter<  OutputImageType > WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( args_info.output_arg );
  writer->SetInput( median->GetOutput() );
  if(args_info.verbose_flag)
    std::cout << "Projecting and writing... " << std::flush;
  TRY_AND_EXIT_ON_ITK_EXCEPTION( writer->Update() );

  writer->SetFileName( "orginal.mha" );
  writer->SetInput( reader->GetOutput() );
  if(args_info.verbose_flag)
    std::cout << "Projecting and writing... " << std::flush;
  TRY_AND_EXIT_ON_ITK_EXCEPTION( writer->Update() );

  return EXIT_SUCCESS;
}
<commit_msg>Added missing IO factories<commit_after>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  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.txt
 *
 *  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 "rtkmedian_ggo.h"
#include "rtkGgoFunctions.h"

#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayEllipsoidIntersectionImageFilter.h"
#include "rtkMedianImageFilter.h"
#include "rtkProjectionsReader.h"
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkRegularExpressionSeriesFileNames.h>
#include <itkTimeProbe.h>

int main(int argc, char * argv[])
{
  GGO(rtkmedian, args_info);
  rtk::RegisterIOFactories();

  typedef unsigned short OutputPixelType;
  const unsigned int     Dimension = 2;
  unsigned int           medianWindow[2];

  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;

  // Input reader
  if(args_info.verbose_flag)
    std::cout << "Reading input volume "
              << args_info.input_arg
              << "..."
              << std::flush;
  itk::TimeProbe readerProbe;
  typedef itk::ImageFileReader< OutputImageType > ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( args_info.input_arg );
  readerProbe.Start();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( reader->Update() )
  readerProbe.Stop();
  if(args_info.verbose_flag)
    std::cout << " done in "
              << readerProbe.GetMean() << ' ' << readerProbe.GetUnit()
              << '.' << std::endl;

  // Reading median Window
  if(args_info.median_given<Dimension)
  {
    for(unsigned int i=0; i<Dimension; i++)
      medianWindow[i] = args_info.median_arg[0];
  }
  else
    for(unsigned int i=0; i<Dimension; i++)
      medianWindow[i] = args_info.median_arg[i];

  // Median filter
  typedef rtk::MedianImageFilter MEDFilterType;
  MEDFilterType::Pointer median=MEDFilterType::New();
  median->SetInput(reader->GetOutput());
  median->SetMedianWindow(medianWindow);
  median->Update();
  // Write
  typedef itk::ImageFileWriter<  OutputImageType > WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( args_info.output_arg );
  writer->SetInput( median->GetOutput() );
  if(args_info.verbose_flag)
    std::cout << "Projecting and writing... " << std::flush;
  TRY_AND_EXIT_ON_ITK_EXCEPTION( writer->Update() );

  writer->SetFileName( "orginal.mha" );
  writer->SetInput( reader->GetOutput() );
  if(args_info.verbose_flag)
    std::cout << "Projecting and writing... " << std::flush;
  TRY_AND_EXIT_ON_ITK_EXCEPTION( writer->Update() );

  return EXIT_SUCCESS;
}
<|endoftext|>


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

#ifndef TCC_GRAPH_STREE_DEFINED
#define TCC_GRAPH_STREE_DEFINED

// Default libraries
#include <vector>
#include <utility>
#include <iostream>
#include <initializer_list>

// Libraries
#include "Arc.tcc"
#include "Cycle.tcc"
#include "Vertex.tcc"

namespace graph
{
    template<
        typename Vertex = graph::Vertex<>,
        typename Arc    = graph::Arc<Vertex>,
        typename Cycle  = graph::Cycle<Arc>
    >class STree
    {
        public:
            typedef Vertex                   vertex_type;
            typedef Arc                      arc_type;
            typedef typename Vertex::id_type vertex_id;

        private:
            std::vector<vertex_id> parnt;
            std::vector<int>       depth;
            vertex_id              radix;
            int                    max_depth;

        public:
            STree(size_t num_vertices, vertex_id radix,
                  std::initializer_list<Arc> arcs)
                : parnt(num_vertices),
                  depth(num_vertices,-1),
                  radix{}, max_depth{-1}
            {
                for(const Arc& arc : arcs)
                {
                    if(depth[arc.beg] == -1
                    && depth[arc.end] != -1)
                    {
                        radix = arc.beg;
                        parnt[arc.beg] = arc.end;
                        depth[arc.beg] = depth[arc.end]+1;
                    }
                    else if(depth[arc.beg] != -1
                         && depth[arc.end] == -1)
                    {
                        parnt[arc.end] = arc.beg;
                        depth[arc.end] = depth[arc.beg]+1;
                    }
                    else if(depth[arc.beg] == -1
                         && depth[arc.end] == -1)
                    {
                        parnt[arc.end] = arc.beg;
                        depth[arc.beg] = 0;
                        depth[arc.end] = 1;
                    }
                    for(int d : depth)
                        if(d > max_depth) max_depth = d;
                }
            }

            Cycle fundamental_cycle(const Arc& inserted)
            {
                Cycle cycle { inserted };
                vertex_id l { inserted.beg };
                vertex_id r { inserted.end };
                int depth = depth[inserted.beg()];

                if(depth[inserted.end()] > depth)
                    depth = depth[inserted.beg()];
                l = inserted.beg; r = inserted.end;

                // Intermediate arcs
                // (when with different depths)
                for(vertex_id lp = parnt[l]; depth[l] != depth; l = lp)
                    cycle.push_back( Arc{lp,l} );
                for(vertex_id rp = parnt[r]; depth[r] != depth; r = rp)
                    cycle.push_front( Arc{rp,r} );

                while(r != l)
                {
                    // Intermediate arcs
                    // (when with the same depth)
                    vertex_id lp = parnt[l];
                    vertex_id rp = parnt[r];
                    cycle.push_back ( Arc{lp,l} );
                    cycle.push_front( Arc{rp,r} );
                    r = rp; l = lp;
                }

                // Last arc
                cycle.push_back({parnt[l],l});

                return cycle;
            }

            friend std::ostream&
            operator<<(std::ostream& os, const STree& st)
            {
                for(int i = 0; i <= st.max_depth; i++)
                {
                    for(int d : st.depth)
                        if(d == i) os << d << " ";
                    os << std::endl;
                }
                return os;
            }
    };
}

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

#ifndef TCC_GRAPH_STREE_DEFINED
#define TCC_GRAPH_STREE_DEFINED

// Default libraries
#include <vector>
#include <utility>
#include <iostream>
#include <initializer_list>

// Libraries
#include "Arc.tcc"
#include "Cycle.tcc"
#include "Vertex.tcc"

namespace graph
{
    template<
        typename Graph,
        typename Cycle = graph::Cycle<typename Graph::arc_type>
    >class STree
    {
        public:
            typedef typename Graph::arc_type    arc_type;
            typedef typename Graph::arc_list    arc_list;
            typedef typename Graph::vertex_id   vertex_id;
            typedef typename Graph::vertex_type vertex_type;

        private:
            Graph*                 base;
            std::vector<vertex_id> parnt;
            std::vector<int>       depth;
            vertex_id              radix;
            int                    max_depth;

        public:
            STree(Graph& base, size_t num_vertices,
                  vertex_id radix, arc_list arcs)
                : base{&base}, parnt(num_vertices),
                  depth(num_vertices,-1), radix{}, max_depth{-1}
            {
                for(const arc_type& arc : arcs)
                {
                    if(depth[arc.beg] == -1
                    && depth[arc.end] != -1)
                    {
                        radix = arc.beg;
                        parnt[arc.beg] = arc.end;
                        depth[arc.beg] = depth[arc.end]+1;
                    }
                    else if(depth[arc.beg] != -1
                         && depth[arc.end] == -1)
                    {
                        parnt[arc.end] = arc.beg;
                        depth[arc.end] = depth[arc.beg]+1;
                    }
                    else if(depth[arc.beg] == -1
                         && depth[arc.end] == -1)
                    {
                        parnt[arc.end] = arc.beg;
                        depth[arc.beg] = 0;
                        depth[arc.end] = 1;
                    }
                    for(int d : depth)
                        if(d > max_depth) max_depth = d;
                }
            }

            Cycle fundamental_cycle(const arc_type& inserted)
            {
                Cycle cycle { inserted };
                vertex_id l { inserted.beg };
                vertex_id r { inserted.end };
                int depth = depth[inserted.beg()];

                if(depth[inserted.end()] > depth)
                    depth = depth[inserted.beg()];
                l = inserted.beg; r = inserted.end;

                // Intermediate arcs
                // (when with different depths)
                for(vertex_id lp = parnt[l]; depth[l] != depth; l = lp)
                    cycle.push_back( arc_type{lp,l} );
                for(vertex_id rp = parnt[r]; depth[r] != depth; r = rp)
                    cycle.push_front( arc_type{rp,r} );

                while(r != l)
                {
                    // Intermediate arcs
                    // (when with the same depth)
                    vertex_id lp = parnt[l];
                    vertex_id rp = parnt[r];
                    cycle.push_back ( arc_type{lp,l} );
                    cycle.push_front( arc_type{rp,r} );
                    r = rp; l = lp;
                }

                // Last arc
                cycle.push_back({parnt[l],l});

                return cycle;
            }

            friend std::ostream&
            operator<<(std::ostream& os, const STree& st)
            {
                for(int i = 0; i <= st.max_depth; i++)
                {
                    for(int d : st.depth)
                        if(d == i) os << d << " ";
                    os << std::endl;
                }
                return os;
            }
    };
}

#endif
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
#include "audiobuffer.h"

TEST_CASE( "RingBuffer", "[AudioBuffer]" ) {
    SECTION("Allocation") {
        AudioBuffer buffer;
        buffer.allocateRingbuffers(1024);
        REQUIRE(buffer.numberOfChannels() == 0);
        REQUIRE(buffer.ringBufferContainer.size() == 0);
        REQUIRE(buffer.ringBufferSize == 1024);
    }
    SECTION("Channels") {
        AudioBuffer buffer;
        QList<unsigned int> channels({1,5});
        buffer.allocateRingbuffers(1024, channels);
        REQUIRE(buffer.numberOfChannels() == channels.size());
        REQUIRE(buffer.ringBufferContainer.size() == channels.size());

        REQUIRE(buffer.activeChannelId(1) == channels.at(1));
        REQUIRE(buffer.activeChannelId(2) == 2);
    }
    SECTION("Rotation") {
        AudioBuffer buffer;
        QList<unsigned int> channels({0});
        buffer.allocateRingbuffers(10, channels);

        // Initialize buffer with values
        for( unsigned int ch=0; ch<buffer.numberOfChannels(); ch++ ) {
            QVector<double> *frames = &buffer.ringBufferContainer[ch];
            for( unsigned int i=0; i<buffer.ringBufferSize; i++ ) {
                (*frames)[i] = i;
            }
        }

        // Test buffer initialization
        foreach (QVector<double> frames, buffer.ringBufferContainer) {
            //for( int i=0; i<frames.size(); i++ ) { std::cerr << frames.at(i) << ", "; }
            REQUIRE(frames.at(3) == 3);
        }

        // Rotate and test frames
        unsigned int delta = 5;
        REQUIRE(buffer.rotateRingbuffers(delta) == true );
        foreach (QVector<double> frames, buffer.ringBufferContainer) {
            //for( int i=0; i<frames.size(); i++ ) { std::cerr << frames.at(i) << ", "; }
            REQUIRE(frames.at(delta) == 0);
        }
        REQUIRE(buffer.rotateRingbuffers(buffer.ringBufferSize+1) == false);
    }
}
<commit_msg>Restructured audiobuffer test cases<commit_after>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
#include "audiobuffer.h"

TEST_CASE( "RingBuffer", "[AudioBuffer]" )
{
    AudioBuffer* buffer = new AudioBuffer();
    SECTION("Allocation") {
        buffer->allocateRingbuffers(1024);
        REQUIRE(buffer->numberOfChannels() == 0);
        REQUIRE(buffer->ringBufferContainer.size() == 0);
        REQUIRE(buffer->ringBufferSize == 1024);
    }
    SECTION("Channels") {
        QList<unsigned int> channels({1,5});
        buffer->allocateRingbuffers(1024, channels);
        REQUIRE(buffer->numberOfChannels() == channels.size());
        REQUIRE(buffer->ringBufferContainer.size() == channels.size());

        REQUIRE(buffer->activeChannelId(1) == channels.at(1));
        REQUIRE(buffer->activeChannelId(2) == 2);
    }
    SECTION("Rotation") {
        QList<unsigned int> channels({0});
        buffer->allocateRingbuffers(10, channels);

        // Initialize buffer with values
        for( unsigned int ch=0; ch<buffer->numberOfChannels(); ch++ ) {
            QVector<double> *frames = &buffer->ringBufferContainer[ch];
            for( unsigned int i=0; i<buffer->ringBufferSize; i++ ) {
                (*frames)[i] = i;
            }
        }

        // Test buffer initialization
        foreach (QVector<double> frames, buffer->ringBufferContainer) {
            //for( int i=0; i<frames.size(); i++ ) { std::cerr << frames.at(i) << ", "; }
            REQUIRE(frames.at(3) == 3);
        }

        // Rotate and test frames
        unsigned int delta = 5;
        REQUIRE(buffer->rotateRingbuffers(delta) == true );
        foreach (QVector<double> frames, buffer->ringBufferContainer) {
            //for( int i=0; i<frames.size(); i++ ) { std::cerr << frames.at(i) << ", "; }
            REQUIRE(frames.at(delta) == 0);
        }
        REQUIRE(buffer->rotateRingbuffers(buffer->ringBufferSize+1) == false);
    }

    delete buffer;
}
<|endoftext|>


<commit_before>//
//  inpal_prime.hpp
//  inpalprime
//
//  Created by bryan triana on 7/13/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_prime_hpp
#define inpal_prime_hpp

#include <vector>
#include <string>

namespace inpal
{
    class prime
    {
    public:
        static std::size_t max_prime(std::size_t range);
        static std::size_t prime_count(std::size_t range);
        static double prime_density(double range);
        static bool prime_test(std::size_t num);
        static bool twin_test(std::size_t num);
        static bool cousin_test(std::size_t num);
        static bool sexy_test(std::size_t num);
        static std::size_t max_palprime(std::size_t range);
        static std::size_t max_factor(std::size_t num);
        static std::size_t count_factors(std::size_t num);
    private:
        static std::vector<bool> prime_sieve(std::size_t range);
        static std::vector<std::size_t> factorizer(std::size_t num);
        static bool pal_test(std::size_t num);
    };
}

#endif /* inpal_prime_hpp */
<commit_msg>Update inpal_prime.hpp<commit_after>//
//  inpal_prime.hpp
//  InversePalindrome
//
//  Created by Bryan Triana on 7/13/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_prime_hpp
#define inpal_prime_hpp

#include <vector>
#include <string>

namespace inpal
{
    class prime
    {
    public:
        static std::size_t max_prime(std::size_t range);
        static std::size_t prime_count(std::size_t range);
        static double prime_density(double range);
        static bool prime_test(std::size_t num);
        static bool twin_test(std::size_t num);
        static bool cousin_test(std::size_t num);
        static bool sexy_test(std::size_t num);
        static std::size_t max_palprime(std::size_t range);
        static std::size_t max_factor(std::size_t num);
        static std::size_t count_factors(std::size_t num);
    private:
        static std::vector<bool> prime_sieve(std::size_t range);
        static std::vector<std::size_t> factorizer(std::size_t num);
        static bool pal_test(std::size_t num);
    };
}

#endif /* inpal_prime_hpp */
<|endoftext|>