00001 #include "BeamData.h"
00002 #include <OnlineUtil/rawBlockIds.h>
00003 #include <OnlineUtil/rdChecksum.h>
00004 #include <OnlineUtil/rototalk.h>
00005 #include <OnlineUtil/rawBeamDataBlockLayout.h>
00006
00007 #include <map>
00008 #include <string>
00009 #include <vector>
00010 #include <cassert>
00011 #include <iostream>
00012 #include <cstdio>
00013 #include <unistd.h>
00014
00015 using namespace std;
00016
00017 struct Header {
00018 int nwords;
00019 int chksum;
00020 int blkid;
00021 };
00022 struct HeaderBlock {
00023 struct Header header;
00024 int sec, nsec, spill;
00025 };
00026
00027
00028 int make_block_id(int majorid, int minorid=0)
00029 {
00030 int cfns=(1<<1) + (1<<0);
00031 int csf = 0;
00032 return (csf << 28) + (cfns<<24) + (majorid<<8) + (minorid<<0);
00033 }
00034 class BeamDataImp {
00035 string fCurrentFile;
00036 int fSeconds, fNanosecs, fSpillcount;
00037 int fTclkEvent, fTclkDelay;
00038 struct DeviceData {
00039 DeviceData() : sec(0),msec(0),data(vector<int>()) {}
00040 ~DeviceData() {}
00041 int sec, msec;
00042 vector<int> data;
00043 };
00044 typedef map<string,DeviceData> Payload;
00045 typedef Payload::iterator PayloadItr;
00046 Payload fPayload;
00047
00048 public:
00049
00050 BeamDataImp() { this->clear(); fCurrentFile = ""; }
00051 ~BeamDataImp() {}
00052
00053 void clear() {
00054 fSeconds = fNanosecs = fSpillcount = 0;
00055 fTclkEvent = fTclkDelay = 0;
00056 fPayload.clear();
00057 }
00058 int words() {
00059 int s = 0;
00060
00061 s += zzzz_last;
00062
00063 s += pld_indx_data_start;
00064
00065
00066
00067 s += (pld_nvalues_offset+1) * fPayload.size();
00068
00069
00070 PayloadItr it, done = fPayload.end();
00071 for (it = fPayload.begin(); it != done; ++it) {
00072 s += it->second.data.size();
00073 }
00074 return s;
00075 }
00076
00077 long int* create_block() {
00078 int siz = this->words();
00079 long int* data = new long int[siz];
00080
00081
00082 long int* hdr = data;
00083 hdr[hdr_indx_size] = zzzz_last;
00084 hdr[hdr_indx_checksum] = 0;
00085 hdr[hdr_indx_blockid] = make_block_id(kMdBlockBeamMonHeader);
00086 hdr[hdr_indx_sec] = fSeconds;
00087 hdr[hdr_indx_nsec] = fNanosecs;
00088 hdr[hdr_indx_spillcnt] = fSpillcount;
00089 rdxsum_fill(hdr,0);
00090
00091
00092 long int* pld = data+hdr[hdr_indx_size];
00093 siz -= hdr[hdr_indx_size];
00094 pld[pld_indx_size] = siz;
00095 pld[pld_indx_checksum] = 0;
00096 pld[pld_indx_blockid] = make_block_id(kMdBlockBeamMonPayload);
00097 pld[pld_indx_clbk_event] = fTclkEvent;
00098 pld[pld_indx_clbk_delay] = fTclkDelay;
00099 pld[pld_indx_num_devices] = fPayload.size();
00100
00101 int count=0, index = pld_indx_data_start;
00102 PayloadItr it, done = fPayload.end();
00103 for (it = fPayload.begin(); it != done; ++it) {
00104 string name = it->first;
00105 DeviceData& dd = it->second;
00106
00107
00108
00109 pld[index++] = (name[0]<<24)+(name[1]<<16)+(name[2]<<8)+name[3];
00110 pld[index++] = (name[4]<<24)+(name[5]<<16)+(name[6]<<8)+name[7];
00111
00112
00113 pld[index++] = dd.sec;
00114 pld[index++] = dd.msec;
00115
00116
00117 int nvalues = dd.data.size();
00118 pld[index++] = nvalues;
00119 for (int ind=0; ind<nvalues; ++ind) pld[index++] = dd.data[ind];
00120 ++count;
00121 }
00122 rdxsum_fill(data+6,0);
00123
00124 assert (siz == index);
00125 assert (count == pld[pld_indx_num_devices]);
00126 return data;
00127 }
00128 void delete_block(long int* data) { delete [] data; }
00129
00130 int header(int sec, int nsec, int spill, int event, int delay) {
00131 fSeconds = sec;
00132 fNanosecs = nsec;
00133 fSpillcount = spill;
00134 fTclkEvent = event;
00135 fTclkDelay = delay;
00136 }
00137
00138 DeviceData& get_device(string name) {
00139
00140 while (name.size() < 8u) name.push_back(' ');
00141
00142 PayloadItr it = fPayload.find(name);
00143 if (it == fPayload.end()) {
00144 fPayload[name] = DeviceData();
00145 return fPayload[name];
00146 }
00147 else return it->second;
00148 }
00149 void set_device_header(string name, int sec, int msec) {
00150 DeviceData& d = get_device(name);
00151 d.sec = sec;
00152 d.msec = msec;
00153 }
00154 void append_payload(string name, int value[2]) {
00155 DeviceData& d = get_device(name);
00156 d.data.push_back(value[0]);
00157 d.data.push_back(value[1]);
00158 }
00159
00160 string& current_file() { return fCurrentFile; }
00161 };
00162
00163
00164 BeamData::BeamData()
00165 {
00166 fImp = new BeamDataImp;
00167 }
00168 BeamData::~BeamData()
00169 {
00170 if (fImp) delete fImp;
00171 }
00172
00173 int BeamData::open_connection(const char* host)
00174 {
00175 return roto_open_BeamMon_connection(host);
00176 }
00177
00178 int BeamData::close_connection()
00179 {
00180 return roto_close_connection();
00181 }
00182
00183
00184 string secnsec2filename(int sec, int nsec)
00185 {
00186 const int nspersec = 1000000000;
00187 while (nsec<0) {
00188 nsec += nspersec;
00189 sec -= 1;
00190 }
00191 while (nsec >= nspersec) {
00192 nsec -= nspersec;
00193 sec -= 1;
00194 }
00195
00196 time_t atime = sec;
00197 struct tm *ptm = gmtime(&atime);
00198 int dat = (1900+ptm->tm_year)*10000+(1+ptm->tm_mon)*100+ptm->tm_mday;
00199 if (dat>19700000) dat %= 100000;
00200 int tim = ptm->tm_hour*10000 + ptm->tm_min*100 + ptm->tm_sec;
00201
00202 char buf[80];
00203 snprintf(buf,80,"B%6.6d_%6.6d.mbeam.root",dat,tim);
00204 string fname = buf;
00205 return fname;
00206 }
00207
00208 int BeamData::open_file(int sec, int nanosec)
00209 {
00210 int ret = roto_open_beammonfile(sec,nanosec);
00211 if (ret) {
00212 fImp->current_file() = "";
00213 return ret;
00214 }
00215 fImp->current_file() = secnsec2filename(sec,nanosec);
00216 return ret;
00217 }
00218 int BeamData::close_file()
00219 {
00220 int ret = roto_close_beammonfile();
00221 fImp->current_file() = "";
00222 return ret;
00223 }
00224
00225 int BeamData::send_data()
00226 {
00227 long int* data = fImp->create_block();
00228
00229 int res = roto_send_record(data,fImp->words()*4);
00230 fImp->delete_block(data);
00231 return res;
00232 }
00233
00234 void BeamData::start_block(int seconds, int nanosecs, int spillcount,
00235 int event, int delay)
00236 {
00237 fImp->clear();
00238 fImp->header(seconds,nanosecs,spillcount,event,delay);
00239 }
00240
00241 void BeamData::set_device_header(const char* name, int sec, int msec)
00242 {
00243 fImp->set_device_header(name,sec,msec);
00244 }
00245 void BeamData::add_device_value(const char* name, double value)
00246 {
00247 int temp[2] = { 0 };
00248
00249 memcpy(temp,&value,sizeof(double));
00250 fImp->append_payload(name,temp);
00251 }
00252
00253 const char* BeamData::current_filename()
00254 {
00255 return fImp->current_file().c_str();
00256 }
00257
00258 const char* BeamData::error(int err)
00259 {
00260 const char* errtable[] = {
00261 "rototalk_success",
00262 "rototalk_err_whoami",
00263 "rototalk_err_alreadyconn",
00264 "rototalk_err_unknownhost",
00265 "rototalk_err_notinethost",
00266 "rototalk_err_socketfail",
00267 "rototalk_err_connectfail",
00268 "rototalk_err_notconnected",
00269 "rototalk_err_illegalmethod",
00270 "rototalk_err_badsender",
00271 "rototalk_err_badsendcmd",
00272 "rototalk_err_badsendsize",
00273 "rototalk_err_badsenddata",
00274 "rototalk_err_badrecvack",
00275 "rototalk_err_badrecvacksize",
00276 "rototalk_err_badrecvackdata",
00277 "rototalk_err_badrecvstate",
00278 "rototalk_err_nack",
00279 "rototalk_err_reallocate",
00280 "rototalk_err_badconfig",
00281 "rototalk_last_of_errors",
00282 0
00283 };
00284 if (err < 0 || err >= rototalk_last_of_errors) return "unknown";
00285 return errtable[err];
00286 }