object_manager.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:18k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: object_manager.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:23:28  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.33
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: object_manager.cpp,v 1000.2 2004/06/01 19:23:28 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:
  35. *           Andrei Gourianov
  36. *           Aleksey Grichenko
  37. *           Michael Kimelman
  38. *           Denis Vakatov
  39. *
  40. * File Description:
  41. *           Object manager manages data objects,
  42. *           provides them to Scopes when needed
  43. *
  44. */
  45. #include <ncbi_pch.hpp>
  46. #include <objmgr/object_manager.hpp>
  47. #include <objmgr/data_loader.hpp>
  48. #include <objmgr/impl/scope_impl.hpp>
  49. #include <objmgr/impl/data_source.hpp>
  50. #include <objmgr/objmgr_exception.hpp>
  51. #include <objects/seqset/Seq_entry.hpp>
  52. BEGIN_NCBI_SCOPE
  53. BEGIN_SCOPE(objects)
  54. CObjectManager::CObjectManager(void)
  55. {
  56.   //LOG_POST("CObjectManager - new :" << this );
  57. }
  58. CObjectManager::~CObjectManager(void)
  59. {
  60.     //LOG_POST("~CObjectManager - delete " << this );
  61.     // delete scopes
  62.     TWriteLockGuard guard(m_OM_Lock);
  63.     if(!m_setScope.empty()) {
  64.         ERR_POST("Attempt to delete Object Manager with open scopes");
  65.         while ( !m_setScope.empty() ) {
  66.             // this will cause calling RegisterScope and changing m_setScope
  67.             // be careful with data access synchronization
  68.             (*m_setScope.begin())->x_DetachFromOM();
  69.         }
  70.     }
  71.     // release data sources
  72.     m_setDefaultSource.clear();
  73.     
  74.     while (!m_mapToSource.empty()) {
  75.         CDataSource* pSource = m_mapToSource.begin()->second.GetPointer();
  76.         _ASSERT(pSource);
  77.         if ( !pSource->ReferencedOnlyOnce() ) {
  78.             ERR_POST("Attempt to delete Object Manager with used data sources");
  79.         }
  80.         m_mapToSource.erase(m_mapToSource.begin());
  81.     }
  82.     // LOG_POST("~CObjectManager - delete " << this << "  done");
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // configuration functions
  86. void CObjectManager::RegisterDataLoader(CDataLoader& loader,
  87.                                         EIsDefault   is_default,
  88.                                         CPriorityNode::TPriority priority)
  89. {
  90.     TWriteLockGuard guard(m_OM_Lock);
  91.     x_RegisterLoader(loader, priority, is_default);
  92. }
  93. void CObjectManager::RegisterDataLoader(CDataLoaderFactory& factory,
  94.                                         EIsDefault is_default,
  95.                                         CPriorityNode::TPriority priority)
  96. {
  97.     string loader_name = factory.GetName();
  98.     _ASSERT(!loader_name.empty());
  99.     // if already registered
  100.     TWriteLockGuard guard(m_OM_Lock);
  101.     if ( x_GetLoaderByName(loader_name) ) {
  102.         ERR_POST(Warning <<
  103.             "CObjectManager::RegisterDataLoader: " <<
  104.             "data loader " << loader_name << " already registered");
  105.         return;
  106.     }
  107.     // in case factory was not put in a CRef container by the caller
  108.     // it will be deleted here
  109.     CRef<CDataLoaderFactory> p(&factory);
  110.     // create loader
  111.     CDataLoader* loader = factory.Create();
  112.     // register
  113.     x_RegisterLoader(*loader, priority, is_default);
  114. }
  115. void CObjectManager::RegisterDataLoader(TFACTORY_AUTOCREATE factory,
  116.                                         const string& loader_name,
  117.                                         EIsDefault is_default,
  118.                                         CPriorityNode::TPriority priority)
  119. {
  120.     _ASSERT(!loader_name.empty());
  121.     // if already registered
  122.     TWriteLockGuard guard(m_OM_Lock);
  123.     if ( x_GetLoaderByName(loader_name) ) {
  124.         ERR_POST(Warning <<
  125.             "CObjectManager::RegisterDataLoader: " <<
  126.             "data loader " << loader_name << " already registered");
  127.         return;
  128.     }
  129.     // create one
  130.     CDataLoader* loader = CREATE_AUTOCREATE(CDataLoader,factory);
  131.     loader->SetName(loader_name);
  132.     // register
  133.     x_RegisterLoader(*loader, priority, is_default);
  134. }
  135. bool CObjectManager::RevokeDataLoader(CDataLoader& loader)
  136. {
  137.     string loader_name = loader.GetName();
  138.     TWriteLockGuard guard(m_OM_Lock);
  139.     // make sure it is registered
  140.     CDataLoader* my_loader = x_GetLoaderByName(loader_name);
  141.     if ( my_loader != &loader ) {
  142.         NCBI_THROW(CObjMgrException, eRegisterError,
  143.             "Data loader " + loader_name + " not registered");
  144.     }
  145.     TDataSourceLock lock = x_RevokeDataLoader(&loader);
  146.     guard.Release();
  147.     return lock;
  148. }
  149. bool CObjectManager::RevokeDataLoader(const string& loader_name)
  150. {
  151.     TWriteLockGuard guard(m_OM_Lock);
  152.     CDataLoader* loader = x_GetLoaderByName(loader_name);
  153.     // if not registered
  154.     if ( !loader ) {
  155.         NCBI_THROW(CObjMgrException, eRegisterError,
  156.             "Data loader " + loader_name + " not registered");
  157.     }
  158.     TDataSourceLock lock = x_RevokeDataLoader(loader);
  159.     guard.Release();
  160.     return lock;
  161. }
  162. CObjectManager::TDataSourceLock
  163. CObjectManager::x_RevokeDataLoader(CDataLoader* loader)
  164. {
  165.     TMapToSource::iterator iter = m_mapToSource.find(loader);
  166.     _ASSERT(iter != m_mapToSource.end());
  167.     _ASSERT(iter->second->GetDataLoader() == loader);
  168.     bool is_default = m_setDefaultSource.erase(iter->second) != 0;
  169.     if ( !iter->second->ReferencedOnlyOnce() ) {
  170.         // this means it is in use
  171.         if ( is_default )
  172.             _VERIFY(m_setDefaultSource.insert(iter->second).second);
  173.         ERR_POST("CObjectManager::RevokeDataLoader: "
  174.                  "data loader is in use");
  175.         return TDataSourceLock();
  176.     }
  177.     // remove from the maps
  178.     TDataSourceLock lock(iter->second);
  179.     m_mapNameToLoader.erase(loader->GetName());
  180.     m_mapToSource.erase(loader);
  181.     return lock;
  182. }
  183. /*
  184. void CObjectManager::RegisterTopLevelSeqEntry(CSeq_entry& top_entry)
  185. {
  186.     TWriteLockGuard guard(m_OM_Mutex);
  187.     x_RegisterTSE(top_entry);
  188. }
  189. */
  190. /////////////////////////////////////////////////////////////////////////////
  191. // functions for scopes
  192. void CObjectManager::RegisterScope(CScope_Impl& scope)
  193. {
  194.     TWriteLockGuard guard(m_OM_ScopeLock);
  195.     _VERIFY(m_setScope.insert(&scope).second);
  196. }
  197. void CObjectManager::RevokeScope(CScope_Impl& scope)
  198. {
  199.     TWriteLockGuard guard(m_OM_ScopeLock);
  200.     _VERIFY(m_setScope.erase(&scope));
  201. }
  202. void CObjectManager::AcquireDefaultDataSources(TDataSourcesLock& sources)
  203. {
  204.     TReadLockGuard guard(m_OM_Lock);
  205.     sources = m_setDefaultSource;
  206. }
  207. CObjectManager::TDataSourceLock
  208. CObjectManager::AcquireDataLoader(CDataLoader& loader)
  209. {
  210.     TReadLockGuard guard(m_OM_Lock);
  211.     TDataSourceLock lock = x_FindDataSource(&loader);
  212.     if ( !lock ) {
  213.         guard.Release();
  214.         TWriteLockGuard wguard(m_OM_Lock);
  215.         lock = x_RegisterLoader(loader, kPriority_NotSet, eNonDefault, true);
  216.     }
  217.     return lock;
  218. }
  219. CObjectManager::TDataSourceLock
  220. CObjectManager::AcquireDataLoader(const string& loader_name)
  221. {
  222.     TReadLockGuard guard(m_OM_Lock);
  223.     CDataLoader* loader = x_GetLoaderByName(loader_name);
  224.     if ( !loader ) {
  225.         NCBI_THROW(CObjMgrException, eRegisterError,
  226.             "Data loader " + loader_name + " not found");
  227.     }
  228.     TDataSourceLock lock = x_FindDataSource(loader);
  229.     _ASSERT(lock);
  230.     return lock;
  231. }
  232. CObjectManager::TDataSourceLock
  233. CObjectManager::AcquireTopLevelSeqEntry(CSeq_entry& top_entry)
  234. {
  235.     TReadLockGuard guard(m_OM_Lock);
  236.     TDataSourceLock lock = x_FindDataSource(&top_entry);
  237.     if ( !lock ) {
  238.         guard.Release();
  239.         
  240.         TDataSourceLock source(new CDataSource(top_entry, *this));
  241.         source->DoDeleteThisObject();
  242.         
  243.         TWriteLockGuard wguard(m_OM_Lock);
  244.         lock = m_mapToSource.insert(
  245.             TMapToSource::value_type(&top_entry, source)).first->second;
  246.         _ASSERT(lock);
  247.     }
  248.     return lock;
  249. }
  250. /////////////////////////////////////////////////////////////////////////////
  251. // private functions
  252. CObjectManager::TDataSourceLock
  253. CObjectManager::x_FindDataSource(const CObject* key)
  254. {
  255.     TMapToSource::iterator iter = m_mapToSource.find(key);
  256.     return iter == m_mapToSource.end()? TDataSourceLock(): iter->second;
  257. }
  258. CObjectManager::TDataSourceLock
  259. CObjectManager::x_RegisterLoader(CDataLoader& loader,
  260.                                  CPriorityNode::TPriority priority,
  261.                                  EIsDefault is_default,
  262.                                  bool no_warning)
  263. {
  264.     string loader_name = loader.GetName();
  265.     _ASSERT(!loader_name.empty());
  266.     // if already registered
  267.     pair<TMapNameToLoader::iterator, bool> ins =
  268.         m_mapNameToLoader.insert(TMapNameToLoader::value_type(loader_name,0));
  269.     if ( !ins.second ) {
  270.         if ( ins.first->second != &loader ) {
  271.             NCBI_THROW(CObjMgrException, eRegisterError,
  272.                 "Attempt to register different data loaders "
  273.                 "with the same name");
  274.         }
  275.         if ( !no_warning ) {
  276.             ERR_POST(Warning <<
  277.                      "CObjectManager::RegisterDataLoader() -- data loader " <<
  278.                      loader_name << " already registered");
  279.         }
  280.         TMapToSource::const_iterator it = m_mapToSource.find(&loader);
  281.         _ASSERT(it != m_mapToSource.end() && bool(it->second));
  282.         return it->second;
  283.     }
  284.     ins.first->second = &loader;
  285.     // create data source
  286.     TDataSourceLock source(new CDataSource(loader, *this));
  287.     source->DoDeleteThisObject();
  288.     if (priority != kPriority_NotSet) {
  289.         source->SetDefaultPriority(priority);
  290.     }
  291.     _VERIFY(m_mapToSource.insert(TMapToSource::value_type(&loader,
  292.                                                           source)).second);
  293.     if (is_default == eDefault) {
  294.         m_setDefaultSource.insert(source);
  295.     }
  296.     return source;
  297. }
  298. CObjectManager::TDataSourceLock
  299. CObjectManager::x_RegisterTSE(CSeq_entry& top_entry)
  300. {
  301.     TDataSourceLock ret = x_FindDataSource(&top_entry);
  302.     if ( !ret ) {
  303.         TDataSourceLock source(new CDataSource(top_entry, *this));
  304.         source->DoDeleteThisObject();
  305.         ret = m_mapToSource.insert(
  306.             TMapToSource::value_type(&top_entry, source)).first->second;
  307.     }
  308.     
  309.     _ASSERT(ret);
  310.     return ret;
  311. }
  312. CDataLoader* CObjectManager::x_GetLoaderByName(const string& name) const
  313. {
  314.     TMapNameToLoader::const_iterator itMap = m_mapNameToLoader.find(name);
  315.     return itMap == m_mapNameToLoader.end()? 0: itMap->second;
  316. }
  317. bool CObjectManager::ReleaseDataSource(TDataSourceLock& pSource)
  318. {
  319.     CDataSource& ds = *pSource;
  320.     _ASSERT(pSource->Referenced());
  321.     CDataLoader* loader = ds.GetDataLoader();
  322.     if ( loader ) {
  323.         pSource.Reset();
  324.         return false;
  325.     }
  326.     CConstRef<CSeq_entry> key = ds.GetTopEntry();
  327.     if ( !key ) {
  328.         ERR_POST("CObjectManager::ReleaseDataSource: "
  329.                  "unknown data source key");
  330.         pSource.Reset();
  331.         return false;
  332.     }
  333.     TWriteLockGuard guard(m_OM_Lock);
  334.     TMapToSource::iterator iter = m_mapToSource.find(key.GetPointer());
  335.     if ( iter == m_mapToSource.end() ) {
  336.         guard.Release();
  337.         ERR_POST("CObjectManager::ReleaseDataSource: "
  338.                  "unknown data source");
  339.         pSource.Reset();
  340.         return false;
  341.     }
  342.     _ASSERT(pSource == iter->second);
  343.     _ASSERT(ds.Referenced() && !ds.ReferencedOnlyOnce());
  344.     pSource.Reset();
  345.     if ( ds.ReferencedOnlyOnce() ) {
  346.         // Destroy data source if it's linked to an entry and is not
  347.         // referenced by any scope.
  348.         if ( !ds.GetDataLoader() ) {
  349.             pSource = iter->second;
  350.             m_mapToSource.erase(iter);
  351.             _ASSERT(ds.ReferencedOnlyOnce());
  352.             guard.Release();
  353.             pSource.Reset();
  354.             return true;
  355.         }
  356.     }
  357.     return false;
  358. }
  359. /*
  360. CConstRef<CBioseq> CObjectManager::GetBioseq(const CSeq_id& id)
  361. {
  362.     CScope* pScope = *(m_setScope.begin());
  363.     return CConstRef<CBioseq>(&((pScope->GetBioseqHandle(id)).GetBioseq()));
  364. }
  365. */
  366. void CObjectManager::DebugDump(CDebugDumpContext ddc, unsigned int depth) const
  367. {
  368.     ddc.SetFrame("CObjectManager");
  369.     CObject::DebugDump( ddc, depth);
  370.     if (depth == 0) {
  371.         DebugDumpValue(ddc,"m_setDefaultSource.size()", m_setDefaultSource.size());
  372.         DebugDumpValue(ddc,"m_mapNameToLoader.size()",  m_mapNameToLoader.size());
  373.         DebugDumpValue(ddc,"m_mapToSource.size()",m_mapToSource.size());
  374.         DebugDumpValue(ddc,"m_setScope.size()",         m_setScope.size());
  375.     } else {
  376.         
  377.         DebugDumpRangePtr(ddc,"m_setDefaultSource",
  378.             m_setDefaultSource.begin(), m_setDefaultSource.end(), depth);
  379.         DebugDumpPairsValuePtr(ddc,"m_mapNameToLoader",
  380.             m_mapNameToLoader.begin(), m_mapNameToLoader.end(), depth);
  381.         DebugDumpPairsPtrPtr(ddc,"m_mapToSource",
  382.             m_mapToSource.begin(), m_mapToSource.end(), depth);
  383.         DebugDumpRangePtr(ddc,"m_setScope",
  384.             m_setScope.begin(), m_setScope.end(), depth);
  385.     }
  386. }
  387. END_SCOPE(objects)
  388. END_NCBI_SCOPE
  389. /*
  390. * ---------------------------------------------------------------------------
  391. * $Log: object_manager.cpp,v $
  392. * Revision 1000.2  2004/06/01 19:23:28  gouriano
  393. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.33
  394. *
  395. * Revision 1.33  2004/05/21 21:42:12  gorelenk
  396. * Added PCH ncbi_pch.hpp
  397. *
  398. * Revision 1.32  2004/03/24 18:30:29  vasilche
  399. * Fixed edit API.
  400. * Every *_Info object has its own shallow copy of original object.
  401. *
  402. * Revision 1.31  2004/03/17 16:05:21  vasilche
  403. * IRIX CC won't implicitly convert CRef<CSeq_entry> to CObject*
  404. *
  405. * Revision 1.30  2004/03/16 15:47:27  vasilche
  406. * Added CBioseq_set_Handle and set of EditHandles
  407. *
  408. * Revision 1.29  2003/09/30 16:22:02  vasilche
  409. * Updated internal object manager classes to be able to load ID2 data.
  410. * SNP blobs are loaded as ID2 split blobs - readers convert them automatically.
  411. * Scope caches results of requests for data to data loaders.
  412. * Optimized CSeq_id_Handle for gis.
  413. * Optimized bioseq lookup in scope.
  414. * Reduced object allocations in annotation iterators.
  415. * CScope is allowed to be destroyed before other objects using this scope are
  416. * deleted (feature iterators, bioseq handles etc).
  417. * Optimized lookup for matching Seq-ids in CSeq_id_Mapper.
  418. * Added 'adaptive' option to objmgr_demo application.
  419. *
  420. * Revision 1.28  2003/09/05 17:29:40  grichenk
  421. * Structurized Object Manager exceptions
  422. *
  423. * Revision 1.27  2003/08/04 17:04:31  grichenk
  424. * Added default data-source priority assignment.
  425. * Added support for iterating all annotations from a
  426. * seq-entry or seq-annot.
  427. *
  428. * Revision 1.26  2003/06/19 18:34:28  vasilche
  429. * Fixed compilation on Windows.
  430. *
  431. * Revision 1.25  2003/06/19 18:23:46  vasilche
  432. * Added several CXxx_ScopeInfo classes for CScope related information.
  433. * CBioseq_Handle now uses reference to CBioseq_ScopeInfo.
  434. * Some fine tuning of locking in CScope.
  435. *
  436. * Revision 1.23  2003/05/20 15:44:37  vasilche
  437. * Fixed interaction of CDataSource and CDataLoader in multithreaded app.
  438. * Fixed some warnings on WorkShop.
  439. * Added workaround for memory leak on WorkShop.
  440. *
  441. * Revision 1.22  2003/04/24 16:12:38  vasilche
  442. * Object manager internal structures are splitted more straightforward.
  443. * Removed excessive header dependencies.
  444. *
  445. * Revision 1.21  2003/04/09 16:04:32  grichenk
  446. * SDataSourceRec replaced with CPriorityNode
  447. * Added CScope::AddScope(scope, priority) to allow scope nesting
  448. *
  449. * Revision 1.20  2003/03/11 14:15:52  grichenk
  450. * +Data-source priority
  451. *
  452. * Revision 1.19  2003/02/05 17:59:17  dicuccio
  453. * Moved formerly private headers into include/objects/objmgr/impl
  454. *
  455. * Revision 1.18  2003/01/29 22:03:46  grichenk
  456. * Use single static CSeq_id_Mapper instead of per-OM model.
  457. *
  458. * Revision 1.17  2002/11/08 21:07:15  ucko
  459. * CConstRef<> now requires an explicit constructor.
  460. *
  461. * Revision 1.16  2002/11/04 21:29:12  grichenk
  462. * Fixed usage of const CRef<> and CRef<> constructor
  463. *
  464. * Revision 1.15  2002/09/19 20:05:44  vasilche
  465. * Safe initialization of static mutexes
  466. *
  467. * Revision 1.14  2002/07/12 18:33:23  grichenk
  468. * Fixed the bug with querying destroyed datasources
  469. *
  470. * Revision 1.13  2002/07/10 21:11:36  grichenk
  471. * Destroy any data source not linked to a loader
  472. * and not used by any scope.
  473. *
  474. * Revision 1.12  2002/07/08 20:51:02  grichenk
  475. * Moved log to the end of file
  476. * Replaced static mutex (in CScope, CDataSource) with the mutex
  477. * pool. Redesigned CDataSource data locking.
  478. *
  479. * Revision 1.11  2002/06/04 17:18:33  kimelman
  480. * memory cleanup :  new/delete/Cref rearrangements
  481. *
  482. * Revision 1.10  2002/05/28 18:00:43  gouriano
  483. * DebugDump added
  484. *
  485. * Revision 1.9  2002/05/06 03:28:47  vakatov
  486. * OM/OM1 renaming
  487. *
  488. * Revision 1.8  2002/05/02 20:42:37  grichenk
  489. * throw -> THROW1_TRACE
  490. *
  491. * Revision 1.7  2002/04/22 20:04:11  grichenk
  492. * Fixed TSE dropping
  493. *
  494. * Revision 1.6  2002/02/21 19:27:06  grichenk
  495. * Rearranged includes. Added scope history. Added searching for the
  496. * best seq-id match in data sources and scopes. Updated tests.
  497. *
  498. * Revision 1.5  2002/01/29 17:45:21  grichenk
  499. * Removed debug output
  500. *
  501. * Revision 1.4  2002/01/23 21:59:31  grichenk
  502. * Redesigned seq-id handles and mapper
  503. *
  504. * Revision 1.3  2002/01/18 15:53:29  gouriano
  505. * implemented RegisterTopLevelSeqEntry
  506. *
  507. * Revision 1.2  2002/01/16 16:25:58  gouriano
  508. * restructured objmgr
  509. *
  510. * Revision 1.1  2002/01/11 19:06:21  gouriano
  511. * restructured objmgr
  512. *
  513. *
  514. * ===========================================================================
  515. */