<commit_before>// Copyright Yangqing Jia 2013
// pycaffe provides a wrapper of the caffe::Net class as well as some
// caffe::Caffe functions so that one could easily call it from Python.
// Note that for python, we will simply use float as the data type.

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <numpy/arrayobject.h>
#include "caffe/caffe.hpp"

// Temporary solution for numpy < 1.7 versions: old macro.
#ifndef NPY_ARRAY_C_CONTIGUOUS
#define NPY_ARRAY_C_CONTIGUOUS NPY_C_CONTIGUOUS
#endif

using namespace caffe;
using boost::python::extract;
using boost::python::len;
using boost::python::list;
using boost::python::object;
using boost::python::handle;
using boost::python::vector_indexing_suite;

// wrap shared_ptr<Blob<float> > in a class that we construct in C++ and pass
//  to Python
class CaffeBlob {
 public:

  CaffeBlob(const shared_ptr<Blob<float> > &blob)
      : blob_(blob) {}

  CaffeBlob()
  {}

  int num() const { return blob_->num(); }
  int channels() const { return blob_->channels(); }
  int height() const { return blob_->height(); }
  int width() const { return blob_->width(); }
  int count() const { return blob_->count(); }

  bool operator == (const CaffeBlob &other)
  {
      return this->blob_ == other.blob_;
  }

 protected:
  shared_ptr<Blob<float> > blob_;
};

// we need another wrapper (used as boost::python's HeldType) that receives a
//  self PyObject * which we can use as ndarray.base, so that data/diff memory
//  is not freed while still being used in Python
class CaffeBlobWrap : public CaffeBlob {
 public:
  CaffeBlobWrap(PyObject *p, shared_ptr<Blob<float> > &blob)
      : CaffeBlob(blob), self_(p) {}

  CaffeBlobWrap(PyObject *p, const CaffeBlob &blob)
      : CaffeBlob(blob), self_(p) {}

  object get_data()
  {
      npy_intp dims[] = {num(), channels(), height(), width()};

      PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
                                                blob_->mutable_cpu_data());
      PyArray_SetBaseObject(reinterpret_cast<PyArrayObject *>(obj), self_);
      Py_INCREF(self_);
      handle<> h(obj);

      return object(h);
  }

  object get_diff()
  {
      npy_intp dims[] = {num(), channels(), height(), width()};

      PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
                                                blob_->mutable_cpu_diff());
      PyArray_SetBaseObject(reinterpret_cast<PyArrayObject *>(obj), self_);
      Py_INCREF(self_);
      handle<> h(obj);

      return object(h);
  }

 private:
  PyObject *self_;
};

// A simple wrapper over CaffeNet that runs the forward process.
struct CaffeNet
{
  CaffeNet(string param_file, string pretrained_param_file) {
    net_.reset(new Net<float>(param_file));
    net_->CopyTrainedLayersFrom(pretrained_param_file);
  }

  virtual ~CaffeNet() {}

  inline void check_array_against_blob(
      PyArrayObject* arr, Blob<float>* blob) {
    CHECK(PyArray_FLAGS(arr) & NPY_ARRAY_C_CONTIGUOUS);
    CHECK_EQ(PyArray_NDIM(arr), 4);
    CHECK_EQ(PyArray_ITEMSIZE(arr), 4);
    npy_intp* dims = PyArray_DIMS(arr);
    CHECK_EQ(dims[0], blob->num());
    CHECK_EQ(dims[1], blob->channels());
    CHECK_EQ(dims[2], blob->height());
    CHECK_EQ(dims[3], blob->width());
  }

  // The actual forward function. It takes in a python list of numpy arrays as
  // input and a python list of numpy arrays as output. The input and output
  // should all have correct shapes, are single-precisionabcdnt- and c contiguous.
  void Forward(list bottom, list top) {
    vector<Blob<float>*>& input_blobs = net_->input_blobs();
    CHECK_EQ(len(bottom), input_blobs.size());
    CHECK_EQ(len(top), net_->num_outputs());
    // First, copy the input
    for (int i = 0; i < input_blobs.size(); ++i) {
      object elem = bottom[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, input_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(input_blobs[i]->mutable_cpu_data(), PyArray_DATA(arr),
            sizeof(float) * input_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(input_blobs[i]->mutable_gpu_data(), PyArray_DATA(arr),
            sizeof(float) * input_blobs[i]->count(), cudaMemcpyHostToDevice);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
    //LOG(INFO) << "Start";
    const vector<Blob<float>*>& output_blobs = net_->ForwardPrefilled();
    //LOG(INFO) << "End";
    for (int i = 0; i < output_blobs.size(); ++i) {
      object elem = top[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, output_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(PyArray_DATA(arr), output_blobs[i]->cpu_data(),
            sizeof(float) * output_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(PyArray_DATA(arr), output_blobs[i]->gpu_data(),
            sizeof(float) * output_blobs[i]->count(), cudaMemcpyDeviceToHost);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
  }

  void Backward(list top_diff, list bottom_diff) {
    vector<Blob<float>*>& output_blobs = net_->output_blobs();
    vector<Blob<float>*>& input_blobs = net_->input_blobs();
    CHECK_EQ(len(bottom_diff), input_blobs.size());
    CHECK_EQ(len(top_diff), output_blobs.size());
    // First, copy the output diff
    for (int i = 0; i < output_blobs.size(); ++i) {
      object elem = top_diff[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, output_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(output_blobs[i]->mutable_cpu_diff(), PyArray_DATA(arr),
            sizeof(float) * output_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(output_blobs[i]->mutable_gpu_diff(), PyArray_DATA(arr),
            sizeof(float) * output_blobs[i]->count(), cudaMemcpyHostToDevice);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
    //LOG(INFO) << "Start";
    net_->Backward();
    //LOG(INFO) << "End";
    for (int i = 0; i < input_blobs.size(); ++i) {
      object elem = bottom_diff[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, input_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(PyArray_DATA(arr), input_blobs[i]->cpu_diff(),
            sizeof(float) * input_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(PyArray_DATA(arr), input_blobs[i]->gpu_diff(),
            sizeof(float) * input_blobs[i]->count(), cudaMemcpyDeviceToHost);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
  }

  // The caffe::Caffe utility functions.
  void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); }
  void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); }
  void set_phase_train() { Caffe::set_phase(Caffe::TRAIN); }
  void set_phase_test() { Caffe::set_phase(Caffe::TEST); }
  void set_device(int device_id) { Caffe::SetDevice(device_id); }

  vector<CaffeBlob> blobs() {
      return vector<CaffeBlob>(net_->blobs().begin(), net_->blobs().end());
  }

  }

  // The pointer to the internal caffe::Net instant.
	shared_ptr<Net<float> > net_;
};

// The boost python module definition.
BOOST_PYTHON_MODULE(pycaffe)
{

  boost::python::class_<CaffeNet>(
      "CaffeNet", boost::python::init<string, string>())
      .def("Forward",         &CaffeNet::Forward)
      .def("Backward",        &CaffeNet::Backward)
      .def("set_mode_cpu",    &CaffeNet::set_mode_cpu)
      .def("set_mode_gpu",    &CaffeNet::set_mode_gpu)
      .def("set_phase_train", &CaffeNet::set_phase_train)
      .def("set_phase_test",  &CaffeNet::set_phase_test)
      .def("set_device",      &CaffeNet::set_device)
      .def("blobs",           &CaffeNet::blobs)
  ;

  boost::python::class_<CaffeBlob, CaffeBlobWrap>(
      "CaffeBlob", boost::python::no_init)
      .add_property("num",      &CaffeBlob::num)
      .add_property("channels", &CaffeBlob::channels)
      .add_property("height",   &CaffeBlob::height)
      .add_property("width",    &CaffeBlob::width)
      .add_property("count",    &CaffeBlob::count)
      .add_property("data",     &CaffeBlobWrap::get_data)
      .add_property("diff",     &CaffeBlobWrap::get_diff)
  ;

  boost::python::class_<vector<CaffeBlob> >("BlobVec")
      .def(vector_indexing_suite<vector<CaffeBlob>, true>());

  import_array();

}
<commit_msg>Expose params in Python interface<commit_after>// Copyright Yangqing Jia 2013
// pycaffe provides a wrapper of the caffe::Net class as well as some
// caffe::Caffe functions so that one could easily call it from Python.
// Note that for python, we will simply use float as the data type.

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <numpy/arrayobject.h>
#include "caffe/caffe.hpp"

// Temporary solution for numpy < 1.7 versions: old macro.
#ifndef NPY_ARRAY_C_CONTIGUOUS
#define NPY_ARRAY_C_CONTIGUOUS NPY_C_CONTIGUOUS
#endif

using namespace caffe;
using boost::python::extract;
using boost::python::len;
using boost::python::list;
using boost::python::object;
using boost::python::handle;
using boost::python::vector_indexing_suite;

// wrap shared_ptr<Blob<float> > in a class that we construct in C++ and pass
//  to Python
class CaffeBlob {
 public:

  CaffeBlob(const shared_ptr<Blob<float> > &blob)
      : blob_(blob) {}

  CaffeBlob()
  {}

  int num() const { return blob_->num(); }
  int channels() const { return blob_->channels(); }
  int height() const { return blob_->height(); }
  int width() const { return blob_->width(); }
  int count() const { return blob_->count(); }

  bool operator == (const CaffeBlob &other)
  {
      return this->blob_ == other.blob_;
  }

 protected:
  shared_ptr<Blob<float> > blob_;
};

// we need another wrapper (used as boost::python's HeldType) that receives a
//  self PyObject * which we can use as ndarray.base, so that data/diff memory
//  is not freed while still being used in Python
class CaffeBlobWrap : public CaffeBlob {
 public:
  CaffeBlobWrap(PyObject *p, shared_ptr<Blob<float> > &blob)
      : CaffeBlob(blob), self_(p) {}

  CaffeBlobWrap(PyObject *p, const CaffeBlob &blob)
      : CaffeBlob(blob), self_(p) {}

  object get_data()
  {
      npy_intp dims[] = {num(), channels(), height(), width()};

      PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
                                                blob_->mutable_cpu_data());
      PyArray_SetBaseObject(reinterpret_cast<PyArrayObject *>(obj), self_);
      Py_INCREF(self_);
      handle<> h(obj);

      return object(h);
  }

  object get_diff()
  {
      npy_intp dims[] = {num(), channels(), height(), width()};

      PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
                                                blob_->mutable_cpu_diff());
      PyArray_SetBaseObject(reinterpret_cast<PyArrayObject *>(obj), self_);
      Py_INCREF(self_);
      handle<> h(obj);

      return object(h);
  }

 private:
  PyObject *self_;
};

// A simple wrapper over CaffeNet that runs the forward process.
struct CaffeNet
{
  CaffeNet(string param_file, string pretrained_param_file) {
    net_.reset(new Net<float>(param_file));
    net_->CopyTrainedLayersFrom(pretrained_param_file);
  }

  virtual ~CaffeNet() {}

  inline void check_array_against_blob(
      PyArrayObject* arr, Blob<float>* blob) {
    CHECK(PyArray_FLAGS(arr) & NPY_ARRAY_C_CONTIGUOUS);
    CHECK_EQ(PyArray_NDIM(arr), 4);
    CHECK_EQ(PyArray_ITEMSIZE(arr), 4);
    npy_intp* dims = PyArray_DIMS(arr);
    CHECK_EQ(dims[0], blob->num());
    CHECK_EQ(dims[1], blob->channels());
    CHECK_EQ(dims[2], blob->height());
    CHECK_EQ(dims[3], blob->width());
  }

  // The actual forward function. It takes in a python list of numpy arrays as
  // input and a python list of numpy arrays as output. The input and output
  // should all have correct shapes, are single-precisionabcdnt- and c contiguous.
  void Forward(list bottom, list top) {
    vector<Blob<float>*>& input_blobs = net_->input_blobs();
    CHECK_EQ(len(bottom), input_blobs.size());
    CHECK_EQ(len(top), net_->num_outputs());
    // First, copy the input
    for (int i = 0; i < input_blobs.size(); ++i) {
      object elem = bottom[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, input_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(input_blobs[i]->mutable_cpu_data(), PyArray_DATA(arr),
            sizeof(float) * input_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(input_blobs[i]->mutable_gpu_data(), PyArray_DATA(arr),
            sizeof(float) * input_blobs[i]->count(), cudaMemcpyHostToDevice);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
    //LOG(INFO) << "Start";
    const vector<Blob<float>*>& output_blobs = net_->ForwardPrefilled();
    //LOG(INFO) << "End";
    for (int i = 0; i < output_blobs.size(); ++i) {
      object elem = top[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, output_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(PyArray_DATA(arr), output_blobs[i]->cpu_data(),
            sizeof(float) * output_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(PyArray_DATA(arr), output_blobs[i]->gpu_data(),
            sizeof(float) * output_blobs[i]->count(), cudaMemcpyDeviceToHost);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
  }

  void Backward(list top_diff, list bottom_diff) {
    vector<Blob<float>*>& output_blobs = net_->output_blobs();
    vector<Blob<float>*>& input_blobs = net_->input_blobs();
    CHECK_EQ(len(bottom_diff), input_blobs.size());
    CHECK_EQ(len(top_diff), output_blobs.size());
    // First, copy the output diff
    for (int i = 0; i < output_blobs.size(); ++i) {
      object elem = top_diff[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, output_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(output_blobs[i]->mutable_cpu_diff(), PyArray_DATA(arr),
            sizeof(float) * output_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(output_blobs[i]->mutable_gpu_diff(), PyArray_DATA(arr),
            sizeof(float) * output_blobs[i]->count(), cudaMemcpyHostToDevice);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
    //LOG(INFO) << "Start";
    net_->Backward();
    //LOG(INFO) << "End";
    for (int i = 0; i < input_blobs.size(); ++i) {
      object elem = bottom_diff[i];
      PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
      check_array_against_blob(arr, input_blobs[i]);
      switch (Caffe::mode()) {
      case Caffe::CPU:
        memcpy(PyArray_DATA(arr), input_blobs[i]->cpu_diff(),
            sizeof(float) * input_blobs[i]->count());
        break;
      case Caffe::GPU:
        cudaMemcpy(PyArray_DATA(arr), input_blobs[i]->gpu_diff(),
            sizeof(float) * input_blobs[i]->count(), cudaMemcpyDeviceToHost);
        break;
      default:
        LOG(FATAL) << "Unknown Caffe mode.";
      }  // switch (Caffe::mode())
    }
  }

  // The caffe::Caffe utility functions.
  void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); }
  void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); }
  void set_phase_train() { Caffe::set_phase(Caffe::TRAIN); }
  void set_phase_test() { Caffe::set_phase(Caffe::TEST); }
  void set_device(int device_id) { Caffe::SetDevice(device_id); }

  vector<CaffeBlob> blobs() {
      return vector<CaffeBlob>(net_->blobs().begin(), net_->blobs().end());
  }

  vector<CaffeBlob> params() {
      return vector<CaffeBlob>(net_->params().begin(), net_->params().end());
  }

  // The pointer to the internal caffe::Net instant.
	shared_ptr<Net<float> > net_;
};

// The boost python module definition.
BOOST_PYTHON_MODULE(pycaffe)
{

  boost::python::class_<CaffeNet>(
      "CaffeNet", boost::python::init<string, string>())
      .def("Forward",         &CaffeNet::Forward)
      .def("Backward",        &CaffeNet::Backward)
      .def("set_mode_cpu",    &CaffeNet::set_mode_cpu)
      .def("set_mode_gpu",    &CaffeNet::set_mode_gpu)
      .def("set_phase_train", &CaffeNet::set_phase_train)
      .def("set_phase_test",  &CaffeNet::set_phase_test)
      .def("set_device",      &CaffeNet::set_device)
      .def("blobs",           &CaffeNet::blobs)
      .def("params",          &CaffeNet::params)
  ;

  boost::python::class_<CaffeBlob, CaffeBlobWrap>(
      "CaffeBlob", boost::python::no_init)
      .add_property("num",      &CaffeBlob::num)
      .add_property("channels", &CaffeBlob::channels)
      .add_property("height",   &CaffeBlob::height)
      .add_property("width",    &CaffeBlob::width)
      .add_property("count",    &CaffeBlob::count)
      .add_property("data",     &CaffeBlobWrap::get_data)
      .add_property("diff",     &CaffeBlobWrap::get_diff)
  ;

  boost::python::class_<vector<CaffeBlob> >("BlobVec")
      .def(vector_indexing_suite<vector<CaffeBlob>, true>());

  import_array();

}
<|endoftext|>


<commit_before> AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", Float_t radius = 0.4,Int_t nSkip = 0,Int_t kWriteAOD = kFALSE,char* deltaFile = "",Float_t ptTrackCut = 0.15);

Int_t kBackgroundMode = 0;
Float_t kPtTrackCut = 0.15;
Float_t kTrackEtaCut = 0.8;

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", UInt_t iFlag){
   AliAnalysisTaskJetCluster *js = 0;
   if(kUseAODMC&&false){// do not use the MC info yet
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }
   else{
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }

   return js;
 }

 AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,UInt_t iPhysicsSelectionFlag,Char_t *jf,Float_t radius,Int_t nSkip,Int_t kWriteAOD,char *deltaFile,Float_t ptTrackCut)
 {
 // Creates a jet fider task, configures it and adds it to the analysis manager.
   kPtTrackCut = ptTrackCut;

   TString outputFile(deltaFile);
    // Get the pointer to the existing analysis manager via the static access method.
    //==============================================================================
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
       ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
       return NULL;
    }

    // Check the analysis type using the event handlers connected to the analysis manager.
    //==============================================================================
    if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskJetCluster", "This task requires an input event handler");
       return NULL;
    }

    TString type = mgr->GetInputEventHandler()->GetDataType();
    TString typeRec(bRec);
    TString typeGen(bGen);
    if(!typeRec.Contains("AODextra")) {
      typeGen.ToUpper();
      typeRec.ToUpper();
    }
    cout << "typeRec: " << typeRec << endl;
    // Create the task and configure it.
    //===========================================================================

    TString cAdd = "";
    cAdd += Form("%02d_",(int)((radius+0.01)*10.));
    cAdd += Form("B%d",(int)kBackgroundMode);
    cAdd += Form("_Filter%05d",filterMask);
    cAdd += Form("_Cut%05d",(int)(1000.*kPtTrackCut));
    cAdd += Form("_Skip%02d",nSkip);
    Printf("%s %E",cAdd.Data(),kPtTrackCut);
    AliAnalysisTaskJetCluster* pwg4spec = new  AliAnalysisTaskJetCluster(Form("JetCluster%s_%s%s",bRec,jf,cAdd.Data()));

   // or a config file
   // pwg4spec->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)pwg4spec->SetAODInput(kTRUE);
   // pwg4spec->SetDebugLevel(11);
   pwg4spec->SetFilterMask(filterMask);
   //   pwg4spec->SetUseGlobalSelection(kTRUE);

   if(type == "AOD"){
     // Assume all jet are produced already
     pwg4spec->SetAODTrackInput(kTRUE);
     pwg4spec->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
     pwg4spec->SetTrackPtCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AODMC2")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
     pwg4spec->SetTrackPtCut(5);
   }
   else if (typeRec.Contains("AODMC")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
     pwg4spec->SetTrackPtCut(5);
   }
   else if (typeRec.Contains("AODextraonly")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextraonly);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackPtCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AODextra")) {
     cout << "AliAnalysisTaskJetCluster::kTrackAODextra: " << AliAnalysisTaskJetCluster::kTrackAODextra << endl;
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextra);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackPtCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AOD")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackPtCut(kTrackEtaCut);
   }

   pwg4spec->SetRparam(radius);

   switch (jf) {
   case "ANTIKT":
     pwg4spec->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     pwg4spec->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     pwg4spec->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(kWriteAOD){
     if(outputFile.Length())pwg4spec->SetJetOutputFile(outputFile);
     pwg4spec->SetJetOutputBranch(Form("clusters%s_%s%s",bRec,jf,cAdd.Data()));
     pwg4spec->SetJetOutputMinPt(0); // store only jets / clusters above a certain threshold
   }

   pwg4spec->SetNSkipLeadingRan(nSkip);

   if(iPhysicsSelectionFlag)pwg4spec->SelectCollisionCandidates(iPhysicsSelectionFlag);

   mgr->AddTask(pwg4spec);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("pwg4cluster_%s_%s_%s%s",bRec,bGen,jf,cAdd.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWG4_cluster_%s_%s_%s%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cAdd.Data()));

   mgr->ConnectInput  (pwg4spec, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (pwg4spec, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (pwg4spec,  1, coutput1_Spec );

   return pwg4spec;
}
<commit_msg>fixed seeting of eta cut<commit_after> AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", Float_t radius = 0.4,Int_t nSkip = 0,Int_t kWriteAOD = kFALSE,char* deltaFile = "",Float_t ptTrackCut = 0.15);

Int_t kBackgroundMode = 0;
Float_t kPtTrackCut = 0.15;
Float_t kTrackEtaCut = 0.8;

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", UInt_t iFlag){
   AliAnalysisTaskJetCluster *js = 0;
   if(kUseAODMC&&false){// do not use the MC info yet
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }
   else{
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }

   return js;
 }

 AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,UInt_t iPhysicsSelectionFlag,Char_t *jf,Float_t radius,Int_t nSkip,Int_t kWriteAOD,char *deltaFile,Float_t ptTrackCut)
 {
 // Creates a jet fider task, configures it and adds it to the analysis manager.
   kPtTrackCut = ptTrackCut;

   TString outputFile(deltaFile);
    // Get the pointer to the existing analysis manager via the static access method.
    //==============================================================================
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
       ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
       return NULL;
    }

    // Check the analysis type using the event handlers connected to the analysis manager.
    //==============================================================================
    if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskJetCluster", "This task requires an input event handler");
       return NULL;
    }

    TString type = mgr->GetInputEventHandler()->GetDataType();
    TString typeRec(bRec);
    TString typeGen(bGen);
    if(!typeRec.Contains("AODextra")) {
      typeGen.ToUpper();
      typeRec.ToUpper();
    }
    cout << "typeRec: " << typeRec << endl;
    // Create the task and configure it.
    //===========================================================================

    TString cAdd = "";
    cAdd += Form("%02d_",(int)((radius+0.01)*10.));
    cAdd += Form("B%d",(int)kBackgroundMode);
    cAdd += Form("_Filter%05d",filterMask);
    cAdd += Form("_Cut%05d",(int)(1000.*kPtTrackCut));
    cAdd += Form("_Skip%02d",nSkip);
    Printf("%s %E",cAdd.Data(),kPtTrackCut);
    AliAnalysisTaskJetCluster* pwg4spec = new  AliAnalysisTaskJetCluster(Form("JetCluster%s_%s%s",bRec,jf,cAdd.Data()));

   // or a config file
   // pwg4spec->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)pwg4spec->SetAODInput(kTRUE);
   // pwg4spec->SetDebugLevel(11);
   pwg4spec->SetFilterMask(filterMask);
   //   pwg4spec->SetUseGlobalSelection(kTRUE);

   if(type == "AOD"){
     // Assume all jet are produced already
     pwg4spec->SetAODTrackInput(kTRUE);
     pwg4spec->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AODMC2")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(5);
   }
   else if (typeRec.Contains("AODMC")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(5);
   }
   else if (typeRec.Contains("AODextraonly")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextraonly);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AODextra")) {
     cout << "AliAnalysisTaskJetCluster::kTrackAODextra: " << AliAnalysisTaskJetCluster::kTrackAODextra << endl;
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextra);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(kTrackEtaCut);
   }
   else if (typeRec.Contains("AOD")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
     pwg4spec->SetTrackPtCut(kPtTrackCut);
     pwg4spec->SetTrackEtaCut(kTrackEtaCut);
   }

   pwg4spec->SetRparam(radius);

   switch (jf) {
   case "ANTIKT":
     pwg4spec->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     pwg4spec->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     pwg4spec->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(kWriteAOD){
     if(outputFile.Length())pwg4spec->SetJetOutputFile(outputFile);
     pwg4spec->SetJetOutputBranch(Form("clusters%s_%s%s",bRec,jf,cAdd.Data()));
     pwg4spec->SetJetOutputMinPt(0); // store only jets / clusters above a certain threshold
   }

   pwg4spec->SetNSkipLeadingRan(nSkip);

   if(iPhysicsSelectionFlag)pwg4spec->SelectCollisionCandidates(iPhysicsSelectionFlag);

   mgr->AddTask(pwg4spec);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("pwg4cluster_%s_%s_%s%s",bRec,bGen,jf,cAdd.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWG4_cluster_%s_%s_%s%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cAdd.Data()));

   mgr->ConnectInput  (pwg4spec, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (pwg4spec, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (pwg4spec,  1, coutput1_Spec );

   return pwg4spec;
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/isolation.hxx
 *
 *   DESCRIPTION
 *      definitions of transaction isolation levels
 *   Policies and traits describing SQL transaction isolation levels
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.
 *
 * Copyright (c) 2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/util"

namespace pqxx
{

/// Transaction isolation levels; PostgreSQL doesn't implement all SQL levels
/** The only levels implemented in postgres are read_committed and serializable;
 * SQL also defines read_uncommitted and repeatable_read.  Unless you're bent on
 * using nasty tricks to communicate between ongoing transactions and such, you
 * won't really need isolation levels for anything except performance
 * optimization.  In that case, you can safely emulate read_uncommitted by using
 * read_committed and repeatable_read by using serializable.  In general,
 * serializable is the safest choice.
 */
enum PQXX_LIBEXPORT isolation_level
{
  // read_uncommitted,
  read_committed,
  // repeatable_read,
  serializable
};

/// Traits class to describe an isolation level; primarly for libpqxx's own use
template<isolation_level LEVEL> struct isolation_traits
{
  static isolation_level level() throw () { return LEVEL; }
  static const char *name() throw ();

  /// Only defined for implemented levels; nonexistant levels yield link errors
  static void implemented() throw ();
};

template<> inline void isolation_traits<read_committed>::implemented() throw(){}
template<> inline void isolation_traits<serializable>::implemented() throw(){}

template<> inline const char *isolation_traits<read_committed>::name() throw ()
	{ return "READ COMMITTED"; }
template<> inline const char *isolation_traits<serializable>::name() throw ()
	{ return "SERIALIZABLE"; }

}

<commit_msg>Removed unused stuff<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/isolation.hxx
 *
 *   DESCRIPTION
 *      definitions of transaction isolation levels
 *   Policies and traits describing SQL transaction isolation levels
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.
 *
 * Copyright (c) 2003-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/util"

namespace pqxx
{

/// Transaction isolation levels; PostgreSQL doesn't implement all SQL levels
/** The only levels implemented in postgres are read_committed and serializable;
 * SQL also defines read_uncommitted and repeatable_read.  Unless you're bent on
 * using nasty tricks to communicate between ongoing transactions and such, you
 * won't really need isolation levels for anything except performance
 * optimization.  In that case, you can safely emulate read_uncommitted by using
 * read_committed and repeatable_read by using serializable.  In general,
 * serializable is the safest choice.
 */
enum PQXX_LIBEXPORT isolation_level
{
  // read_uncommitted,
  read_committed,
  // repeatable_read,
  serializable
};

/// Traits class to describe an isolation level; primarly for libpqxx's own use
template<isolation_level LEVEL> struct isolation_traits
{
  static isolation_level level() throw () { return LEVEL; }
  static const char *name() throw ();
};

template<> inline const char *isolation_traits<read_committed>::name() throw ()
	{ return "READ COMMITTED"; }
template<> inline const char *isolation_traits<serializable>::name() throw ()
	{ return "SERIALIZABLE"; }

}

<|endoftext|>


<commit_before>#pragma once
#include <PluginFactory/details/NullPluginService.hpp>
#include <PluginFactory/details/PluginHandle.hpp>
#include <PluginFactory/details/PolicyHolder.hpp>
#include <PluginFactory/details/PluginLoader.hpp>
#include <PluginFactory/details/PolicyProperties.hpp>
#include <PluginFactory/Exceptions.hpp>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

namespace PluginFactory {

    // A tag type to indicate we want to create a shared_ptr to
    struct AsSharedTagType {};

    // <PluginInterface> is the abstract interface of the plugin object itself. You'll need
    // a PluginFactory for each different type of plugin you wish to support.
    //
    // <PluginServiceInterface> is the interface given to the plugin to allow it to make
    // modifications to the main program. This is to encourage plugin developers not to
    // engage in crazy behavior like calling willy-nilly into the base process's code.
    //
    // NOTE: lifetime management using plugins can be difficult. It is essential
    // the PluginFactory stays in scope longer than any instanced plugin. Failure
    // to do so will most likely end in the process crashing.
    template<class PluginInterface, class PluginServiceInterface = details::NullPluginService, class PolicyOwnershipProperty = details::PolicyIsInternal>
    class PluginFactory : public details::PolicyHolder<PluginServiceInterface, PolicyOwnershipProperty>
    {
    public:
        static AsSharedTagType create_shared;

        // @pluginDirectory is the directory path to load plugins from.
        template<typename... Args>
        PluginFactory(const boost::filesystem::path& pluginDirectory, Args&&... args);

        void load();        // load all found plugins
        void load(const boost::filesystem::path& pluginPath);   // load a specific plugin (@pluginPath)

        void unload();      // unload all loaded plugins
        void unload(const boost::filesystem::path& pluginPath); // unload a specific plugin (@pluginPath)

        std::unique_ptr<PluginInterface> instance(const std::string& plugin);
        std::shared_ptr<PluginInterface> instance(const std::string& pluginName, AsSharedTagType /*create_shared*/);

        std::vector<std::string> availablePlugins() const;

    private:
        using PluginPath = std::string;
        using PluginInstanceMethod = std::function<PluginInterface* (PluginServiceInterface&)>;
        std::unordered_map<PluginPath, PluginHandle<PluginInterface, PluginServiceInterface>> plugins_;

        boost::filesystem::path pluginDirectory_;

        std::string pluginVersion_;
        std::string compilerToken_;
        std::string serviceVersion_;
    };

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    template<typename... Args>
    PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::PluginFactory(const boost::filesystem::path& pluginDirectory, Args&&... args)
        : details::PolicyHolder<PluginServiceInterface, PolicyOwnershipProperty>(std::forward<Args>(args)...)
        , pluginDirectory_(pluginDirectory)
    {
        if(!boost::filesystem::exists(pluginDirectory_))
        {
            throw PluginPathDoesntExist(pluginDirectory_);
        }

        if(!boost::filesystem::is_directory(pluginDirectory_))
        {
            throw PluginPathIsntDirectory(pluginDirectory_);
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::load()
    {
        for(boost::filesystem::directory_iterator iter(pluginDirectory_), end; iter != end; ++iter)
        {
            // TODO: check each regular file's extension to see if it is the correct
            // extension for a shared lib on this platform.
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::load(const boost::filesystem::path& pluginPath)
    {
        try
        {
            details::PluginLoader loader(pluginPath);

            loader.validateCompiler(compilerToken_);
            loader.validatePluginVersion(pluginVersion_);
            loader.validatePluginServiceVersion(serviceVersion_);

            auto pluginHandle = loader.getPluginHandle<PluginInterface, PluginServiceInterface>();
            plugins_.emplace(pluginPath.string(), pluginHandle);
        }
        // TODO: make this exception more specific, we don't want to catch all of
        // e
        catch(const std::exception& e)
        {
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::unload()
    {
        plugins_.clear();
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::unload(const boost::filesystem::path& pluginPath)
    {
        auto iter = plugins_.find(pluginPath.string());
        if(iter != plugins_.end())
        {
            plugins_.erase(iter);
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::unique_ptr<PluginInterface> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::instance(const std::string& pluginName)
    {
        std::unique_ptr<PluginInterface> p;

        auto iter = plugins_.find(pluginName);
        if(iter != plugins_.end())
        {
            auto& createPlugin = iter->second;
            p.reset(createPlugin(this->policy_));
        }

        return p;
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::shared_ptr<PluginInterface> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::instance(const std::string& pluginName, AsSharedTagType)
    {
        std::shared_ptr<PluginInterface> p;

        auto iter = plugins_.find(pluginName);
        if(iter != plugins_.end())
        {
            auto& createPlugin = iter->second;
            p.reset(createPlugin(this->policy_));
        }

        return p;
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::vector<std::string> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::availablePlugins() const
    {
        std::vector<std::string> plugins;
        plugins.reserve(plugins_.size());

        for(const auto& info : plugins_)
        {
            const auto& key = info.first;
            plugins.push_back(key);
        }

        return plugins;
    }
}
<commit_msg>comment: improving comments.<commit_after>#pragma once
#include <PluginFactory/details/NullPluginService.hpp>
#include <PluginFactory/details/PluginHandle.hpp>
#include <PluginFactory/details/PolicyHolder.hpp>
#include <PluginFactory/details/PluginLoader.hpp>
#include <PluginFactory/details/PolicyProperties.hpp>
#include <PluginFactory/Exceptions.hpp>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

namespace PluginFactory {

    // A tag type to indicate we want to create a std::shared_ptr of the plugin
    // rather than std::unique_ptr
    struct AsSharedTagType {};

    // <PluginInterface> is the abstract interface of the plugin object itself. You'll need
    // a PluginFactory for each different type of plugin you wish to support.
    //
    // <PluginServiceInterface> is the interface given to the plugin to allow it to make
    // modifications to the main program. This is to encourage plugin developers not to
    // engage in crazy behavior like calling willy-nilly into the base process's code.
    //
    // NOTE: lifetime management using plugins can be difficult. It is essential
    // the PluginFactory stays in scope longer than any instanced plugin. Failure
    // to do so will most likely end in the process crashing.
    template<class PluginInterface, class PluginServiceInterface = details::NullPluginService, class PolicyOwnershipProperty = details::PolicyIsInternal>
    class PluginFactory : public details::PolicyHolder<PluginServiceInterface, PolicyOwnershipProperty>
    {
    public:
        static AsSharedTagType create_shared;

        // @pluginDirectory is the directory path to load plugins from.
        template<typename... Args>
        PluginFactory(const boost::filesystem::path& pluginDirectory, Args&&... args);

        void load();        // load all found plugins
        void load(const boost::filesystem::path& pluginPath);   // load a specific plugin (@pluginPath)

        void unload();      // unload all loaded plugins
        void unload(const boost::filesystem::path& pluginPath); // unload a specific plugin (@pluginPath)

        std::unique_ptr<PluginInterface> instance(const std::string& plugin);
        std::shared_ptr<PluginInterface> instance(const std::string& pluginName, AsSharedTagType /*create_shared*/);

        std::vector<std::string> availablePlugins() const;

    private:
        using PluginPath = std::string;
        using PluginInstanceMethod = std::function<PluginInterface* (PluginServiceInterface&)>;
        std::unordered_map<PluginPath, PluginHandle<PluginInterface, PluginServiceInterface>> plugins_;

        boost::filesystem::path pluginDirectory_;

        std::string pluginVersion_;
        std::string compilerToken_;
        std::string serviceVersion_;
    };

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    template<typename... Args>
    PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::PluginFactory(const boost::filesystem::path& pluginDirectory, Args&&... args)
        : details::PolicyHolder<PluginServiceInterface, PolicyOwnershipProperty>(std::forward<Args>(args)...)
        , pluginDirectory_(pluginDirectory)
    {
        if(!boost::filesystem::exists(pluginDirectory_))
        {
            throw PluginPathDoesntExist(pluginDirectory_);
        }

        if(!boost::filesystem::is_directory(pluginDirectory_))
        {
            throw PluginPathIsntDirectory(pluginDirectory_);
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::load()
    {
        for(boost::filesystem::directory_iterator iter(pluginDirectory_), end; iter != end; ++iter)
        {
            // TODO: check each regular file's extension to see if it is the correct
            // extension for a shared lib on this platform.
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::load(const boost::filesystem::path& pluginPath)
    {
        try
        {
            details::PluginLoader loader(pluginPath);

            loader.validateCompiler(compilerToken_);
            loader.validatePluginVersion(pluginVersion_);
            loader.validatePluginServiceVersion(serviceVersion_);

            auto pluginHandle = loader.getPluginHandle<PluginInterface, PluginServiceInterface>();
            plugins_.emplace(pluginPath.string(), pluginHandle);
        }
        // TODO: make this exception more specific, we don't want to catch all of
        // e
        catch(const std::exception& e)
        {
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::unload()
    {
        plugins_.clear();
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    void PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::unload(const boost::filesystem::path& pluginPath)
    {
        auto iter = plugins_.find(pluginPath.string());
        if(iter != plugins_.end())
        {
            plugins_.erase(iter);
        }
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::unique_ptr<PluginInterface> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::instance(const std::string& pluginName)
    {
        std::unique_ptr<PluginInterface> p;

        auto iter = plugins_.find(pluginName);
        if(iter != plugins_.end())
        {
            auto& createPlugin = iter->second;
            p.reset(createPlugin(this->policy_));
        }

        return p;
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::shared_ptr<PluginInterface> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::instance(const std::string& pluginName, AsSharedTagType)
    {
        std::shared_ptr<PluginInterface> p;

        auto iter = plugins_.find(pluginName);
        if(iter != plugins_.end())
        {
            auto& createPlugin = iter->second;
            p.reset(createPlugin(this->policy_));
        }

        return p;
    }

    template<class PluginInterface, class PluginServiceInterface, class PolicyOwnershipProperty>
    std::vector<std::string> PluginFactory<PluginInterface, PluginServiceInterface, PolicyOwnershipProperty>::availablePlugins() const
    {
        std::vector<std::string> plugins;
        plugins.reserve(plugins_.size());

        for(const auto& info : plugins_)
        {
            const auto& key = info.first;
            plugins.push_back(key);
        }

        return plugins;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <graphene/witness/witness.hpp>

#include <graphene/chain/database.hpp>
#include <graphene/chain/witness_object.hpp>

#include <graphene/utilities/key_conversion.hpp>

#include <fc/thread/thread.hpp>

#include <iostream>

using namespace graphene::witness_plugin;
using std::string;
using std::vector;

namespace bpo = boost::program_options;

void new_chain_banner( const graphene::chain::database& db )
{
   ilog("\n"
      "********************************\n"
      "*                              *\n"
      "*   ------- NEW CHAIN ------   *\n"
      "*   - Welcome to Graphene! -   *\n"
      "*   ------------------------   *\n"
      "*                              *\n"
      "********************************\n"
      "\n");
   if( db.get_slot_at_time( fc::time_point::now() ) > 200 )
   {
      wlog("Your genesis seems to have an old timestamp");
      wlog("Please consider using the --genesis-timestamp option to give your genesis a recent timestamp");
   }
}

void witness_plugin::plugin_set_program_options(
   boost::program_options::options_description& command_line_options,
   boost::program_options::options_description& config_file_options)
{
   auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
   string witness_id_example = fc::json::to_string(chain::witness_id_type(5));
   command_line_options.add_options()
         ("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale.")
         ("required-participation", bpo::value<uint32_t>()->default_value(33), "Percent of witnesses (0-100) that must be participating in order to produce blocks")
         ("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
          ("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
         ("private-key", bpo::value<vector<string>>()->composing()->multitoken()->
          DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
          "Tuple of [PublicKey, WIF private key] (may specify multiple times)")
         ;
   config_file_options.add(command_line_options);
}

std::string witness_plugin::plugin_name()const
{
   return "witness";
}

void witness_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
   ilog("witness plugin:  plugin_initialize() begin");
   _options = &options;
   LOAD_VALUE_SET(options, "witness-id", _witnesses, chain::witness_id_type)

   if( options.count("private-key") )
   {
      const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>();
      for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
      {
         auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string, 5);
         ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first));
         fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
         if (!private_key)
         {
            // the key isn't in WIF format; see if they are still passing the old native private key format.  This is
            // just here to ease the transition, can be removed soon
            try
            {
               private_key = fc::variant(key_id_to_wif_pair.second, 2).as<fc::ecc::private_key>(1);
            }
            catch (const fc::exception&)
            {
               FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
            }
         }
         _private_keys[key_id_to_wif_pair.first] = *private_key;
      }
   }
   if(options.count("required-participation"))
   {
       auto required_participation = options["required-participation"].as<uint32_t>();
       FC_ASSERT(required_participation <= 100);
       _required_witness_participation = options["required-participation"].as<uint32_t>()*GRAPHENE_1_PERCENT;
       if(required_participation < 10)
           wlog("witness plugin: Warning - Low required participation of ${rp}% found", ("rp", required_participation));
       else if(required_participation > 90)
           wlog("witness plugin: Warning - High required participation of ${rp}% found", ("rp", required_participation));
   }
   ilog("witness plugin:  plugin_initialize() end");
} FC_LOG_AND_RETHROW() }

void witness_plugin::plugin_startup()
{ try {
   ilog("witness plugin:  plugin_startup() begin");
   chain::database& d = database();
   if( !_witnesses.empty() )
   {
      ilog("Launching block production for ${n} witnesses.", ("n", _witnesses.size()));
      app().set_block_production(true);
      if( _production_enabled )
      {
         if( d.head_block_num() == 0 )
            new_chain_banner(d);
         _production_skip_flags |= graphene::chain::database::skip_undo_history_check;
      }
      refresh_witness_key_cache();
      d.applied_block.connect( [this]( const chain::signed_block& b )
      {
         refresh_witness_key_cache();
      });
      schedule_production_loop();
   }
   else
   {
      ilog("No witness configured.");
   }
   ilog("witness plugin:  plugin_startup() end");
} FC_CAPTURE_AND_RETHROW() }

void witness_plugin::plugin_shutdown()
{
   stop_block_production();
}

void witness_plugin::stop_block_production()
{
   _shutting_down = true;

   try {
      if( _block_production_task.valid() )
         _block_production_task.cancel_and_wait(__FUNCTION__);
   } catch(fc::canceled_exception&) {
      //Expected exception. Move along.
   } catch(fc::exception& e) {
      edump((e.to_detail_string()));
   }
}

void witness_plugin::refresh_witness_key_cache()
{
   const auto& db = database();
   for( const chain::witness_id_type wit_id : _witnesses )
   {
      const chain::witness_object* wit_obj = db.find( wit_id );
      if( wit_obj )
         _witness_key_cache[wit_id] = wit_obj->signing_key;
      else
         _witness_key_cache[wit_id] = fc::optional<chain::public_key_type>();
   }
}

void witness_plugin::schedule_production_loop()
{
   if (_shutting_down) return;

   //Schedule for the next second's tick regardless of chain state
   // If we would wait less than 50ms, wait for the whole second.
   fc::time_point now = fc::time_point::now();
   int64_t time_to_next_second = 1000000 - (now.time_since_epoch().count() % 1000000);
   if( time_to_next_second < 50000 )      // we must sleep for at least 50ms
       time_to_next_second += 1000000;

   fc::time_point next_wakeup( now + fc::microseconds( time_to_next_second ) );

   _block_production_task = fc::schedule([this]{block_production_loop();},
                                         next_wakeup, "Witness Block Production");
}

block_production_condition::block_production_condition_enum witness_plugin::block_production_loop()
{
   block_production_condition::block_production_condition_enum result;
   fc::limited_mutable_variant_object capture( GRAPHENE_MAX_NESTED_OBJECTS );

   if (_shutting_down)
   {
      result = block_production_condition::shutdown;
   }
   else
   {
      try
      {
         result = maybe_produce_block(capture);
      }
      catch( const fc::canceled_exception& )
      {
         //We're trying to exit. Go ahead and let this one out.
         throw;
      }
      catch( const fc::exception& e )
      {
         elog("Got exception while generating block:\n${e}", ("e", e.to_detail_string()));
         result = block_production_condition::exception_producing_block;
      }
   }

   switch( result )
   {
      case block_production_condition::produced:
         ilog("Generated block #${n} with ${x} transaction(s) and timestamp ${t} at time ${c}", (capture));
         break;
      case block_production_condition::not_synced:
         ilog("Not producing block because production is disabled until we receive a recent block (see: --enable-stale-production)");
         break;
      case block_production_condition::not_my_turn:
         break;
      case block_production_condition::not_time_yet:
         break;
      case block_production_condition::no_private_key:
         ilog("Not producing block because I don't have the private key for ${scheduled_key}", (capture) );
         break;
      case block_production_condition::low_participation:
         elog("Not producing block because node appears to be on a minority fork with only ${pct}% witness participation", (capture) );
         break;
      case block_production_condition::lag:
         elog("Not producing block because node didn't wake up within 2500ms of the slot time.");
         break;
      case block_production_condition::exception_producing_block:
         elog( "exception producing block" );
         break;
      case block_production_condition::shutdown:
         ilog( "shutdown producing block" );
         return result;
      default:
         elog( "unknown condition ${result} while producing block", ("result", (unsigned char)result) );
         break;
   }

   schedule_production_loop();
   return result;
}

block_production_condition::block_production_condition_enum witness_plugin::maybe_produce_block( fc::limited_mutable_variant_object& capture )
{
   chain::database& db = database();
   fc::time_point now_fine = fc::time_point::now();
   fc::time_point_sec now = now_fine + fc::microseconds( 500000 );

   // If the next block production opportunity is in the present or future, we're synced.
   if( !_production_enabled )
   {
      if( db.get_slot_time(1) >= now )
         _production_enabled = true;
      else
         return block_production_condition::not_synced;
   }

   // is anyone scheduled to produce now or one second in the future?
   uint32_t slot = db.get_slot_at_time( now );
   if( slot == 0 )
   {
      capture("next_time", db.get_slot_time(1));
      return block_production_condition::not_time_yet;
   }

   //
   // this assert should not fail, because now <= db.head_block_time()
   // should have resulted in slot == 0.
   //
   // if this assert triggers, there is a serious bug in get_slot_at_time()
   // which would result in allowing a later block to have a timestamp
   // less than or equal to the previous block
   //
   assert( now > db.head_block_time() );

   graphene::chain::witness_id_type scheduled_witness = db.get_scheduled_witness( slot );
   // we must control the witness scheduled to produce the next block.
   if( _witnesses.find( scheduled_witness ) == _witnesses.end() )
   {
      capture("scheduled_witness", scheduled_witness);
      return block_production_condition::not_my_turn;
   }

   fc::time_point_sec scheduled_time = db.get_slot_time( slot );
   graphene::chain::public_key_type scheduled_key = *_witness_key_cache[scheduled_witness]; // should be valid
   auto private_key_itr = _private_keys.find( scheduled_key );

   if( private_key_itr == _private_keys.end() )
   {
      capture("scheduled_key", scheduled_key);
      return block_production_condition::no_private_key;
   }

   uint32_t prate = db.witness_participation_rate();
   if( prate < _required_witness_participation )
   {
      capture("pct", uint32_t(100*uint64_t(prate) / GRAPHENE_1_PERCENT));
      return block_production_condition::low_participation;
   }

   if( llabs((scheduled_time - now).count()) > fc::milliseconds( 2500 ).count() )
   {
      capture("scheduled_time", scheduled_time)("now", now);
      return block_production_condition::lag;
   }

   auto block = db.generate_block(
      scheduled_time,
      scheduled_witness,
      private_key_itr->second,
      _production_skip_flags
      );
   capture("n", block.block_num())("t", block.timestamp)("c", now)("x", block.transactions.size());
   fc::async( [this,block](){ p2p_node().broadcast(net::block_message(block)); } );

   return block_production_condition::produced;
}
<commit_msg>wrap long lines in witness.cpp file<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <graphene/witness/witness.hpp>

#include <graphene/chain/database.hpp>
#include <graphene/chain/witness_object.hpp>

#include <graphene/utilities/key_conversion.hpp>

#include <fc/thread/thread.hpp>

#include <iostream>

using namespace graphene::witness_plugin;
using std::string;
using std::vector;

namespace bpo = boost::program_options;

void new_chain_banner( const graphene::chain::database& db )
{
   ilog("\n"
      "********************************\n"
      "*                              *\n"
      "*   ------- NEW CHAIN ------   *\n"
      "*   - Welcome to Graphene! -   *\n"
      "*   ------------------------   *\n"
      "*                              *\n"
      "********************************\n"
      "\n");
   if( db.get_slot_at_time( fc::time_point::now() ) > 200 )
   {
      wlog("Your genesis seems to have an old timestamp");
      wlog("Please consider using the --genesis-timestamp option to give your genesis a recent timestamp");
   }
}

void witness_plugin::plugin_set_program_options(
   boost::program_options::options_description& command_line_options,
   boost::program_options::options_description& config_file_options)
{
   auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
   string witness_id_example = fc::json::to_string(chain::witness_id_type(5));
   command_line_options.add_options()
         ("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}),
               "Enable block production, even if the chain is stale.")
         ("required-participation", bpo::value<uint32_t>()->default_value(33),
               "Percent of witnesses (0-100) that must be participating in order to produce blocks")
         ("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
               ("ID of witness controlled by this node (e.g. " + witness_id_example +
               ", quotes are required, may specify multiple times)").c_str())
         ("private-key", bpo::value<vector<string>>()->composing()->multitoken()->
          DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()),
                graphene::utilities::key_to_wif(default_priv_key))),
                "Tuple of [PublicKey, WIF private key] (may specify multiple times)")
         ;
   config_file_options.add(command_line_options);
}

std::string witness_plugin::plugin_name()const
{
   return "witness";
}

void witness_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
   ilog("witness plugin:  plugin_initialize() begin");
   _options = &options;
   LOAD_VALUE_SET(options, "witness-id", _witnesses, chain::witness_id_type)

   if( options.count("private-key") )
   {
      const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>();
      for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
      {
         auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >
               (key_id_to_wif_pair_string, 5);
         ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first));
         fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
         if (!private_key)
         {
            // the key isn't in WIF format; see if they are still passing the old native private key format.  This is
            // just here to ease the transition, can be removed soon
            try
            {
               private_key = fc::variant(key_id_to_wif_pair.second, 2).as<fc::ecc::private_key>(1);
            }
            catch (const fc::exception&)
            {
               FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
            }
         }
         _private_keys[key_id_to_wif_pair.first] = *private_key;
      }
   }
   if(options.count("required-participation"))
   {
       auto required_participation = options["required-participation"].as<uint32_t>();
       FC_ASSERT(required_participation <= 100);
       _required_witness_participation = options["required-participation"].as<uint32_t>()*GRAPHENE_1_PERCENT;
       if(required_participation < 10)
           wlog("witness plugin: Warning - Low required participation of ${rp}% found", ("rp", required_participation));
       else if(required_participation > 90)
           wlog("witness plugin: Warning - High required participation of ${rp}% found", ("rp", required_participation));
   }
   ilog("witness plugin:  plugin_initialize() end");
} FC_LOG_AND_RETHROW() }

void witness_plugin::plugin_startup()
{ try {
   ilog("witness plugin:  plugin_startup() begin");
   chain::database& d = database();
   if( !_witnesses.empty() )
   {
      ilog("Launching block production for ${n} witnesses.", ("n", _witnesses.size()));
      app().set_block_production(true);
      if( _production_enabled )
      {
         if( d.head_block_num() == 0 )
            new_chain_banner(d);
         _production_skip_flags |= graphene::chain::database::skip_undo_history_check;
      }
      refresh_witness_key_cache();
      d.applied_block.connect( [this]( const chain::signed_block& b )
      {
         refresh_witness_key_cache();
      });
      schedule_production_loop();
   }
   else
   {
      ilog("No witness configured.");
   }
   ilog("witness plugin:  plugin_startup() end");
} FC_CAPTURE_AND_RETHROW() }

void witness_plugin::plugin_shutdown()
{
   stop_block_production();
}

void witness_plugin::stop_block_production()
{
   _shutting_down = true;

   try {
      if( _block_production_task.valid() )
         _block_production_task.cancel_and_wait(__FUNCTION__);
   } catch(fc::canceled_exception&) {
      //Expected exception. Move along.
   } catch(fc::exception& e) {
      edump((e.to_detail_string()));
   }
}

void witness_plugin::refresh_witness_key_cache()
{
   const auto& db = database();
   for( const chain::witness_id_type wit_id : _witnesses )
   {
      const chain::witness_object* wit_obj = db.find( wit_id );
      if( wit_obj )
         _witness_key_cache[wit_id] = wit_obj->signing_key;
      else
         _witness_key_cache[wit_id] = fc::optional<chain::public_key_type>();
   }
}

void witness_plugin::schedule_production_loop()
{
   if (_shutting_down) return;

   //Schedule for the next second's tick regardless of chain state
   // If we would wait less than 50ms, wait for the whole second.
   fc::time_point now = fc::time_point::now();
   int64_t time_to_next_second = 1000000 - (now.time_since_epoch().count() % 1000000);
   if( time_to_next_second < 50000 )      // we must sleep for at least 50ms
       time_to_next_second += 1000000;

   fc::time_point next_wakeup( now + fc::microseconds( time_to_next_second ) );

   _block_production_task = fc::schedule([this]{block_production_loop();},
                                         next_wakeup, "Witness Block Production");
}

block_production_condition::block_production_condition_enum witness_plugin::block_production_loop()
{
   block_production_condition::block_production_condition_enum result;
   fc::limited_mutable_variant_object capture( GRAPHENE_MAX_NESTED_OBJECTS );

   if (_shutting_down)
   {
      result = block_production_condition::shutdown;
   }
   else
   {
      try
      {
         result = maybe_produce_block(capture);
      }
      catch( const fc::canceled_exception& )
      {
         //We're trying to exit. Go ahead and let this one out.
         throw;
      }
      catch( const fc::exception& e )
      {
         elog("Got exception while generating block:\n${e}", ("e", e.to_detail_string()));
         result = block_production_condition::exception_producing_block;
      }
   }

   switch( result )
   {
      case block_production_condition::produced:
         ilog("Generated block #${n} with ${x} transaction(s) and timestamp ${t} at time ${c}", (capture));
         break;
      case block_production_condition::not_synced:
         ilog("Not producing block because production is disabled until we receive a recent block "
              "(see: --enable-stale-production)");
         break;
      case block_production_condition::not_my_turn:
         break;
      case block_production_condition::not_time_yet:
         break;
      case block_production_condition::no_private_key:
         ilog("Not producing block because I don't have the private key for ${scheduled_key}", (capture) );
         break;
      case block_production_condition::low_participation:
         elog("Not producing block because node appears to be on a minority fork with only ${pct}% witness participation",
               (capture) );
         break;
      case block_production_condition::lag:
         elog("Not producing block because node didn't wake up within 2500ms of the slot time.");
         break;
      case block_production_condition::exception_producing_block:
         elog( "exception producing block" );
         break;
      case block_production_condition::shutdown:
         ilog( "shutdown producing block" );
         return result;
      default:
         elog( "unknown condition ${result} while producing block", ("result", (unsigned char)result) );
         break;
   }

   schedule_production_loop();
   return result;
}

block_production_condition::block_production_condition_enum witness_plugin::maybe_produce_block(
      fc::limited_mutable_variant_object& capture )
{
   chain::database& db = database();
   fc::time_point now_fine = fc::time_point::now();
   fc::time_point_sec now = now_fine + fc::microseconds( 500000 );

   // If the next block production opportunity is in the present or future, we're synced.
   if( !_production_enabled )
   {
      if( db.get_slot_time(1) >= now )
         _production_enabled = true;
      else
         return block_production_condition::not_synced;
   }

   // is anyone scheduled to produce now or one second in the future?
   uint32_t slot = db.get_slot_at_time( now );
   if( slot == 0 )
   {
      capture("next_time", db.get_slot_time(1));
      return block_production_condition::not_time_yet;
   }

   //
   // this assert should not fail, because now <= db.head_block_time()
   // should have resulted in slot == 0.
   //
   // if this assert triggers, there is a serious bug in get_slot_at_time()
   // which would result in allowing a later block to have a timestamp
   // less than or equal to the previous block
   //
   assert( now > db.head_block_time() );

   graphene::chain::witness_id_type scheduled_witness = db.get_scheduled_witness( slot );
   // we must control the witness scheduled to produce the next block.
   if( _witnesses.find( scheduled_witness ) == _witnesses.end() )
   {
      capture("scheduled_witness", scheduled_witness);
      return block_production_condition::not_my_turn;
   }

   fc::time_point_sec scheduled_time = db.get_slot_time( slot );
   graphene::chain::public_key_type scheduled_key = *_witness_key_cache[scheduled_witness]; // should be valid
   auto private_key_itr = _private_keys.find( scheduled_key );

   if( private_key_itr == _private_keys.end() )
   {
      capture("scheduled_key", scheduled_key);
      return block_production_condition::no_private_key;
   }

   uint32_t prate = db.witness_participation_rate();
   if( prate < _required_witness_participation )
   {
      capture("pct", uint32_t(100*uint64_t(prate) / GRAPHENE_1_PERCENT));
      return block_production_condition::low_participation;
   }

   if( llabs((scheduled_time - now).count()) > fc::milliseconds( 2500 ).count() )
   {
      capture("scheduled_time", scheduled_time)("now", now);
      return block_production_condition::lag;
   }

   auto block = db.generate_block(
      scheduled_time,
      scheduled_witness,
      private_key_itr->second,
      _production_skip_flags
      );
   capture("n", block.block_num())("t", block.timestamp)("c", now)("x", block.transactions.size());
   fc::async( [this,block](){ p2p_node().broadcast(net::block_message(block)); } );

   return block_production_condition::produced;
}
<|endoftext|>


<commit_before><commit_msg>Remove dead code<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/remote_command.hpp"

#include <caf/scoped_actor.hpp>

#include <iostream>

#include "vast/detail/narrow.hpp"
#include "vast/error.hpp"
#include "vast/logger.hpp"
#include "vast/system/connect_to_node.hpp"

using namespace std::chrono_literals;

namespace vast::system {

caf::message
remote_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Get a convenient and blocking way to interact with actors.
  caf::scoped_actor self{sys};
  // Get VAST node.
  auto node_opt = connect_to_node(self, invocation.options);
  if (!node_opt)
    return caf::make_message(std::move(node_opt.error()));
  auto node = std::move(*node_opt);
  self->monitor(node);
  // Delegate invocation to node.
  caf::error err;
  self->send(node, std::move(invocation));
  self->receive(
    [&](const caf::down_msg&) {
      err = ec::remote_node_down;
    },
    [&](caf::ok_atom) {
      // Standard reply for success.
    },
    [&](caf::actor&) {
      // "vast spawn" returns an actor.
    },
    [&](const std::string& str) {
      // Status messages or query results.
      std::cout << str << std::endl;
    },
    [&](caf::error& e) {
      err = std::move(e);
    }
  );
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<commit_msg>Allow all remote commands to work with `--node`<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/remote_command.hpp"

#include "vast/detail/narrow.hpp"
#include "vast/error.hpp"
#include "vast/logger.hpp"
#include "vast/scope_linked.hpp"
#include "vast/system/spawn_or_connect_to_node.hpp"

#include <caf/actor.hpp>
#include <caf/scoped_actor.hpp>

#include <iostream>

using namespace std::chrono_literals;

namespace vast::system {

caf::message
remote_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Get a convenient and blocking way to interact with actors.
  caf::scoped_actor self{sys};
  // Get VAST node.
  auto node_opt
    = spawn_or_connect_to_node(self, invocation.options, content(sys.config()));
  if (auto err = caf::get_if<caf::error>(&node_opt))
    return caf::make_message(std::move(*err));
  auto& node = caf::holds_alternative<caf::actor>(node_opt)
                 ? caf::get<caf::actor>(node_opt)
                 : caf::get<scope_linked_actor>(node_opt).get();
  self->monitor(node);
  // Delegate invocation to node.
  caf::error err;
  self->send(node, std::move(invocation));
  self->receive(
    [&](const caf::down_msg&) {
      err = ec::remote_node_down;
    },
    [&](caf::ok_atom) {
      // Standard reply for success.
    },
    [&](caf::actor&) {
      // "vast spawn" returns an actor.
    },
    [&](const std::string& str) {
      // Status messages or query results.
      std::cout << str << std::endl;
    },
    [&](caf::error& e) {
      err = std::move(e);
    }
  );
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<|endoftext|>


<commit_before>#pragma once
/*
 * Copyright (c) 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifndef _QI_DETAILS_TRACKABLE_HXX_
#define _QI_DETAILS_TRACKABLE_HXX_

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/function_types/result_type.hpp>

namespace qi
{
  template<typename T>
  inline Trackable<T>::Trackable(T* ptr)
  : _wasDestroyed(false)
  {
    _ptr = boost::shared_ptr<T>(ptr, boost::bind(&Trackable::_destroyed, _1));
  }

  template<typename T>
  inline void Trackable<T>::destroy()
  {
    _ptr.reset();
    wait();
  }

  template<typename T>
  inline void Trackable<T>::wait()
  {
    boost::mutex::scoped_lock lock(_mutex);
    while (!_wasDestroyed)
    {
      _cond.wait(lock);
    }
  }

  template<typename T>
  inline void Trackable<T>::_destroyed()
  {
    // unblock
    _wasDestroyed = true;
    _cond.notify_all();
  }

  template<typename T>
  inline Trackable<T>::~Trackable()
  {
    // We expect destroy() to have been called from parent destructor, so from
    // this thread.
    if (!_wasDestroyed)
    {
      qiLogError("qi.Trackable") << "Trackable destroyed without calling destroy()";
      // do it to mitigate the effect, but it's too late
      destroy();
    }
  }

  template<typename T>
  inline boost::shared_ptr<T> Trackable<T>::lock()
  {
    return _ptr;
  }

  template<typename T>
  inline boost::weak_ptr<T> Trackable<T>::weakPtr()
  {
    return boost::weak_ptr<T>(_ptr);
  }

  namespace detail
  {
    // Functor that locks a weak ptr and make a call if successful
    // Generalize on shared_ptr and weak_ptr types in case we ever have
    // other types with their semantics
    template<typename WT, typename ST, typename F>
    class LockAndCall
    {
    public:
      typedef typename boost::function_types::result_type<F>::type Result;
      LockAndCall(const WT& arg, boost::function<F> func)
      : _wptr(arg)
      , _f(func)
      {}

#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
     QI_GEN_MAYBE_TEMPLATE_OPEN(comma)                        \
     ATYPEDECL                                             \
     QI_GEN_MAYBE_TEMPLATE_CLOSE(comma)                        \
     Result operator()(ADECL) {                        \
       ST s = _wptr.lock();                                    \
        if (s)                                     \
          return _f(AUSE);                        \
        else                                       \
          return Result();                         \
      }
      QI_GEN(genCall)
#undef genCall
      WT _wptr;
      boost::function<F> _f;
    };

    template<typename T, bool IS_TRACKABLE> struct BindTransform
    {
      typedef const T& type;
      static type transform(const T& arg)
      {
        return arg;
      }
      template<typename F>
      static boost::function<F> wrap(const T& arg, boost::function<F> func)
      {
        return func;
      }
    };

    template<typename T> struct BindTransform<boost::weak_ptr<T>, false >
    {
      typedef T* type;
      static T* transform(const boost::weak_ptr<T>& arg)
      {
        // Note that we assume that lock if successful always return the same pointer
        // And that if lock fails once, it will fail forever from that point
        return arg.lock().get();
      }
      template<typename F>
      static boost::function<F> wrap(const boost::weak_ptr<T>& arg, boost::function<F> func)
      {
        return LockAndCall<boost::weak_ptr<T>, boost::shared_ptr<T>, F>(arg, func);
      }
    };

    template<typename T> struct BindTransform<T*, true>
    {
      typedef T* type;
      static T* transform(T* const & arg)
      {
        // Note that we assume that lock if successful always return the same pointer
        return arg;
      }
      template<typename F>
      static boost::function<F> wrap(T*const & arg, boost::function<F> func)
      {
        return LockAndCall<boost::weak_ptr<T>, boost::shared_ptr<T>, F>(arg->weakPtr(), func);
      }
    };
  }

#ifndef DOXYGEN
  template<typename RF, typename AF>
  boost::function<RF> bind(const AF& fun)
  {
    return fun;
  }
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
template<typename RF, typename AF, typename ARG0 comma ATYPEDECL>      \
  boost::function<RF> bind(const AF& fun, const ARG0& arg0 comma ADECL)  \
  {                                                                      \
    typedef typename detail::BindTransform<ARG0, boost::is_base_of<TrackableBase, typename boost::remove_pointer<ARG0>::type>::value> Transform;     \
    typename Transform::type transformed = Transform::transform(arg0);   \
    boost::function<RF> f = boost::bind(fun, transformed comma AUSE);           \
    return Transform::wrap(arg0, f);                                     \
  }
  QI_GEN(genCall)
#undef genCall
#endif // DOXYGEN
}

#endif  // _QI_DETAILS_TRACKABLE_HXX_
<commit_msg>Trackable: Fix a race condition (sic).<commit_after>#pragma once
/*
 * Copyright (c) 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifndef _QI_DETAILS_TRACKABLE_HXX_
#define _QI_DETAILS_TRACKABLE_HXX_

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/function_types/result_type.hpp>

namespace qi
{
  template<typename T>
  inline Trackable<T>::Trackable(T* ptr)
  : _wasDestroyed(false)
  {
    _ptr = boost::shared_ptr<T>(ptr, boost::bind(&Trackable::_destroyed, _1));
  }

  template<typename T>
  inline void Trackable<T>::destroy()
  {
    _ptr.reset();
    wait();
  }

  template<typename T>
  inline void Trackable<T>::wait()
  {
    boost::mutex::scoped_lock lock(_mutex);
    while (!_wasDestroyed)
    {
      _cond.wait(lock);
    }
  }

  template<typename T>
  inline void Trackable<T>::_destroyed()
  {
    // unblock
    boost::mutex::scoped_lock lock(_mutex);
    _wasDestroyed = true;
    _cond.notify_all();
  }

  template<typename T>
  inline Trackable<T>::~Trackable()
  {
    // We expect destroy() to have been called from parent destructor, so from
    // this thread.
    if (!_wasDestroyed)
    {
      qiLogError("qi.Trackable") << "Trackable destroyed without calling destroy()";
      // do it to mitigate the effect, but it's too late
      destroy();
    }
  }

  template<typename T>
  inline boost::shared_ptr<T> Trackable<T>::lock()
  {
    return _ptr;
  }

  template<typename T>
  inline boost::weak_ptr<T> Trackable<T>::weakPtr()
  {
    return boost::weak_ptr<T>(_ptr);
  }

  namespace detail
  {
    // Functor that locks a weak ptr and make a call if successful
    // Generalize on shared_ptr and weak_ptr types in case we ever have
    // other types with their semantics
    template<typename WT, typename ST, typename F>
    class LockAndCall
    {
    public:
      typedef typename boost::function_types::result_type<F>::type Result;
      LockAndCall(const WT& arg, boost::function<F> func)
      : _wptr(arg)
      , _f(func)
      {}

#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
     QI_GEN_MAYBE_TEMPLATE_OPEN(comma)                        \
     ATYPEDECL                                             \
     QI_GEN_MAYBE_TEMPLATE_CLOSE(comma)                        \
     Result operator()(ADECL) {                        \
       ST s = _wptr.lock();                                    \
        if (s)                                     \
          return _f(AUSE);                        \
        else                                       \
          return Result();                         \
      }
      QI_GEN(genCall)
#undef genCall
      WT _wptr;
      boost::function<F> _f;
    };

    template<typename T, bool IS_TRACKABLE> struct BindTransform
    {
      typedef const T& type;
      static type transform(const T& arg)
      {
        return arg;
      }
      template<typename F>
      static boost::function<F> wrap(const T& arg, boost::function<F> func)
      {
        return func;
      }
    };

    template<typename T> struct BindTransform<boost::weak_ptr<T>, false >
    {
      typedef T* type;
      static T* transform(const boost::weak_ptr<T>& arg)
      {
        // Note that we assume that lock if successful always return the same pointer
        // And that if lock fails once, it will fail forever from that point
        return arg.lock().get();
      }
      template<typename F>
      static boost::function<F> wrap(const boost::weak_ptr<T>& arg, boost::function<F> func)
      {
        return LockAndCall<boost::weak_ptr<T>, boost::shared_ptr<T>, F>(arg, func);
      }
    };

    template<typename T> struct BindTransform<T*, true>
    {
      typedef T* type;
      static T* transform(T* const & arg)
      {
        // Note that we assume that lock if successful always return the same pointer
        return arg;
      }
      template<typename F>
      static boost::function<F> wrap(T*const & arg, boost::function<F> func)
      {
        return LockAndCall<boost::weak_ptr<T>, boost::shared_ptr<T>, F>(arg->weakPtr(), func);
      }
    };
  }

#ifndef DOXYGEN
  template<typename RF, typename AF>
  boost::function<RF> bind(const AF& fun)
  {
    return fun;
  }
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
template<typename RF, typename AF, typename ARG0 comma ATYPEDECL>      \
  boost::function<RF> bind(const AF& fun, const ARG0& arg0 comma ADECL)  \
  {                                                                      \
    typedef typename detail::BindTransform<ARG0, boost::is_base_of<TrackableBase, typename boost::remove_pointer<ARG0>::type>::value> Transform;     \
    typename Transform::type transformed = Transform::transform(arg0);   \
    boost::function<RF> f = boost::bind(fun, transformed comma AUSE);           \
    return Transform::wrap(arg0, f);                                     \
  }
  QI_GEN(genCall)
#undef genCall
#endif // DOXYGEN
}

#endif  // _QI_DETAILS_TRACKABLE_HXX_
<|endoftext|>