![]() |
|
|
Generated: 8 Jan 2009 |
00001 // $Id: PoolDbNTupleCnv.cpp,v 1.16 2008/10/27 16:41:33 marcocle Exp $ 00002 //------------------------------------------------------------------------------ 00003 // 00004 // Implementation of class : PoolDbNTupleCnv 00005 // 00006 // Author : Markus Frank 00007 // 00008 //------------------------------------------------------------------------------ 00009 00010 // FIXME: missing in CORAL 00011 #include <algorithm> 00012 00013 #define ALLOW_ALL_TYPES 00014 // Include files 00015 #include "GaudiPoolDb/IPoolDbMgr.h" 00016 #include "GaudiPoolDb/PoolDbAddress.h" 00017 #include "GaudiPoolDb/PoolDbNTupleCnv.h" 00018 #include "GaudiPoolDb/PoolDbLinkManager.h" 00019 #include "GaudiPoolDb/PoolDbNTupleDescriptor.h" 00020 #include "GaudiPoolDb/PoolDbTupleCallback.h" 00021 00022 #include "GaudiKernel/xtoa.h" 00023 #include "GaudiKernel/NTuple.h" 00024 #include "GaudiKernel/SmartIF.h" 00025 #include "GaudiKernel/SmartRef.h" 00026 #include "GaudiKernel/MsgStream.h" 00027 #include "GaudiKernel/INTupleSvc.h" 00028 #include "GaudiKernel/IRegistry.h" 00029 #include "GaudiKernel/ISelectStatement.h" 00030 #include "GaudiKernel/ContainedObject.h" 00031 #include "GaudiKernel/GenericAddress.h" 00032 #include "GaudiKernel/CnvFactory.h" 00033 00034 #include "StorageSvc/DbSelect.h" 00035 #include "StorageSvc/DbReflex.h" 00036 #include "StorageSvc/DbColumn.h" 00037 #include "StorageSvc/DbTypeInfo.h" 00038 #include "StorageSvc/DbObjectCallBack.h" 00039 00040 #define S_OK StatusCode::SUCCESS 00041 #define S_FAIL StatusCode::FAILURE 00042 #include "Reflex/Builder/ReflexBuilder.h" 00043 00044 #include <memory> 00045 00046 namespace pool { 00047 const std::string typeName(const std::type_info& typ); 00048 } 00049 00050 void popCurrentDataObject(); 00051 void pushCurrentDataObject(DataObject** pobjAddr); 00052 00053 namespace pool { void genMD5(const std::string& s, void* code); } 00054 using pool::genMD5; 00055 00056 template <class T> static inline 00057 void* save(pool::DbBlob& s, const void* buffer, int len, bool save_len) { 00058 const T* buff = (const T*)buffer; 00059 if ( len > 1 ) { 00060 s << len; 00061 s.swapToBuffer(buff, len*sizeof(T)); 00062 return 0; 00063 } 00064 else if ( save_len ) { 00065 s << len; 00066 return 0; 00067 } 00068 return (void*)buff; 00069 } 00070 00071 static void* save(const void* b, PoolDbTokenWrap* lnk) { 00072 IOpaqueAddress* pA = (*(IOpaqueAddress**)b); 00073 pool::Token& tok = lnk->token; 00074 pool::Guid guid(pool::Guid::null()); 00075 if ( pA ) { 00076 const std::string* spar = pA->par(); 00077 const unsigned long* ipar = pA->ipar(); 00078 guid.Data1 = pA->clID(); 00079 tok.setTechnology(pA->svcType()); 00080 tok.setDb(spar[0]).setCont(spar[1]); 00081 tok.oid().first = ipar[0]; 00082 tok.oid().second = ipar[1]; 00083 } 00084 else { 00085 tok.setTechnology(0).setDb("").setCont(""); 00086 tok.oid().first = tok.oid().second = pool::INVALID; 00087 } 00088 tok.setClassID(guid); 00089 return lnk; 00090 } 00091 00092 // Helper to read 00093 template <class T> static inline int load(pool::DbBlob& s, void* buff) { 00094 int len; 00095 s >> len; 00096 s.swapFromBuffer(buff, len*sizeof(T)); 00097 return 0; 00098 } 00099 00100 // Helper to read specialized for strings 00101 template <> inline int load<std::string>(pool::DbBlob& s, void* ptr) { 00102 std::string* str = (std::string*)ptr; 00103 s >> (*str); 00104 return 0; 00105 } 00106 00107 // Helper to read specialized for opaque addresses 00108 static inline int load(void* ptr,PoolDbTokenWrap* lnk) { 00109 IOpaqueAddress* pA = *(IOpaqueAddress**)ptr; 00110 GenericAddress* pAddr = (GenericAddress*)(pA); 00111 if ( 0 != pAddr ) { 00112 pool::Token& tok = lnk->token; 00113 std::string* spar = (std::string*)pAddr->par(); 00114 unsigned long* ipar = (unsigned long*)pAddr->ipar(); 00115 pAddr->setClID(tok.classID().Data1); 00116 pAddr->setSvcType(tok.technology()); 00117 ipar[0] = tok.oid().first; 00118 ipar[1] = tok.oid().second; 00119 spar[0] = tok.dbID(); 00120 spar[1] = tok.contID(); 00121 return 0; 00122 } 00123 else if ( pA ) { 00124 return 10; 00125 } 00126 return 11; 00127 } 00128 00129 // Instantiation of a static factory class used by clients to create 00130 // instances of this service 00131 PLUGINSVC_FACTORY_WITH_ID( PoolDbNTupleCnv, 00132 ConverterID(POOL_StorageType,CLID_RowWiseTuple), 00133 IConverter*(long, CLID, ISvcLocator*) ); 00134 00135 PLUGINSVC_FACTORY_WITH_ID( PoolDbNTupleCnv, 00136 ConverterID(POOL_StorageType,CLID_ColumnWiseTuple), 00137 IConverter*(long, CLID, ISvcLocator*) ); 00138 00139 static inline std::istream& loadLong(std::istream& is) { 00140 long i; 00141 is >> i; 00142 return is; 00143 } 00144 static inline std::istream& 00145 operator>>(std::istream& is, SmartRef<DataObject>& /*pObj*/) { 00146 return loadLong(is); 00147 } 00148 static inline std::istream& 00149 operator>>(std::istream& is, SmartRef<ContainedObject>& /*pObj*/) { 00150 return loadLong(is); 00151 } 00152 static inline std::istream& 00153 operator>>(std::istream& is, IOpaqueAddress*& /*pObj*/) { 00154 return loadLong(is); 00155 } 00156 static inline std::istream& 00157 operator>>(std::istream& is, std::string& /*pObj*/) 00158 { 00159 return loadLong(is); 00160 } 00161 00162 template<class TYP> static 00163 StatusCode createItem ( INTuple* tuple, std::istream& is, 00164 const std::string& name, 00165 const TYP& null) 00166 { 00167 std::string idxName; 00168 long len, ndim, dim[4], hasIdx, idxLow, idxLen; 00169 long dim1 = 1, dim2 = 1; 00170 INTupleItem* it = 0; 00171 char c; 00172 is >> len >> c 00173 >> ndim >> c 00174 >> hasIdx >> c; 00175 if ( hasIdx ) { 00176 std::getline(is, idxName, ';') >> idxLow >> c >> idxLen >> c; 00177 } 00178 for ( int i = 0; i < ndim; i++ ) 00179 is >> dim[i] >> c; 00180 00181 TYP low = null, high = null; 00182 is >> low >> c >> high >> c; 00183 is >> c; 00184 switch( ndim ) { 00185 case 0: 00186 it = NTuple::_Item<TYP>::create (tuple, name, typeid(TYP), low, high, null); 00187 break; 00188 case 1: 00189 dim1 = (hasIdx) ? idxLen : dim[0]; 00190 it = NTuple::_Array<TYP>::create (tuple, 00191 name, 00192 typeid(TYP), 00193 idxName, 00194 dim1, 00195 low, 00196 high, 00197 null); 00198 break; 00199 case 2: 00200 dim1 = (hasIdx) ? idxLen : dim[0]; 00201 dim2 = (hasIdx) ? dim[0] : dim[1]; 00202 it = NTuple::_Matrix<TYP>::create ( tuple, 00203 name, 00204 typeid(TYP), 00205 idxName, 00206 dim1, 00207 dim2, 00208 low, 00209 high, 00210 null); 00211 break; 00212 default: 00213 return S_FAIL; 00214 } 00215 return tuple->add(it); 00216 } 00217 00218 template <class T> static inline 00219 void putRange(std::ostream& os, NTuple::_Data<T>* it) 00220 { 00221 const NTuple::Range<T>& x = it->range(); 00222 os << x.lower() << ';' << x.upper() << ';'; 00223 } 00224 00226 PoolDbNTupleCnv::PoolDbNTupleCnv(long typ, const CLID& clid, ISvcLocator* svc) 00227 : PoolDbStatCnv(typ, clid, svc) 00228 { 00229 m_class = 0; 00230 } 00231 00232 PoolDbNTupleCnv::~PoolDbNTupleCnv() { 00233 } 00234 00235 // Converter overrides: Update the references of an updated transient object. 00236 StatusCode 00237 PoolDbNTupleCnv::createObj(IOpaqueAddress* pAddress, DataObject*& refpObject) 00238 { 00239 StatusCode status = S_FAIL; 00240 PoolDbAddress* pdbA = dynamic_cast<PoolDbAddress*>(pAddress); 00241 if ( 0 != pdbA ) { 00242 const pool::Token* tok = pdbA->token(); 00243 if ( tok ) { 00244 pool::DbContainer cntH(tok->technology()); 00245 status = m_dbMgr->connect(tok->dbID(),tok->contID(),cntH); 00246 if ( status.isSuccess() ) { 00247 std::string par_val, par_guid, par_typ; 00248 std::auto_ptr<pool::DbSelect> iter(m_dbMgr->createSelect("*", tok->dbID(), "GaudiStatisticsDescription")); 00249 if ( iter.get() ) { 00250 pool::Token* token; 00251 ROOT::Reflex::Type typ = pool::DbReflex::forTypeName("PoolDbNTupleDescriptor"); 00252 pool::DbObjectCallBack* call = new pool::DbObjectCallBack(typ); 00253 while( iter->next(token).isSuccess() ) { 00254 typedef pool::DbObjectHandle<pool::DbObject> ObjH; 00255 pool::DbContainer& cH = iter->container(); 00256 if ( ObjH::openEx(cH, *token, call, pool::READ).isSuccess() ) { 00257 PoolDbNTupleDescriptor* ref = (PoolDbNTupleDescriptor*)call->object(); 00258 if ( ref->container == tok->contID() ) { 00259 par_val = ref->description; 00260 par_typ = ref->optional; 00261 par_guid = ref->guid; 00262 token->release(); 00263 call->release(); 00264 call = 0; 00265 delete ref; 00266 break; 00267 } 00268 delete ref; 00269 } 00270 token->release(); 00271 } 00272 if ( call ) call->release(); 00273 } 00274 if ( !par_val.empty() && !par_guid.empty() && !par_typ.empty() ) 00275 { 00276 SmartIF<INTupleSvc> ntupleSvc(IID_INTupleSvc, dataProvider()); 00277 if ( ntupleSvc.isValid() ) { 00278 char c; 00279 CLID clid; 00280 int siz, typ; 00281 std::string title; 00282 NTuple::Tuple* nt = 0; 00283 std::istringstream is(par_val); 00284 std::getline(is, title, ';') >> clid >> c >> siz >> c; 00285 status = ntupleSvc->create(clid, title, nt); 00286 for ( int j = 0; j < siz && status.isSuccess(); j++ ) { 00287 is >> c; 00288 std::getline(is, title, ';') >> typ >> c; 00289 switch ( typ ) { 00290 case DataTypeInfo::UCHAR: 00291 status = createItem(nt, is, title, (unsigned char)0); 00292 break; 00293 case DataTypeInfo::USHORT: 00294 status = createItem(nt, is, title, (unsigned short)0); 00295 break; 00296 case DataTypeInfo::UINT: 00297 status = createItem(nt, is, title, (unsigned int)0); 00298 break; 00299 case DataTypeInfo::ULONG: 00300 status = createItem(nt, is, title, (unsigned long)0); 00301 break; 00302 case DataTypeInfo::CHAR: 00303 status = createItem(nt, is, title, char(0)); 00304 break; 00305 case DataTypeInfo::SHORT: 00306 status = createItem(nt, is, title, short(0)); 00307 break; 00308 case DataTypeInfo::INT: 00309 status = createItem(nt, is, title, int(0)); 00310 break; 00311 case DataTypeInfo::LONG: 00312 status = createItem(nt, is, title, long(0)); 00313 break; 00314 case DataTypeInfo::BOOL: 00315 status = createItem(nt, is, title, false); 00316 break; 00317 case DataTypeInfo::FLOAT: 00318 status = createItem(nt, is, title, float(0.0)); 00319 break; 00320 case DataTypeInfo::DOUBLE: 00321 status = createItem(nt, is, title, double(0.0)); 00322 break; 00323 /* 00324 case DataTypeInfo::NTCHAR: 00325 case DataTypeInfo::LONG_NTCHAR: 00326 status = 00327 createItem(nt, is, title, (char*)0); 00328 break; 00329 case DataTypeInfo::STRING: 00330 case DataTypeInfo::LONG_STRING: 00331 status = 00332 createItem(nt, is, title, std::string("")); 00333 break; 00334 */ 00335 case DataTypeInfo::OBJECT_ADDR: 00336 status = createItem(nt, is, title, (IOpaqueAddress*)0); 00337 break; 00338 case DataTypeInfo::POINTER: 00339 status = createItem(nt, is, title, (void*)0); 00340 break; 00341 case DataTypeInfo::UNKNOWN: 00342 default: 00343 status = S_FAIL; 00344 break; 00345 } 00346 if ( !status.isSuccess() ) { 00347 MsgStream err(msgSvc(),"NTupleCnv"); 00348 err << MSG::FATAL 00349 << "Error connecting (Unknown) column:" << j << endmsg 00350 << par_val << endmsg; 00351 return makeError("createObj[NTuple]> Cannot determine column!"); 00352 } 00353 } 00354 if ( status.isSuccess() ) { 00355 PoolDbTupleCallback* hdlr = new PoolDbTupleCallback(nt); 00356 const pool::DbTypeInfo* typ = pool::DbTypeInfo::fromString(par_typ); 00357 hdlr->configure(nt, typ, cntH); 00358 pdbA->setHandler(hdlr); 00359 refpObject = nt; 00360 } 00361 else { 00362 refpObject = 0; 00363 if ( nt ) nt->release(); 00364 } 00365 } 00366 } 00367 } 00368 } 00369 } 00370 return status; 00371 } 00372 00373 // Update the transient object: NTuples end here when reading records 00374 StatusCode 00375 PoolDbNTupleCnv::updateObj(IOpaqueAddress* pAddr, DataObject* pObj) { 00376 INTuple* tupl = dynamic_cast<INTuple*>(pObj); 00377 PoolDbAddress* pdbA = dynamic_cast<PoolDbAddress*>(pAddr); 00378 if ( 0 != tupl && 0 != pdbA ) { 00379 PoolDbTupleCallback* hdlr = dynamic_cast<PoolDbTupleCallback*>(pdbA->handler()); 00380 pool::DbSelect* it = hdlr->iterator(); 00381 if ( 0 == it ) { 00382 it = hdlr->select(tupl->selector()); 00383 } 00384 if ( it ) { 00385 pool::Token* t = 0; 00386 if ( hdlr->iterator()->next(t).isSuccess() ) { 00387 std::auto_ptr<pool::Token> next(t); 00388 // Now reload! 00389 if ( bindRead(tupl, hdlr).isSuccess() ) { 00390 // No support for SmartRefs<T> for N-tuples 00391 //pushCurrentDataObject((DataObject**)&pObj); 00392 if ( m_dbMgr->read(hdlr, *next.get()).isSuccess() ) { 00393 if ( readData(tupl, hdlr).isSuccess() ) { 00394 //popCurrentDataObject(); 00395 return S_OK; 00396 } 00397 //popCurrentDataObject(); 00398 return makeError("updateObj> Cannot interprete data."); 00399 } 00400 //popCurrentDataObject(); 00401 return makeError("updateObj> Cannot read data."); 00402 } 00403 return makeError("updateObj> Cannot bind data."); 00404 } 00405 return S_FAIL; 00406 } 00407 return makeError("updateObj> Token selection failed!"); 00408 } 00409 return makeError("updateObj> Invalid Tuple reference."); 00410 } 00411 00413 StatusCode 00414 PoolDbNTupleCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) { 00415 IRegistry* pRegistry = pObj->registry(); 00416 if ( 0 != pRegistry ) { 00417 pAddr = pRegistry->address(); 00418 PoolDbAddress* pdbA = dynamic_cast<PoolDbAddress*>(pAddr); 00419 if ( 0 == pdbA ) { 00420 const INTuple* nt = dynamic_cast<const INTuple*>(pObj); 00421 std::string loc = containerName(pObj->registry()); 00422 if ( 0 != nt ) { 00423 const INTuple::ItemContainer& items = nt->items(); 00424 std::vector<const pool::DbColumn*> cols; 00425 std::vector<int> item_map(items.size()+1,-1); 00426 std::ostringstream os; 00427 int pool_type = 0; 00428 size_t item_no; 00429 os << nt->title()<<';'<<pObj->clID()<<';'<<items.size()<< ';'; 00430 for(item_no = 0; item_no < items.size(); ++item_no ) { 00431 pool::DbColumn* col = 0; 00432 INTupleItem* it = items[item_no]; 00433 os << '{' 00434 << it->name() << ';' 00435 << it->type() << ';' 00436 << it->length() << ';' 00437 << it->ndim() << ';' 00438 << it->hasIndex() << ';'; 00439 if ( it->hasIndex() ) { 00440 os << it->index() << ';'; 00441 INTupleItem* itm = it->indexItem(); 00442 switch( itm->type() ) { 00443 case DataTypeInfo::UCHAR: 00444 putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(itm)); 00445 break; 00446 case DataTypeInfo::USHORT: 00447 putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(itm)); 00448 break; 00449 case DataTypeInfo::UINT: 00450 putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(itm)); 00451 break; 00452 case DataTypeInfo::ULONG: 00453 putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(itm)); 00454 break; 00455 case DataTypeInfo::CHAR: 00456 putRange(os, dynamic_cast<NTuple::_Data<char>*>(itm)); 00457 break; 00458 case DataTypeInfo::SHORT: 00459 putRange(os, dynamic_cast<NTuple::_Data<short>*>(itm)); 00460 break; 00461 case DataTypeInfo::INT: 00462 putRange(os, dynamic_cast<NTuple::_Data<int>*>(itm)); 00463 break; 00464 case DataTypeInfo::LONG: 00465 putRange(os, dynamic_cast<NTuple::_Data<long>*>(itm)); 00466 break; 00467 default: { 00468 MsgStream err(msgSvc(), "NTuple:"+pRegistry->name()); 00469 err << MSG::ERROR << "Column " << it->index() 00470 << " is not a valid index column!" << endreq; 00471 return S_FAIL; 00472 } 00473 } 00474 } 00475 for ( long k = 0; k < it->ndim(); k++ ) { 00476 os << it->dim(k) << ';'; 00477 } 00478 switch(it->type()) { 00479 case DataTypeInfo::STRING: 00480 pool_type = pool::DbColumn::STRING; 00481 os << 0 << ';' << 0 << ';'; 00482 break; 00483 case DataTypeInfo::NTCHAR: 00484 pool_type = pool::DbColumn::NTCHAR; 00485 os << 0 << ';' << 0 << ';'; 00486 break; 00487 case DataTypeInfo::OBJECT_ADDR: 00488 if ( it->length() == 1 ) { 00489 col = new pool::DbColumn(it->name(), 00490 pool::typeName(typeid(PoolDbTokenWrap)), 00491 pool::DbColumn::POINTER, 00492 0); 00493 item_map[item_no] = cols.size(); 00494 cols.push_back(col); 00495 } 00496 os << 0 << ';' << 0 << ';'; 00497 break; 00498 case DataTypeInfo::POINTER: 00499 if ( it->length() == 1 ) { 00500 ROOT::Reflex::Type typ = ROOT::Reflex::Type::ByName(it->typeName()); 00501 col = new pool::DbColumn(it->name(), 00502 typ.Name(ROOT::Reflex::SCOPED), 00503 pool::DbColumn::POINTER, 00504 0); 00505 item_map[item_no] = cols.size(); 00506 cols.push_back(col); 00507 os << 0 << ';' << 0 << ';'; 00508 } 00509 break; 00510 case DataTypeInfo::UCHAR: 00511 pool_type = pool::DbColumn::UCHAR; 00512 putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(it)); 00513 goto MakeCol; 00514 case DataTypeInfo::USHORT: 00515 pool_type = pool::DbColumn::USHORT; 00516 putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(it)); 00517 goto MakeCol; 00518 case DataTypeInfo::UINT: 00519 pool_type = pool::DbColumn::UINT; 00520 putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(it)); 00521 goto MakeCol; 00522 case DataTypeInfo::ULONG: 00523 pool_type = pool::DbColumn::ULONG; 00524 putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(it)); 00525 goto MakeCol; 00526 case DataTypeInfo::CHAR: 00527 pool_type = pool::DbColumn::CHAR; 00528 putRange(os, dynamic_cast<NTuple::_Data<char>*>(it)); 00529 goto MakeCol; 00530 case DataTypeInfo::SHORT: 00531 pool_type = pool::DbColumn::SHORT; 00532 putRange(os, dynamic_cast<NTuple::_Data<short>*>(it)); 00533 goto MakeCol; 00534 case DataTypeInfo::INT: 00535 pool_type = pool::DbColumn::INT; 00536 putRange(os, dynamic_cast<NTuple::_Data<int>*>(it)); 00537 goto MakeCol; 00538 case DataTypeInfo::LONG: 00539 pool_type = pool::DbColumn::LONG; 00540 putRange(os, dynamic_cast<NTuple::_Data<long>*>(it)); 00541 goto MakeCol; 00542 case DataTypeInfo::BOOL: 00543 pool_type = pool::DbColumn::BOOL; 00544 putRange(os, dynamic_cast<NTuple::_Data<bool>*>(it)); 00545 goto MakeCol; 00546 case DataTypeInfo::FLOAT: 00547 pool_type = pool::DbColumn::FLOAT; 00548 putRange(os, dynamic_cast<NTuple::_Data<float>*>(it)); 00549 goto MakeCol; 00550 case DataTypeInfo::DOUBLE: 00551 pool_type = pool::DbColumn::DOUBLE; 00552 putRange(os, dynamic_cast<NTuple::_Data<double>*>(it)); 00553 goto MakeCol; 00554 MakeCol: 00555 if ( it->length() == 1 ) { 00556 pool::DbColumn* col = new pool::DbColumn(it->name(), 00557 pool_type, 00558 0, 00559 DataTypeInfo::size(it->type())); 00560 item_map[item_no] = cols.size(); 00561 cols.push_back(col); 00562 } 00563 // Everything else CANNOT be identified using SQL 00564 break; 00565 case DataTypeInfo::UNKNOWN: 00566 default: 00567 std::cout << "Create item[FAIL]]: " << it->name() 00568 << " Typ:" << it->type() << std::endl; 00569 break; 00570 } 00571 os << '}'; 00572 } 00573 item_map[item_no] = cols.size(); 00574 pool::DbColumn* col = 00575 new pool::DbColumn("BlobData", 00576 pool::DbColumn::BLOB, 00577 0, 00578 DataTypeInfo::size(pool::DbColumn::BLOB)); 00579 cols.push_back(col); 00580 pool::Guid guid; 00581 std::string cntName = containerName(pRegistry); 00582 std::string path = fileName(pRegistry); 00583 genMD5(os.str(), &guid); 00584 const pool::DbTypeInfo* typH = pool::DbTypeInfo::createEx(guid, cols); 00585 StatusCode sc = saveDescription(path, 00586 cntName, 00587 os.str(), 00588 typH->toString(), 00589 guid, 00590 pObj->clID(), 00591 "UPDATE"); 00592 if ( sc.isSuccess() ) { 00593 // Check if the database container can be connected 00594 pool::DbContainer cntH(POOL_StorageType); 00595 StatusCode sc = 00596 m_dbMgr->connectContainer(IPoolDbMgr::UNKNOWN, 00597 path, 00598 cntName, 00599 pool::RECREATE|pool::UPDATE, 00600 typH, 00601 cntH); 00602 if ( sc.isSuccess() ) { 00603 PoolDbTupleCallback* hdlr = new PoolDbTupleCallback(pObj); 00604 pool::Token* tok = new pool::Token(cntH.token()); 00605 PoolDbAddress* add = new PoolDbAddress(tok); 00606 hdlr->configure(nt, typH, cntH); 00607 tok->oid().second = 0; 00608 tok->release(); 00609 pAddr = add; 00610 add->setHandler(hdlr); 00611 return m_dbMgr->commitOutput(path, true); 00612 } 00613 return S_FAIL; 00614 } 00615 return sc; 00616 } 00617 } 00618 else { 00619 return S_OK; 00620 } 00621 } 00622 return S_FAIL; 00623 } 00624 00626 StatusCode 00627 PoolDbNTupleCnv::fillRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) 00628 { 00629 INTuple* pTuple = dynamic_cast<INTuple*>(pObj); 00630 if ( pTuple ) { 00631 IRegistry* pRegistry = pObj->registry(); 00632 if ( 0 != pRegistry ) { 00633 pAddr = pRegistry->address(); 00634 PoolDbAddress* pdbA = dynamic_cast<PoolDbAddress*>(pAddr); 00635 if ( 0 != pdbA ) { 00636 PoolDbTupleCallback* cb = dynamic_cast<PoolDbTupleCallback*>(pdbA->handler()); 00637 if ( cb ) { 00638 const pool::DbTypeInfo* typH = dynamic_cast<const pool::DbTypeInfo*>(cb->shape()); 00639 if ( typH ) { 00640 if ( bindWrite(pTuple, cb).isSuccess() ) { 00641 std::string path = fileName(pRegistry); 00642 std::string cntName = containerName(pRegistry); 00643 if ( !m_dbMgr->connectOutput(path, "UPDATE").isSuccess() ) { 00644 MsgStream log(msgSvc(), "PoolDbNTupleCnv"); 00645 log << MSG::ERROR << "Error: connectOutput(path, UPDATE)" << endmsg; 00646 return S_FAIL; 00647 } 00648 if ( m_dbMgr->markWrite(cb->clone(), cntName, &pdbA).isSuccess() ) { 00649 if ( m_dbMgr->commitOutput(path, true).isSuccess() ) { 00650 typedef INTuple::ItemContainer Cont; 00651 Cont& it = pTuple->items(); 00652 for(Cont::iterator i = it.begin(); i != it.end(); ++i) { 00653 (*i)->reset(); 00654 } 00655 return S_OK; 00656 } 00657 } 00658 } 00659 } 00660 } 00661 } 00662 } 00663 } 00664 return S_FAIL; 00665 } 00666 00667 StatusCode PoolDbNTupleCnv::bindRead(INTuple* nt, 00668 PoolDbTupleCallback* cb) 00669 { 00670 typedef INTuple::ItemContainer Cont; 00671 int cnt = 0; 00672 //pool::DbBlob& s = cb->stream(); 00673 std::vector<void*>& addr = cb->addresses(); 00674 std::vector<PoolDbTokenWrap*>& links = cb->links(); 00675 const std::vector<int>& mapping = cb->mapping(); 00676 Cont& items = nt->items(); 00677 for (Cont::iterator i = items.begin(); i != items.end(); ++i, ++cnt ) { 00678 int count = mapping[cnt]; 00679 if ( count >= 0 ) { 00680 char* buf = (char*)(*i)->buffer(); 00681 switch( (*i)->type() ) { 00682 case DataTypeInfo::OBJECT_ADDR: 00683 addr[count] = &links[cnt]; 00684 break; 00685 default: 00686 addr[count] = buf; 00687 break; 00688 } 00689 } 00690 } 00691 return S_OK; 00692 } 00693 00694 StatusCode PoolDbNTupleCnv::readData(INTuple* nt, 00695 PoolDbTupleCallback* cb) 00696 { 00697 typedef INTuple::ItemContainer Cont; 00698 int cnt = 0; 00699 pool::DbBlob& s = cb->stream(); 00700 std::vector<PoolDbTokenWrap*>& links = cb->links(); 00701 const std::vector<int>& mapping = cb->mapping(); 00702 INTuple::ItemContainer& items = nt->items(); 00703 for (Cont::iterator i = items.begin(); i != items.end(); ++i, ++cnt ) { 00704 int count = mapping[cnt]; 00705 int typ = (*i)->type(); 00706 if(count < 0 || typ == DataTypeInfo::OBJECT_ADDR || typ == DataTypeInfo::POINTER) { 00707 char* buf = (char*)(*i)->buffer(); 00708 int sc = 11; 00709 switch( (*i)->type() ) { 00710 case DataTypeInfo::UCHAR: sc=load<unsigned char> (s,buf); break; 00711 case DataTypeInfo::USHORT: sc=load<unsigned short>(s,buf); break; 00712 case DataTypeInfo::UINT: sc=load<unsigned int> (s,buf); break; 00713 case DataTypeInfo::ULONG: sc=load<unsigned long> (s,buf); break; 00714 case DataTypeInfo::CHAR: sc=load<char> (s,buf); break; 00715 case DataTypeInfo::SHORT: sc=load<short> (s,buf); break; 00716 case DataTypeInfo::INT: sc=load<int> (s,buf); break; 00717 case DataTypeInfo::LONG: sc=load<long> (s,buf); break; 00718 case DataTypeInfo::BOOL: sc=load<bool> (s,buf); break; 00719 case DataTypeInfo::FLOAT: sc=load<float> (s,buf); break; 00720 case DataTypeInfo::DOUBLE: sc=load<double> (s,buf); break; 00721 case DataTypeInfo::STRING: sc=load<std::string> (s,buf); break; 00722 case DataTypeInfo::NTCHAR: sc=load<char*> (s,buf); break; 00723 case DataTypeInfo::OBJECT_ADDR: sc=load(buf,links[count]); break; 00724 case DataTypeInfo::POINTER: break; 00725 case DataTypeInfo::UNKNOWN: break; 00726 default: break; 00727 } 00728 if ( 0 != sc ) { 00729 MsgStream log(msgSvc(), "PoolDbNTupleCnv"); 00730 log << MSG::DEBUG; 00731 switch (sc) { 00732 case 10: 00733 log << "CANNOT Set Ntuple token: dynamic_cast<GenericAddress*> is NULL"; 00734 break; 00735 case 11: 00736 log << "CANNOT Set Ntuple token: invalid address buffer"; 00737 break; 00738 } 00739 log << endmsg; 00740 } 00741 } 00742 } 00743 return S_OK; 00744 } 00745 00747 StatusCode PoolDbNTupleCnv::bindWrite(INTuple* nt, PoolDbTupleCallback* cb) 00748 { 00749 int cnt = 0; 00750 pool::DbBlob& s = cb->stream(); 00751 std::vector<void*>& addr = cb->addresses(); 00752 std::vector<PoolDbTokenWrap*>& links = cb->links(); 00753 const std::vector<int>& mapping = cb->mapping(); 00754 const INTuple::ItemContainer& items = nt->items(); 00755 INTuple::ItemContainer::const_iterator i; 00756 00757 s.setMode(pool::DbBlob::WRITING); 00758 for(i = items.begin(); i != items.end(); ++i, ++cnt ) { 00759 char* b = (char*)(*i)->buffer(); 00760 int len = (*i)->filled(); 00761 long ndim = (*i)->ndim(); 00762 int count = mapping[cnt]; 00763 void* ptr = 0; 00764 switch( (*i)->type() ) { 00765 case DataTypeInfo::UCHAR: ptr=save<unsigned char >(s,b,len,ndim>0); break; 00766 case DataTypeInfo::USHORT: ptr=save<unsigned short>(s,b,len,ndim>0); break; 00767 case DataTypeInfo::UINT: ptr=save<unsigned int >(s,b,len,ndim>0); break; 00768 case DataTypeInfo::ULONG: ptr=save<unsigned long >(s,b,len,ndim>0); break; 00769 case DataTypeInfo::CHAR: ptr=save<char >(s,b,len,ndim>0); break; 00770 case DataTypeInfo::SHORT: ptr=save<short >(s,b,len,ndim>0); break; 00771 case DataTypeInfo::INT: ptr=save<int >(s,b,len,ndim>0); break; 00772 case DataTypeInfo::LONG: ptr=save<long >(s,b,len,ndim>0); break; 00773 case DataTypeInfo::BOOL: ptr=save<bool >(s,b,len,ndim>0); break; 00774 case DataTypeInfo::FLOAT: ptr=save<float >(s,b,len,ndim>0); break; 00775 case DataTypeInfo::DOUBLE: ptr=save<double >(s,b,len,ndim>0); break; 00776 case DataTypeInfo::STRING: ptr=save<std::string >(s,b,len,ndim>0); break; 00777 case DataTypeInfo::NTCHAR: ptr=save<char* >(s,b,len,ndim>0); break; 00778 case DataTypeInfo::POINTER: ptr=*(void**)b; break; 00779 case DataTypeInfo::OBJECT_ADDR: ptr=save(b,links[count]); break; 00780 case DataTypeInfo::UNKNOWN: break; 00781 default: /* Do we have to take some action here ? */ break; 00782 } 00783 if ( count >= 0 ) { 00784 addr[count] = ptr; 00785 } 00786 } 00787 return S_OK; 00788 }