CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/IOPool/Streamer/interface/Messages.h

Go to the documentation of this file.
00001 #ifndef IOPool_Streamer_Messages_h
00002 #define IOPool_Streamer_Messages_h
00003 
00004 /*
00005   The header for each of the data buffer that will be transferred.
00006   The packing and unpacking of the data in the header is directly
00007   handled here.
00008 
00009   Every incoming message has a length and message code. Beyond that,
00010   each type has a specific header, followed by a specific 
00011   payload - the packed ROOT data buffer.
00012 */
00013 
00014 #include <vector>
00015 #include <cassert>
00016 #include <iostream>
00017 
00018 #include "DataFormats/Provenance/interface/EventID.h"
00019 
00020 /*
00021   There is still a problem here - the message lengths are not
00022   well specified.  There is dataSize, msgSize, getDataSize, 
00023   and payloadSize calls.  This sounds like too many.
00024 
00025  There is still an inconsistency between the way that dataSize is treated
00026  in the EventMsg and in the InitMsg.  The EventMsg method is better.  The
00027  problem is that the base class (MsgCode) may have a zero size if it is
00028  referring to an incoming buffer.  This makes a call to payloadSize useless.
00029  */
00030 
00031 namespace edm {
00032 
00033   inline unsigned int decodeInt(unsigned char* v)
00034   {
00035     // first four bytes are code,  LSB first
00036     unsigned int a=v[0], b=v[1], c=v[2], d=v[3];
00037     a|=(b<<8)|(c<<16)|(d<<24);
00038     return a;
00039   }
00040 
00041   inline void encodeInt(unsigned int i, unsigned char* v)
00042   {
00043     v[0]=i&0xff;
00044     v[1]=(i>>8)&0xff;
00045     v[2]=(i>>16)&0xff;
00046     v[3]=(i>>24)&0xff;
00047   }
00048 
00049   // -----------------------------------------------
00050 
00051   // we currently only support two message types:
00052   //  1 = SendJobHead (INIT)
00053   //  2 = SendEvent (EVENT)
00054 
00055   class MsgCode
00056   {
00057   public:
00058     enum Codes { INVALID = 0, INIT = 1, EVENT = 2, DONE = 3 };
00059     
00060     // header is the message code
00061     // the size kept in this object is the available space (i.e. -header)
00062     
00063     // the entire size of the buffer
00064     MsgCode(void* buffer, int size):
00065       buffer_((unsigned char*)buffer),size_(size<4?0:size-4)
00066     { assert(size_>=0); } 
00067     
00068     // unknown size
00069     explicit MsgCode(void* buffer):
00070       buffer_((unsigned char*)buffer),size_(0)
00071     { } 
00072 
00073     // with header message code set
00074     MsgCode(void* buffer, Codes c):
00075       buffer_((unsigned char*)buffer),size_(0)
00076     { setCode(c); }
00077 
00078     // with header message code set and a total buffer length
00079     MsgCode(void* buffer, int size, Codes c):
00080       buffer_((unsigned char*)buffer),size_(size-4)
00081     { setCode(c); }
00082 
00083     void setCode(Codes c)
00084     {
00085       encodeInt(c,buffer_);
00086     }
00087 
00088     Codes getCode() const
00089     {
00090       return (Codes)decodeInt(buffer_);
00091     }
00092 
00093     // adjust for header (header not included in payload address
00094     void* payload() const { return &buffer_[4]; }
00095     int payloadSize() const { return size_; }
00096     int codeSize() const { return 4; }
00097     int totalSize() const { return size_+4; }
00098 
00099   private:
00100     unsigned char* buffer_;
00101     int size_;
00102 
00103   };
00104 
00105   // -----------------------------------------------
00106 
00107   /*
00108     added two more fields - "the m out of n data".
00109     Each message will contain these fragment counts and the header
00110     data.
00111 
00112     Event Message Format:
00113     |MSG_ID|WHICH_SEG|TOTAL_SEGS|EVENT_ID|RUN_ID|DATA_SIZE| ...DATA... |
00114     |-code-|-------------------header --------------------|
00115 
00116     In order to know the original data, you must concatenate all the
00117     segments in the proper order.  The field WHICH_SEG which one of the
00118     TOTAL_SEGS this part of the data is.
00119    */
00120 
00121   class EventMsg : public MsgCode
00122   {
00123   public:
00124     struct EventMsgHeader
00125     {
00126       unsigned char which_seg_[4];
00127       unsigned char total_segs_[4];
00128       unsigned char event_num_[4];
00129       unsigned char run_num_[4];
00130       unsigned char data_size_[4];
00131     };
00132 
00133     // incoming data buffer to be looked at
00134     EventMsg(MsgCode& mc):
00135       MsgCode(mc),
00136       head_((EventMsgHeader*)MsgCode::payload()),
00137       which_seg_(getWhichSeg()),
00138       total_segs_(getTotalSegs()),
00139       event_num_(getEventNumber()),
00140       run_num_(getRunNumber()),
00141       data_size_(getDataSize())
00142     { }
00143     
00144     // incoming data buffer to be looked at
00145     explicit EventMsg(void* buffer, int size=0):
00146       MsgCode(buffer,size),
00147       head_((EventMsgHeader*)MsgCode::payload()),
00148       which_seg_(getWhichSeg()),
00149       total_segs_(getTotalSegs()),
00150       event_num_(getEventNumber()),
00151       run_num_(getRunNumber()),
00152       data_size_(getDataSize())
00153     { }
00154 
00155     // outgoing data buffer to be filled
00156     EventMsg(void* buffer, int size,
00157              edm::EventNumber_t e,
00158              edm::RunNumber_t r,
00159              int which_seg,
00160              int total_segs):
00161       MsgCode(buffer,size),
00162       head_((EventMsgHeader*)MsgCode::payload()),
00163       which_seg_(which_seg),
00164       total_segs_(total_segs),
00165       event_num_(e),
00166       run_num_(r),
00167       data_size_(payloadSize() - sizeof(EventMsgHeader))
00168     {
00169       setCode(MsgCode::EVENT);
00170       setWhichSeg(which_seg);
00171       setTotalSegs(total_segs);
00172       setEventNumber(e);
00173       setRunNumber(r);
00174       setDataSize(data_size_);
00175     }
00176 
00177     // the data is really a SendEvent
00178     void* data()   const { return (char*)payload() + sizeof(EventMsgHeader); } 
00179     // the size is max size here
00180     int dataSize() const { return data_size_ + sizeof(EventMsgHeader); }
00181 
00182     int getDataSize() const 
00183     {
00184       return decodeInt(head_->data_size_);
00185     }
00186 
00187     void setDataSize(int s)
00188     {
00189       encodeInt(s,head_->data_size_);
00190     }
00191 
00192     int getWhichSeg() const 
00193     {
00194       return decodeInt(head_->which_seg_);
00195     }
00196 
00197     void setWhichSeg(int s)
00198     {
00199       encodeInt(s,head_->which_seg_);
00200     }
00201 
00202     int getTotalSegs() const 
00203     {
00204       return decodeInt(head_->total_segs_);
00205     }
00206 
00207     void setTotalSegs(int s)
00208     {
00209       encodeInt(s,head_->total_segs_);
00210     }
00211 
00212     edm::EventNumber_t getEventNumber() const 
00213     {
00214       assert(sizeof(edm::EventNumber_t) == sizeof(int) && "event ID streaming only knows how to work with 4 byte event ID numbers right now");
00215       return decodeInt(head_->event_num_);
00216     }
00217 
00218     void setEventNumber(edm::EventNumber_t e)
00219     {
00220       assert(sizeof(edm::RunNumber_t) == sizeof(int) && "run number streaming only knows how to work with 4 byte event ID numbers right now");
00221       encodeInt(e,head_->event_num_);
00222     }
00223 
00224     edm::RunNumber_t getRunNumber() const
00225     {
00226       assert(sizeof(edm::EventNumber_t) == sizeof(int) && "event ID streaming only knows how to work with 4 byte event ID numbers right now");
00227       return decodeInt(head_->run_num_);
00228     }
00229 
00230     void setRunNumber(edm::RunNumber_t r)
00231     {
00232       assert(sizeof(edm::RunNumber_t) == sizeof(int) && "run number streaming only knows how to work with 4 byte event ID numbers right now");
00233       return encodeInt(r,head_->run_num_);
00234     }
00235 
00236     // the number of bytes used, including the headers
00237     int msgSize() const
00238     {
00239       return codeSize()+sizeof(EventMsgHeader)+getDataSize();
00240     }
00241 
00242   private:
00243     EventMsgHeader* head_;
00244     int which_seg_;
00245     int total_segs_;
00246     edm::EventNumber_t event_num_;
00247     edm::RunNumber_t run_num_;
00248     int data_size_;
00249   };
00250   
00251   // -------------------------------------------------
00252   /*
00253     Format:
00254     | MSG_ID | DATA_SIZE | ... DATA ... |
00255    */
00256 
00257   class InitMsg : public MsgCode
00258   {
00259   public:
00260     struct InitMsgHeader
00261     {
00262       unsigned char data_size_[4];
00263     };
00264 
00265     InitMsg(MsgCode& m):
00266       MsgCode(m),
00267       head_((InitMsgHeader*)MsgCode::payload()),
00268       data_size_(payloadSize() - sizeof(InitMsgHeader))
00269     { setDataSize(data_size_); }
00270 
00271     InitMsg(void* buffer, int size, bool setcode = false):
00272       MsgCode(buffer,size),
00273       head_((InitMsgHeader*)MsgCode::payload()),
00274       data_size_(payloadSize() - sizeof(InitMsgHeader)) // default to full length
00275     {
00276       if(setcode)
00277         {
00278           // for new message
00279           setCode(MsgCode::INIT);
00280           setDataSize(data_size_);
00281         }
00282       else
00283         // for existing message
00284         data_size_ = getDataSize();
00285     }
00286 
00287     // the data is really a SendJobHeader
00288     // for this message, there is nothing manually encoded/decoded in the
00289     // header, it is all contained in the ROOT buffer.
00290     // currently we supply no extra data header
00291     void* data() const { return (char*)payload()+sizeof(InitMsgHeader); } 
00292     int dataSize() const { return payloadSize() + sizeof(InitMsgHeader); }
00293 
00294     int getDataSize() const 
00295     {
00296       return decodeInt(head_->data_size_);
00297     }
00298 
00299     void setDataSize(int s)
00300     {
00301       encodeInt(s,head_->data_size_);
00302     }
00303 
00304     // the number of bytes used, including the headers
00305     int msgSize() const
00306     {
00307       return codeSize()+sizeof(InitMsgHeader)+getDataSize();
00308     }
00309 
00310   private:
00311     InitMsgHeader* head_;
00312     int data_size_;
00313   };
00314 
00315 }
00316 #endif
00317