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

#include <cstring>
#include <map>
#include <string>
#include <vector>

#include "caffe/caffe.hpp"

using caffe::Blob;
using caffe::Caffe;
using caffe::Net;
using caffe::Layer;
using caffe::shared_ptr;
using caffe::Timer;
using caffe::vector;

// Used in device query
DEFINE_int32(device_id, 0,
             "[device_query,time] The device id to use.");
// Used in training
DEFINE_string(solver_proto_file, "",
              "[train] The protobuf containing the solver definition.");
DEFINE_string(net_proto_file, "",
              "[time] The net proto file to use.");
DEFINE_string(resume_point_file, "",
              "[train] (optional) The snapshot from which to resume training.");
DEFINE_string(pretrained_net_file, "",
              "[train] (optional) A pretrained network to run finetune from. "
              "Cannot be set simultaneously with resume_point_file.");
DEFINE_int32(run_iterations, 50,
             "[time] The number of iterations to run.");
DEFINE_bool(time_with_gpu, false,
            "[time] Test the model with GPU.");

// A simple registry for caffe commands.
typedef int (*BrewFunction)();
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;

#define RegisterBrewFunction(func) \
namespace { \
class __Registerer_##func { \
 public: /* NOLINT */ \
  __Registerer_##func() { \
    g_brew_map[#func] = &func; \
  } \
}; \
__Registerer_##func g_registerer_##func; \
}

static BrewFunction GetBrewFunction(const caffe::string& name) {
  if (g_brew_map.count(name)) {
    return g_brew_map[name];
  } else {
    LOG(ERROR) << "Available caffe actions:";
    for (BrewMap::iterator it = g_brew_map.begin();
         it != g_brew_map.end(); ++it) {
      LOG(ERROR) << "\t" << it->first;
    }
    LOG(FATAL) << "Unknown action: " << name;
    return NULL;  // not reachable, just to suppress old compiler warnings.
  }
}

// caffe actions that could be called in the form
//     caffe.bin action
// To do so, define actions as "int action()" functions, and register it with
// RegisterBrewFunction(action);

int device_query() {
  LOG(INFO) << "Querying device_id = " << FLAGS_device_id;
  caffe::Caffe::SetDevice(FLAGS_device_id);
  caffe::Caffe::DeviceQuery();
  return 0;
}
RegisterBrewFunction(device_query);

int train() {
  CHECK_GT(FLAGS_solver_proto_file.size(), 0);

  caffe::SolverParameter solver_param;
  caffe::ReadProtoFromTextFileOrDie(FLAGS_solver_proto_file, &solver_param);

  LOG(INFO) << "Starting Optimization";
  caffe::SGDSolver<float> solver(solver_param);
  if (FLAGS_resume_point_file.size()) {
    LOG(INFO) << "Resuming from " << FLAGS_resume_point_file;
    solver.Solve(FLAGS_resume_point_file);
  } else if (FLAGS_pretrained_net_file.size()) {
    LOG(INFO) << "Finetuning from " << FLAGS_pretrained_net_file;
    solver.net()->CopyTrainedLayersFrom(FLAGS_pretrained_net_file);
    solver.Solve();
  } else {
    solver.Solve();
  }
  LOG(INFO) << "Optimization Done.";
  return 0;
}
RegisterBrewFunction(train);

int time() {
  // Set device id and mode
  if (FLAGS_time_with_gpu) {
    LOG(INFO) << "Use GPU with device id " << FLAGS_device_id;
    Caffe::SetDevice(FLAGS_device_id);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Caffe::set_phase(Caffe::TRAIN);
  Net<float> caffe_net(FLAGS_net_proto_file);

  // Do a clean forward and backward pass, so that memory allocation are done
  // and future iterations will be more stable.
  LOG(INFO) << "Performing Forward";
  // Note that for the speed benchmark, we will assume that the network does
  // not take any input blobs.
  float initial_loss;
  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
  LOG(INFO) << "Initial loss: " << initial_loss;
  LOG(INFO) << "Performing Backward";
  caffe_net.Backward();

  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
  vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
  vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
  const vector<vector<bool> >& bottom_need_backward =
      caffe_net.bottom_need_backward();
  LOG(INFO) << "*** Benchmark begins ***";
  LOG(INFO) << "Testing for " << FLAGS_run_iterations << " iterations.";
  Timer total_timer;
  total_timer.Start();
  Timer forward_timer;
  forward_timer.Start();
  Timer timer;
  for (int i = 0; i < layers.size(); ++i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    timer.Start();
    for (int j = 0; j < FLAGS_run_iterations; ++j) {
      layers[i]->Forward(bottom_vecs[i], &top_vecs[i]);
    }
    LOG(INFO) << layername << "\tforward: " << timer.MilliSeconds() <<
        " milli seconds.";
  }
  LOG(INFO) << "Forward pass: " << forward_timer.MilliSeconds() <<
      " milli seconds.";
  Timer backward_timer;
  backward_timer.Start();
  for (int i = layers.size() - 1; i >= 0; --i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    timer.Start();
    for (int j = 0; j < FLAGS_run_iterations; ++j) {
      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
                          &bottom_vecs[i]);
    }
    LOG(INFO) << layername << "\tbackward: "
        << timer.MilliSeconds() << " milli seconds.";
  }
  LOG(INFO) << "Backward pass: " << backward_timer.MilliSeconds() <<
      " milli seconds.";
  LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() <<
      " milli seconds.";
  LOG(INFO) << "*** Benchmark ends ***";
  return 0;
}
RegisterBrewFunction(time);

int main(int argc, char** argv) {
  caffe::GlobalInit(&argc, &argv);
  CHECK_EQ(argc, 2);
  return GetBrewFunction(caffe::string(argv[1]))();
}
<commit_msg>consolidaet GPU flag for caffe cli<commit_after>#include <gflags/gflags.h>
#include <glog/logging.h>

#include <cstring>
#include <map>
#include <string>
#include <vector>

#include "caffe/caffe.hpp"

using caffe::Blob;
using caffe::Caffe;
using caffe::Net;
using caffe::Layer;
using caffe::shared_ptr;
using caffe::Timer;
using caffe::vector;

// Used in device query
DEFINE_int32(device_id, 0,
             "[device_query,time] The device id to use.");
// Used in training
DEFINE_string(solver_proto_file, "",
              "[train] The protobuf containing the solver definition.");
DEFINE_string(net_proto_file, "",
              "[time] The net proto file to use.");
DEFINE_string(resume_point_file, "",
              "[train] (optional) The snapshot from which to resume training.");
DEFINE_string(pretrained_net_file, "",
              "[train] (optional) A pretrained network to run finetune from. "
              "Cannot be set simultaneously with resume_point_file.");
DEFINE_int32(run_iterations, 50,
             "[time] The number of iterations to run.");
DEFINE_bool(gpu, false,
            "[time] Run in GPU mode when true.");

// A simple registry for caffe commands.
typedef int (*BrewFunction)();
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;

#define RegisterBrewFunction(func) \
namespace { \
class __Registerer_##func { \
 public: /* NOLINT */ \
  __Registerer_##func() { \
    g_brew_map[#func] = &func; \
  } \
}; \
__Registerer_##func g_registerer_##func; \
}

static BrewFunction GetBrewFunction(const caffe::string& name) {
  if (g_brew_map.count(name)) {
    return g_brew_map[name];
  } else {
    LOG(ERROR) << "Available caffe actions:";
    for (BrewMap::iterator it = g_brew_map.begin();
         it != g_brew_map.end(); ++it) {
      LOG(ERROR) << "\t" << it->first;
    }
    LOG(FATAL) << "Unknown action: " << name;
    return NULL;  // not reachable, just to suppress old compiler warnings.
  }
}

// caffe actions that could be called in the form
//     caffe.bin action
// To do so, define actions as "int action()" functions, and register it with
// RegisterBrewFunction(action);

int device_query() {
  LOG(INFO) << "Querying device_id = " << FLAGS_device_id;
  caffe::Caffe::SetDevice(FLAGS_device_id);
  caffe::Caffe::DeviceQuery();
  return 0;
}
RegisterBrewFunction(device_query);

int train() {
  CHECK_GT(FLAGS_solver_proto_file.size(), 0);

  caffe::SolverParameter solver_param;
  caffe::ReadProtoFromTextFileOrDie(FLAGS_solver_proto_file, &solver_param);

  LOG(INFO) << "Starting Optimization";
  caffe::SGDSolver<float> solver(solver_param);
  if (FLAGS_resume_point_file.size()) {
    LOG(INFO) << "Resuming from " << FLAGS_resume_point_file;
    solver.Solve(FLAGS_resume_point_file);
  } else if (FLAGS_pretrained_net_file.size()) {
    LOG(INFO) << "Finetuning from " << FLAGS_pretrained_net_file;
    solver.net()->CopyTrainedLayersFrom(FLAGS_pretrained_net_file);
    solver.Solve();
  } else {
    solver.Solve();
  }
  LOG(INFO) << "Optimization Done.";
  return 0;
}
RegisterBrewFunction(train);

int time() {
  // Set device id and mode
  if (FLAGS_gpu) {
    LOG(INFO) << "Use GPU with device id " << FLAGS_device_id;
    Caffe::SetDevice(FLAGS_device_id);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Caffe::set_phase(Caffe::TRAIN);
  Net<float> caffe_net(FLAGS_net_proto_file);

  // Do a clean forward and backward pass, so that memory allocation are done
  // and future iterations will be more stable.
  LOG(INFO) << "Performing Forward";
  // Note that for the speed benchmark, we will assume that the network does
  // not take any input blobs.
  float initial_loss;
  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
  LOG(INFO) << "Initial loss: " << initial_loss;
  LOG(INFO) << "Performing Backward";
  caffe_net.Backward();

  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
  vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
  vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
  const vector<vector<bool> >& bottom_need_backward =
      caffe_net.bottom_need_backward();
  LOG(INFO) << "*** Benchmark begins ***";
  LOG(INFO) << "Testing for " << FLAGS_run_iterations << " iterations.";
  Timer total_timer;
  total_timer.Start();
  Timer forward_timer;
  forward_timer.Start();
  Timer timer;
  for (int i = 0; i < layers.size(); ++i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    timer.Start();
    for (int j = 0; j < FLAGS_run_iterations; ++j) {
      layers[i]->Forward(bottom_vecs[i], &top_vecs[i]);
    }
    LOG(INFO) << layername << "\tforward: " << timer.MilliSeconds() <<
        " milli seconds.";
  }
  LOG(INFO) << "Forward pass: " << forward_timer.MilliSeconds() <<
      " milli seconds.";
  Timer backward_timer;
  backward_timer.Start();
  for (int i = layers.size() - 1; i >= 0; --i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    timer.Start();
    for (int j = 0; j < FLAGS_run_iterations; ++j) {
      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
                          &bottom_vecs[i]);
    }
    LOG(INFO) << layername << "\tbackward: "
        << timer.MilliSeconds() << " milli seconds.";
  }
  LOG(INFO) << "Backward pass: " << backward_timer.MilliSeconds() <<
      " milli seconds.";
  LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() <<
      " milli seconds.";
  LOG(INFO) << "*** Benchmark ends ***";
  return 0;
}
RegisterBrewFunction(time);

int main(int argc, char** argv) {
  caffe::GlobalInit(&argc, &argv);
  CHECK_EQ(argc, 2);
  return GetBrewFunction(caffe::string(argv[1]))();
}
<|endoftext|>


<commit_before>/****************************************************************************

    TTL2C - LV2 Port Enum Generator

    This program reads an RDF file (in the Turtle syntax) describing
    an LV2 plugin and generates a C header file with data structures
    that contain information about the plugin.

    Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>

    Modified 2012 Michael Fisher <mfisher31@gmail.com>
      - renamed to ttl2c to avoid conflict with lv2-c++-tools

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307  USA

****************************************************************************/

#include <cfloat>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "turtleparser.hpp"
#include "query.hpp"
#include "namespaces.hpp"

#ifndef VERSION
#define VERSION "UNKNOWNVERSION"
#endif

using namespace std;
using namespace PAQ;

struct PortInfo {
  PortInfo()
    : min(-FLT_MAX),
      max(FLT_MAX),
      default_value(min),
      toggled(false),
      integer(false),
      logarithmic(false) { }
  string name;
  float min;
  float max;
  float default_value;
  bool toggled;
  bool integer;
  bool logarithmic;
};

int main(int argc, char** argv) {

  for (int i = 1; i < argc; ++i) {
    if (string(argv[i]) == "-V" || string(argv[i]) == "--version") {
      cout<<"ttl2c "<<VERSION<<" by Lars Luthman <lars.luthman@gmail.com>"
          <<endl;
      return 0;
    }
  }

  if (argc < 3) {
    cerr<<"Usage: ttl2c <input file> <output file> "<<endl;
    return -1;
  }

  // parse turtle file
  TurtleParser tp;
  RDFData data;
  if (!tp.parse_ttl_file(argv[1], data)) {
    cerr<<"Could not parse input. Not valid Turtle syntax."<<endl;
    return -1;
  }

  // find all plugins in the file
  Namespace lv2("<http://lv2plug.in/ns/lv2core#>");
  Namespace cx("<http://ll-plugins.nongnu.org/lv2/dev/contexts/1#>");
  Namespace ll("<http://ll-plugins.nongnu.org/lv2/namespace#>");
  Variable plugin, pegname;
  vector<QueryResult> qr =
    select(plugin, pegname)
    .where(plugin, ll("pegName"), pegname)
    .where(plugin, rdf("type"), lv2("Plugin"))
    .run(data);
  map<string, string> plugins;
  for (unsigned i = 0; i < qr.size(); ++i)
    plugins[qr[i][plugin]->name] = qr[i][pegname]->name;

  // iterate over all plugins
  map<string, map<int, PortInfo> > info;
  map<string, string>::const_iterator plug_iter;
  for (plug_iter = plugins.begin(); plug_iter != plugins.end(); ++plug_iter) {

    // query the plugin ports
    Variable port, index, symbol;
    qr = select(index, symbol)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("symbol"), symbol)
      .run(data);

    // put ports in a map so they get sorted
    map<int, PortInfo> ports;
    for (size_t i = 0; i < qr.size(); ++i) {
      int port_index = atoi(qr[i][index]->name.c_str());
      if (ports.find(port_index) != ports.end()) {
	cerr<<"Index "<<port_index<<" is used for more than one port"<<endl;
	return -1;
      }
      ports[port_index].name = qr[i][symbol]->name;
    }

    // query the context ports
    Variable cx_pred, context;
    qr = select(index, symbol)
      .where(plug_iter->first, cx_pred, context)
      .where(context, cx("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("symbol"), symbol)
      .filter(or_filter(cx_pred == cx("optionalContext"),
			cx_pred == cx("requiredContext")))
      .run(data);

    // put them in the map too
    for (size_t i = 0; i < qr.size(); ++i) {
      int port_index = atoi(qr[i][index]->name.c_str());
      if (ports.find(port_index) != ports.end()) {
	cerr<<"Index "<<port_index<<" is used for more than one port"<<endl;
	return -1;
      }
      ports[port_index].name = qr[i][symbol]->name;
    }

    // check that the port indices are OK
    map<int, PortInfo>::const_iterator iter;
    int next = 0;
    for (iter = ports.begin(); iter != ports.end(); ++iter) {
      if (iter->first != next) {
        cerr<<"There was no description of port "<<next
            <<" in plugin "<<plug_iter->first<<endl;
        return -1;
      }
      ++next;
    }

    // get min values
    Variable value;
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("minimum"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].min =
        atof(qr[i][value]->name.c_str());

    // get max values
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("maximum"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].max =
        atof(qr[i][value]->name.c_str());

    // get default values
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("default"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].default_value =
        atof(qr[i][value]->name.c_str());

    // get port hints
    Variable hint;
    qr = select(index, hint)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("portHint"), hint)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i) {
      if (qr[i][hint]->name == lv2("toggled"))
        ports[atoi(qr[i][index]->name.c_str())].toggled = true;
      if (qr[i][hint]->name == lv2("integer"))
        ports[atoi(qr[i][index]->name.c_str())].integer = true;
      if (qr[i][hint]->name == lv2("logarithmic"))
        ports[atoi(qr[i][index]->name.c_str())].logarithmic = true;
    }

    info[plug_iter->first] = ports;

  }

  // write the header file
  string header_guard = argv[2];
  for (size_t i = 0; i < header_guard.size(); ++i) {
    char& c = header_guard[i];
    if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_')))
      header_guard[i] = '_';
  }
  ofstream fout(argv[2]);
  fout<<"#ifndef "<<header_guard<<endl
      <<"#define "<<header_guard<<endl<<endl<<endl;

  // define data structure
  fout<<"#ifndef PEG_STRUCT"<<endl
      <<"#define PEG_STRUCT"<<endl
      <<"typedef struct {"<<endl
      <<"  float min;"<<endl
      <<"  float max;"<<endl
      <<"  float default_value;"<<endl
      <<"  char toggled;"<<endl
      <<"  char integer;"<<endl
      <<"  char logarithmic;"<<endl
      <<"} peg_data_t;"<<endl
      <<"#endif"<<endl<<endl;

  map<string, map<int, PortInfo> >::const_iterator piter;
  for (piter = info.begin(); piter != info.end(); ++piter) {
    fout<<"/* "<<piter->first<<" */"<<endl<<endl;

    // write the URI
    fout<<"static const char "<<plugins[piter->first]<<"_uri[] = \""
        <<piter->first.substr(1, piter->first.size() - 2)<<"\";"<<endl<<endl;

    // write port labels
    fout<<"enum "<<plugins[piter->first]<<"_port_enum {"<<endl;
    map<int, PortInfo>::const_iterator iter;
    for (iter = piter->second.begin(); iter != piter->second.end(); ++iter)
      fout<<"  "<<plugins[piter->first]<<"_"<<iter->second.name<<","<<endl;
    fout<<"  "<<plugins[piter->first]<<"_n_ports"<<endl
        <<"};"<<endl<<endl;

    // write port info
    fout<<"static const peg_data_t "
        <<plugins[piter->first]<<"_ports[] = {"<<endl;
    for (iter = piter->second.begin(); iter != piter->second.end(); ++iter) {
      fout<<"  { "
          <<iter->second.min<<", "
          <<iter->second.max<<", "
          <<iter->second.default_value<<", "
          <<(iter->second.toggled ? "1" : "0")<<", "
          <<(iter->second.integer ? "1" : "0")<<", "
          <<(iter->second.logarithmic ? "1" : "0")<<" }, "<<endl;
    }
    fout<<"};"<<endl<<endl<<endl;

  }

  fout<<"#endif /* "<<header_guard<<" */"<<endl;

  return 0;
}
<commit_msg>ttl2c looks for portProperty instead of portHint<commit_after>/****************************************************************************

    TTL2C - LV2 Port Enum Generator

    This program reads an RDF file (in the Turtle syntax) describing
    an LV2 plugin and generates a C header file with data structures
    that contain information about the plugin.

    Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>

    Modified 2012 Michael Fisher <mfisher31@gmail.com>
      - renamed to ttl2c to avoid conflict with lv2-c++-tools

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307  USA

****************************************************************************/

#include <cfloat>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "turtleparser.hpp"
#include "query.hpp"
#include "namespaces.hpp"

#ifndef VERSION
#define VERSION "UNKNOWNVERSION"
#endif

using namespace std;
using namespace PAQ;

struct PortInfo {
  PortInfo()
    : min(-FLT_MAX),
      max(FLT_MAX),
      default_value(min),
      toggled(false),
      integer(false),
      logarithmic(false) { }
  string name;
  float min;
  float max;
  float default_value;
  bool toggled;
  bool integer;
  bool logarithmic;
};

int main(int argc, char** argv) {

  for (int i = 1; i < argc; ++i) {
    if (string(argv[i]) == "-V" || string(argv[i]) == "--version") {
      cout<<"ttl2c "<<VERSION<<" by Lars Luthman <lars.luthman@gmail.com>"
          <<endl;
      return 0;
    }
  }

  if (argc < 3) {
    cerr<<"Usage: ttl2c <input file> <output file> "<<endl;
    return -1;
  }

  // parse turtle file
  TurtleParser tp;
  RDFData data;
  if (!tp.parse_ttl_file(argv[1], data)) {
    cerr<<"Could not parse input. Not valid Turtle syntax."<<endl;
    return -1;
  }

  // find all plugins in the file
  Namespace lv2("<http://lv2plug.in/ns/lv2core#>");
  Namespace cx("<http://ll-plugins.nongnu.org/lv2/dev/contexts/1#>");
  Namespace ll("<http://ll-plugins.nongnu.org/lv2/namespace#>");
  Namespace pprops("<http://lv2plug.in/ns/ext/port-props#>");
  Variable plugin, pegname;
  vector<QueryResult> qr =
    select(plugin, pegname)
    .where(plugin, ll("pegName"), pegname)
    .where(plugin, rdf("type"), lv2("Plugin"))
    .run(data);
  map<string, string> plugins;
  for (unsigned i = 0; i < qr.size(); ++i)
    plugins[qr[i][plugin]->name] = qr[i][pegname]->name;

  // iterate over all plugins
  map<string, map<int, PortInfo> > info;
  map<string, string>::const_iterator plug_iter;
  for (plug_iter = plugins.begin(); plug_iter != plugins.end(); ++plug_iter) {

    // query the plugin ports
    Variable port, index, symbol;
    qr = select(index, symbol)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("symbol"), symbol)
      .run(data);

    // put ports in a map so they get sorted
    map<int, PortInfo> ports;
    for (size_t i = 0; i < qr.size(); ++i) {
      int port_index = atoi(qr[i][index]->name.c_str());
      if (ports.find(port_index) != ports.end()) {
	cerr<<"Index "<<port_index<<" is used for more than one port"<<endl;
	return -1;
      }
      ports[port_index].name = qr[i][symbol]->name;
    }

    // query the context ports
    Variable cx_pred, context;
    qr = select(index, symbol)
      .where(plug_iter->first, cx_pred, context)
      .where(context, cx("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("symbol"), symbol)
      .filter(or_filter(cx_pred == cx("optionalContext"),
			cx_pred == cx("requiredContext")))
      .run(data);

    // put them in the map too
    for (size_t i = 0; i < qr.size(); ++i) {
      int port_index = atoi(qr[i][index]->name.c_str());
      if (ports.find(port_index) != ports.end()) {
	cerr<<"Index "<<port_index<<" is used for more than one port"<<endl;
	return -1;
      }
      ports[port_index].name = qr[i][symbol]->name;
    }

    // check that the port indices are OK
    map<int, PortInfo>::const_iterator iter;
    int next = 0;
    for (iter = ports.begin(); iter != ports.end(); ++iter) {
      if (iter->first != next) {
        cerr<<"There was no description of port "<<next
            <<" in plugin "<<plug_iter->first<<endl;
        return -1;
      }
      ++next;
    }

    // get min values
    Variable value;
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("minimum"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].min =
        atof(qr[i][value]->name.c_str());

    // get max values
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("maximum"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].max =
        atof(qr[i][value]->name.c_str());

    // get default values
    qr = select(index, value)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("default"), value)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i)
      ports[atoi(qr[i][index]->name.c_str())].default_value =
        atof(qr[i][value]->name.c_str());

    // get port properties
    Variable property;
    qr = select(index, property)
      .where(plug_iter->first, lv2("port"), port)
      .where(port, lv2("index"), index)
      .where(port, lv2("portProperty"), property)
      .run(data);
    for (unsigned i = 0; i < qr.size(); ++i) {
      if (qr[i][property]->name == lv2("toggled"))
        ports[atoi(qr[i][index]->name.c_str())].toggled = true;
      if (qr[i][property]->name == lv2("integer"))
        ports[atoi(qr[i][index]->name.c_str())].integer = true;
      if (qr[i][property]->name == pprops("logarithmic"))
        ports[atoi(qr[i][index]->name.c_str())].logarithmic = true;
    }

    info[plug_iter->first] = ports;

  }

  // write the header file
  string header_guard = argv[2];
  for (size_t i = 0; i < header_guard.size(); ++i) {
    char& c = header_guard[i];
    if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_')))
      header_guard[i] = '_';
  }
  ofstream fout(argv[2]);
  fout<<"#ifndef "<<header_guard<<endl
      <<"#define "<<header_guard<<endl<<endl<<endl;

  // define data structure
  fout<<"#ifndef PEG_STRUCT"<<endl
      <<"#define PEG_STRUCT"<<endl
      <<"typedef struct {"<<endl
      <<"  float min;"<<endl
      <<"  float max;"<<endl
      <<"  float default_value;"<<endl
      <<"  char toggled;"<<endl
      <<"  char integer;"<<endl
      <<"  char logarithmic;"<<endl
      <<"} peg_data_t;"<<endl
      <<"#endif"<<endl<<endl;

  map<string, map<int, PortInfo> >::const_iterator piter;
  for (piter = info.begin(); piter != info.end(); ++piter) {
    fout<<"/* "<<piter->first<<" */"<<endl<<endl;

    // write the URI
    fout<<"static const char "<<plugins[piter->first]<<"_uri[] = \""
        <<piter->first.substr(1, piter->first.size() - 2)<<"\";"<<endl<<endl;

    // write port labels
    fout<<"enum "<<plugins[piter->first]<<"_port_enum {"<<endl;
    map<int, PortInfo>::const_iterator iter;
    for (iter = piter->second.begin(); iter != piter->second.end(); ++iter)
      fout<<"  "<<plugins[piter->first]<<"_"<<iter->second.name<<","<<endl;
    fout<<"  "<<plugins[piter->first]<<"_n_ports"<<endl
        <<"};"<<endl<<endl;

    // write port info
    fout<<"static const peg_data_t "
        <<plugins[piter->first]<<"_ports[] = {"<<endl;
    for (iter = piter->second.begin(); iter != piter->second.end(); ++iter) {
      fout<<"  { "
          <<iter->second.min<<", "
          <<iter->second.max<<", "
          <<iter->second.default_value<<", "
          <<(iter->second.toggled ? "1" : "0")<<", "
          <<(iter->second.integer ? "1" : "0")<<", "
          <<(iter->second.logarithmic ? "1" : "0")<<" }, "<<endl;
    }
    fout<<"};"<<endl<<endl<<endl;

  }

  fout<<"#endif /* "<<header_guard<<" */"<<endl;

  return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2010-2012, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QtCore>
#include <QSysInfo>
#include <TWebApplication>
#include <TSystemGlobal>
#include "servermanager.h"
#include "processinfo.h"

#ifdef Q_OS_UNIX
# include <sys/utsname.h>
#endif

namespace TreeFrog {

#ifdef Q_OS_WIN
extern void WINAPI winServiceMain(DWORD argc, LPTSTR *argv);
#endif

enum CommandOption {
    Invalid = 0,
    EnvironmentSpecified,
    SocketSpecified,
    PrintVersion,
    PrintUsage,
    DaemonMode,
    WindowsServiceMode,
    SendSignal,
};

typedef QHash<int, QString> VersionHash;

#ifdef Q_OS_WIN
Q_GLOBAL_STATIC_WITH_INITIALIZER(VersionHash, winVersion,
{
    x->insert(QSysInfo::WV_XP,       "Windows XP");
    x->insert(QSysInfo::WV_2003,     "Windows Server 2003");
    x->insert(QSysInfo::WV_VISTA,    "Windows Vista or Windows Server 2008");
    x->insert(QSysInfo::WV_WINDOWS7, "Windows 7 or Windows Server 2008 R2");
})
#endif

#ifdef Q_OS_DARWIN
Q_GLOBAL_STATIC_WITH_INITIALIZER(VersionHash, macVersion,
{
    x->insert(QSysInfo::MV_10_3, "Mac OS X 10.3 Panther");
    x->insert(QSysInfo::MV_10_4, "Mac OS X 10.4 Tiger");
    x->insert(QSysInfo::MV_10_5, "Mac OS X 10.5 Leopard");
    x->insert(QSysInfo::MV_10_6, "Mac OS X 10.6 Snow Leopard");
#if QT_VERSION >= 0x040800
    x->insert(QSysInfo::MV_10_7, "Mac OS X 10.7 Lion");
    x->insert(QSysInfo::MV_10_8, "Mac OS X 10.8 Mountain Lion");
#endif
})
#endif

typedef QHash<QString, int> OptionHash;
Q_GLOBAL_STATIC_WITH_INITIALIZER(OptionHash, options,
{
    x->insert("-e", EnvironmentSpecified);
    x->insert("-s", SocketSpecified);
    x->insert("-v", PrintVersion);
    x->insert("-h", PrintUsage);
    x->insert("-d", DaemonMode);
    x->insert("-w", WindowsServiceMode);
    x->insert("-k", SendSignal);
})

static void usage()
{
    char text[] =
        "Usage: %1 [-d] [-e environment] [application-directory]\n"     \
        "Usage: %1 [-k stop|abort|restart] [application-directory]\n"   \
        "Options:\n"                                                    \
        "  -d              : run as a daemon process\n"                 \
        "  -e environment  : specify an environment of the database settings\n" \
        "  -k              : send signal to a manager process\n\n"      \
        "Type '%1 -h' to show this information.\n"                      \
        "Type '%1 -v' to show the program version.";

    QString cmd = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    puts(qPrintable(QString(text).arg(cmd)));
}

static bool checkArguments()
{
    for (QStringListIterator i(QCoreApplication::arguments()); i.hasNext(); ) {
        const QString &arg = i.next();
        if (arg.startsWith('-') && options()->value(arg, Invalid) == Invalid) {
            fprintf(stderr, "invalid argument\n");
            return false;
        }
    }
    return true;
}

static bool startDaemon()
{
    bool success;
    QStringList args = QCoreApplication::arguments();
    args.removeAll("-d");
#ifdef Q_OS_WIN
    PROCESS_INFORMATION pinfo;
    STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    success = CreateProcess(0, (wchar_t*)args.join(" ").utf16(),
                            0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT, 0,
                            (wchar_t*)QDir::currentPath().utf16(),
                            &startupInfo, &pinfo);
    if (success) {
        CloseHandle(pinfo.hThread);
        CloseHandle(pinfo.hProcess);
    }
#else
    args.removeFirst();  // Removes the program name
    success = QProcess::startDetached(QCoreApplication::applicationFilePath(), args, QDir::currentPath());
#endif

    return success;
}

static void writeStartupLog()
{
    tSystemInfo("TreeFrog Framework version " TF_VERSION_STR);

    QString qtversion = "Qt " QT_VERSION_STR;
#if defined(Q_OS_WIN)
    qtversion += QLatin1String(" / ") + winVersion()->value(QSysInfo::WindowsVersion, "Windows");
#elif defined(Q_OS_DARWIN)
    qtversion += QLatin1String(" / ") + macVersion()->value(QSysInfo::MacintoshVersion, "Mac OS X");
#elif defined(Q_OS_UNIX)
    struct utsname uts;
    if (uname(&uts) == 0) {
        qtversion += QString(" / %1 %2").arg(uts.sysname).arg(uts.release);
    }
#endif
    tSystemInfo("%s", qtversion.toLatin1().data());
}

static QString pidFilePath()
{
    QString base = QFileInfo(QCoreApplication::applicationFilePath()).baseName();
    return Tf::app()->tmpPath() + base + ".pid";
}

static qint64 readPidFileOfApplication()
{
    QFile pidf(pidFilePath());
    if (pidf.open(QIODevice::ReadOnly)) {
        qint64 pid = pidf.readLine(100).toLongLong();
        if (pid > 0) {
            return pid;
        }
    }
    return -1;
}

static qint64 runningApplicationPid()
{
    qint64 pid = readPidFileOfApplication();
    if (pid > 0) {
        QString name = ProcessInfo(pid).processName().toLower();
        if (name == "treefrog" || name == "treefrogd")
            return pid;
    }
    return -1;
}

static int killTreeFrogProcess(const QString &cmd)
{
    qint64 pid = runningApplicationPid();
    if (pid < 0) {
        printf("TreeFrog server not running\n");
        return 1;
    }

    ProcessInfo pi(pid);

    if (cmd == "stop") {  // stop command
        pi.terminate();
        if (pi.waitForTerminated()) {
            printf("TreeFrog application servers shutdown completed\n");
        } else {
            fprintf(stderr, "TreeFrog application servers shutdown failed\n");
        }

    } else if (cmd == "abort") {  // abort command
        pi.kill();
        tSystemInfo("Killed TreeFrog manager process  pid:%ld", (long)pid);
        ::unlink(pidFilePath().toLatin1().data());

        // kill all 'tadpole' processes
#if defined(Q_OS_WIN) && !defined(TF_NO_DEBUG)
        ProcessInfo::killProcesses("tadpoled");
#else
        ProcessInfo::killProcesses("tadpole");
#endif
        tSystemInfo("Killed TreeFrog application server processes");
        printf("Killed TreeFrog application server processes\n");

    } else if (cmd == "restart") {  // restart command
        pi.restart();
        printf("Sent a restart request\n");

    } else {
        usage();
        return 1;
    }
    return 0;
}

int managerMain(int argc, char *argv[])
{
    TWebApplication app(argc, argv);

    // Creates the semaphore for system log
    QSystemSemaphore semaphore("TreeFrogSystemLog", 1, QSystemSemaphore::Create);
    tSetupSystemLoggers();

#if defined(Q_OS_UNIX)
    app.watchUnixSignal(SIGTERM);
    app.watchUnixSignal(SIGINT);
    app.watchUnixSignal(SIGHUP);
#elif defined(Q_OS_WIN)
    app.watchConsoleSignal();
#endif

    // Sets codec
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec);

    if (!checkArguments()) {
        return 1;
    }

    bool daemonMode = false;
    QString signalCmd;

    QStringList args = QCoreApplication::arguments();
    args.removeFirst();
    for (QStringListIterator i(args); i.hasNext(); ) {
        const QString &arg = i.next();
        int cmd = options()->value(arg, Invalid);
        switch (cmd) {
        case PrintVersion:
            printf("%s version " TF_VERSION_STR " (r%d) (built on %s)\n", qPrintable(QFileInfo(argv[0]).baseName()), TF_SRC_REVISION, __DATE__);
            return 0;
            break;

        case PrintUsage:
            usage();
            return 0;
            break;

        case DaemonMode:
            daemonMode = true;
            break;

        case WindowsServiceMode:
            // ignore
            break;

        case SendSignal:
            signalCmd = i.next(); // assign a command
            break;

        default:
            // do nothing
            break;
        }
    }

    if (!app.appSettingsFileExists()) {
        fprintf(stderr, "INI file not found [%s]\n\n", qPrintable(app.appSettingsFilePath()));
        return 1;
    }

    if (!signalCmd.isEmpty()) {
        return killTreeFrogProcess(signalCmd);
    }

    // Check TreeFrog processes are running
    qint64 pid = runningApplicationPid();
    if (pid > 0) {
        fprintf(stderr, "Already running  pid:%ld\n", (long)pid);
        return 1;
    }

    if (!app.isValidDatabaseSettings()) {
        tSystemError("Database settings not found  [environment: %s]", qPrintable(app.databaseEnvironment()));
        fprintf(stderr, "database settings not found  [environment: %s]\n\n", qPrintable(app.databaseEnvironment()));
        usage();
        return 1;
    }

    // Check a port number
    quint16 listenPort = 0;
    QString svrname = app.appSettings().value("ListenPort").toString();
    if (svrname.startsWith("unix:", Qt::CaseInsensitive)) {
        svrname.remove(0, 5);
    } else {
        int port = svrname.toInt();
        if (port <= 0 || port > USHRT_MAX) {
            tSystemError("Invalid port number: %d", port);
            return 1;
        }
        listenPort = port;
        svrname.clear();
    }

    // start daemon process
    if (daemonMode) {
        if ( !startDaemon() ) {
            fprintf(stderr, "Failed to create process\n\n");
            return 1;
        }
        return 0;
    }

    int ret = 0;
    QFile pidfile;

    for (;;) {
        ServerManager *manager = 0;
        switch ( app.multiProcessingModule() ) {
        case TWebApplication::Thread: {
            manager = new ServerManager(1, 1, 0, &app);
            break; }

        case TWebApplication::Prefork: {
            int max = app.appSettings().value("MPM.prefork.MaxServers").toInt();
            int min = app.appSettings().value("MPM.prefork.MinServers").toInt();
            int spare = app.appSettings().value("MPM.prefork.SpareServers").toInt();
            manager = new ServerManager(max, min, spare, &app);
            break; }

        default:
            tSystemError("Invalid MPM specified");
            return 1;
        }

        // Startup
        writeStartupLog();
        bool started;
        if (listenPort > 0) {
            // TCP/IP
            started = manager->start(QHostAddress::Any, listenPort);
        } else {
            // UNIX domain
            started = manager->start(svrname);
        }

        if (!started) {
            tSystemError("TreeFrog application server startup failed");
            fprintf(stderr, "TreeFrog application server startup failed\n\n");
            return 1;
        }

        // tmp directory
        QDir tmpDir(app.tmpPath());
        if (!tmpDir.exists()) {
            tmpDir.mkpath(".");
        }

        // Writes the PID
        pidfile.setFileName(pidFilePath());
        if (pidfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            pid = QCoreApplication::applicationPid();
            pidfile.write( QString::number(pid).toLatin1() );
            pidfile.close();
        } else {
            tSystemError("File open failed: %s", qPrintable(pidfile.fileName()));
        }

        ret = app.exec();
        tSystemDebug("tfmanager returnCode:%d", ret);
        manager->stop();

        if (ret == 1) {  // means SIGHUP
            tSystemDebug("Restarts TreeFrog application servers");
            //continue;
        } else {
            break;
        }
    }

    if (!svrname.isEmpty()) {  // UNIX domain file
        QFile(svrname).remove();
    }
    pidfile.remove();  // Removes the PID file
    return 0;
}

} // namespace TreeFrog

int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-w") == 0) {
            // Windows service mode
            SERVICE_TABLE_ENTRY entry[] = { { (LPTSTR)TEXT(""), TreeFrog::winServiceMain }, { 0, 0 } };
            StartServiceCtrlDispatcher(entry);
            return 0;
        }
    }
#endif
    return TreeFrog::managerMain(argc, argv);
}
<commit_msg>changed CRLF -> LF.<commit_after>/* Copyright (c) 2010-2012, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QtCore>
#include <QSysInfo>
#include <TWebApplication>
#include <TSystemGlobal>
#include "servermanager.h"
#include "processinfo.h"

#ifdef Q_OS_UNIX
# include <sys/utsname.h>
#endif

namespace TreeFrog {

#ifdef Q_OS_WIN
extern void WINAPI winServiceMain(DWORD argc, LPTSTR *argv);
#endif

enum CommandOption {
    Invalid = 0,
    EnvironmentSpecified,
    SocketSpecified,
    PrintVersion,
    PrintUsage,
    DaemonMode,
    WindowsServiceMode,
    SendSignal,
};

typedef QHash<int, QString> VersionHash;

#ifdef Q_OS_WIN
Q_GLOBAL_STATIC_WITH_INITIALIZER(VersionHash, winVersion,
{
    x->insert(QSysInfo::WV_XP,       "Windows XP");
    x->insert(QSysInfo::WV_2003,     "Windows Server 2003");
    x->insert(QSysInfo::WV_VISTA,    "Windows Vista or Windows Server 2008");
    x->insert(QSysInfo::WV_WINDOWS7, "Windows 7 or Windows Server 2008 R2");
})
#endif

#ifdef Q_OS_DARWIN
Q_GLOBAL_STATIC_WITH_INITIALIZER(VersionHash, macVersion,
{
    x->insert(QSysInfo::MV_10_3, "Mac OS X 10.3 Panther");
    x->insert(QSysInfo::MV_10_4, "Mac OS X 10.4 Tiger");
    x->insert(QSysInfo::MV_10_5, "Mac OS X 10.5 Leopard");
    x->insert(QSysInfo::MV_10_6, "Mac OS X 10.6 Snow Leopard");
#if QT_VERSION >= 0x040800
    x->insert(QSysInfo::MV_10_7, "Mac OS X 10.7 Lion");
    x->insert(QSysInfo::MV_10_8, "Mac OS X 10.8 Mountain Lion");
#endif
})
#endif

typedef QHash<QString, int> OptionHash;
Q_GLOBAL_STATIC_WITH_INITIALIZER(OptionHash, options,
{
    x->insert("-e", EnvironmentSpecified);
    x->insert("-s", SocketSpecified);
    x->insert("-v", PrintVersion);
    x->insert("-h", PrintUsage);
    x->insert("-d", DaemonMode);
    x->insert("-w", WindowsServiceMode);
    x->insert("-k", SendSignal);
})

static void usage()
{
    char text[] =
        "Usage: %1 [-d] [-e environment] [application-directory]\n"     \
        "Usage: %1 [-k stop|abort|restart] [application-directory]\n"   \
        "Options:\n"                                                    \
        "  -d              : run as a daemon process\n"                 \
        "  -e environment  : specify an environment of the database settings\n" \
        "  -k              : send signal to a manager process\n\n"      \
        "Type '%1 -h' to show this information.\n"                      \
        "Type '%1 -v' to show the program version.";

    QString cmd = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    puts(qPrintable(QString(text).arg(cmd)));
}

static bool checkArguments()
{
    for (QStringListIterator i(QCoreApplication::arguments()); i.hasNext(); ) {
        const QString &arg = i.next();
        if (arg.startsWith('-') && options()->value(arg, Invalid) == Invalid) {
            fprintf(stderr, "invalid argument\n");
            return false;
        }
    }
    return true;
}

static bool startDaemon()
{
    bool success;
    QStringList args = QCoreApplication::arguments();
    args.removeAll("-d");
#ifdef Q_OS_WIN
    PROCESS_INFORMATION pinfo;
    STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    success = CreateProcess(0, (wchar_t*)args.join(" ").utf16(),
                            0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT, 0,
                            (wchar_t*)QDir::currentPath().utf16(),
                            &startupInfo, &pinfo);
    if (success) {
        CloseHandle(pinfo.hThread);
        CloseHandle(pinfo.hProcess);
    }
#else
    args.removeFirst();  // Removes the program name
    success = QProcess::startDetached(QCoreApplication::applicationFilePath(), args, QDir::currentPath());
#endif

    return success;
}

static void writeStartupLog()
{
    tSystemInfo("TreeFrog Framework version " TF_VERSION_STR);

    QString qtversion = "Qt " QT_VERSION_STR;
#if defined(Q_OS_WIN)
    qtversion += QLatin1String(" / ") + winVersion()->value(QSysInfo::WindowsVersion, "Windows");
#elif defined(Q_OS_DARWIN)
    qtversion += QLatin1String(" / ") + macVersion()->value(QSysInfo::MacintoshVersion, "Mac OS X");
#elif defined(Q_OS_UNIX)
    struct utsname uts;
    if (uname(&uts) == 0) {
        qtversion += QString(" / %1 %2").arg(uts.sysname).arg(uts.release);
    }
#endif
    tSystemInfo("%s", qtversion.toLatin1().data());
}

static QString pidFilePath()
{
    QString base = QFileInfo(QCoreApplication::applicationFilePath()).baseName();
    return Tf::app()->tmpPath() + base + ".pid";
}

static qint64 readPidFileOfApplication()
{
    QFile pidf(pidFilePath());
    if (pidf.open(QIODevice::ReadOnly)) {
        qint64 pid = pidf.readLine(100).toLongLong();
        if (pid > 0) {
            return pid;
        }
    }
    return -1;
}

static qint64 runningApplicationPid()
{
    qint64 pid = readPidFileOfApplication();
    if (pid > 0) {
        QString name = ProcessInfo(pid).processName().toLower();
        if (name == "treefrog" || name == "treefrogd")
            return pid;
    }
    return -1;
}

static int killTreeFrogProcess(const QString &cmd)
{
    qint64 pid = runningApplicationPid();
    if (pid < 0) {
        printf("TreeFrog server not running\n");
        return 1;
    }

    ProcessInfo pi(pid);

    if (cmd == "stop") {  // stop command
        pi.terminate();
        if (pi.waitForTerminated()) {
            printf("TreeFrog application servers shutdown completed\n");
        } else {
            fprintf(stderr, "TreeFrog application servers shutdown failed\n");
        }

    } else if (cmd == "abort") {  // abort command
        pi.kill();
        tSystemInfo("Killed TreeFrog manager process  pid:%ld", (long)pid);
        ::unlink(pidFilePath().toLatin1().data());

        // kill all 'tadpole' processes
#if defined(Q_OS_WIN) && !defined(TF_NO_DEBUG)
        ProcessInfo::killProcesses("tadpoled");
#else
        ProcessInfo::killProcesses("tadpole");
#endif
        tSystemInfo("Killed TreeFrog application server processes");
        printf("Killed TreeFrog application server processes\n");

    } else if (cmd == "restart") {  // restart command
        pi.restart();
        printf("Sent a restart request\n");

    } else {
        usage();
        return 1;
    }
    return 0;
}

int managerMain(int argc, char *argv[])
{
    TWebApplication app(argc, argv);

    // Creates the semaphore for system log
    QSystemSemaphore semaphore("TreeFrogSystemLog", 1, QSystemSemaphore::Create);
    tSetupSystemLoggers();

#if defined(Q_OS_UNIX)
    app.watchUnixSignal(SIGTERM);
    app.watchUnixSignal(SIGINT);
    app.watchUnixSignal(SIGHUP);
#elif defined(Q_OS_WIN)
    app.watchConsoleSignal();
#endif

    // Sets codec
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec);

    if (!checkArguments()) {
        return 1;
    }

    bool daemonMode = false;
    QString signalCmd;

    QStringList args = QCoreApplication::arguments();
    args.removeFirst();
    for (QStringListIterator i(args); i.hasNext(); ) {
        const QString &arg = i.next();
        int cmd = options()->value(arg, Invalid);
        switch (cmd) {
        case PrintVersion:
            printf("%s version " TF_VERSION_STR " (r%d) (built on %s)\n", qPrintable(QFileInfo(argv[0]).baseName()), TF_SRC_REVISION, __DATE__);
            return 0;
            break;

        case PrintUsage:
            usage();
            return 0;
            break;

        case DaemonMode:
            daemonMode = true;
            break;

        case WindowsServiceMode:
            // ignore
            break;

        case SendSignal:
            signalCmd = i.next(); // assign a command
            break;

        default:
            // do nothing
            break;
        }
    }

    if (!app.appSettingsFileExists()) {
        fprintf(stderr, "INI file not found [%s]\n\n", qPrintable(app.appSettingsFilePath()));
        return 1;
    }

    if (!signalCmd.isEmpty()) {
        return killTreeFrogProcess(signalCmd);
    }

    // Check TreeFrog processes are running
    qint64 pid = runningApplicationPid();
    if (pid > 0) {
        fprintf(stderr, "Already running  pid:%ld\n", (long)pid);
        return 1;
    }

    if (!app.isValidDatabaseSettings()) {
        tSystemError("Database settings not found  [environment: %s]", qPrintable(app.databaseEnvironment()));
        fprintf(stderr, "database settings not found  [environment: %s]\n\n", qPrintable(app.databaseEnvironment()));
        usage();
        return 1;
    }

    // Check a port number
    quint16 listenPort = 0;
    QString svrname = app.appSettings().value("ListenPort").toString();
    if (svrname.startsWith("unix:", Qt::CaseInsensitive)) {
        svrname.remove(0, 5);
    } else {
        int port = svrname.toInt();
        if (port <= 0 || port > USHRT_MAX) {
            tSystemError("Invalid port number: %d", port);
            return 1;
        }
        listenPort = port;
        svrname.clear();
    }

    // start daemon process
    if (daemonMode) {
        if ( !startDaemon() ) {
            fprintf(stderr, "Failed to create process\n\n");
            return 1;
        }
        return 0;
    }

    int ret = 0;
    QFile pidfile;

    for (;;) {
        ServerManager *manager = 0;
        switch ( app.multiProcessingModule() ) {
        case TWebApplication::Thread: {
            manager = new ServerManager(1, 1, 0, &app);
            break; }

        case TWebApplication::Prefork: {
            int max = app.appSettings().value("MPM.prefork.MaxServers").toInt();
            int min = app.appSettings().value("MPM.prefork.MinServers").toInt();
            int spare = app.appSettings().value("MPM.prefork.SpareServers").toInt();
            manager = new ServerManager(max, min, spare, &app);
            break; }

        default:
            tSystemError("Invalid MPM specified");
            return 1;
        }

        // Startup
        writeStartupLog();
        bool started;
        if (listenPort > 0) {
            // TCP/IP
            started = manager->start(QHostAddress::Any, listenPort);
        } else {
            // UNIX domain
            started = manager->start(svrname);
        }

        if (!started) {
            tSystemError("TreeFrog application server startup failed");
            fprintf(stderr, "TreeFrog application server startup failed\n\n");
            return 1;
        }

        // tmp directory
        QDir tmpDir(app.tmpPath());
        if (!tmpDir.exists()) {
            tmpDir.mkpath(".");
        }

        // Writes the PID
        pidfile.setFileName(pidFilePath());
        if (pidfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            pid = QCoreApplication::applicationPid();
            pidfile.write( QString::number(pid).toLatin1() );
            pidfile.close();
        } else {
            tSystemError("File open failed: %s", qPrintable(pidfile.fileName()));
        }

        ret = app.exec();
        tSystemDebug("tfmanager returnCode:%d", ret);
        manager->stop();

        if (ret == 1) {  // means SIGHUP
            tSystemDebug("Restarts TreeFrog application servers");
            //continue;
        } else {
            break;
        }
    }

    if (!svrname.isEmpty()) {  // UNIX domain file
        QFile(svrname).remove();
    }
    pidfile.remove();  // Removes the PID file
    return 0;
}

} // namespace TreeFrog

int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-w") == 0) {
            // Windows service mode
            SERVICE_TABLE_ENTRY entry[] = { { (LPTSTR)TEXT(""), TreeFrog::winServiceMain }, { 0, 0 } };
            StartServiceCtrlDispatcher(entry);
            return 0;
        }
    }
#endif
    return TreeFrog::managerMain(argc, argv);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *   Copyright (C) 2011-2013 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of Teapotnet.                                     *
 *                                                                       *
 *   Teapotnet is free software: you can redistribute it and/or modify   *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   Teapotnet is distributed in the hope that it will be useful, but    *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the        *
 *   GNU Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with Teapotnet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#ifndef TPN_INCLUDE_H
#define TPN_INCLUDE_H

//#define DEBUG			1
#define APPNAME			"Teapotnet"
#define APPVERSION		"0.10.1"
#define APPMAGIC		 0x54504f54 // "TPOT"
#define APPAUTHOR		"Paul-Louis Ageneau"
#define APPLINK			"https://teapotnet.org/"
#define SOURCELINK		"https://teapotnet.org/source"
#define HELPLINK		"https://teapotnet.org/help"
#define DOWNLOADURL		"https://teapotnet.org/download"
#define BUGSLINK		"mailto:bugs@teapotnet.org"

#include "pla/include.hpp"
#include "pla/string.hpp"
#include "pla/binarystring.hpp"

using namespace pla;

namespace tpn
{
	typedef BinaryString Identifier;
	typedef std::pair<Identifier, Identifier> IdentifierPair;
}

#endif

<commit_msg>Removed useless debug flag, version 0.10.1 ready<commit_after>/*************************************************************************
 *   Copyright (C) 2011-2013 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of Teapotnet.                                     *
 *                                                                       *
 *   Teapotnet is free software: you can redistribute it and/or modify   *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   Teapotnet is distributed in the hope that it will be useful, but    *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the        *
 *   GNU Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with Teapotnet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#ifndef TPN_INCLUDE_H
#define TPN_INCLUDE_H

#define APPNAME			"Teapotnet"
#define APPVERSION		"0.10.1"
#define APPMAGIC		 0x54504f54 // "TPOT"
#define APPAUTHOR		"Paul-Louis Ageneau"
#define APPLINK			"https://teapotnet.org/"
#define SOURCELINK		"https://teapotnet.org/source"
#define HELPLINK		"https://teapotnet.org/help"
#define DOWNLOADURL		"https://teapotnet.org/download"
#define BUGSLINK		"mailto:bugs@teapotnet.org"

#include "pla/include.hpp"
#include "pla/string.hpp"
#include "pla/binarystring.hpp"

using namespace pla;

namespace tpn
{
	typedef BinaryString Identifier;
	typedef std::pair<Identifier, Identifier> IdentifierPair;
}

#endif

<|endoftext|>


<commit_before>#include "application.h"
#include "TimeAlarms.h"
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#undef now()

bool isDST(int dayOfMonth, int month, int dayOfWeek, String rule);
void refreshDisplayTime();

Adafruit_7segment display = Adafruit_7segment();

const int ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
unsigned long lastSync = millis();
int timeZone = -8; //UTC time zone offset TODO: Must be set/recieved from web/cloud
String DSTRule = "US"; //US, EU, or OFF TODO: Must be set/recieved from web/cloud
int DSTJumpHour; //When DST takes effect
int hourFormat = 12; //12 or 24 TODO: Must be set/recieved from web/cloud

void setup() {
  if(DSTRule == "US") {
    DSTJumpHour = 2;
  } else if(DSTRule == "EU") {
    DSTJumpHour = 1+timeZone;
  } else {
    DSTJumpHour = 0;
  }

  //Set the proper time zone according to DST status
  Time.zone(isDST(Time.day(), Time.month(), Time.weekday(), DSTRule) ? timeZone+1 : timeZone);

  //Setup the 7-segment display
  display.begin(0x70);
  display.setBrightness(15); //TODO: adjust brightness to optimize for veneer/time
}

void loop() {
  //Request time synchronization from the Spark Cloud every 24 hours
  if (millis() - lastSync > ONE_DAY_MILLIS) {
    //Spark.syncTime();
    lastSync = millis();
  }

  //Update time zone at DSTJumpHour incase DST is now in effect
  if(Time.hour() == DSTJumpHour && Time.minute() == 0) {
    Time.zone(isDST(Time.day(), Time.month(), Time.weekday(), DSTRule) ? timeZone+1 : timeZone);
  }

  refreshDisplayTime();

  //Delay for checking alarms/timers
  Alarm.delay(500);
}

//Return true if DST is currently observed
bool isDST(int dayOfMonth, int month, int dayOfWeek, String rule) {
  if(rule == "US") {
    //Month quick check
    if (month < 3 || month > 11) {
      return false;
    } else if (month > 3 && month < 11) {
      return true;
    }
    //The US observes DST from the first Sunday of March
    //The US observes DST until the first Sunday of November
    int previousSunday = dayOfMonth - dayOfWeek + 1;
    if (month == 3) {
      return previousSunday >= 1;
    } else {
      return previousSunday <= 0;
    }
  } else if(rule == "EU") {
    //Month quick check
    if (month < 3 || month > 10) {
      return false;
    } else if (month > 3 && month < 10) {
      return true;
    }
    //The EU observes DST from the last Sunday of March
    //The EU observes DST until the last Sunday of November
    int previousSunday = dayOfMonth - dayOfWeek + 1;
    if(month == 3) {
      if(previousSunday+7>31) {
        return true;
      } else {
        return false;
      }
    } else {
      if(previousSunday+7>31) {
        return false;
      } else {
        return true;
      }
    }
  } else {
    return false;
  }
}

//display the current time on the 7-segment display
void refreshDisplayTime() {
  unsigned long currentTime = Time.now();
  int minute = Time.minute(currentTime);
  int hour;

  if(hourFormat == 12) {
    hour = Time.hourFormat12(currentTime);
  } else {
    hour = Time.hour(currentTime);
  }

  display.drawColon(true);
  if(hour/10 != 0) {
    display.writeDigitNum(0, hour/10);
  }
  display.writeDigitNum(1, hour%10);
  display.writeDigitNum(2, minute/10);
  display.writeDigitNum(3, minute%10);
  display.writeDisplay();
}
<commit_msg>Fixes 7-Segment Display Issues<commit_after>#include "application.h"
#include "TimeAlarms.h"
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#undef now()

bool isDST(int dayOfMonth, int month, int dayOfWeek, String rule);
void refreshDisplayTime();

Adafruit_7segment display = Adafruit_7segment();

const int ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
unsigned long lastSync = millis();
int timeZone = -8; //UTC time zone offset TODO: Must be set/recieved from web/cloud
String DSTRule = "US"; //US, EU, or OFF TODO: Must be set/recieved from web/cloud
int DSTJumpHour; //When DST takes effect
int hourFormat = 12; //12 or 24 TODO: Must be set/recieved from web/cloud

void setup() {
  if(DSTRule == "US") {
    DSTJumpHour = 2;
  } else if(DSTRule == "EU") {
    DSTJumpHour = 1+timeZone;
  } else {
    DSTJumpHour = 0;
  }

  //Set the proper time zone according to DST status
  Time.zone(isDST(Time.day(), Time.month(), Time.weekday(), DSTRule) ? timeZone+1 : timeZone);

  //Setup the 7-segment display
  display.begin(0x70);
  display.setBrightness(15); //TODO: adjust brightness to optimize for veneer/time
}

void loop() {
  //Request time synchronization from the Spark Cloud every 24 hours
  if (millis() - lastSync > ONE_DAY_MILLIS) {
    Spark.syncTime();
    lastSync = millis();
  }

  //Update time zone at DSTJumpHour incase DST is now in effect
  if(Time.hour() == DSTJumpHour && Time.minute() == 0) {
    Time.zone(isDST(Time.day(), Time.month(), Time.weekday(), DSTRule) ? timeZone+1 : timeZone);
  }

  refreshDisplayTime();

  //Delay for checking alarms/timers
  Alarm.delay(500);
}

//Return true if DST is currently observed
bool isDST(int dayOfMonth, int month, int dayOfWeek, String rule) {
  if(rule == "US") {
    //Month quick check
    if (month < 3 || month > 11) {
      return false;
    } else if (month > 3 && month < 11) {
      return true;
    }
    //The US observes DST from the first Sunday of March
    //The US observes DST until the first Sunday of November
    int previousSunday = dayOfMonth - dayOfWeek + 1;
    if (month == 3) {
      return previousSunday >= 1;
    } else {
      return previousSunday <= 0;
    }
  } else if(rule == "EU") {
    //Month quick check
    if (month < 3 || month > 10) {
      return false;
    } else if (month > 3 && month < 10) {
      return true;
    }
    //The EU observes DST from the last Sunday of March
    //The EU observes DST until the last Sunday of November
    int previousSunday = dayOfMonth - dayOfWeek + 1;
    if(month == 3) {
      if(previousSunday+7>31) {
        return true;
      } else {
        return false;
      }
    } else {
      if(previousSunday+7>31) {
        return false;
      } else {
        return true;
      }
    }
  } else {
    return false;
  }
}

//display the current time on the 7-segment display
void refreshDisplayTime() {
  unsigned long currentTime = Time.now();
  int minute = Time.minute(currentTime);
  int hour;
  int digits;

  if(hourFormat == 12) {
    hour = Time.hourFormat12(currentTime);
  } else {
    hour = Time.hour(currentTime);
  }

  digits = hour/10*1000 + hour%10*100 + minute/10*10 + minute%10;

  display.print(digits);
  display.drawColon(true);
  display.writeDisplay();
}
<|endoftext|>


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

#include <folly/Executor.h>

#include <stdexcept>

#include <glog/logging.h>

#include <folly/ExceptionString.h>
#include <folly/Portability.h>
#include <folly/lang/Exception.h>

namespace folly {

void Executor::invokeCatchingExnsLog(
    char const* const prefix, std::exception const* const ex) {
  auto const message = " threw unhandled ";
  if (ex) {
    LOG(ERROR) << prefix << message << exceptionStr(*ex);
  } else {
    auto ep = std::current_exception();
    LOG(ERROR) << prefix << message << exceptionStr(ep);
  }
}

void Executor::addWithPriority(Func, int8_t /* priority */) {
  throw std::runtime_error(
      "addWithPriority() is not implemented for this Executor");
}

bool Executor::keepAliveAcquire() noexcept {
  return false;
}

void Executor::keepAliveRelease() noexcept {
  LOG(FATAL) << __func__ << "() should not be called for folly::Executor types "
             << "which do not override keepAliveAcquire()";
}

// Base case of permitting with no termination to avoid nullptr tests
static ExecutorBlockingList emptyList{nullptr, {false, false, {}}};

#if defined(FOLLY_TLS)

extern constexpr bool const executor_blocking_list_enabled = true;
thread_local ExecutorBlockingList* executor_blocking_list = &emptyList;

#else

extern constexpr bool const executor_blocking_list_enabled = false;
ExecutorBlockingList* executor_blocking_list = &emptyList;

#endif

Optional<ExecutorBlockingContext> getExecutorBlockingContext() noexcept {
  return //
      !executor_blocking_list->curr.forbid ? none : //
      make_optional(executor_blocking_list->curr);
}

ExecutorBlockingGuard::ExecutorBlockingGuard(PermitTag) noexcept
    : list_{*executor_blocking_list} {
  if (executor_blocking_list_enabled) {
    list_.prev = executor_blocking_list;
    list_.curr.forbid = false;
    list_.curr.name = {};
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::ExecutorBlockingGuard(
    TrackTag, StringPiece name) noexcept
    : list_{*executor_blocking_list} {
  if (executor_blocking_list_enabled) {
    list_.prev = executor_blocking_list;
    list_.curr.forbid = true;
    list_.curr.name = name;
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::ExecutorBlockingGuard(
    ProhibitTag, StringPiece name) noexcept
    : list_{*executor_blocking_list} {
  if (executor_blocking_list_enabled) {
    list_.prev = executor_blocking_list;
    list_.curr.forbid = true;
    list_.curr.allowTerminationOnBlocking = true;
    list_.curr.name = name;
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::~ExecutorBlockingGuard() {
  if (executor_blocking_list_enabled) {
    if (executor_blocking_list != &list_) {
      terminate_with<std::logic_error>("dtor mismatch");
    }
    executor_blocking_list = list_.prev;
  }
}

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

#include <folly/Executor.h>

#include <stdexcept>

#include <glog/logging.h>

#include <folly/ExceptionString.h>
#include <folly/Portability.h>
#include <folly/lang/Exception.h>

namespace folly {

void Executor::invokeCatchingExnsLog(
    char const* const prefix, std::exception const* const ex) {
  auto const message = " threw unhandled ";
  if (ex) {
    LOG(ERROR) << prefix << message << exceptionStr(*ex);
  } else {
    auto ep = std::current_exception();
    LOG(ERROR) << prefix << message << exceptionStr(ep);
  }
}

void Executor::addWithPriority(Func, int8_t /* priority */) {
  throw std::runtime_error(
      "addWithPriority() is not implemented for this Executor");
}

bool Executor::keepAliveAcquire() noexcept {
  return false;
}

void Executor::keepAliveRelease() noexcept {
  LOG(FATAL) << __func__ << "() should not be called for folly::Executor types "
             << "which do not override keepAliveAcquire()";
}

// Base case of permitting with no termination to avoid nullptr tests
static ExecutorBlockingList emptyList{nullptr, {false, false, {}}};

thread_local ExecutorBlockingList* executor_blocking_list = &emptyList;

Optional<ExecutorBlockingContext> getExecutorBlockingContext() noexcept {
  return //
      kIsMobile || !executor_blocking_list->curr.forbid ? none : //
      make_optional(executor_blocking_list->curr);
}

ExecutorBlockingGuard::ExecutorBlockingGuard(PermitTag) noexcept {
  if (!kIsMobile) {
    list_ = *executor_blocking_list;
    list_.prev = executor_blocking_list;
    list_.curr.forbid = false;
    list_.curr.name = {};
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::ExecutorBlockingGuard(
    TrackTag, StringPiece name) noexcept {
  if (!kIsMobile) {
    list_ = *executor_blocking_list;
    list_.prev = executor_blocking_list;
    list_.curr.forbid = true;
    list_.curr.name = name;
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::ExecutorBlockingGuard(
    ProhibitTag, StringPiece name) noexcept {
  if (!kIsMobile) {
    list_ = *executor_blocking_list;
    list_.prev = executor_blocking_list;
    list_.curr.forbid = true;
    list_.curr.allowTerminationOnBlocking = true;
    list_.curr.name = name;
    executor_blocking_list = &list_;
  }
}

ExecutorBlockingGuard::~ExecutorBlockingGuard() {
  if (!kIsMobile) {
    if (executor_blocking_list != &list_) {
      terminate_with<std::logic_error>("dtor mismatch");
    }
    executor_blocking_list = list_.prev;
  }
}

} // namespace folly
<|endoftext|>


<commit_before>#include "forth_common.th"

.global INBUF .global INPOS .global INLEN
.L_INBUF_before:
INBUF:
#if TEST_LOOKUP
    .word 5 .utf32 "words"
#endif
       .word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.L_INBUF_after:
INPOS: .word 0
INLEN: .word .L_INBUF_after - .L_INBUF_before

.set link, 0
head(start,start): .word
    @NOOP

top: .word
#if TEST_LOOKUP
    @TIB, @TO_IN, @FETCH, @ADD,
    @FIND,
    @LITERAL, @find_word, @RELOC, @SET_IP,
#endif

    @TIB, @DUP, @TO_IN, @SWAP, @SUB,        // tib used
    @IN_LEN, @SWAP, @SUB,                   // tib left
    @ACCEPT                                 // count

strip_spaces: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FETCHR, @BL, @CMP_EQ,
    IFNOT0(advance,done_stripping)
advance: .word
    @LITERAL, 1, @CHARS, @TO_IN, @ADDMEM,
    @LITERAL, @strip_spaces, @RELOC, @SET_IP

done_stripping: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FETCHR, @EMIT,
    @EXIT
find_word: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FIND,
    IFNOT0(found,notfound)
notfound: .word
    // TODO complain
    @LITERAL, 'X', @EMIT,
    @LITERAL, '\n', @EMIT,
    @ABORT

found: .word
    //@DROP, // drop flag for now, assume found
    @DUP,         @EMIT_UNSIGNED, @BL, @EMIT, @LITERAL, ':', @EMIT, @BL, @EMIT, @CR,
    @DUP, @RELOC, @EMIT_UNSIGNED, @BL, @EMIT, @LITERAL, ':', @EMIT, @BL, @EMIT, @CR,
    @RELOC, @EXECUTE,
	//@EXIT,

    // example of a computed branch
    @LITERAL, 0,
    IFNOT0(top,bottom)
bottom: .word
    @NOOP

wordstart: .word
    @KEY,
    @DUP, @LITERAL, '\n', @CMP_EQ,
    IFNOT0(linedone,checkspace)
checkspace: .word
    @DUP, @BL, @CMP_EQ,
    IFNOT0(worddone,regular),
    @NOOP
regular: .word
    @EMIT,
    @LITERAL, @wordstart, @RELOC, @SET_IP
worddone: .word
    @DROP,
    @CR,
    @LITERAL, @wordstart, @RELOC, @SET_IP
linedone: .word
    @CR,
    @EXIT

//------------------------------------------------------------------------------
// TODO explicit echoing
head(ACCEPT,ACCEPT): .word                      // ( c-addr +n1 -- +n2 )
    @ENTER,

    @OVER, @SWAP                                // C-addr c-addr n1
L_ACCEPT_key: .word
    @KEY,                                       // C-addr c-addr n1 c
    @DUP, @LITERAL, '\n', @CMP_EQ,              // C-addr c-addr n1 c flag
    IFNOT0(L_ACCEPT_exit,L_ACCEPT_regular)
L_ACCEPT_regular: .word
    @ROT,                                       // C-addr n1 c c-addr
    @TUCK,                                      // C-addr n1 c-addr c c-addr
    @STOCHR,                                    // C-addr n1 c-addr
    @LITERAL, 1, @CHARS, @ADD,                  // C-addr n1 c-addr++
    @SWAP,                                      // C-addr c-addr n1
    @SUB_1,                                     // C-addr c-addr n1--
    @DUP, @EQZ,                                 // C-addr c-addr n1 flag
    IFNOT0(L_ACCEPT_done,L_ACCEPT_key)
L_ACCEPT_exit: .word
    @DROP                                       // C-addr c-addr n1
L_ACCEPT_done: .word
    @DROP,                                      // C-addr c-addr
    @SWAP, @SUB,                                // n2
    @EXIT

//------------------------------------------------------------------------------

head(IN_LEN,IN_LEN): .word
    @ENTER,
    @LITERAL, @INLEN, @RELOC, @FETCH,
    @EXIT

head(MASK4BITS,MASK4BITS): .word
    @ENTER,
    @LITERAL, 15, @AND,
    @EXIT

head(HEXTABLE,HEXTABLE): .word
    @ENTER,
    @LITERAL, @hexchars, @RELOC,
    @EXIT

hexchars:
    .word '0','1','2','3','4','5','6','7',
          '8','9','A','B','C','D','E','F'

head(TOHEXCHAR,>HEXCHAR): .word
    @ENTER,
    @HEXTABLE, @ADD, @FETCHR,
    @EXIT

head(PUTS,PUTS): .word
    @ENTER,
    // TODO
    @EXIT

head(SET_IP,SET_IP): .word . + 1
    S   <- S + 1
    I   <- [S]
    goto(NEXT)

head(GET_IP,GET_IP): .word . + 1
    I   -> [S]
    S   <- S - 1
    goto(NEXT)

head(GET_PSP,GET_PSP): .word . + 1
    S   -> [S]
    S   <- S - 1
    goto(NEXT)

head(GET_RSP,GET_RSP): .word . + 1
    R   -> [S]
    S   <- S - 1
    goto(NEXT)

head(RELOC,RELOC): .word . + 1
    W   <- [S + 1]
    W   <- rel(W)
    W   -> [S + 1]
    goto(NEXT)

<commit_msg>Use new WORD<commit_after>#include "forth_common.th"
#define TEST_LOOKUP 1

.global INBUF .global INPOS .global INLEN
.L_INBUF_before:
INBUF:
#if TEST_LOOKUP
    .utf32 "words "
#endif
    .utf32 "                                               "
    .utf32 "                                               "
.L_INBUF_after:
INPOS: .word 0
INLEN: .word .L_INBUF_after - .L_INBUF_before

.set link, 0
head(start,start): .word
    @NOOP

top: .word
#if TEST_LOOKUP
    @TIB, @TO_IN, @FETCH, @ADD,
    @BL, @WORD,
    @FIND,
    IFNOT0(found,notfound),
#endif

    @TIB, @DUP, @TO_IN, @SWAP, @SUB,        // tib used
    @IN_LEN, @SWAP, @SUB,                   // tib left
    @ACCEPT                                 // count

strip_spaces: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FETCHR, @BL, @CMP_EQ,
    IFNOT0(advance,done_stripping)
advance: .word
    @LITERAL, 1, @CHARS, @TO_IN, @ADDMEM,
    @LITERAL, @strip_spaces, @RELOC, @SET_IP

done_stripping: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FETCHR, @EMIT,
    @EXIT
find_word: .word
    @TIB, @TO_IN, @FETCH, @ADD,
    @FIND,
    IFNOT0(found,notfound)
notfound: .word
    // TODO complain
    @LITERAL, 'X', @EMIT,
    @LITERAL, '\n', @EMIT,
    @ABORT

found: .word
    //@DROP, // drop flag for now, assume found
    @DUP,         @EMIT_UNSIGNED, @BL, @EMIT, @LITERAL, ':', @EMIT, @BL, @EMIT, @CR,
    @DUP, @RELOC, @EMIT_UNSIGNED, @BL, @EMIT, @LITERAL, ':', @EMIT, @BL, @EMIT, @CR,
    @RELOC, @EXECUTE,
	//@EXIT,

    // example of a computed branch
    @LITERAL, 0,
    IFNOT0(top,bottom)
bottom: .word
    @NOOP

wordstart: .word
    @KEY,
    @DUP, @LITERAL, '\n', @CMP_EQ,
    IFNOT0(linedone,checkspace)
checkspace: .word
    @DUP, @BL, @CMP_EQ,
    IFNOT0(worddone,regular),
    @NOOP
regular: .word
    @EMIT,
    @LITERAL, @wordstart, @RELOC, @SET_IP
worddone: .word
    @DROP,
    @CR,
    @LITERAL, @wordstart, @RELOC, @SET_IP
linedone: .word
    @CR,
    @EXIT

//------------------------------------------------------------------------------
// TODO explicit echoing
head(ACCEPT,ACCEPT): .word                      // ( c-addr +n1 -- +n2 )
    @ENTER,

    @OVER, @SWAP                                // C-addr c-addr n1
L_ACCEPT_key: .word
    @KEY,                                       // C-addr c-addr n1 c
    @DUP, @LITERAL, '\n', @CMP_EQ,              // C-addr c-addr n1 c flag
    IFNOT0(L_ACCEPT_exit,L_ACCEPT_regular)
L_ACCEPT_regular: .word
    @ROT,                                       // C-addr n1 c c-addr
    @TUCK,                                      // C-addr n1 c-addr c c-addr
    @STOCHR,                                    // C-addr n1 c-addr
    @LITERAL, 1, @CHARS, @ADD,                  // C-addr n1 c-addr++
    @SWAP,                                      // C-addr c-addr n1
    @SUB_1,                                     // C-addr c-addr n1--
    @DUP, @EQZ,                                 // C-addr c-addr n1 flag
    IFNOT0(L_ACCEPT_done,L_ACCEPT_key)
L_ACCEPT_exit: .word
    @DROP                                       // C-addr c-addr n1
L_ACCEPT_done: .word
    @DROP,                                      // C-addr c-addr
    @SWAP, @SUB,                                // n2
    @EXIT

//------------------------------------------------------------------------------

head(IN_LEN,IN_LEN): .word
    @ENTER,
    @LITERAL, @INLEN, @RELOC, @FETCH,
    @EXIT

head(MASK4BITS,MASK4BITS): .word
    @ENTER,
    @LITERAL, 15, @AND,
    @EXIT

head(HEXTABLE,HEXTABLE): .word
    @ENTER,
    @LITERAL, @hexchars, @RELOC,
    @EXIT

hexchars:
    .word '0','1','2','3','4','5','6','7',
          '8','9','A','B','C','D','E','F'

head(TOHEXCHAR,>HEXCHAR): .word
    @ENTER,
    @HEXTABLE, @ADD, @FETCHR,
    @EXIT

head(PUTS,PUTS): .word
    @ENTER,
    // TODO
    @EXIT

head(SET_IP,SET_IP): .word . + 1
    S   <- S + 1
    I   <- [S]
    goto(NEXT)

head(GET_IP,GET_IP): .word . + 1
    I   -> [S]
    S   <- S - 1
    goto(NEXT)

head(GET_PSP,GET_PSP): .word . + 1
    S   -> [S]
    S   <- S - 1
    goto(NEXT)

head(GET_RSP,GET_RSP): .word . + 1
    R   -> [S]
    S   <- S - 1
    goto(NEXT)

head(RELOC,RELOC): .word . + 1
    W   <- [S + 1]
    W   <- rel(W)
    W   -> [S + 1]
    goto(NEXT)

head(SAYTOP,SAYTOP): .word
    @ENTER,
    @DUP, @EMIT_UNSIGNED, @CR,
    @EXIT

<|endoftext|>


<commit_before>#include "SshSetupHandler.hpp"

#include <sys/wait.h>

namespace et {
string SshSetupHandler::SetupSsh(string user, string host, string host_alias,
                                 int port, string jumphost, int jport,
                                 bool kill) {
  string CLIENT_TERM(getenv("TERM"));
  FILE *passkey_p = popen(
      "env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 32", "r");
  if (!passkey_p) {
    LOG(FATAL) << "cannot generate passkey!";
    exit(1);
  }
  char passkey_buffer[1024];
  fgets(passkey_buffer, sizeof(passkey_buffer), passkey_p);
  pclose(passkey_p);
  string passkey = string(passkey_buffer);

  FILE *id_p = popen(
      "env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 16", "r");
  if (!id_p) {
    LOG(FATAL) << "cannot generate id!";
    exit(1);
  }
  char id_buffer[1024];
  fgets(id_buffer, sizeof(id_buffer), id_p);
  pclose(id_p);
  string id = string(id_buffer);
  string SSH_SCRIPT_PREFIX{
      "SERVER_TMP_DIR=${TMPDIR:-${TMP:-${TEMP:-/tmp}}};"
      "TMPFILE=$(mktemp $SERVER_TMP_DIR/et-server.XXXXXXXXXXXX);"
      "PASSKEY=" +
      passkey +
      ";"
      "ID=" +
      id +
      ";"
      "printf \"%s/%s\\n\" \"$ID\" \"$PASSKEY\" > \"${TMPFILE}\";"
      "export TERM=" +
      CLIENT_TERM +
      ";"
      "etserver --idpasskeyfile=\"${TMPFILE}\""};

  // Kill old ET sessions of the user
  if (kill && user != "root") {
    SSH_SCRIPT_PREFIX = "pkill etserver -u " + user + ";" + SSH_SCRIPT_PREFIX;
  }
  string SSH_SCRIPT_DST = SSH_SCRIPT_PREFIX + ";true";

  int link_client[2];
  char buf_client[4096];
  if (pipe(link_client) == -1) {
    LOG(FATAL) << "pipe";
    exit(1);
  }

  pid_t pid = fork();
  string SSH_USER_PREFIX = "";
  if (!user.empty()) {
    SSH_USER_PREFIX += user + "@";
  }
  if (!pid) {
    // start etserver daemon on dst.
    dup2(link_client[1], 1);
    close(link_client[0]);
    close(link_client[1]);
    if (!jumphost.empty()) {
      execl("/usr/bin/ssh", "/usr/bin/ssh", "-J",
            (SSH_USER_PREFIX + jumphost).c_str(),
            (SSH_USER_PREFIX + host_alias).c_str(), (SSH_SCRIPT_DST).c_str(),
            NULL);
    } else {
      execl("/usr/bin/ssh", "/usr/bin/ssh",
            (SSH_USER_PREFIX + host_alias).c_str(), (SSH_SCRIPT_DST).c_str(),
            NULL);
    }

    LOG(INFO) << "execl error";
    exit(1);
  } else if (pid < 0) {
    LOG(INFO) << "Failed to fork";
    exit(1);
  } else {
    close(link_client[1]);
    wait(NULL);
    int nbytes = read(link_client[0], buf_client, sizeof(buf_client));
    try {
      if (nbytes <= 0 || split(string(buf_client), ':').size() != 2 ||
          split(string(buf_client), ':')[0] != "IDPASSKEY") {
        cout << "Error:  The Eternal Terminal daemon is not running.  "
                "Please (re)start the et daemon on the server."
             << endl;
        exit(1);
      }
      auto idpasskey = split(string(buf_client), ':')[1];
      idpasskey = idpasskey.substr(0, 16 + 1 + 32);
      auto idpasskey_splited = split(idpasskey, '/');
      string returned_id = idpasskey_splited[0];
      string returned_passkey = idpasskey_splited[1];
      if (returned_id == id && returned_passkey == passkey) {
        LOG(INFO) << "etserver started";
      } else {
        LOG(FATAL) << "client/server idpasskey doesn't match: " << id
                   << " != " << returned_id << " or " << passkey
                   << " != " << returned_passkey;
      }
    } catch (const runtime_error &err) {
      cout << "Error initializing connection" << err.what() << endl;
    }
    // start jumpclient daemon on jumphost.
    if (!jumphost.empty()) {
      /* If jumphost is set, we need to pass dst host and port to jumphost
       * and connect to jumphost here */
      int link_jump[2];
      char buf_jump[4096];
      if (pipe(link_jump) == -1) {
        LOG(FATAL) << "pipe";
        exit(1);
      }
      pid_t pid_jump = fork();
      if (pid_jump < 0) {
        LOG(FATAL) << "Failed to fork";
        exit(1);
      } else if (pid_jump == 0) {
        dup2(link_jump[1], 1);
        close(link_jump[0]);
        close(link_jump[1]);
        string cmdoptions = "";
        cmdoptions +=
            " --jump --dsthost=" + host + " --dstport=" + to_string(port);
        string SSH_SCRIPT_JUMP = SSH_SCRIPT_PREFIX + cmdoptions + ";true";
        execl("/usr/bin/ssh", "/usr/bin/ssh", jumphost.c_str(),
              (SSH_SCRIPT_JUMP).c_str(), NULL);
      } else {
        close(link_jump[1]);
        wait(NULL);
        int nbytes = read(link_jump[0], buf_jump, sizeof(buf_jump));
        if (nbytes <= 0) {
          LOG(FATAL) << "etserver jumpclient failed to start";
          exit(1);
        }
        try {
          auto idpasskey = split(string(buf_jump), ':')[1];
          idpasskey.erase(idpasskey.find_last_not_of(" \n\r\t") + 1);
          idpasskey = idpasskey.substr(0, 16 + 1 + 32);
          auto idpasskey_splited = split(idpasskey, '/');
          string returned_id = idpasskey_splited[0];
          string returned_passkey = idpasskey_splited[1];
          if (returned_id == id && returned_passkey == passkey) {
            LOG(INFO) << "jump client started.";
          } else {
            LOG(INFO) << "ID " << id;
            LOG(INFO) << "Received ID " << returned_id;
            LOG(INFO) << "PASSKEY " << passkey;
            LOG(INFO) << "Received PASSKEY " << returned_passkey;
            LOG(INFO) << "client/server idpasskey doesn't match";
            exit(1);
          }
        } catch (const runtime_error &err) {
          cout << "Error initializing connection" << err.what() << endl;
        }
      }
    }
  }
  return id + "/" + passkey;
}
}  // namespace et
<commit_msg>use ssh in PATH instead hardcoded<commit_after>#include "SshSetupHandler.hpp"

#include <sys/wait.h>

namespace et {
string SshSetupHandler::SetupSsh(string user, string host, string host_alias,
                                 int port, string jumphost, int jport,
                                 bool kill) {
  string CLIENT_TERM(getenv("TERM"));
  FILE *passkey_p = popen(
      "env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 32", "r");
  if (!passkey_p) {
    LOG(FATAL) << "cannot generate passkey!";
    exit(1);
  }
  char passkey_buffer[1024];
  fgets(passkey_buffer, sizeof(passkey_buffer), passkey_p);
  pclose(passkey_p);
  string passkey = string(passkey_buffer);

  FILE *id_p = popen(
      "env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 16", "r");
  if (!id_p) {
    LOG(FATAL) << "cannot generate id!";
    exit(1);
  }
  char id_buffer[1024];
  fgets(id_buffer, sizeof(id_buffer), id_p);
  pclose(id_p);
  string id = string(id_buffer);
  string SSH_SCRIPT_PREFIX{
      "SERVER_TMP_DIR=${TMPDIR:-${TMP:-${TEMP:-/tmp}}};"
      "TMPFILE=$(mktemp $SERVER_TMP_DIR/et-server.XXXXXXXXXXXX);"
      "PASSKEY=" +
      passkey +
      ";"
      "ID=" +
      id +
      ";"
      "printf \"%s/%s\\n\" \"$ID\" \"$PASSKEY\" > \"${TMPFILE}\";"
      "export TERM=" +
      CLIENT_TERM +
      ";"
      "etserver --idpasskeyfile=\"${TMPFILE}\""};

  // Kill old ET sessions of the user
  if (kill && user != "root") {
    SSH_SCRIPT_PREFIX = "pkill etserver -u " + user + ";" + SSH_SCRIPT_PREFIX;
  }
  string SSH_SCRIPT_DST = SSH_SCRIPT_PREFIX + ";true";

  int link_client[2];
  char buf_client[4096];
  if (pipe(link_client) == -1) {
    LOG(FATAL) << "pipe";
    exit(1);
  }

  pid_t pid = fork();
  string SSH_USER_PREFIX = "";
  if (!user.empty()) {
    SSH_USER_PREFIX += user + "@";
  }
  if (!pid) {
    // start etserver daemon on dst.
    dup2(link_client[1], 1);
    close(link_client[0]);
    close(link_client[1]);
    if (!jumphost.empty()) {
      execlp("ssh", "ssh", "-J", (SSH_USER_PREFIX + jumphost).c_str(),
             (SSH_USER_PREFIX + host_alias).c_str(), (SSH_SCRIPT_DST).c_str(),
             NULL);
    } else {
      execlp("ssh", "ssh", (SSH_USER_PREFIX + host_alias).c_str(),
             (SSH_SCRIPT_DST).c_str(), NULL);
    }

    LOG(INFO) << "execl error";
    exit(1);
  } else if (pid < 0) {
    LOG(INFO) << "Failed to fork";
    exit(1);
  } else {
    close(link_client[1]);
    wait(NULL);
    int nbytes = read(link_client[0], buf_client, sizeof(buf_client));
    try {
      if (nbytes <= 0 || split(string(buf_client), ':').size() != 2 ||
          split(string(buf_client), ':')[0] != "IDPASSKEY") {
        cout << "Error:  The Eternal Terminal daemon is not running.  "
                "Please (re)start the et daemon on the server."
             << endl;
        exit(1);
      }
      auto idpasskey = split(string(buf_client), ':')[1];
      idpasskey = idpasskey.substr(0, 16 + 1 + 32);
      auto idpasskey_splited = split(idpasskey, '/');
      string returned_id = idpasskey_splited[0];
      string returned_passkey = idpasskey_splited[1];
      if (returned_id == id && returned_passkey == passkey) {
        LOG(INFO) << "etserver started";
      } else {
        LOG(FATAL) << "client/server idpasskey doesn't match: " << id
                   << " != " << returned_id << " or " << passkey
                   << " != " << returned_passkey;
      }
    } catch (const runtime_error &err) {
      cout << "Error initializing connection" << err.what() << endl;
    }
    // start jumpclient daemon on jumphost.
    if (!jumphost.empty()) {
      /* If jumphost is set, we need to pass dst host and port to jumphost
       * and connect to jumphost here */
      int link_jump[2];
      char buf_jump[4096];
      if (pipe(link_jump) == -1) {
        LOG(FATAL) << "pipe";
        exit(1);
      }
      pid_t pid_jump = fork();
      if (pid_jump < 0) {
        LOG(FATAL) << "Failed to fork";
        exit(1);
      } else if (pid_jump == 0) {
        dup2(link_jump[1], 1);
        close(link_jump[0]);
        close(link_jump[1]);
        string cmdoptions = "";
        cmdoptions +=
            " --jump --dsthost=" + host + " --dstport=" + to_string(port);
        string SSH_SCRIPT_JUMP = SSH_SCRIPT_PREFIX + cmdoptions + ";true";
        execlp("ssh", "ssh", jumphost.c_str(), (SSH_SCRIPT_JUMP).c_str(), NULL);
      } else {
        close(link_jump[1]);
        wait(NULL);
        int nbytes = read(link_jump[0], buf_jump, sizeof(buf_jump));
        if (nbytes <= 0) {
          LOG(FATAL) << "etserver jumpclient failed to start";
          exit(1);
        }
        try {
          auto idpasskey = split(string(buf_jump), ':')[1];
          idpasskey.erase(idpasskey.find_last_not_of(" \n\r\t") + 1);
          idpasskey = idpasskey.substr(0, 16 + 1 + 32);
          auto idpasskey_splited = split(idpasskey, '/');
          string returned_id = idpasskey_splited[0];
          string returned_passkey = idpasskey_splited[1];
          if (returned_id == id && returned_passkey == passkey) {
            LOG(INFO) << "jump client started.";
          } else {
            LOG(INFO) << "ID " << id;
            LOG(INFO) << "Received ID " << returned_id;
            LOG(INFO) << "PASSKEY " << passkey;
            LOG(INFO) << "Received PASSKEY " << returned_passkey;
            LOG(INFO) << "client/server idpasskey doesn't match";
            exit(1);
          }
        } catch (const runtime_error &err) {
          cout << "Error initializing connection" << err.what() << endl;
        }
      }
    }
  }
  return id + "/" + passkey;
}
}  // namespace et
<|endoftext|>