CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/CondCore/DBCommon/plugins/TBufferBlobStreamingService.cc

Go to the documentation of this file.
00001 #include "CondCore/DBCommon/interface/BlobStreamerPluginFactory.h"
00002 #include "CondCore/DBCommon/interface/Exception.h"
00003 #include "TBufferBlobStreamingService.h"
00004 //
00005 #include <algorithm>
00006 #include <typeinfo>
00007 #include <string>
00008 #include <cstring>
00009 //
00010 #include "TBufferFile.h"
00011 #include "Reflex/Reflex.h"
00012 #include "Cintex/Cintex.h"
00013 
00014 typedef void (TBuffer::*WriteArrayFn_t)(const void *obj, Int_t n);
00015 typedef void (TBuffer::*ReadArrayFn_t)(void *obj, Int_t n);
00016 
00017 #define PRIMITIVE(x) { \
00018         typeid(x), \
00019         reinterpret_cast<WriteArrayFn_t>( \
00020                 (void (TBuffer::*)(const x*, Int_t))&TBuffer::WriteFastArray), \
00021         reinterpret_cast<ReadArrayFn_t>( \
00022                 (void (TBuffer::*)(x*, Int_t))&TBuffer::ReadFastArray) \
00023 }
00024 
00025 struct Primitive {
00026         const std::type_info    &type;
00027         WriteArrayFn_t          writeArrayFn;
00028         ReadArrayFn_t           readArrayFn;
00029 
00030         inline bool operator == (const std::type_info &other) const
00031         { return type == other; }
00032 } static const primitives[] = {
00033         PRIMITIVE(Bool_t),
00034         PRIMITIVE(Char_t),
00035         PRIMITIVE(UChar_t),
00036         PRIMITIVE(Short_t),
00037         PRIMITIVE(UShort_t),
00038         PRIMITIVE(Int_t),
00039         PRIMITIVE(UInt_t),
00040         PRIMITIVE(Long_t),
00041         PRIMITIVE(ULong_t),
00042         PRIMITIVE(Long64_t),
00043         PRIMITIVE(ULong64_t),
00044         PRIMITIVE(Float_t),
00045         PRIMITIVE(Double_t)
00046 };
00047 
00048 static const std::size_t nPrimitives =
00049                                 (sizeof primitives / sizeof primitives[0]);
00050 
00051 #undef PRIMTIVE
00052 
00053 cond::TBufferBlobTypeInfo::TBufferBlobTypeInfo( Reflex::Type const & type_)
00054  : m_arraySize(0), m_class(0), m_primitive(0)
00055 {
00056   static bool cintexInitialized = false;
00057   if (!cintexInitialized) {
00058     cintexInitialized = true;
00059     ROOT::Cintex::Cintex::Enable();
00060   }
00061 
00062   Reflex::Type type = type_;
00063   while(true) {
00064     type = type.FinalType();
00065 
00066     if (!type.IsArray())
00067       break;
00068 
00069     if (!m_arraySize)
00070       m_arraySize = 1;
00071     m_arraySize *= type.ArrayLength();
00072     type = type.ToType();
00073   }
00074 
00075   if (type.IsClass()) {
00076     const std::type_info &typeInfo = type.TypeInfo();
00077     m_class = TClass::GetClass(typeInfo);
00078     if (!m_class)
00079       throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00080                             "No ROOT class registered for " + type.Name());
00081   } else if (type.IsFundamental()) {
00082     if (!m_arraySize)
00083         throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00084                               "Only arrays of primitive types supported. "
00085                               "Please to not use a Blob for this member.");
00086 
00087     m_primitive = std::find(primitives, primitives + nPrimitives,
00088                             type.TypeInfo()) - primitives;
00089     if (m_primitive >= nPrimitives)
00090       throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00091                             "Cannot handle primitive type " + type.Name());
00092   } else
00093     throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00094                           "Cannot handle C++ type " + type.Name());
00095 }
00096 
00097 
00098 cond::TBufferBlobStreamingService::TBufferBlobStreamingService(){
00099 }
00100 
00101 cond::TBufferBlobStreamingService::~TBufferBlobStreamingService(){
00102 }
00103 
00104 #include <boost/bind.hpp>
00105 namespace {
00106   char * reallocInBlob( boost::shared_ptr<coral::Blob> theBlob, char* p, size_t newsize, size_t oldsize) {
00107     // various checks missing....
00108     theBlob->resize(newsize);
00109     return (char*)theBlob->startingAddress();
00110     
00111   }
00112 }
00113 
00114 boost::shared_ptr<coral::Blob> cond::TBufferBlobStreamingService::write( const void* addr,
00115                                                                          Reflex::Type const & classDictionary,
00116                                                                          bool ){
00117   TBufferBlobTypeInfo theType( classDictionary );
00118   if (theType.m_class && theType.m_class->GetActualClass(addr) != theType.m_class)
00119     throw cond::Exception("TBufferBlobWriter::write object to stream is "
00120                           "not of actual class.");
00121   
00122   boost::shared_ptr<coral::Blob> theBlob( new coral::Blob );
00123   //theBlob->resize(1024);
00124   
00125   // with new root...
00126   // TBufferFile buffer(TBufferFile::kWrite, theBlob->size(), theBlob->startingAddress(), kFALSE, boost::bind(reallocInBlob, theBlob,_1,_2,_3));
00127   TBufferFile buffer(TBufferFile::kWrite);
00128   buffer.InitMap();
00129   
00130   if (theType.m_arraySize && !theType.m_class)
00131     (buffer.*primitives[theType.m_primitive].writeArrayFn)(addr, theType.m_arraySize);
00132   else if (theType.m_arraySize)
00133     buffer.WriteFastArray(const_cast<void*>(addr), theType.m_class, theType.m_arraySize);
00134   else
00135     buffer.StreamObject(const_cast<void*>(addr), theType.m_class);
00136 
00137   Int_t size = buffer.Length();
00138 
00139   theBlob->resize(size);
00140   void *startingAddress = theBlob->startingAddress();
00141   std::memcpy(startingAddress, buffer.Buffer(), size);
00142 
00143   return theBlob;
00144 }
00145 
00146 void cond::TBufferBlobStreamingService::read( const coral::Blob& blobData,
00147                                               void* addr,
00148                                                Reflex::Type const & classDictionary ){
00149   TBufferBlobTypeInfo theType( classDictionary );
00150   const void *startingAddress = blobData.startingAddress();
00151   size_t size = blobData.size();
00152   if (!size)
00153     return;
00154 
00155   TBufferFile buffer(TBufferFile::kRead, size,
00156                  const_cast<void*>(startingAddress), kFALSE);
00157 
00158   buffer.InitMap();
00159 
00160   if (theType.m_arraySize && !theType.m_class)
00161     (buffer.*primitives[theType.m_primitive].readArrayFn)(addr, theType.m_arraySize);
00162   else if (theType.m_arraySize)
00163     buffer.ReadFastArray(addr, theType.m_class, theType.m_arraySize);
00164   else
00165     buffer.StreamObject(addr, theType.m_class);
00166 }
00167