00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #define DBCNV_DBBASECONVERTER_CPP
00012
00013
00014
00015 #include "GaudiKernel/System.h"
00016 #include "GaudiKernel/DataObject.h"
00017 #include "GaudiKernel/RegistryEntry.h"
00018 #include "GaudiKernel/SmartDataPtr.h"
00019 #include "GaudiKernel/MsgStream.h"
00020 #include "GaudiKernel/ISvcLocator.h"
00021 #include "GaudiKernel/IConversionSvc.h"
00022 #include "GaudiKernel/IAddressCreator.h"
00023 #include "GaudiKernel/IDataProviderSvc.h"
00024 #include "GaudiKernel/IObjManager.h"
00025
00026 #include "GaudiDb/IOODataBase.h"
00027 #include "GaudiDb/IDataBaseMgr.h"
00028 #include "GaudiDb/DbVArray.h"
00029 #include "GaudiDb/DbDataBase.h"
00030 #include "GaudiDb/DbBaseConverter.h"
00031 #include "GaudiDb/DbAddress.h"
00032
00034 DbBaseConverter::DbBaseConverter(const CLID& clid, IOODataBase* db, ISvcLocator* svc)
00035 : Converter(db->type(), clid, svc), m_db(db), m_type(0)
00036 {
00037 std::string typName = System::typeinfoName(typeid(DbObject));
00038 m_type = db->typeInfo(typName);
00039 m_cnvSvcName = db->name().substr(0,db->name().rfind("."));
00040 m_helperServices.clear();
00041 m_persSvcName = "EventPersistencySvc";
00042 m_dataSvcName = "EventDataSvc";
00043 }
00044
00046 DbBaseConverter::~DbBaseConverter() {
00047 }
00048
00050 const DbTypeInfo* DbBaseConverter::typeInfo() const {
00051 return m_type;
00052 }
00053
00055 StatusCode DbBaseConverter::initialize() {
00056 StatusCode status = Converter::initialize();
00057 MsgStream log(msgSvc(),"DbBaseConverter");
00058 if ( !status.isSuccess() ) {
00059 log << MSG::ERROR << "Cannot initialize base class \"Converter\"" << endreq;
00060 return status;
00061 }
00062 m_helperServices.clear();
00063
00064 status = serviceLocator()->getService(m_cnvSvcName,IID_IDataBaseMgr,(IInterface*&)m_helperServices.DbaseMgr);
00065 if ( !status.isSuccess() ) {
00066 log << MSG::ERROR << "Cannot connect to \"" << m_cnvSvcName << "\"" << endreq;
00067 return status;
00068 }
00069 status = serviceLocator()->getService(m_persSvcName,IID_IConversionSvc,(IInterface*&)m_helperServices.PersSvc);
00070 if ( !status.isSuccess() ) {
00071 log << MSG::ERROR << "Cannot connect to \"" << m_persSvcName << "\"" << endreq;
00072 return status;
00073 }
00074 status = serviceLocator()->getService(m_dataSvcName,IID_IDataProviderSvc,(IInterface*&)m_helperServices.DataSvc);
00075 if ( !status.isSuccess() ) {
00076 log << MSG::ERROR << "Cannot connect to \"" << m_dataSvcName << "\"" << endreq;
00077 return status;
00078 }
00079 status = serviceLocator()->queryInterface(IID_IObjManager, (void**)&m_helperServices.ObjManager);
00080 if ( !status.isSuccess() ) {
00081 log << MSG::ERROR << "Cannot connect to \"ObjManager\"" << endreq;
00082 return status;
00083 }
00084 m_helperServices.PersSvc->queryInterface(IID_IAddressCreator, (void**)&m_helperServices.AddrCreator);
00085 m_helperServices.DbaseMgr->queryInterface(IID_IConversionSvc, (void**)&m_helperServices.CnvSvc);
00086 m_helperServices.SvcLocator = serviceLocator();
00087 m_helperServices.MessageSvc = messageService();
00088 if ( 0 == m_type ) {
00089 log << MSG::ERROR << "No type information availible...." << endreq;
00090 return StatusCode::FAILURE;
00091 }
00092 return status;
00093 }
00094
00096 StatusCode DbBaseConverter::finalize() {
00097 StatusCode status = Converter::finalize();
00098 m_helperServices.clear();
00099 return status;
00100 }
00101
00103 DataObject* DbBaseConverter::createTransient() {
00104 return new DataObject();
00105 }
00106
00108 const std::string DbBaseConverter::containerName(IDataDirectory* pDir) const {
00109 return pDir->fullpath();
00110 }
00111
00113 dbHandle<DbObject> DbBaseConverter::createPersistent(dbHandle<DbContainer>& cntH) {
00114 dbHandle<DbObject> handle = new(cntH, *m_type) DbObject();
00115 return handle;
00116 }
00117
00119 StatusCode DbBaseConverter::createObj(IOpaqueAddress* , DataObject*& refpObject) {
00120 refpObject = createTransient();
00121 return StatusCode::SUCCESS;
00122 }
00123
00125 StatusCode DbBaseConverter::fillObjRefs(IOpaqueAddress* pAddress, DataObject* pObject ) {
00126 return updateObjRefs(pAddress, pObject);
00127 }
00128
00130 StatusCode DbBaseConverter::updateObj(IOpaqueAddress* , DataObject* ) {
00131 return StatusCode::SUCCESS;
00132 }
00133
00135 StatusCode DbBaseConverter::updateObjRefs(IOpaqueAddress* pAddress, DataObject* pObject) {
00136 try {
00137 DbAddress* pAddr = dynamic_cast<DbAddress*>(pAddress);
00138 if ( 0 != pObject && 0 != pAddr ) {
00139
00140 dbHandle<DbDefObject> objH = pAddr->objectHdl();
00141 dbHandle<DbLink> lnkH = *pAddr;
00142 if ( objH.open(pAddr->containerHdl(), lnkH) ) {
00143 StatusCode status = updateTransientDirectoryLinks( objH, pObject );
00144 if ( status.isSuccess() ) {
00145 status = updateTransientSymbolicLinks( objH, pObject );
00146 if ( status.isSuccess() ) {
00147 status = beginTransientUpdate( objH, pObject );
00148 if ( status.isSuccess() ) {
00149 status = doTransientUpdate( objH, pObject );
00150 if ( status.isSuccess() ) {
00151 status = endTransientUpdate( objH, pObject );
00152 if ( status.isSuccess() ) {
00153 return afterTransientUpdate( objH, pObject );
00154 }
00155 }
00156 }
00157 }
00158 }
00159 }
00160 }
00161 }
00162 catch (...) {
00163 }
00164 MsgStream log(messageService(),"DbBaseConverter");
00165 log << MSG::INFO << "updateObjRefs: Cannot load object data from persistent medium..." << endreq;
00166 return StatusCode::FAILURE;
00167 }
00168
00170 StatusCode DbBaseConverter::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress) {
00171 refpAddress = 0;
00172 if ( 0 != pObject ) {
00173 try {
00174 dbHandle<DbContainer> cntH;
00175 dbHandle<DbDataBase> dbH = m_helperServices.DbaseMgr->defaultDbHdl();
00176 std::string cntName = containerName(pObject->directory());
00177 if ( cntH.open(dbH, cntName, *m_type, DbOOMs::UPDATE|DbOOMs::CREATE) ) {
00178 dbHandle<DbObject> objH = createPersistent(cntH);
00179 if ( objH.isValid() ) {
00180 refpAddress = new DbAddress(objH, pObject->clID());
00181 if ( updateRep(refpAddress, pObject).isSuccess() ) {
00182 return StatusCode::SUCCESS;
00183 }
00184 }
00185 }
00186 }
00187 catch (...) {
00188 }
00189 }
00190 if ( 0 != refpAddress ) {
00191 refpAddress->release();
00192 refpAddress = 0;
00193 }
00194 MsgStream log(messageService(),"DbBaseConverter");
00195 log << MSG::FATAL << "Fatal Error in createRep:" << __FILE__ << " line " << __LINE__ << endreq;
00196 return StatusCode::FAILURE;
00197 }
00198
00200 StatusCode DbBaseConverter::fillRepRefs(IOpaqueAddress* pAddress, DataObject* pObject) {
00201 try {
00202 DbAddress* pAddr = dynamic_cast<DbAddress*>(pAddress);
00203 StatusCode status = doUpdateRepRefs(pAddress, pObject);
00204 if ( status.isSuccess() && 0 != pAddr ) {
00205 dbHandle<DbObject>& objH = pAddr->objectHdl();
00206
00207 if ( pAddr->containerHdl().addEntry(objH) ) {
00208 dbHandle<DbDefObject> dobjH = objH;
00209 status = afterPersistentUpdate(dobjH, pObject);
00210 if ( status.isSuccess() ) {
00211 return StatusCode::SUCCESS;
00212 }
00213 }
00214 }
00215 }
00216 catch (...) {
00217 }
00218 return StatusCode::FAILURE;
00219 }
00220
00222 StatusCode DbBaseConverter::updateRepRefs(IOpaqueAddress* pAddress, DataObject* pObject) {
00223 try {
00224 DbAddress* pAddr = dynamic_cast<DbAddress*>(pAddress);
00225 StatusCode status = doUpdateRepRefs(pAddress, pObject);
00226 if ( status.isSuccess() && 0 != pAddr ) {
00227 dbHandle<DbObject>& objH = pAddr->objectHdl();
00228
00229 if ( pAddr->containerHdl().updateEntry(objH) ) {
00230 dbHandle<DbDefObject> dobjH = objH;
00231 status = afterPersistentUpdate(dobjH, pObject);
00232 if ( status.isSuccess() ) {
00233 return StatusCode::SUCCESS;
00234 }
00235 }
00236 }
00237 }
00238 catch (...) {
00239 }
00240 return StatusCode::FAILURE;
00241 }
00242
00244 StatusCode DbBaseConverter::updateRep(IOpaqueAddress* pAddress, DataObject* pObject) {
00245 StatusCode status = StatusCode::FAILURE;
00246 try {
00247 DbAddress* pAddr = dynamic_cast<DbAddress*>(pAddress);
00248 if ( 0 != pObject && 0 != pAddr && pAddr->isValid() ) {
00249 dbHandle<DbObject>& oH = pAddr->objectHdl();
00250 if ( !oH.isValid() ) {
00251 dbHandle<DbLink> lnkH = *pAddr;
00252 oH.open(pAddr->containerHdl(), lnkH);
00253 }
00254 dbHandle<DbDefObject> objH = oH;
00255 if ( objH.isValid() ) {
00256 status = preparePersistentUpdate( objH, pObject );
00257 if ( status.isSuccess() ) {
00258 return beginPersistentUpdate( objH, pObject );
00259 }
00260 }
00261 }
00262 }
00263 catch (...) {
00264 }
00265 MsgStream log(messageService(),"DbBaseConverter");
00266 log << MSG::FATAL << "Fatal Error in updateRep:" << __FILE__ << " line " << __LINE__ << endreq;
00267 return StatusCode::FAILURE;
00268 }
00269
00271 StatusCode DbBaseConverter::doUpdateRepRefs(IOpaqueAddress* pAddress, DataObject* pObj) {
00272 std::string error = "Unknown exception";
00273 try {
00274 DbAddress* pAddr = dynamic_cast<DbAddress*>(pAddress);
00275 if ( 0 != pObj && 0 != pAddr ) {
00276 dbHandle<DbDefObject> objH = pAddr->objectHdl();
00277 if ( objH.isValid() ) {
00278
00279 objH->links().remove_all();
00280 StatusCode status = doPersistentUpdate( objH, pObj );
00281 if ( status.isSuccess() ) {
00282 status = endPersistentUpdate(objH, pObj);
00283 if ( status.isSuccess() ) {
00284 status = addPersistentDirectoryLinks(objH, pObj);
00285 if ( status.isSuccess() ) {
00286 return addPersistentSymbolicLinks(objH, pObj);
00287 }
00288 else {
00289 error = "addPersistentDirectoryLinks";
00290 }
00291 }
00292 else {
00293 error = "endPersistentUpdate";
00294 }
00295 }
00296 else {
00297 error = "doPersistentUpdate";
00298 }
00299 }
00300 else {
00301 error = "Invalid Obj handle";
00302 }
00303 }
00304 else {
00305 error = "invalid address/object";
00306 }
00307 }
00308 catch (...) {
00309 }
00310 MsgStream log(messageService(),"DbBaseConverter");
00311 log << MSG::FATAL << "Fatal Error in doUpdateRepRefs:" << __FILE__ << " line " << __LINE__
00312 << " Obj:" << pObj->fullpath()
00313 << " Error: " << error
00314 << endreq;
00315 return StatusCode::FAILURE;
00316 }
00317
00319 StatusCode DbBaseConverter::addPersistentLink(IOpaqueAddress* pA, dbHandle<DbDefObject>& , const DataObject* pObj) {
00320 StatusCode iret = StatusCode::FAILURE;
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 if ( !iret.isSuccess() ) {
00336 MsgStream err(messageService(),"DbBaseConverter");
00337 err << MSG::FATAL << "Entry:" << pObj->fullpath()
00338 << " Cannot add persistent Reference ";
00339 if ( 0 != pA )err << pA->dbName()
00340 << ":" << pA->containerName()
00341 << "#" << pA->objectName();
00342 err << endreq;
00343 }
00344 return iret;
00345 }
00346
00348 StatusCode DbBaseConverter::addPersistentDirectoryLinks(dbHandle<DbDefObject>& objH, const DataObject* pObj) {
00349 StatusCode status = StatusCode::SUCCESS, iret;
00350 for( DataObject::DirIterator i = pObj->dirBegin(), iend = pObj->dirEnd(); i != iend; i++ ) {
00351 IOpaqueAddress* pA = (*i)->address();
00352 iret = StatusCode::FAILURE;
00353 if ( 0 != pA ) {
00354 dbHandle<DbLink> to(*pA->genericLink());
00355
00356 dbHandle<DbDataBase> dbH = objH.containedIn().containedIn();
00357 if ( dbH.addAssocEntry(pA->dbName(), pA->containerName(), pA->objectName(), to) ) {
00358 iret = objH->links().extend(to);
00359 }
00360 }
00361 else {
00362
00363
00364
00365 iret = objH->addInvalidLink();
00366 }
00367 if ( !iret.isSuccess() ) {
00368 status = iret;
00369 MsgStream err(messageService(),"DbBaseConverter");
00370 err << MSG::FATAL << "Entry:" << pObj->fullpath()
00371 << " Cannot add persistent directory reference ";
00372 if ( 0 != pA )err << pA->dbName()
00373 << ":" << pA->containerName()
00374 << "#" << pA->objectName();
00375 err << endreq;
00376 }
00377 }
00378 return status;
00379 }
00380
00382 StatusCode DbBaseConverter::addPersistentSymbolicLinks(dbHandle<DbDefObject>& objH, const DataObject* pObj) {
00383 StatusCode status = StatusCode::SUCCESS, iret;
00384 int cnt = 0;
00385
00386 for( DataObject::ConstLinkIterator j = pObj->linkBegin(), jend = pObj->linkEnd(); j != jend; j++ ) {
00387 IOpaqueAddress* pA = (*j)->address();
00388 iret = StatusCode::FAILURE;
00389 cnt++;
00390 if ( 0 != pA ) {
00391 dbHandle<DbLink> to(*pA->genericLink(), true);
00392
00393 dbHandle<DbDataBase> dbH = objH.containedIn().containedIn();
00394 if ( dbH.addAssocEntry(pA->dbName(), pA->containerName(), (*j)->path(), to) ) {
00395 iret = objH->links().extend(to);
00396 }
00397 }
00398 else {
00399
00400
00401
00402
00403 iret = objH->addInvalidLink();
00404 }
00405 if ( !iret.isSuccess() ) {
00406 status = iret;
00407 MsgStream err(messageService(),"DbBaseConverter");
00408 err << MSG::FATAL << "Entry:" << pObj->fullpath()
00409 << " Cannot add persistent symbolic reference ";
00410 if ( 0 != pA )err << pA->dbName()
00411 << ":" << pA->containerName()
00412 << "#" << pA->objectName();
00413 err << endreq;
00414 }
00415 }
00416 objH->setNumSymLink(cnt);
00417 return status;
00418 }
00419
00421 StatusCode DbBaseConverter::preparePersistentUpdate( dbHandle<DbDefObject>& , const DataObject* pObject) {
00422 bool needsUpdate = false;
00423 DataObject* pPtr = 0;
00424
00425
00426
00427
00428 for( DataObject::ConstLinkIterator j = pObject->linkBegin(), jend = pObject->linkEnd(); j != jend; j++ ) {
00429 if ( 0 == (*j)->object() ) {
00430 StatusCode iret = dataProvider()->retrieveObject((*j)->path(), pPtr);
00431 if ( iret.isSuccess() ) {
00432 needsUpdate = true;
00433 }
00434 }
00435 }
00436 if ( needsUpdate ) {
00437 dataProvider()->updateObject(const_cast<IDataDirectory*>(pObject->directory()));
00438 }
00439 return StatusCode::SUCCESS;
00440 }
00441
00443 StatusCode DbBaseConverter::beginPersistentUpdate( dbHandle<DbDefObject>& objH, const DataObject* pObject) {
00444 return objH->beginPersistentUpdate(m_helperServices, pObject);
00445 }
00446
00448 StatusCode DbBaseConverter::doPersistentUpdate( dbHandle<DbDefObject>& objH, const DataObject* pObject) {
00449 return objH->doPersistentUpdate( m_helperServices, pObject );
00450 }
00451
00453 StatusCode DbBaseConverter::endPersistentUpdate( dbHandle<DbDefObject>& objH, const DataObject* pObject) {
00454 return objH->endPersistentUpdate(m_helperServices, pObject);
00455 }
00456
00458 StatusCode DbBaseConverter::afterPersistentUpdate(dbHandle<DbDefObject>& , const DataObject* ) {
00459 return StatusCode::SUCCESS;
00460 }
00461
00463 StatusCode DbBaseConverter::beginTransientUpdate(dbHandle<DbDefObject>& , DataObject* pObject) {
00464 pObject->clearLinks();
00465 return StatusCode::SUCCESS;
00466 }
00467
00469 StatusCode DbBaseConverter::endTransientUpdate(dbHandle<DbDefObject>& , DataObject* ) {
00470 return StatusCode::SUCCESS;
00471 }
00472
00474 StatusCode DbBaseConverter::afterTransientUpdate(dbHandle<DbDefObject>& , DataObject* ) {
00475 return StatusCode::SUCCESS;
00476 }
00477
00479 StatusCode DbBaseConverter::doTransientUpdate(dbHandle<DbDefObject>& objH, DataObject* pObject) {
00480 return objH->doTransientUpdate( m_helperServices, pObject );
00481 }
00482
00483 static inline bool isInvalidLink(const GenericLinkBase& link) {
00484 if ( 0 == link.svcType() && 0 == link.clID() &&
00485 0xFFFFFFFF == link.genericInfo()->m_info[0] &&
00486 0xFFFFFFFF == link.genericInfo()->m_info[1] ) {
00487 return true;
00488 }
00489 return false;
00490 }
00491
00493 StatusCode DbBaseConverter::updateTransientDirectoryLinks(dbHandle<DbDefObject>& objH, DataObject* pObject) {
00494 long numLinks = objH->numLink();
00495 long numSymLinks = objH->numSymLink();
00496 IOpaqueAddress* pA;
00497 std::string fname, cname, oname;
00498 StatusCode iret, status = StatusCode::SUCCESS;
00499 RegistryEntry* pEntry = dynamic_cast<RegistryEntry*>(pObject->directory());
00500 dbVarray< dbHandle<DbLink> >& links = objH->links();
00501
00502
00503 for ( long i = 0, num = numLinks-numSymLinks; i < num; i++ ) {
00504 dbHandle<DbLink>& link = links[i];
00505 iret = objH.validateAssoc(link, fname, cname, oname);
00506 if ( iret.isSuccess() ) {
00507 iret = m_helperServices.AddrCreator->createAddress(link, fname, cname, oname, pA);
00508 if ( iret.isSuccess() ) {
00509 int loc = oname.rfind(IDataDirectory::SEPARATOR);
00510 std::string objname(oname, loc>0 ? loc : 0, oname.length());
00511 iret = pEntry->add( objname, pA);
00512 if ( !iret.isSuccess() ) {
00513 pA->release();
00514 }
00515 }
00516 else {
00517 MsgStream err(messageService(),"DbBaseConverter");
00518 err << MSG::DEBUG << "Entry:" << fname << ":" << cname << "->" << oname
00519 << " Cannot add transient directory reference "
00520 << endreq;
00521
00522 }
00523 }
00524 else if ( isInvalidLink(link) ) {
00525 MsgStream err(messageService(),"DbBaseConverter");
00526 err << MSG::DEBUG << "Entry:" << pEntry->fullpath()
00527 << " Cannot vaidate transient directory reference "
00528 << "Reference is invalid...maybe an error" << endreq;
00529
00530 }
00531 else {
00532 MsgStream err(messageService(),"DbBaseConverter");
00533 err << MSG::DEBUG << "Entry:" << pEntry->fullpath()
00534 << " Cannot vaidate transient symbolic reference "
00535 << " Typ:" << long(link.svcType())
00536 << " CLID:" << long(link.clID())
00537 << " [1]=" << (unsigned long)link.genericInfo()->m_info[0] << " "
00538 << " [2]=" << (unsigned long)link.genericInfo()->m_info[1] << " "
00539 << endreq;
00540
00541 }
00542 }
00543 return status;
00544 }
00545
00547 StatusCode DbBaseConverter::updateTransientSymbolicLinks(dbHandle<DbDefObject>& objH, DataObject* pObject) {
00548 long numLinks = objH->numLink();
00549 long numSymLinks = objH->numSymLink();
00550 std::string fname, cname, oname;
00551 StatusCode iret, status = StatusCode::SUCCESS;
00552 dbVarray< dbHandle<DbLink> >& links = objH->links();
00553
00554
00555 for ( long j = numLinks-numSymLinks; j < numLinks; j++ ) {
00556 dbHandle<DbLink>& link = links[j];
00557 link.makeSymbolic();
00558 iret = objH.validateAssoc(link, fname, cname, oname);
00559 if ( iret.isSuccess() ) {
00560 pObject->addLink(oname, 0);
00561 }
00562 else if ( isInvalidLink(link) ) {
00563 IDataDirectory* pEntry = pObject->directory();
00564 MsgStream err(messageService(),"DbBaseConverter");
00565 err << MSG::DEBUG << "Entry:" << pEntry->fullpath()
00566 << " Cannot vaidate transient symbolic reference "
00567 << "Reference is invalid...maybe an error" << endreq;
00568
00569 }
00570 else {
00571 IDataDirectory* pEntry = pObject->directory();
00572 MsgStream err(messageService(),"DbBaseConverter");
00573 err << MSG::DEBUG << "Entry:" << pEntry->fullpath()
00574 << " Cannot vaidate transient symbolic reference "
00575 << " Typ:" << long(link.svcType())
00576 << " CLID:" << long(link.clID())
00577 << " [1]=" << (unsigned long)link.genericInfo()->m_info[0] << " "
00578 << " [2]=" << (unsigned long)link.genericInfo()->m_info[1] << " "
00579 << endreq;
00580
00581 }
00582 }
00583 return status;
00584 }
00585
00586
00587
00588
00589
00590
00591