00001
00002 #include "artdaq-utilities/Plugins/MetricMacros.hh"
00003 #include "fhiclcpp/ParameterSet.h"
00004 #include "messagefacility/MessageLogger/MessageLogger.h"
00005 #define TRACE_NAME "procFile_metric"
00006 #include "trace.h"
00007
00008 #include <sys/stat.h>
00009 #include <fcntl.h>
00010 #include <stdlib.h>
00011 #include <ctime>
00012 #include <string>
00013 #include <boost/thread.hpp>
00014 #include <map>
00015
00016 namespace artdaq
00017 {
00024 class ProcFileMetric : public MetricPlugin
00025 {
00026 private:
00027 std::string pipe_;
00028 std::unordered_map<std::string, std::string> value_map_;
00029 bool stopped_;
00030 boost::thread thread_;
00031 public:
00042 explicit ProcFileMetric(fhicl::ParameterSet config) : MetricPlugin(config)
00043 , pipe_(pset.get<std::string>("pipe", "/tmp/eventQueueStat"))
00044 , value_map_()
00045 , stopped_(true)
00046 {
00047 auto names = pset.get<std::vector<std::string>>("names", std::vector<std::string>());
00048
00049 for (auto name : names)
00050 {
00051 value_map_[name] = "";
00052 }
00053
00054 int sts = mkfifo(pipe_.c_str(), 0777);
00055 if (sts != 0) { perror("ProcFileMetric mkfifo"); }
00056 TRACE(10, "ProcFileMetric mkfifo(" + pipe_ + ") sts=%d", sts);
00057 startMetrics();
00058 }
00059
00063 ~ProcFileMetric() {
00064 TRACE( 11, "~ProcFileMetric" );
00065 stopMetrics();
00066 }
00067
00072 std::string getLibName() const override { return "procFile"; }
00073
00079 void sendMetric_(const std::string& name, const std::string& value, const std::string&) override {
00080 if (value_map_.count(name)) {
00081 TRACE(12, "sendMetric_ setting value="+ value);
00082 value_map_[name] = value;
00083 }
00084 }
00085
00092 void sendMetric_(const std::string& name, const int& value, const std::string& unit) override {
00093 sendMetric_(name, std::to_string(value), unit);
00094 }
00095
00102 void sendMetric_(const std::string& name, const double& value, const std::string& unit) override {
00103 sendMetric_(name, std::to_string(value), unit);
00104 }
00105
00112 void sendMetric_(const std::string& name, const float& value, const std::string& unit) override {
00113 sendMetric_(name, std::to_string(value), unit);
00114 }
00115
00122 void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
00123 {
00124 sendMetric_(name, std::to_string(value), unit);
00125 }
00126
00130 void startMetrics_() override
00131 {
00132 if (stopped_)
00133 {
00134
00135 stopped_ = false;
00136 boost::thread::attributes attrs;
00137 attrs.set_stack_size(4096 * 200);
00138 thread_ = boost::thread(attrs, boost::bind(&ProcFileMetric::writePipe, this));
00139 }
00140 }
00141
00145 void stopMetrics_() override
00146 {
00147 if (!stopped_)
00148 {
00149 stopped_ = true;
00150
00151 TRACE(11, "stopMetrics_ before open " + pipe_);
00152 int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
00153 if (fd == -1) { perror("stopMetrics_ open(\"r\")"); exit(1); }
00154 TRACE(10, "stopMetrics_ between open and unlink" + pipe_ + " fd=%d", fd);
00155 unlink(pipe_.c_str());
00156 TRACE(11, "stopMetrics_ unlinked " + pipe_);
00157 # if 0
00158 char buf[256];
00159 read(fd, buf, sizeof(buf));
00160 # endif
00161 usleep(10000);
00162 close(fd);
00163 TRACE(11, "stopMetrics_ after close " + pipe_);
00164 if (thread_.joinable()) thread_.join();
00165 }
00166 }
00167
00171 void writePipe()
00172 {
00173 while (!stopped_)
00174 {
00175 TRACE(11, "writePipe before open");
00176 int fd = open(pipe_.c_str(), O_WRONLY);
00177 std::string str;
00178 for (auto value : value_map_) {
00179 TRACE(10, "writePipe open fd="+std::to_string(fd)+" name="+value.first+" value="+value.second );
00180 str += value.first + ": " + value.second + "\n";
00181
00182 }
00183 int sts = write(fd, str.c_str(), str.size());
00184 TRACE(11, "writePipe write complete sts=%d", sts);
00185 close(fd);
00186 TRACE(11, "writePipe after close -- about to usleep");
00187 usleep(400000);
00188 }
00189
00190 }
00191 };
00192 }
00193
00194 DEFINE_ARTDAQ_METRIC(artdaq::ProcFileMetric)