Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

BeamData.cc

Go to the documentation of this file.
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;          // per device timestamp;
00042         vector<int> data;       // per device data array
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         // header block is constant size
00061         s += zzzz_last;
00062         // Number of words to get to start of payload
00063         s += pld_indx_data_start; 
00064 
00065         // Offset from above index + 1 gives number of values in the
00066         // prefix of each device data
00067         s += (pld_nvalues_offset+1) * fPayload.size();
00068 
00069         // Finally count up the actual payloads
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         // The header block
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         // The payload block
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             // Pack the ACNET name.  This does it in machine order
00108             // unpacking assumes it is written on ix86 ordering.
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             // Set the relative timestamp
00113             pld[index++] = dd.sec;
00114             pld[index++] = dd.msec;
00115 
00116             // Pack number of device values and the values themselves.
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         // space pad name
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 // Ripped to match Rotorooter/RotoServer.cxx and Validity/VldTimeStamp.cxx
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     //cerr << data[9] << " devices, block 1 " << data[0] << " words, block 2 " << data[6] << " words, total words = " << fImp->words() << endl;
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     // Egads!  Avert yer eye's if ye worry about yer sanity
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 }

Generated on Sat Nov 21 22:45:30 2009 for loon by  doxygen 1.3.9.1