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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seq_id_handle.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:24:02  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seq_id_handle.cpp,v 1000.3 2004/06/01 19:24:02 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. * Author: Aleksey Grichenko, Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Seq-id handle for Object Manager
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbiobj.hpp>
  42. #include <corelib/ncbimtx.hpp>
  43. #include <corelib/ncbiatomic.hpp>
  44. #include <objmgr/seq_id_handle.hpp>
  45. #include <objmgr/seq_id_mapper.hpp>
  46. #include <objmgr/impl/seq_id_tree.hpp>
  47. #include <serial/typeinfo.hpp>
  48. BEGIN_NCBI_SCOPE
  49. BEGIN_SCOPE(objects)
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CSeq_id_Info
  52. //
  53. //#define NCBI_SLOW_ATOMIC_SWAP
  54. #ifdef NCBI_SLOW_ATOMIC_SWAP
  55. DEFINE_STATIC_FAST_MUTEX(sx_GetSeqIdMutex);
  56. #endif
  57. CConstRef<CSeq_id> CSeq_id_Info::GetGiSeqId(int gi) const
  58. {
  59.     CConstRef<CSeq_id> ret;
  60. #if defined NCBI_SLOW_ATOMIC_SWAP
  61.     CFastMutexGuard guard(sx_GetSeqIdMutex);
  62.     ret = m_Seq_id;
  63.     const_cast<CSeq_id_Info*>(this)->m_Seq_id.Reset();
  64.     if ( !ret || !ret->ReferencedOnlyOnce() ) {
  65.         ret.Reset(new CSeq_id);
  66.     }
  67.     const_cast<CSeq_id_Info*>(this)->m_Seq_id = ret;
  68. #else
  69.     const_cast<CSeq_id_Info*>(this)->m_Seq_id.AtomicReleaseTo(ret);
  70.     if ( !ret || !ret->ReferencedOnlyOnce() ) {
  71.         ret.Reset(new CSeq_id);
  72.     }
  73.     const_cast<CSeq_id_Info*>(this)->m_Seq_id.AtomicResetFrom(ret);
  74. #endif
  75.     const_cast<CSeq_id&>(*ret).SetGi(gi);
  76.     return ret;
  77. }
  78. CSeq_id_Info::~CSeq_id_Info(void)
  79. {
  80.     _ASSERT(m_Counter.Get() == 0 && m_Tree);
  81.     m_Tree = 0;
  82. }
  83. void CSeq_id_Info::x_RemoveLastReference(void) const
  84. {
  85.     m_Tree->DropInfo(this);
  86. }
  87. ////////////////////////////////////////////////////////////////////
  88. //
  89. //  CSeq_id_Handle::
  90. //
  91. CConstRef<CSeq_id> CSeq_id_Handle::GetSeqId(void) const
  92. {
  93.     _ASSERT(m_Info);
  94.     CConstRef<CSeq_id> ret;
  95.     if ( IsGi() ) {
  96.         ret = m_Info->GetGiSeqId(GetGi());
  97.     }
  98.     else {
  99.         ret = m_Info->GetSeqId();
  100.     }
  101.     return ret;
  102. }
  103. CConstRef<CSeq_id> CSeq_id_Handle::GetSeqIdOrNull(void) const
  104. {
  105.     CConstRef<CSeq_id> ret;
  106.     if ( IsGi() ) {
  107.         _ASSERT(m_Info);
  108.         ret = m_Info->GetGiSeqId(GetGi());
  109.     }
  110.     else if ( m_Info ) {
  111.         ret = m_Info->GetSeqId();
  112.     }
  113.     return ret;
  114. }
  115. CSeq_id_Handle CSeq_id_Handle::GetGiHandle(int gi)
  116. {
  117.     return CSeq_id_Mapper::GetSeq_id_Mapper().GetGiHandle(gi);
  118. }
  119. CSeq_id_Handle CSeq_id_Handle::GetHandle(const CSeq_id& id)
  120. {
  121.     return CSeq_id_Mapper::GetSeq_id_Mapper().GetHandle(id);
  122. }
  123. #ifdef _DEBUG
  124. static int s_GetDebugSeqIds(void)
  125. {
  126.     const char* env = getenv("NCBI_OBJMGR_DEBUG_SEQID");
  127.     if ( !env || !*env ) return 0;
  128.     if ( *env >= '0' && *env <= '9' ) return *env - '0';
  129.     return 1;
  130. }
  131. static int s_DebugSeqIds(void)
  132. {
  133.     static int debug = s_GetDebugSeqIds();
  134.     return debug;
  135. }
  136. static int s_GetDebugSeqIdsCounter(void)
  137. {
  138.     const char* env = getenv("NCBI_OBJMGR_DEBUG_SEQID_COUNTER");
  139.     if ( !env || !*env ) return 0;
  140.     try {
  141.         return NStr::StringToInt(env);
  142.     }
  143.     catch ( ... ) {
  144.         return 0;
  145.     }
  146. }
  147. static int s_DebugSeqIdsCounter(void)
  148. {
  149.     static int debug = s_GetDebugSeqIdsCounter();
  150.     return debug;
  151. }
  152. DEFINE_STATIC_FAST_MUTEX(s_RegisterMutex);
  153. typedef map<const CSeq_id_Handle*, int> TRegisterSet;
  154. static TRegisterSet* s_RegisterSet = 0;
  155. static int s_Counter = 0;
  156. #endif
  157. void CSeq_id_Handle::x_Register(void)
  158. {
  159. #ifdef _DEBUG
  160.     int debug = s_DebugSeqIds();
  161.     if ( debug ) {
  162.         CFastMutexGuard guard(s_RegisterMutex);
  163.         if ( debug >= 5 ) {
  164.             ERR_POST(Warning << "Register of CSeq_id_Handle: "<<this);
  165.         }
  166.         if ( ++s_Counter == s_DebugSeqIdsCounter() ) {
  167.             _ASSERT("CSeq_id_Handle counter" && 0);
  168.         }
  169.         if ( !s_RegisterSet ) s_RegisterSet = new TRegisterSet;
  170.         pair<TRegisterSet::iterator, bool> ins = 
  171.             s_RegisterSet->insert(TRegisterSet::value_type(this, s_Counter));
  172.         if ( !ins.second ) {
  173.             ERR_POST("Double register of CSeq_id_Handle: "<<this<<
  174.                      " index: "<<s_Counter<<
  175.                      ", first index: " << ins.first->second);
  176.         }
  177.     }
  178. #endif
  179. }
  180. void CSeq_id_Handle::x_Deregister(void)
  181. {
  182. #ifdef _DEBUG
  183.     int debug = s_DebugSeqIds();
  184.     if ( debug ) {
  185.         CFastMutexGuard guard(s_RegisterMutex);
  186.         if ( debug >= 5 ) {
  187.             ERR_POST(Warning << "Deregister of CSeq_id_Handle: "<<this);
  188.         }
  189.         if ( !s_RegisterSet || !s_RegisterSet->erase(this) ) {
  190.             ERR_POST("Deregister of non-registered CSeq_id_Handle: "<<this);
  191.         }
  192.         if ( s_RegisterSet && s_RegisterSet->empty() ) {
  193.             delete s_RegisterSet;
  194.             s_RegisterSet = 0;
  195.         }
  196.     }
  197. #endif
  198. }
  199. void CSeq_id_Handle::DumpRegister(const char* _DEBUG_ARG(msg))
  200. {
  201. #ifdef _DEBUG
  202.     if ( s_DebugSeqIds() ) {
  203.         CFastMutexGuard guard(s_RegisterMutex);
  204.         if ( s_RegisterSet && !s_RegisterSet->empty() ) {
  205.             ERR_POST("CSeq_id_Handle::x_DumpRegister: " << msg);
  206.             ITERATE ( TRegisterSet, it, *s_RegisterSet ) {
  207.                 ERR_POST("    CSeq_id_Handle: "<<it->first<<
  208.                          " was registered at index: "<<it->second);
  209.             }
  210.         }
  211.     }
  212. #endif
  213. }
  214. bool CSeq_id_Handle::x_Match(const CSeq_id_Handle& handle) const
  215. {
  216.     // Different mappers -- handle can not be equal
  217.     if ( !*this ) {
  218.         return !handle;
  219.     }
  220.     if ( !handle )
  221.         return false;
  222.     return GetSeqId()->Match(*handle.GetSeqId());
  223. }
  224. bool CSeq_id_Handle::IsBetter(const CSeq_id_Handle& h) const
  225. {
  226.     return CSeq_id_Mapper::GetSeq_id_Mapper().x_IsBetter(*this, h);
  227. }
  228. bool CSeq_id_Handle::operator==(const CSeq_id& id) const
  229. {
  230.     if ( IsGi() ) {
  231.         return id.IsGi() && id.GetGi() == GetGi();
  232.     }
  233.     return *this == CSeq_id_Mapper::GetSeq_id_Mapper().GetHandle(id);
  234. }
  235. string CSeq_id_Handle::AsString() const
  236. {
  237.     CNcbiOstrstream os;
  238.     if ( IsGi() ) {
  239.         os << "gi|" << GetGi();
  240.     }
  241.     else if ( m_Info ) {
  242.         m_Info->GetSeqId()->WriteAsFasta(os);
  243.     }
  244.     else {
  245.         os << "unknown";
  246.     }
  247.     return CNcbiOstrstreamToString(os);
  248. }
  249. END_SCOPE(objects)
  250. END_NCBI_SCOPE
  251. /*
  252. * ---------------------------------------------------------------------------
  253. * $Log: seq_id_handle.cpp,v $
  254. * Revision 1000.3  2004/06/01 19:24:02  gouriano
  255. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  256. *
  257. * Revision 1.21  2004/05/21 21:42:13  gorelenk
  258. * Added PCH ncbi_pch.hpp
  259. *
  260. * Revision 1.20  2004/03/24 18:30:30  vasilche
  261. * Fixed edit API.
  262. * Every *_Info object has its own shallow copy of original object.
  263. *
  264. * Revision 1.19  2004/02/19 17:25:34  vasilche
  265. * Use CRef<> to safely hold pointer to CSeq_id_Info.
  266. * CSeq_id_Info holds pointer to owner CSeq_id_Which_Tree.
  267. * Reduce number of calls to CSeq_id_Handle.GetSeqId().
  268. *
  269. * Revision 1.18  2004/01/22 20:10:41  vasilche
  270. * 1. Splitted ID2 specs to two parts.
  271. * ID2 now specifies only protocol.
  272. * Specification of ID2 split data is moved to seqsplit ASN module.
  273. * For now they are still reside in one resulting library as before - libid2.
  274. * As the result split specific headers are now in objects/seqsplit.
  275. * 2. Moved ID2 and ID1 specific code out of object manager.
  276. * Protocol is processed by corresponding readers.
  277. * ID2 split parsing is processed by ncbi_xreader library - used by all readers.
  278. * 3. Updated OBJMGR_LIBS correspondingly.
  279. *
  280. * Revision 1.17  2004/01/07 20:42:01  grichenk
  281. * Fixed matching of accession to accession.version
  282. *
  283. * Revision 1.16  2003/11/26 17:56:00  vasilche
  284. * Implemented ID2 split in ID1 cache.
  285. * Fixed loading of splitted annotations.
  286. *
  287. * Revision 1.15  2003/10/07 13:43:23  vasilche
  288. * Added proper handling of named Seq-annots.
  289. * Added feature search from named Seq-annots.
  290. * Added configurable adaptive annotation search (default: gene, cds, mrna).
  291. * Fixed selection of blobs for loading from GenBank.
  292. * Added debug checks to CSeq_id_Mapper for easier finding lost CSeq_id_Handles.
  293. * Fixed leaked split chunks annotation stubs.
  294. * Moved some classes definitions in separate *.cpp files.
  295. *
  296. * Revision 1.14  2003/09/30 16:22:03  vasilche
  297. * Updated internal object manager classes to be able to load ID2 data.
  298. * SNP blobs are loaded as ID2 split blobs - readers convert them automatically.
  299. * Scope caches results of requests for data to data loaders.
  300. * Optimized CSeq_id_Handle for gis.
  301. * Optimized bioseq lookup in scope.
  302. * Reduced object allocations in annotation iterators.
  303. * CScope is allowed to be destroyed before other objects using this scope are
  304. * deleted (feature iterators, bioseq handles etc).
  305. * Optimized lookup for matching Seq-ids in CSeq_id_Mapper.
  306. * Added 'adaptive' option to objmgr_demo application.
  307. *
  308. * Revision 1.13  2003/06/10 19:06:35  vasilche
  309. * Simplified CSeq_id_Mapper and CSeq_id_Handle.
  310. *
  311. * Revision 1.11  2003/04/24 16:12:38  vasilche
  312. * Object manager internal structures are splitted more straightforward.
  313. * Removed excessive header dependencies.
  314. *
  315. * Revision 1.10  2003/03/14 19:10:41  grichenk
  316. * + SAnnotSelector::EIdResolving; fixed operator=() for several classes
  317. *
  318. * Revision 1.9  2002/12/26 20:55:18  dicuccio
  319. * Moved seq_id_mapper.hpp, tse_info.hpp, and bioseq_info.hpp -> include/ tree
  320. *
  321. * Revision 1.8  2002/12/26 16:39:24  vasilche
  322. * Object manager class CSeqMap rewritten.
  323. *
  324. * Revision 1.7  2002/07/08 20:51:02  grichenk
  325. * Moved log to the end of file
  326. * Replaced static mutex (in CScope, CDataSource) with the mutex
  327. * pool. Redesigned CDataSource data locking.
  328. *
  329. * Revision 1.6  2002/05/29 21:21:13  gouriano
  330. * added debug dump
  331. *
  332. * Revision 1.5  2002/05/06 03:28:47  vakatov
  333. * OM/OM1 renaming
  334. *
  335. * Revision 1.4  2002/03/15 18:10:08  grichenk
  336. * Removed CRef<CSeq_id> from CSeq_id_Handle, added
  337. * key to seq-id map th CSeq_id_Mapper
  338. *
  339. * Revision 1.3  2002/02/21 19:27:06  grichenk
  340. * Rearranged includes. Added scope history. Added searching for the
  341. * best seq-id match in data sources and scopes. Updated tests.
  342. *
  343. * Revision 1.2  2002/02/12 19:41:42  grichenk
  344. * Seq-id handles lock/unlock moved to CSeq_id_Handle 'ctors.
  345. *
  346. * Revision 1.1  2002/01/23 21:57:22  grichenk
  347. * Splitted id_handles.hpp
  348. *
  349. *
  350. * ===========================================================================
  351. */