1 /*  $Id: tse_info.cpp 611141 2020-06-29 20:55:12Z vasilche $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Aleksey Grichenko, Eugene Vasilchenko
27 *
28 * File Description:
29 *   TSE info -- entry for data source seq-id to TSE map
30 *
31 */
32 
33 
34 #include <ncbi_pch.hpp>
35 #include <objmgr/impl/data_source.hpp>
36 #include <objmgr/impl/tse_info.hpp>
37 #include <objmgr/impl/tse_split_info.hpp>
38 #include <objmgr/impl/tse_chunk_info.hpp>
39 #include <objmgr/impl/tse_assigner.hpp>
40 #include <objmgr/impl/bioseq_info.hpp>
41 #include <objmgr/impl/bioseq_set_info.hpp>
42 #include <objmgr/impl/annot_object.hpp>
43 #include <objmgr/impl/seq_annot_info.hpp>
44 #include <objmgr/impl/snp_annot_info.hpp>
45 #include <objmgr/impl/annot_type_index.hpp>
46 #include <objmgr/impl/handle_range.hpp>
47 #include <objmgr/impl/handle_range_map.hpp>
48 
49 #include <objects/seqset/Seq_entry.hpp>
50 #include <objects/submit/Seq_submit.hpp>
51 
52 #include <objmgr/objmgr_exception.hpp>
53 #include <objmgr/error_codes.hpp>
54 
55 #include <algorithm>
56 
57 
58 #define NCBI_USE_ERRCODE_X   ObjMgr_TSEinfo
59 
60 BEGIN_NCBI_SCOPE
61 
62 NCBI_DEFINE_ERR_SUBCODE_X(3);
63 
BEGIN_SCOPE(objects)64 BEGIN_SCOPE(objects)
65 
66 
67 SIdAnnotObjs::SIdAnnotObjs(void)
68 {
69 }
70 
71 
~SIdAnnotObjs(void)72 SIdAnnotObjs::~SIdAnnotObjs(void)
73 {
74     NON_CONST_ITERATE ( TAnnotSet, it, m_AnnotSet ) {
75         delete *it;
76         *it = 0;
77     }
78 }
79 
80 
x_GetRangeMap(size_t index)81 SIdAnnotObjs::TRangeMap& SIdAnnotObjs::x_GetRangeMap(size_t index)
82 {
83     if ( index >= m_AnnotSet.size() ) {
84         m_AnnotSet.resize(index+1);
85     }
86     TRangeMap*& slot = m_AnnotSet[index];
87     if ( !slot ) {
88         slot = new TRangeMap;
89     }
90     return *slot;
91 }
92 
93 
x_CleanRangeMaps(void)94 bool SIdAnnotObjs::x_CleanRangeMaps(void)
95 {
96     while ( !m_AnnotSet.empty() ) {
97         TRangeMap*& slot = m_AnnotSet.back();
98         if ( slot ) {
99             if ( !slot->empty() ) {
100                 return false;
101             }
102             delete slot;
103             slot = 0;
104         }
105         m_AnnotSet.pop_back();
106     }
107     return true;
108 }
109 
110 
SIdAnnotObjs(const SIdAnnotObjs & _DEBUG_ARG (objs))111 SIdAnnotObjs::SIdAnnotObjs(const SIdAnnotObjs& _DEBUG_ARG(objs))
112 {
113     _ASSERT(objs.m_AnnotSet.empty());
114     _ASSERT(objs.m_SNPSet.empty());
115 }
116 
117 
118 ////////////////////////////////////////////////////////////////////
119 //
120 //  CTSE_Info::
121 //
122 //    General information and indexes for top level seq-entries
123 //
124 
125 
CTSE_Info(void)126 CTSE_Info::CTSE_Info(void)
127     : m_InternalBioObjNumber(0),
128       m_MasterSeqSegmentsLoaded(false)
129 {
130     x_Initialize();
131 
132     x_TSEAttach(*this);
133 }
134 
135 
CTSE_Info(const TBlobId & blob_id,TBlobVersion blob_version)136 CTSE_Info::CTSE_Info(const TBlobId& blob_id,
137                      TBlobVersion blob_version)
138     : m_InternalBioObjNumber(0),
139       m_MasterSeqSegmentsLoaded(false)
140 {
141     x_Initialize();
142 
143     m_BlobId = blob_id;
144     m_BlobVersion = blob_version;
145 
146     x_TSEAttach(*this);
147 }
148 
149 
CTSE_Info(CSeq_entry & entry,TBlobState blob_state,const TBlobId & blob_id,TBlobVersion blob_version)150 CTSE_Info::CTSE_Info(CSeq_entry& entry,
151                      TBlobState blob_state,
152                      const TBlobId& blob_id,
153                      TBlobVersion blob_version)
154     : m_InternalBioObjNumber(0),
155       m_MasterSeqSegmentsLoaded(false)
156 {
157     x_Initialize();
158 
159     m_BlobId = blob_id;
160     m_BlobVersion = blob_version;
161     m_BlobState = blob_state;
162 
163     SetSeq_entry(entry);
164     m_LoadState = eLoaded;
165 
166     x_TSEAttach(*this);
167 }
168 
169 
CTSE_Info(CSeq_entry & entry,TBlobState blob_state)170 CTSE_Info::CTSE_Info(CSeq_entry& entry,
171                      TBlobState blob_state)
172     : m_InternalBioObjNumber(0),
173       m_MasterSeqSegmentsLoaded(false)
174 {
175     x_Initialize();
176 
177     m_BlobState = blob_state;
178 
179     SetSeq_entry(entry);
180     m_LoadState = eLoaded;
181 
182     x_TSEAttach(*this);
183 }
184 
185 
CTSE_Info(const CTSE_Lock & tse)186 CTSE_Info::CTSE_Info(const CTSE_Lock& tse)
187     : m_BaseTSE(new SBaseTSE(tse)),
188       m_InternalBioObjNumber(0),
189       m_MasterSeqSegmentsLoaded(false)
190 {
191     x_Initialize();
192 
193     m_BlobState = tse->m_BlobState;
194     m_TopLevelObjectType = tse->m_TopLevelObjectType;
195     m_Name = tse->m_Name;
196     m_UsedMemory = tse->m_UsedMemory;
197     m_LoadState = eLoaded;
198 
199     // update Seq-inst object with split data
200     tse->x_Update(fNeedUpdate_children_seq_data|fNeedUpdate_children_bioseq);
201     x_SetObject(*tse, &m_BaseTSE->m_ObjectCopyMap);
202     x_TSEAttach(*this);
203 
204     m_Split = tse->m_Split;
205     if (m_Split) {
206         CRef<ITSE_Assigner> lsnr = m_Split->GetAssigner(*tse);
207         if( !lsnr )
208             lsnr.Reset(new CTSE_Default_Assigner);
209         m_Split->x_TSEAttach(*this, lsnr);
210         m_BioseqUpdater = tse->m_BioseqUpdater;
211     }
212     if (tse->HasDataSource()) {
213         CDataLoader* ld = tse->GetDataSource().GetDataLoader();
214         if ( ld ) {
215             m_EditSaver = ld->GetEditSaver();
216             m_BlobId = tse->m_BlobId;
217             //CBlobIdKey(new CBlobIdString(tse->m_BlobId.ToString()));
218         }
219     }
220 }
221 
222 
~CTSE_Info(void)223 CTSE_Info::~CTSE_Info(void)
224 {
225     _ASSERT(m_LockCounter.Get() == 0);
226     _ASSERT(m_DataSource == 0);
227     if( m_Split )
228         m_Split->x_TSEDetach(*this);
229 }
230 
231 
Assign(const CTSE_Lock & tse)232 CTSE_Info& CTSE_Info::Assign(const CTSE_Lock& tse)
233 {
234     //    m_BaseTSE.reset(new SBaseTSE(tse));
235     m_BlobState = tse->m_BlobState;
236     m_TopLevelObjectType = tse->m_TopLevelObjectType;
237     m_Name = tse->m_Name;
238     m_UsedMemory = tse->m_UsedMemory;
239 
240     if (tse->m_Contents)
241         x_SetObject(*tse,NULL);//tse->m_BaseTSE->m_ObjectCopyMap);
242     //x_TSEAttach(*this);
243 
244     m_Split = tse->m_Split;
245     if (m_Split) {
246         CRef<ITSE_Assigner> listener = m_Split->GetAssigner(*tse);
247         if( !listener )
248             listener.Reset(new CTSE_Default_Assigner);
249         m_Split->x_TSEAttach(*this, listener);
250     }
251     return *this;
252 }
253 
254 
Assign(const CTSE_Lock & tse,CRef<CSeq_entry> entry)255 CTSE_Info& CTSE_Info::Assign(const CTSE_Lock& tse,
256                              CRef<CSeq_entry> entry)
257 //                             CRef<ITSE_Assigner> listener)
258 {
259     m_BlobState = tse->m_BlobState;
260     m_TopLevelObjectType = tse->m_TopLevelObjectType;
261     m_Name = tse->m_Name;
262     m_UsedMemory = tse->m_UsedMemory;
263 
264     if (entry)
265         SetSeq_entry(*entry);
266 
267     m_Split = tse->m_Split;
268     if (m_Split) {
269         CRef<ITSE_Assigner> listener = m_Split->GetAssigner(*tse);
270         if( !listener )
271             listener.Reset(new CTSE_Default_Assigner);
272         m_Split->x_TSEAttach(*this, listener);
273         /*
274         if( !listener ) {
275             listener = m_Split->GetAssigner(*tse);
276             if( !listener ) {
277                 listener.Reset(new CTSE_Default_Assigner);
278             }
279         }
280         m_Split->x_TSEAttach(*this, listener);
281         */
282     }
283 
284     //x_TSEAttach(*this);
285     return *this;
286 }
287 
288 
x_Initialize(void)289 void CTSE_Info::x_Initialize(void)
290 {
291     m_DataSource = 0;
292     m_BlobVersion = -1;
293     m_BlobState = CBioseq_Handle::fState_none;
294     m_TopLevelObjectType = CTSE_Handle::eTopLevel_Seq_entry;
295     m_UsedMemory = 0;
296     m_LoadState = eNotLoaded;
297     m_CacheState = eNotInCache;
298     m_AnnotIdsFlags = 0;
299 }
300 
301 
x_Reset(void)302 void CTSE_Info::x_Reset(void)
303 {
304     m_Bioseq_sets.clear();
305     m_Bioseqs.clear();
306     m_Removed_Bioseq_sets.clear();
307     m_Removed_Bioseqs.clear();
308     m_Split.Reset();
309     m_SetObjectInfo.Reset();
310     m_NamedAnnotObjs.clear();
311     m_IdAnnotInfoMap.clear();
312     m_FeatIdIndex.clear();
313     m_BaseTSE.reset();
314     m_EditSaver.Reset();
315     m_InternalBioObjNumber = 0;
316     m_BioObjects.clear();
317 
318     m_Object.Reset();
319     m_Which = CSeq_entry::e_not_set;
320     m_Contents.Reset();
321 }
322 
323 
SetBlobVersion(TBlobVersion version)324 void CTSE_Info::SetBlobVersion(TBlobVersion version)
325 {
326     _ASSERT(version >= 0);
327     _ASSERT(m_LoadState == eNotLoaded || !m_Object ||
328             m_BlobVersion < 0 || m_BlobVersion == version);
329     m_BlobVersion = version;
330 }
331 
332 
SetName(const CAnnotName & name)333 void CTSE_Info::SetName(const CAnnotName& name)
334 {
335     m_Name = name;
336 }
337 
338 
SetUsedMemory(size_t size)339 void CTSE_Info::SetUsedMemory(size_t size)
340 {
341     m_UsedMemory = size;
342 }
343 
344 
AddUsedMemory(size_t size)345 void CTSE_Info::AddUsedMemory(size_t size)
346 {
347     m_UsedMemory += size;
348 }
349 
350 
SetSeq_entry(CSeq_entry & entry,CTSE_SetObjectInfo * set_info)351 void CTSE_Info::SetSeq_entry(CSeq_entry& entry, CTSE_SetObjectInfo* set_info)
352 {
353     if ( m_Which != CSeq_entry::e_not_set ) {
354         if ( m_LoadState == eNotLoaded ) {
355             Reset();
356             m_Object.Reset();
357             m_Split.Reset();
358             m_RequestedId.Reset();
359             m_Removed_Bioseq_sets.clear();
360             m_Removed_Bioseqs.clear();
361             m_AnnotIdsFlags = 0;
362         }
363     }
364 
365     entry.Parentize();
366 
367     m_SetObjectInfo = set_info;
368     if ( HasDataSource() ) {
369         {{
370             CDataSource::TMainLock::TWriteLockGuard guard
371                 (GetDataSource().m_DSMainLock);
372             x_SetObject(entry);
373         }}
374         UpdateAnnotIndex();
375     }
376     else {
377         x_SetObject(entry);
378     }
379     if ( set_info ) {
380         if ( !set_info->m_Seq_annot_InfoMap.empty() ) {
381             NCBI_THROW(CObjMgrException, eAddDataError,
382                        "Unknown SNP annots");
383         }
384         m_SetObjectInfo = null;
385     }
386 }
387 
388 
x_IndexBioseq(CBioseq_Info * info)389 CBioObjectId CTSE_Info::x_IndexBioseq(CBioseq_Info* info)
390 {
391     //    x_RegisterRemovedIds(bioseq,info);
392     CBioObjectId uniq_id;
393     _ASSERT(info->GetBioObjectId().GetType() == CBioObjectId::eUnSet);
394     ITERATE ( CBioseq_Info::TId, it, info->GetId() ) {
395         if ( it->IsGi() ) {
396             uniq_id = CBioObjectId(*it);
397             break;
398         }
399     }
400     if ( !info->GetId().empty() ) {
401         x_SetBioseqIds(info);
402     }
403     if (uniq_id.GetType() == CBioObjectId::eUnSet) {
404         if (!info->GetId().empty())
405             uniq_id = CBioObjectId(*info->GetId().begin());
406         else
407             uniq_id = x_RegisterBioObject(*info);
408     }
409     return uniq_id;
410 }
x_IndexBioseq_set(CBioseq_set_Info * info)411 CBioObjectId CTSE_Info::x_IndexBioseq_set(CBioseq_set_Info* info)
412 {
413     CBioObjectId uniq_id;
414     _ASSERT(info->GetBioObjectId().GetType() == CBioObjectId::eUnSet);
415     if (info->m_Bioseq_set_Id > 0)
416         uniq_id = CBioObjectId(CBioObjectId::eSetId, info->m_Bioseq_set_Id);
417     else
418         uniq_id = x_RegisterBioObject(*info);
419     return uniq_id;
420 }
421 
x_RegisterBioObject(CTSE_Info_Object & info)422 CBioObjectId CTSE_Info::x_RegisterBioObject(CTSE_Info_Object& info)
423 {
424     CBioObjectId uniq_id = info.GetBioObjectId();
425     if (uniq_id.GetType() == CBioObjectId::eUniqNumber) {
426         if (m_BioObjects.find(uniq_id) != m_BioObjects.end())
427             return uniq_id;
428     }
429 
430     uniq_id = CBioObjectId(CBioObjectId::eUniqNumber,
431                            ++m_InternalBioObjNumber);
432     m_BioObjects[uniq_id] = &info;
433     return uniq_id;
434 }
435 
x_UnregisterBioObject(CTSE_Info_Object & info)436 void CTSE_Info::x_UnregisterBioObject(CTSE_Info_Object& info)
437 {
438     const CBioObjectId& uid = info.GetBioObjectId();
439     if (uid.GetType() == CBioObjectId::eUniqNumber) {
440         TBioObjects::iterator i = m_BioObjects.find(uid);
441         if (i != m_BioObjects.end()) {
442             // i->second->x_SetBioObjectId(CBioObjectId());
443             m_BioObjects.erase(i);
444         }
445     }
446 }
447 
x_FindBioObject(const CBioObjectId & uniq_id) const448 CTSE_Info_Object* CTSE_Info::x_FindBioObject(const CBioObjectId& uniq_id) const
449 {
450     switch (uniq_id.GetType()) {
451     case CBioObjectId::eUniqNumber:
452         {
453             TBioObjects::const_iterator i = m_BioObjects.find(uniq_id);
454             if (i != m_BioObjects.end())
455                 return i->second;
456         }
457         return NULL;
458     case CBioObjectId::eSeqId:
459         {
460             x_GetRecords(uniq_id.GetSeqId(), true);
461             CFastMutexGuard guard(m_BioseqsMutex);
462             TBioseqs::const_iterator it = m_Bioseqs.find(uniq_id.GetSeqId());
463             if ( it != m_Bioseqs.end() ) {
464                 return it->second;
465             }
466         }
467         return NULL;
468     case CBioObjectId::eSetId:
469         {
470             TBioseq_sets::const_iterator it =
471                 m_Bioseq_sets.find(uniq_id.GetSetId());
472             if ( it != m_Bioseq_sets.end() ) {
473                 return it->second;
474             }
475         }
476         return NULL;
477     default:
478         _ASSERT(0);
479     }
480     return NULL;
481 }
482 
483 /*
484 void CTSE_Info::x_RegisterRemovedIds(const CConstRef<CBioseq>& bioseq,
485                                      CBioseq_Info* info)
486 {
487     if (m_SetObjectInfo) {
488         CTSE_SetObjectInfo::TBioseq_InfoMap::iterator iter =
489             m_SetObjectInfo->m_Bioseq_InfoMap.find(bioseq);
490         if ( iter != m_SetObjectInfo->m_Bioseq_InfoMap.end() ) {
491             vector<CSeq_id_Handle>& ids = iter->second.m_Removed_ids;
492             for( vector<CSeq_id_Handle>::const_iterator idit = ids.begin();
493                  idit != ids.end(); ++idit) {
494                 _ASSERT( m_Removed_Bioseqs.find(*idit) == m_Removed_Bioseqs.end());
495                 m_Removed_Bioseqs.insert(TBioseqs::value_type(*idit, info));
496             }
497         }
498     }
499 }
500 */
501 CRef<CSeq_annot_SNP_Info>
x_GetSNP_Info(const CConstRef<CSeq_annot> & annot)502 CTSE_Info::x_GetSNP_Info(const CConstRef<CSeq_annot>& annot)
503 {
504     CRef<CSeq_annot_SNP_Info> ret;
505     if ( m_SetObjectInfo ) {
506         CTSE_SetObjectInfo::TSeq_annot_InfoMap::iterator iter =
507             m_SetObjectInfo->m_Seq_annot_InfoMap.find(annot);
508         if ( iter != m_SetObjectInfo->m_Seq_annot_InfoMap.end() ) {
509             ret = iter->second.m_SNP_annot_Info;
510             m_SetObjectInfo->m_Seq_annot_InfoMap.erase(iter);
511         }
512     }
513     return ret;
514 }
515 
516 
HasAnnot(const CAnnotName & name) const517 bool CTSE_Info::HasAnnot(const CAnnotName& name) const
518 {
519     TAnnotLockReadGuard guard(GetAnnotLock());
520     return m_NamedAnnotObjs.find(name) != m_NamedAnnotObjs.end();
521 }
522 
523 
HasNamedAnnot(const string & name) const524 bool CTSE_Info::HasNamedAnnot(const string& name) const
525 {
526     return HasAnnot(CAnnotName(name));
527 }
528 
529 
HasUnnamedAnnot(void) const530 bool CTSE_Info::HasUnnamedAnnot(void) const
531 {
532     return HasAnnot(CAnnotName());
533 }
534 
535 
GetCompleteTSE(void) const536 CConstRef<CSeq_entry> CTSE_Info::GetCompleteTSE(void) const
537 {
538     return GetCompleteSeq_entry();
539 }
540 
541 
GetTSECore(void) const542 CConstRef<CSeq_entry> CTSE_Info::GetTSECore(void) const
543 {
544     return GetSeq_entryCore();
545 }
546 
547 
x_DSAttachContents(CDataSource & ds)548 void CTSE_Info::x_DSAttachContents(CDataSource& ds)
549 {
550     _ASSERT(!m_DataSource);
551 
552     m_DataSource = &ds;
553     TParent::x_DSAttachContents(ds);
554     if ( m_Split ) {
555         m_Split->x_DSAttach(ds);
556     }
557     ITERATE ( TBioseqs, it, m_Bioseqs ) {
558         ds.x_IndexSeqTSE(it->first, this);
559     }
560     ds.x_IndexAnnotTSEs(this);
561 }
562 
563 
x_DSDetachContents(CDataSource & ds)564 void CTSE_Info::x_DSDetachContents(CDataSource& ds)
565 {
566     _ASSERT(m_DataSource == &ds);
567 
568     ITERATE ( TBioseqs, it, m_Bioseqs ) {
569         ds.x_UnindexSeqTSE(it->first, this);
570     }
571     ds.x_UnindexAnnotTSEs(this);
572     if ( m_Split ) {
573         m_Split->x_DSDetach(ds);
574     }
575     TParent::x_DSDetachContents(ds);
576     m_DataSource = 0;
577 }
578 
579 
x_DSMapObject(CConstRef<TObject> obj,CDataSource & ds)580 void CTSE_Info::x_DSMapObject(CConstRef<TObject> obj, CDataSource& ds)
581 {
582     ds.x_Map(obj, this);
583     TParent::x_DSMapObject(obj, ds);
584 }
585 
586 
x_DSUnmapObject(CConstRef<TObject> obj,CDataSource & ds)587 void CTSE_Info::x_DSUnmapObject(CConstRef<TObject> obj, CDataSource& ds)
588 {
589     ds.x_Unmap(obj, this);
590     TParent::x_DSUnmapObject(obj, ds);
591 }
592 
593 
594 inline
x_IndexSeqTSE(const CSeq_id_Handle & id)595 void CTSE_Info::x_IndexSeqTSE(const CSeq_id_Handle& id)
596 {
597     if ( HasDataSource() ) {
598         GetDataSource().x_IndexSeqTSE(id, this);
599     }
600 }
601 
602 
603 inline
x_UnindexSeqTSE(const CSeq_id_Handle & id)604 void CTSE_Info::x_UnindexSeqTSE(const CSeq_id_Handle& id)
605 {
606     if ( HasDataSource() ) {
607         GetDataSource().x_UnindexSeqTSE(id, this);
608     }
609 }
610 
611 
x_IndexAnnotTSE(const CAnnotName & name,const CSeq_id_Handle & id)612 bool CTSE_Info::x_IndexAnnotTSE(const CAnnotName& name,
613                                 const CSeq_id_Handle& id)
614 {
615     if ( !id.IsGi() ) {
616         m_AnnotIdsFlags |= fAnnotIds_NonGi;
617         if ( id.HaveMatchingHandles() ) {
618             m_AnnotIdsFlags |= fAnnotIds_Matching;
619         }
620     }
621     bool new_id = false;
622     TIdAnnotInfoMap::iterator iter = m_IdAnnotInfoMap.lower_bound(id);
623     if ( iter == m_IdAnnotInfoMap.end() || iter->first != id ) {
624         iter = m_IdAnnotInfoMap
625             .insert(iter, TIdAnnotInfoMap::value_type(id, SIdAnnotInfo()));
626         new_id = true;
627         bool orphan = !ContainsMatchingBioseq(id);
628         iter->second.m_Orphan = orphan;
629         if ( HasDataSource() ) {
630             GetDataSource().x_IndexAnnotTSE(id, this, orphan);
631         }
632     }
633     _VERIFY(iter->second.m_Names.insert(name).second);
634     return new_id;
635 }
636 
637 
x_UnindexAnnotTSE(const CAnnotName & name,const CSeq_id_Handle & id)638 void CTSE_Info::x_UnindexAnnotTSE(const CAnnotName& name,
639                                   const CSeq_id_Handle& id)
640 {
641     TIdAnnotInfoMap::iterator iter = m_IdAnnotInfoMap.lower_bound(id);
642     if ( iter == m_IdAnnotInfoMap.end() || iter->first != id ) {
643         return;
644     }
645     _VERIFY(iter->second.m_Names.erase(name) == 1);
646     if ( iter->second.m_Names.empty() ) {
647         bool orphan = iter->second.m_Orphan;
648         m_IdAnnotInfoMap.erase(iter);
649         if ( HasDataSource() ) {
650             GetDataSource().x_UnindexAnnotTSE(id, this, orphan);
651         }
652     }
653 }
654 
655 
x_DoUpdate(TNeedUpdateFlags flags)656 void CTSE_Info::x_DoUpdate(TNeedUpdateFlags flags)
657 {
658     if ( flags & (fNeedUpdate_core|fNeedUpdate_children_core) ) {
659         if ( m_Split ) {
660             m_Split->x_UpdateCore();
661         }
662     }
663     TParent::x_DoUpdate(flags);
664 }
665 
666 
667 namespace {
x_SortUnique(CTSE_Info::TSeqIds & ids)668     static inline void x_SortUnique(CTSE_Info::TSeqIds& ids)
669     {
670         sort(ids.begin(), ids.end());
671         ids.erase(unique(ids.begin(), ids.end()), ids.end());
672     }
673 }
674 
675 
GetBioseqsIds(TSeqIds & ids) const676 void CTSE_Info::GetBioseqsIds(TSeqIds& ids) const
677 {
678 
679     {{
680         CFastMutexGuard guard(m_BioseqsMutex);
681         ITERATE ( TBioseqs, it, m_Bioseqs ) {
682             ids.push_back(it->first);
683         }
684     }}
685     if ( m_Split ) {
686         m_Split->GetBioseqsIds(ids);
687         // after adding split bioseq Seq-ids the result may contain
688         // duplicates and need to be sorted
689         x_SortUnique(ids);
690     }
691 }
692 
693 
GetAnnotIds(TSeqIds & ids) const694 void CTSE_Info::GetAnnotIds(TSeqIds& ids) const
695 {
696     UpdateAnnotIndex();
697     {{
698         TAnnotLockReadGuard guard(GetAnnotLock());
699         ITERATE ( TNamedAnnotObjs, it, m_NamedAnnotObjs ) {
700             ITERATE ( TAnnotObjs, it2, it->second ) {
701                 ids.push_back(it2->first);
702             }
703         }
704     }}
705     x_SortUnique(ids);
706 }
707 
708 
ContainsBioseq(const CSeq_id_Handle & id) const709 bool CTSE_Info::ContainsBioseq(const CSeq_id_Handle& id) const
710 {
711     {{
712         CFastMutexGuard guard(m_BioseqsMutex);
713         if ( m_Bioseqs.find(id) != m_Bioseqs.end() ) {
714             return true;
715         }
716     }}
717     if ( m_Split ) {
718         return m_Split->ContainsBioseq(id);
719     }
720     return false;
721 }
722 
723 
724 CSeq_id_Handle
ContainsMatchingBioseq(const CSeq_id_Handle & id) const725 CTSE_Info::ContainsMatchingBioseq(const CSeq_id_Handle& id) const
726 {
727     if ( ContainsBioseq(id) ) {
728         return id;
729     }
730     else if ( id.HaveMatchingHandles() ) {
731         CSeq_id_Handle::TMatches ids;
732         id.GetMatchingHandles(ids, eAllowWeakMatch);
733         ITERATE ( CSeq_id_Handle::TMatches, match_it, ids ) {
734             if ( *match_it != id ) {
735                 if ( ContainsBioseq(*match_it) ) {
736                     return *match_it;
737                 }
738             }
739         }
740     }
741     return null;
742 }
743 
744 
FindBioseq(const CSeq_id_Handle & id) const745 CConstRef<CBioseq_Info> CTSE_Info::FindBioseq(const CSeq_id_Handle& id) const
746 {
747     CConstRef<CBioseq_Info> ret;
748     x_GetRecords(id, true);
749     {{
750         CFastMutexGuard guard(m_BioseqsMutex);
751         TBioseqs::const_iterator it = m_Bioseqs.find(id);
752         if ( it != m_Bioseqs.end() ) {
753             ret = it->second;
754         }
755     }}
756     return ret;
757 }
758 
759 
760 CConstRef<CBioseq_Info>
FindMatchingBioseq(const CSeq_id_Handle & id) const761 CTSE_Info::FindMatchingBioseq(const CSeq_id_Handle& id) const
762 {
763     return GetSeqMatch(id).m_Bioseq;
764 }
765 
766 
767 CConstRef<CBioseq_Info>
GetSegSetMaster(void) const768 CTSE_Info::GetSegSetMaster(void) const
769 {
770     for ( CConstRef<CSeq_entry_Info> entry(this); entry->IsSet(); ) {
771         const CBioseq_set_Info& seqset = entry->GetSet();
772         CConstRef<CSeq_entry_Info> first = seqset.GetFirstEntry();
773         if ( !first ) {
774             break;
775         }
776         if ( seqset.GetClass() == CBioseq_set::eClass_segset ) {
777             if ( first->IsSeq() ) {
778                 return ConstRef(&first->GetSeq());
779             }
780             break;
781         }
782         entry = first;
783     }
784     return null;
785 }
786 
787 
GetMasterSeqSegments(void) const788 CConstRef<CMasterSeqSegments> CTSE_Info::GetMasterSeqSegments(void) const
789 {
790     if ( !m_MasterSeqSegmentsLoaded ) {
791         TAnnotLockWriteGuard guard(m_AnnotLock);
792         if ( !m_MasterSeqSegmentsLoaded ) {
793             CConstRef<CBioseq_Info> master_seq = GetSegSetMaster();
794             if ( master_seq ) {
795                 try {
796                     m_MasterSeqSegments = new CMasterSeqSegments(*master_seq);
797                 }
798                 catch ( CException& exc ) {
799                     ERR_POST("Segment set cannot be initialized: "<<exc);
800                 }
801             }
802             m_MasterSeqSegmentsLoaded = true;
803         }
804     }
805     return m_MasterSeqSegments;
806 }
807 
808 
GetSeqMatch(const CSeq_id_Handle & id) const809 SSeqMatch_TSE CTSE_Info::GetSeqMatch(const CSeq_id_Handle& id) const
810 {
811     SSeqMatch_TSE ret;
812     ret.m_Bioseq = FindBioseq(id);
813     if ( ret.m_Bioseq ) {
814         ret.m_Seq_id = id;
815     }
816     else if ( id.HaveMatchingHandles() ) {
817         CSeq_id_Handle::TMatches ids;
818         id.GetMatchingHandles(ids, eAllowWeakMatch);
819         ITERATE ( CSeq_id_Handle::TMatches, match_it, ids ) {
820             if ( *match_it != id ) {
821                 ret.m_Bioseq = FindBioseq(*match_it);
822                 if ( ret.m_Bioseq ) {
823                     ret.m_Seq_id = *match_it;
824                     break;
825                 }
826             }
827         }
828     }
829     return ret;
830 }
831 
832 
x_GetRecords(const CSeq_id_Handle & id,bool bioseq) const833 void CTSE_Info::x_GetRecords(const CSeq_id_Handle& id, bool bioseq) const
834 {
835     if ( m_Split ) {
836         m_Split->x_GetRecords(id, bioseq);
837     }
838 }
839 
840 
x_LoadChunk(TChunkId chunk_id) const841 void CTSE_Info::x_LoadChunk(TChunkId chunk_id) const
842 {
843     m_Split->x_LoadChunk(chunk_id);
844 }
845 
846 
x_LoadChunks(const TChunkIds & chunk_ids) const847 void CTSE_Info::x_LoadChunks(const TChunkIds& chunk_ids) const
848 {
849     if ( !chunk_ids.empty() ) {
850         m_Split->x_LoadChunks(chunk_ids);
851     }
852 }
853 
854 
x_SetBioseqId(const CSeq_id_Handle & id,CBioseq_Info * info)855 void CTSE_Info::x_SetBioseqId(const CSeq_id_Handle& id,
856                               CBioseq_Info* info)
857 {
858     _ASSERT(info);
859     {{
860         CFastMutexGuard guard(m_BioseqsMutex);
861         pair<TBioseqs::iterator, bool> ins =
862             m_Bioseqs.insert(TBioseqs::value_type(id, info));
863         if ( !ins.second ) {
864             // No duplicate bioseqs in the same TSE
865             NCBI_THROW_FMT(CObjMgrException, eAddDataError,
866                            "duplicate Bioseq id " << id << " present in" <<
867                            "\n  seq1: " << ins.first->second->IdString() <<
868                            "\n  seq2: " << info->IdString());
869         }
870     }}
871     // register this TSE in data source as containing the sequence
872     x_IndexSeqTSE(id);
873 }
874 
875 
x_SetBioseqIds(CBioseq_Info * info)876 void CTSE_Info::x_SetBioseqIds(CBioseq_Info* info)
877 {
878     _ASSERT(info);
879     {{
880         CFastMutexGuard guard(m_BioseqsMutex);
881         ITERATE ( CBioseq_Info::TId, it, info->GetId() ) {
882             pair<TBioseqs::iterator, bool> ins =
883                 m_Bioseqs.insert(TBioseqs::value_type(*it, info));
884             if ( !ins.second ) {
885                 // No duplicate bioseqs in the same TSE
886                 NCBI_THROW(CObjMgrException, eAddDataError,
887                            "duplicate Bioseq id "+it->AsString()+" present in"+
888                            "\n  seq1: " + ins.first->second->IdString()+
889                            "\n  seq2: " + info->IdString());
890             }
891         }
892         if ( m_BioseqUpdater ) {
893             m_BioseqUpdater->Update(*info);
894         }
895     }}
896     // register this TSE in data source as containing the sequence
897     if ( HasDataSource() ) {
898         GetDataSource().x_IndexSeqTSE(info->GetId(), this);
899     }
900 }
901 
902 
x_ResetBioseqId(const CSeq_id_Handle & id,CBioseq_Info * info)903 void CTSE_Info::x_ResetBioseqId(const CSeq_id_Handle& id,
904                                 CBioseq_Info* info)
905 {
906     {{
907         CFastMutexGuard guard(m_BioseqsMutex);
908         TBioseqs::iterator iter = m_Bioseqs.lower_bound(id);
909         if ( iter == m_Bioseqs.end() || iter->first != id ) {
910             return;
911         }
912         _ASSERT(iter->second == info);
913         m_Bioseqs.erase(iter);
914 
915         if (m_Split) {
916             iter = m_Removed_Bioseqs.find(id);
917             if (iter == m_Removed_Bioseqs.end())
918                 m_Removed_Bioseqs.insert(TBioseqs::value_type(id, info));
919         }
920 
921     }}
922     x_UnindexSeqTSE(id);
923 }
924 
925 
x_SetBioseq_setId(int key,CBioseq_set_Info * info)926 void CTSE_Info::x_SetBioseq_setId(int key,
927                                   CBioseq_set_Info* info)
928 {
929     pair<TBioseq_sets::iterator, bool> ins =
930         m_Bioseq_sets.insert(TBioseq_sets::value_type(key, info));
931     if ( ins.second ) {
932         // everything is fine
933     }
934     else {
935         // No duplicate bioseqs in the same TSE
936         NCBI_THROW(CObjMgrException, eAddDataError,
937                    " duplicate Bioseq_set id '"+NStr::IntToString(key));
938     }
939 }
940 
941 
x_ResetBioseq_setId(int key,CBioseq_set_Info * info)942 void CTSE_Info::x_ResetBioseq_setId(int key,
943                                     CBioseq_set_Info* info)
944 {
945     TBioseq_sets::iterator iter = m_Bioseq_sets.lower_bound(key);
946     if ( iter != m_Bioseq_sets.end() && iter->first == key ) {
947         _ASSERT(iter->second == info);
948         m_Bioseq_sets.erase(iter);
949         if (m_Split) {
950             iter = m_Removed_Bioseq_sets.find(key);
951             if (iter == m_Removed_Bioseq_sets.end())
952                 m_Removed_Bioseq_sets.insert(TBioseq_sets::value_type(key, info));
953         }
954     }
955 }
956 
957 
x_SetDirtyAnnotIndexNoParent(void)958 void CTSE_Info::x_SetDirtyAnnotIndexNoParent(void)
959 {
960     if ( HasDataSource() ) {
961         GetDataSource().x_SetDirtyAnnotIndex(*this);
962     }
963 }
964 
965 
x_ResetDirtyAnnotIndexNoParent(void)966 void CTSE_Info::x_ResetDirtyAnnotIndexNoParent(void)
967 {
968     if ( HasDataSource() ) {
969         GetDataSource().x_ResetDirtyAnnotIndex(*this);
970     }
971 }
972 
973 
UpdateFeatIdIndex(CSeqFeatData::E_Choice type,EFeatIdType id_type) const974 void CTSE_Info::UpdateFeatIdIndex(CSeqFeatData::E_Choice type,
975                                   EFeatIdType id_type) const
976 {
977     if ( m_Split ) {
978         m_Split.GetNCObject().x_UpdateFeatIdIndex(type, id_type);
979     }
980     UpdateAnnotIndex();
981 }
982 
983 
UpdateFeatIdIndex(CSeqFeatData::ESubtype subtype,EFeatIdType id_type) const984 void CTSE_Info::UpdateFeatIdIndex(CSeqFeatData::ESubtype subtype,
985                                   EFeatIdType id_type) const
986 {
987     if ( m_Split ) {
988         m_Split.GetNCObject().x_UpdateFeatIdIndex(subtype, id_type);
989     }
990     UpdateAnnotIndex();
991 }
992 
993 
UpdateAnnotIndex(const CSeq_id_Handle & id) const994 void CTSE_Info::UpdateAnnotIndex(const CSeq_id_Handle& id) const
995 {
996     x_GetRecords(id, false);
997     const_cast<CTSE_Info*>(this)->UpdateAnnotIndex();
998 }
999 
1000 
UpdateAnnotIndex(void) const1001 void CTSE_Info::UpdateAnnotIndex(void) const
1002 {
1003     const_cast<CTSE_Info*>(this)->UpdateAnnotIndex();
1004 }
1005 
1006 
UpdateAnnotIndex(const CTSE_Info_Object & object) const1007 void CTSE_Info::UpdateAnnotIndex(const CTSE_Info_Object& object) const
1008 {
1009     const_cast<CTSE_Info*>(this)->
1010         UpdateAnnotIndex(const_cast<CTSE_Info_Object&>(object));
1011 }
1012 
1013 
UpdateAnnotIndex(void)1014 void CTSE_Info::UpdateAnnotIndex(void)
1015 {
1016     UpdateAnnotIndex(*this);
1017 }
1018 
1019 
UpdateAnnotIndex(CTSE_Info_Object & object)1020 void CTSE_Info::UpdateAnnotIndex(CTSE_Info_Object& object)
1021 {
1022     _ASSERT(&object.GetTSE_Info() == this);
1023     if ( object.x_DirtyAnnotIndex() ) {
1024         CDataSource::TAnnotLockWriteGuard guard(eEmptyGuard);
1025         if (HasDataSource())
1026             guard.Guard(GetDataSource());
1027         TAnnotLockWriteGuard guard2(GetAnnotLock());
1028         //CStopWatch sw(CStopWatch::eStart);
1029         object.x_UpdateAnnotIndex(*this);
1030         _ASSERT(!object.x_DirtyAnnotIndex());
1031         //LOG_POST(Info<<"Updated annot index in "<<sw.Elapsed());
1032     }
1033 }
1034 
1035 /*
1036 void CTSE_Info::UpdateAnnotIndex(CTSE_Chunk_Info& chunk)
1037 {
1038     CDataSource::TAnnotLockWriteGuard guard(GetDataSource());
1039     TAnnotLockWriteGuard guard2(GetAnnotLock());
1040     chunk.x_UpdateAnnotIndex(*this);
1041 }
1042 */
1043 
x_UpdateAnnotIndexContents(CTSE_Info & tse)1044 void CTSE_Info::x_UpdateAnnotIndexContents(CTSE_Info& tse)
1045 {
1046     _ASSERT(this == &tse);
1047     if ( m_Split ) {
1048         m_Split->x_UpdateAnnotIndex();
1049     }
1050     TParent::x_UpdateAnnotIndexContents(tse);
1051 }
1052 
1053 
x_SetAnnotObjs(const CAnnotName & name)1054 CTSE_Info::TAnnotObjs& CTSE_Info::x_SetAnnotObjs(const CAnnotName& name)
1055 {
1056     TNamedAnnotObjs::iterator iter = m_NamedAnnotObjs.lower_bound(name);
1057     if ( iter == m_NamedAnnotObjs.end() || iter->first != name ) {
1058         typedef TNamedAnnotObjs::value_type value_type;
1059         iter = m_NamedAnnotObjs.insert(iter, value_type(name, TAnnotObjs()));
1060     }
1061     return iter->second;
1062 }
1063 
1064 
x_RemoveAnnotObjs(const CAnnotName & name)1065 void CTSE_Info::x_RemoveAnnotObjs(const CAnnotName& name)
1066 {
1067     m_NamedAnnotObjs.erase(name);
1068 }
1069 
1070 
1071 const CTSE_Info::TAnnotObjs*
x_GetAnnotObjs(const CAnnotName & name) const1072 CTSE_Info::x_GetAnnotObjs(const CAnnotName& name) const
1073 {
1074     TNamedAnnotObjs::const_iterator iter = m_NamedAnnotObjs.lower_bound(name);
1075     if ( iter == m_NamedAnnotObjs.end() || iter->first != name ) {
1076         return 0;
1077     }
1078     return &iter->second;
1079 }
1080 
1081 
1082 const CTSE_Info::TAnnotObjs*
x_GetUnnamedAnnotObjs(void) const1083 CTSE_Info::x_GetUnnamedAnnotObjs(void) const
1084 {
1085     TNamedAnnotObjs::const_iterator iter = m_NamedAnnotObjs.begin();
1086     if ( iter == m_NamedAnnotObjs.end() || iter->first.IsNamed() ) {
1087         return 0;
1088     }
1089     return &iter->second;
1090 }
1091 
1092 
1093 pair<SIdAnnotObjs*, bool>
x_SetIdObjects(TAnnotObjs & objs,const CAnnotName & name,const CSeq_id_Handle & id)1094 CTSE_Info::x_SetIdObjects(TAnnotObjs& objs,
1095                           const CAnnotName& name,
1096                           const CSeq_id_Handle& id)
1097 {
1098     // repeat for more generic types of selector
1099     bool new_id = false;
1100     TAnnotObjs::iterator it = objs.find(id);
1101     if ( it == objs.end() ) {
1102         // new id
1103         it = objs.insert(TAnnotObjs::value_type(id, SIdAnnotObjs())).first;
1104         new_id = x_IndexAnnotTSE(name, id);
1105     }
1106     _ASSERT(it != objs.end() && it->first == id);
1107     return make_pair(&it->second, new_id);
1108 }
1109 
1110 
1111 pair<SIdAnnotObjs*, bool>
x_SetIdObjects(const CAnnotName & name,const CSeq_id_Handle & id)1112 CTSE_Info::x_SetIdObjects(const CAnnotName& name,
1113                           const CSeq_id_Handle& id)
1114 {
1115     return x_SetIdObjects(x_SetAnnotObjs(name), name, id);
1116 }
1117 
1118 
x_GetIdObjects(const TAnnotObjs & objs,const CSeq_id_Handle & idh) const1119 const SIdAnnotObjs* CTSE_Info::x_GetIdObjects(const TAnnotObjs& objs,
1120                                               const CSeq_id_Handle& idh) const
1121 {
1122     TAnnotObjs::const_iterator it = objs.find(idh);
1123     if ( it == objs.end() ) {
1124         return 0;
1125     }
1126     return &it->second;
1127 }
1128 
1129 
x_GetIdObjects(const CAnnotName & name,const CSeq_id_Handle & idh) const1130 const SIdAnnotObjs* CTSE_Info::x_GetIdObjects(const CAnnotName& name,
1131                                               const CSeq_id_Handle& idh) const
1132 {
1133     const TAnnotObjs* objs = x_GetAnnotObjs(name);
1134     if ( !objs ) {
1135         return 0;
1136     }
1137     return x_GetIdObjects(*objs, idh);
1138 }
1139 
1140 
1141 const SIdAnnotObjs*
x_GetUnnamedIdObjects(const CSeq_id_Handle & idh) const1142 CTSE_Info::x_GetUnnamedIdObjects(const CSeq_id_Handle& idh) const
1143 {
1144     const TAnnotObjs* objs = x_GetUnnamedAnnotObjs();
1145     if ( !objs ) {
1146         return 0;
1147     }
1148     return x_GetIdObjects(*objs, idh);
1149 }
1150 
1151 
x_HasIdObjects(const CSeq_id_Handle & idh) const1152 bool CTSE_Info::x_HasIdObjects(const CSeq_id_Handle& idh) const
1153 {
1154     // tse annot index should be locked by TAnnotLockReadGuard
1155     ITERATE ( TNamedAnnotObjs, it, m_NamedAnnotObjs ) {
1156         if ( x_GetIdObjects(it->second, idh) ) {
1157             return true;
1158         }
1159     }
1160     return false;
1161 }
1162 
1163 
1164 inline
x_MapAnnotObject(TRangeMap & rangeMap,const SAnnotObject_Key & key,const SAnnotObject_Index & index)1165 void CTSE_Info::x_MapAnnotObject(TRangeMap& rangeMap,
1166                                  const SAnnotObject_Key& key,
1167                                  const SAnnotObject_Index& index)
1168 {
1169     //_ASSERT(index.m_AnnotObject_Info == key.m_AnnotObject_Info);
1170     rangeMap.insert(TRangeMap::value_type(key.m_Range, index));
1171 }
1172 
1173 
1174 inline
x_UnmapAnnotObject(TRangeMap & rangeMap,const CAnnotObject_Info & info,const SAnnotObject_Key & key)1175 bool CTSE_Info::x_UnmapAnnotObject(TRangeMap& rangeMap,
1176                                    const CAnnotObject_Info& info,
1177                                    const SAnnotObject_Key& key)
1178 {
1179     for ( TRangeMap::iterator it = rangeMap.find(key.m_Range);
1180           it && it->first == key.m_Range; ++it ) {
1181         if ( it->second.m_AnnotObject_Info == &info ) {
1182             rangeMap.erase(it);
1183             return rangeMap.empty();
1184         }
1185     }
1186     _ASSERT(0);
1187     return rangeMap.empty();
1188 }
1189 
1190 
x_MapAnnotObject(SIdAnnotObjs & objs,const SAnnotObject_Key & key,const SAnnotObject_Index & index)1191 void CTSE_Info::x_MapAnnotObject(SIdAnnotObjs& objs,
1192                                  const SAnnotObject_Key& key,
1193                                  const SAnnotObject_Index& index)
1194 {
1195     if ( index.m_AnnotObject_Info->IsLocs() ) {
1196         // Locs may contain multiple indexes
1197         CAnnotObject_Info::TTypeIndexSet idx_set;
1198         index.m_AnnotObject_Info->GetLocsTypes(idx_set);
1199         ITERATE(CAnnotObject_Info::TTypeIndexSet, idx_rg, idx_set) {
1200             for (size_t idx = idx_rg->first; idx < idx_rg->second; ++idx) {
1201                 x_MapAnnotObject(objs.x_GetRangeMap(idx), key, index);
1202             }
1203         }
1204     }
1205     else {
1206         CAnnotType_Index::TIndexRange idx_rg =
1207             CAnnotType_Index::GetTypeIndex(*index.m_AnnotObject_Info);
1208         for (size_t idx = idx_rg.first; idx < idx_rg.second; ++idx) {
1209             x_MapAnnotObject(objs.x_GetRangeMap(idx), key, index);
1210         }
1211     }
1212 }
1213 
1214 
x_UnmapAnnotObject(SIdAnnotObjs & objs,const CAnnotObject_Info & info,const SAnnotObject_Key & key)1215 bool CTSE_Info::x_UnmapAnnotObject(SIdAnnotObjs& objs,
1216                                    const CAnnotObject_Info& info,
1217                                    const SAnnotObject_Key& key)
1218 {
1219     CAnnotType_Index::TIndexRange idx_rg =
1220         CAnnotType_Index::GetTypeIndex(info);
1221     for (size_t idx = idx_rg.first; idx < idx_rg.second; ++idx) {
1222         _ASSERT(idx < objs.x_GetRangeMapCount());
1223         if ( x_UnmapAnnotObject(objs.x_GetRangeMap(idx), info, key) ) {
1224             if ( objs.x_CleanRangeMaps() ) {
1225                 return objs.m_SNPSet.empty();
1226             }
1227         }
1228     }
1229     return false;
1230 }
1231 
1232 
x_MapAnnotObject(TAnnotObjs & objs,const CAnnotName & name,const SAnnotObject_Key & key,const SAnnotObject_Index & index)1233 bool CTSE_Info::x_MapAnnotObject(TAnnotObjs& objs,
1234                                  const CAnnotName& name,
1235                                  const SAnnotObject_Key& key,
1236                                  const SAnnotObject_Index& index)
1237 {
1238     auto id_objs = x_SetIdObjects(objs, name, key.m_Handle);
1239     x_MapAnnotObject(*id_objs.first, key, index);
1240     return id_objs.second;
1241 }
1242 
1243 
x_UnmapAnnotObject(TAnnotObjs & objs,const CAnnotName & name,const CAnnotObject_Info & info,const SAnnotObject_Key & key)1244 bool CTSE_Info::x_UnmapAnnotObject(TAnnotObjs& objs,
1245                                    const CAnnotName& name,
1246                                    const CAnnotObject_Info& info,
1247                                    const SAnnotObject_Key& key)
1248 {
1249     TAnnotObjs::iterator it = objs.find(key.m_Handle);
1250     if ( it != objs.end() && x_UnmapAnnotObject(it->second, info, key) ) {
1251         x_UnindexAnnotTSE(name, key.m_Handle);
1252         objs.erase(it);
1253         return objs.empty();
1254     }
1255     return false;
1256 }
1257 
1258 
x_MapSNP_Table(const CAnnotName & name,const CSeq_id_Handle & key,const CSeq_annot_SNP_Info & snp_info)1259 bool CTSE_Info::x_MapSNP_Table(const CAnnotName& name,
1260                                const CSeq_id_Handle& key,
1261                                const CSeq_annot_SNP_Info& snp_info)
1262 {
1263     auto objs = x_SetIdObjects(name, key);
1264     objs.first->m_SNPSet.push_back(ConstRef(&snp_info));
1265     return objs.second;
1266 }
1267 
1268 
x_UnmapSNP_Table(const CAnnotName & name,const CSeq_id_Handle & key,const CSeq_annot_SNP_Info & snp_info)1269 void CTSE_Info::x_UnmapSNP_Table(const CAnnotName& name,
1270                                  const CSeq_id_Handle& key,
1271                                  const CSeq_annot_SNP_Info& snp_info)
1272 {
1273     SIdAnnotObjs& objs = *x_SetIdObjects(name, key).first;
1274     TSNPSet::iterator iter = find(objs.m_SNPSet.begin(),
1275                                   objs.m_SNPSet.end(),
1276                                   ConstRef(&snp_info));
1277     if ( iter != objs.m_SNPSet.end() ) {
1278         objs.m_SNPSet.erase(iter);
1279     }
1280 }
1281 
1282 
x_MapAnnotObject(const CAnnotName & name,const SAnnotObject_Key & key,const SAnnotObject_Index & index)1283 bool CTSE_Info::x_MapAnnotObject(const CAnnotName& name,
1284                                  const SAnnotObject_Key& key,
1285                                  const SAnnotObject_Index& index)
1286 {
1287     return x_MapAnnotObject(x_SetAnnotObjs(name), name, key, index);
1288 }
1289 
1290 
x_UnmapAnnotObject(const CAnnotName & name,const CAnnotObject_Info & info,const SAnnotObject_Key & key)1291 void CTSE_Info::x_UnmapAnnotObject(const CAnnotName& name,
1292                                    const CAnnotObject_Info& info,
1293                                    const SAnnotObject_Key& key)
1294 {
1295     TAnnotObjs& index = x_SetAnnotObjs(name);
1296 
1297     x_UnmapAnnotObject(index, name, info, key);
1298 
1299     if ( index.empty() ) {
1300         x_RemoveAnnotObjs(name);
1301     }
1302 }
1303 
1304 
x_UnmapAnnotObjects(const SAnnotObjectsIndex & infos)1305 void CTSE_Info::x_UnmapAnnotObjects(const SAnnotObjectsIndex& infos)
1306 {
1307     if ( !infos.IsIndexed() ) {
1308         return;
1309     }
1310     const CAnnotName& name = infos.GetName();
1311     TAnnotObjs& index = x_SetAnnotObjs(name);
1312 
1313     ITERATE ( SAnnotObjectsIndex::TObjectInfos, it, infos.GetInfos() ) {
1314         if ( it->HasSingleKey() ) {
1315             x_UnmapAnnotObject(index, name, *it, it->GetKey());
1316         }
1317         else {
1318             for ( size_t i = it->GetKeysBegin(); i < it->GetKeysEnd(); ++i ) {
1319                 x_UnmapAnnotObject(index, name, *it, infos.GetKey(i));
1320             }
1321         }
1322     }
1323 
1324     if ( index.empty() ) {
1325         x_RemoveAnnotObjs(name);
1326     }
1327 }
1328 
1329 
x_GetBioseq_set(int id)1330 CBioseq_set_Info& CTSE_Info::x_GetBioseq_set(int id)
1331 {
1332     TBioseq_sets::iterator iter;
1333     if (m_Split) {
1334         iter = m_Removed_Bioseq_sets.find(id);
1335         if ( iter != m_Removed_Bioseq_sets.end() )
1336             return *iter->second;
1337     }
1338 
1339     iter = m_Bioseq_sets.find(id);
1340     if ( iter == m_Bioseq_sets.end() ) {
1341         NCBI_THROW(CObjMgrException, eRegisterError,
1342                    "cannot find Bioseq-set by local id");
1343     }
1344     return *iter->second;
1345 }
1346 
1347 
x_GetBioseq(const CSeq_id_Handle & id)1348 CBioseq_Info& CTSE_Info::x_GetBioseq(const CSeq_id_Handle& id)
1349 {
1350     CFastMutexGuard guard(m_BioseqsMutex);
1351     TBioseqs::iterator iter;
1352     if (m_Split) {
1353         iter = m_Removed_Bioseqs.find(id);
1354         if ( iter != m_Removed_Bioseqs.end() )
1355             return *iter->second;
1356     }
1357 
1358     iter = m_Bioseqs.find(id);
1359     if ( iter == m_Bioseqs.end() ) {
1360         NCBI_THROW(CObjMgrException, eRegisterError,
1361                    "cannot find Bioseq by Seq-id "+id.AsString());
1362     }
1363     return *iter->second;
1364 }
1365 
1366 
HasSplitInfo(void) const1367 bool CTSE_Info::HasSplitInfo(void) const
1368 {
1369     return m_Split;
1370 }
1371 
1372 
GetSplitInfo(void) const1373 const CTSE_Split_Info& CTSE_Info::GetSplitInfo(void) const
1374 {
1375     _ASSERT(HasSplitInfo());
1376     return *m_Split;
1377 }
1378 
1379 
GetSplitInfo(void)1380 CTSE_Split_Info& CTSE_Info::GetSplitInfo(void)
1381 {
1382     if ( !m_Split ) {
1383         _ASSERT(m_LoadState == eNotLoaded);
1384         m_Split = new CTSE_Split_Info(GetBlobId(), GetBlobVersion());
1385         CRef<ITSE_Assigner> listener(new CTSE_Default_Assigner);
1386         m_Split->x_TSEAttach(*this, listener);
1387     }
1388     return *m_Split;
1389 }
1390 
1391 
x_NeedsDelayedMainChunk(void) const1392 bool CTSE_Info::x_NeedsDelayedMainChunk(void) const
1393 {
1394     return m_Split && m_Split->x_NeedsDelayedMainChunk();
1395 }
1396 
1397 
x_LoadDelayedMainChunk(void) const1398 void CTSE_Info::x_LoadDelayedMainChunk(void) const
1399 {
1400     if ( m_Split ) {
1401         m_Split->x_LoadDelayedMainChunk();
1402     }
1403 }
1404 
1405 
x_AddFeaturesById(TAnnotObjects & objects,const SFeatIdIndex & index,TFeatIdInt id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1406 void CTSE_Info::x_AddFeaturesById(TAnnotObjects& objects,
1407                                   const SFeatIdIndex& index,
1408                                   TFeatIdInt id,
1409                                   EFeatIdType id_type,
1410                                   const CSeq_annot_Info* src_annot) const
1411 {
1412     if ( !index.m_Chunks.empty() ) {
1413         x_LoadChunks(index.m_Chunks);
1414         UpdateAnnotIndex();
1415     }
1416     if ( !index.m_IndexInt ) {
1417         return;
1418     }
1419     const CSeq_entry_Info* xref_tse = 0;
1420     if ( src_annot ) {
1421         xref_tse = &src_annot->GetXrefTSE();
1422         if ( xref_tse == this ) {
1423             xref_tse = 0;
1424         }
1425     }
1426     const SFeatIdIndex::TIndexInt& index2 = *index.m_IndexInt;
1427     for ( SFeatIdIndex::TIndexInt::const_iterator iter2 = index2.find(id);
1428           iter2 != index2.end() && iter2->first == id; ++iter2 ) {
1429         const SFeatIdInfo& info = iter2->second;
1430         if ( info.m_Type == id_type ) {
1431             if ( info.m_IsChunk ) {
1432                 x_LoadChunk(info.m_ChunkId);
1433                 UpdateAnnotIndex();
1434             }
1435             else {
1436                 if ( xref_tse && xref_tse != &info.m_Info->GetSeq_annot_Info().GetXrefTSE() ) {
1437                     continue;
1438                 }
1439                 objects.push_back(info.m_Info);
1440             }
1441         }
1442     }
1443 }
1444 
1445 
x_HasFeaturesWithId(CSeqFeatData::ESubtype subtype) const1446 bool CTSE_Info::x_HasFeaturesWithId(CSeqFeatData::ESubtype subtype) const
1447 {
1448     TFeatIdIndex::const_iterator iter = m_FeatIdIndex.find(subtype);
1449     return iter != m_FeatIdIndex.end();
1450 }
1451 
1452 
x_AddFeaturesById(TAnnotObjects & objects,CSeqFeatData::ESubtype subtype,TFeatIdInt id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1453 void CTSE_Info::x_AddFeaturesById(TAnnotObjects& objects,
1454                                   CSeqFeatData::ESubtype subtype,
1455                                   TFeatIdInt id,
1456                                   EFeatIdType id_type,
1457                                   const CSeq_annot_Info* src_annot) const
1458 {
1459     TFeatIdIndex::const_iterator iter = m_FeatIdIndex.find(subtype);
1460     if ( iter == m_FeatIdIndex.end() ) {
1461         return;
1462     }
1463     x_AddFeaturesById(objects, iter->second, id, id_type, src_annot);
1464 }
1465 
1466 
x_AddAllFeaturesById(TAnnotObjects & objects,TFeatIdInt id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1467 void CTSE_Info::x_AddAllFeaturesById(TAnnotObjects& objects,
1468                                      TFeatIdInt id,
1469                                      EFeatIdType id_type,
1470                                      const CSeq_annot_Info* src_annot) const
1471 {
1472     //LOG_POST_X(1, this << ": ""x_AddAllFeaturesWithId: " << id);
1473     ITERATE ( TFeatIdIndex, iter, m_FeatIdIndex ) {
1474         x_AddFeaturesById(objects, iter->second, id, id_type, src_annot);
1475     }
1476 }
1477 
1478 
x_AddFeaturesById(TAnnotObjects & objects,const SFeatIdIndex & index,const TFeatIdStr & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1479 void CTSE_Info::x_AddFeaturesById(TAnnotObjects& objects,
1480                                   const SFeatIdIndex& index,
1481                                   const TFeatIdStr& id,
1482                                   EFeatIdType id_type,
1483                                   const CSeq_annot_Info* src_annot) const
1484 {
1485     if ( !index.m_Chunks.empty() ) {
1486         x_LoadChunks(index.m_Chunks);
1487         UpdateAnnotIndex();
1488     }
1489     if ( !index.m_IndexStr ) {
1490         return;
1491     }
1492     const CSeq_entry_Info* xref_tse = 0;
1493     if ( src_annot ) {
1494         xref_tse = &src_annot->GetXrefTSE();
1495         if ( xref_tse == this ) {
1496             xref_tse = 0;
1497         }
1498     }
1499     const SFeatIdIndex::TIndexStr& index2 = *index.m_IndexStr;
1500     for ( SFeatIdIndex::TIndexStr::const_iterator iter2 = index2.find(id);
1501           iter2 != index2.end() && iter2->first == id; ++iter2 ) {
1502         const SFeatIdInfo& info = iter2->second;
1503         if ( info.m_Type == id_type ) {
1504             if ( info.m_IsChunk ) {
1505                 x_LoadChunk(info.m_ChunkId);
1506                 UpdateAnnotIndex();
1507             }
1508             else {
1509                 if ( xref_tse && xref_tse != &info.m_Info->GetSeq_annot_Info().GetXrefTSE() ) {
1510                     continue;
1511                 }
1512                 objects.push_back(info.m_Info);
1513             }
1514         }
1515     }
1516 }
1517 
1518 
x_AddFeaturesById(TAnnotObjects & objects,CSeqFeatData::ESubtype subtype,const TFeatIdStr & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1519 void CTSE_Info::x_AddFeaturesById(TAnnotObjects& objects,
1520                                   CSeqFeatData::ESubtype subtype,
1521                                   const TFeatIdStr& id,
1522                                   EFeatIdType id_type,
1523                                   const CSeq_annot_Info* src_annot) const
1524 {
1525     TFeatIdIndex::const_iterator iter = m_FeatIdIndex.find(subtype);
1526     if ( iter == m_FeatIdIndex.end() ) {
1527         return;
1528     }
1529     x_AddFeaturesById(objects, iter->second, id, id_type, src_annot);
1530 }
1531 
1532 
x_AddAllFeaturesById(TAnnotObjects & objects,const TFeatIdStr & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1533 void CTSE_Info::x_AddAllFeaturesById(TAnnotObjects& objects,
1534                                      const TFeatIdStr& id,
1535                                      EFeatIdType id_type,
1536                                      const CSeq_annot_Info* src_annot) const
1537 {
1538     //LOG_POST_X(1, this << ": ""x_AddAllFeaturesWithId: " << id);
1539     ITERATE ( TFeatIdIndex, iter, m_FeatIdIndex ) {
1540         x_AddFeaturesById(objects, iter->second, id, id_type, src_annot);
1541     }
1542 }
1543 
1544 
1545 CTSE_Info::SFeatIdIndex::TIndexInt&
x_GetFeatIdIndexInt(CSeqFeatData::ESubtype type)1546 CTSE_Info::x_GetFeatIdIndexInt(CSeqFeatData::ESubtype type)
1547 {
1548     //LOG_POST_X(2, this << ": ""x_MapFeatById: " << type);
1549     SFeatIdIndex& index = m_FeatIdIndex[type];
1550     if ( !index.m_IndexInt ) {
1551         index.m_IndexInt.reset(new SFeatIdIndex::TIndexInt);
1552     }
1553     return *index.m_IndexInt;
1554 }
1555 
1556 
1557 CTSE_Info::SFeatIdIndex::TIndexStr&
x_GetFeatIdIndexStr(CSeqFeatData::ESubtype type)1558 CTSE_Info::x_GetFeatIdIndexStr(CSeqFeatData::ESubtype type)
1559 {
1560     //LOG_POST_X(2, this << ": ""x_MapFeatById: " << type);
1561     SFeatIdIndex& index = m_FeatIdIndex[type];
1562     if ( !index.m_IndexStr ) {
1563         index.m_IndexStr.reset(new SFeatIdIndex::TIndexStr);
1564     }
1565     return *index.m_IndexStr;
1566 }
1567 
1568 
x_MapFeatById(TFeatIdInt id,CAnnotObject_Info & info,EFeatIdType id_type)1569 void CTSE_Info::x_MapFeatById(TFeatIdInt id,
1570                               CAnnotObject_Info& info,
1571                               EFeatIdType id_type)
1572 {
1573     //LOG_POST_X(2, this << ": ""x_MapFeatById: " << id << " " << id_type<<" "<<&info);
1574     SFeatIdIndex::TIndexInt& index =
1575         x_GetFeatIdIndexInt(info.GetFeatSubtype());
1576     SFeatIdIndex::TIndexInt::value_type value(id, SFeatIdInfo(id_type, &info));
1577     index.insert(value);
1578 }
1579 
1580 
x_UnmapFeatById(TFeatIdInt id,CAnnotObject_Info & info,EFeatIdType id_type)1581 void CTSE_Info::x_UnmapFeatById(TFeatIdInt id,
1582                                 CAnnotObject_Info& info,
1583                                 EFeatIdType id_type)
1584 {
1585     //LOG_POST_X(3, this << ": ""x_UnmapFeatById: " << id << " " << id_type<<" "<<&info);
1586     SFeatIdIndex::TIndexInt& index =
1587         x_GetFeatIdIndexInt(info.GetFeatSubtype());
1588     for ( SFeatIdIndex::TIndexInt::iterator iter = index.lower_bound(id);
1589           iter != index.end() && iter->first == id; ++iter ) {
1590         if ( iter->second.m_Info == &info && iter->second.m_Type == id_type ) {
1591             index.erase(iter);
1592             return;
1593         }
1594     }
1595     _ASSERT("x_UnmapFeatById: not found" && 0);
1596 }
1597 
1598 
x_MapFeatById(const TFeatIdStr & id,CAnnotObject_Info & info,EFeatIdType id_type)1599 void CTSE_Info::x_MapFeatById(const TFeatIdStr& id,
1600                               CAnnotObject_Info& info,
1601                               EFeatIdType id_type)
1602 {
1603     //LOG_POST_X(2, this << ": ""x_MapFeatById: " << id << " " << id_type<<" "<<&info);
1604     SFeatIdIndex::TIndexStr& index =
1605         x_GetFeatIdIndexStr(info.GetFeatSubtype());
1606     SFeatIdIndex::TIndexStr::value_type value(id, SFeatIdInfo(id_type, &info));
1607     index.insert(value);
1608 }
1609 
1610 
x_UnmapFeatById(const TFeatIdStr & id,CAnnotObject_Info & info,EFeatIdType id_type)1611 void CTSE_Info::x_UnmapFeatById(const TFeatIdStr& id,
1612                                 CAnnotObject_Info& info,
1613                                 EFeatIdType id_type)
1614 {
1615     //LOG_POST_X(3, this << ": ""x_UnmapFeatById: " << id << " " << id_type<<" "<<&info);
1616     SFeatIdIndex::TIndexStr& index =
1617         x_GetFeatIdIndexStr(info.GetFeatSubtype());
1618     for ( SFeatIdIndex::TIndexStr::iterator iter = index.lower_bound(id);
1619           iter != index.end() && iter->first == id; ++iter ) {
1620         if ( iter->second.m_Info == &info && iter->second.m_Type == id_type ) {
1621             index.erase(iter);
1622             return;
1623         }
1624     }
1625     _ASSERT("x_UnmapFeatById: not found" && 0);
1626 }
1627 
1628 
x_MapFeatById(const TFeatId & id,CAnnotObject_Info & info,EFeatIdType id_type)1629 void CTSE_Info::x_MapFeatById(const TFeatId& id,
1630                               CAnnotObject_Info& info,
1631                               EFeatIdType id_type)
1632 {
1633     if ( id.IsId() ) {
1634         x_MapFeatById(id.GetId(), info, id_type);
1635     }
1636     else {
1637         x_MapFeatById(id.GetStr(), info, id_type);
1638     }
1639 }
1640 
1641 
x_UnmapFeatById(const TFeatId & id,CAnnotObject_Info & info,EFeatIdType id_type)1642 void CTSE_Info::x_UnmapFeatById(const TFeatId& id,
1643                                 CAnnotObject_Info& info,
1644                                 EFeatIdType id_type)
1645 {
1646     if ( id.IsId() ) {
1647         x_UnmapFeatById(id.GetId(), info, id_type);
1648     }
1649     else {
1650         x_UnmapFeatById(id.GetStr(), info, id_type);
1651     }
1652 }
1653 
1654 
x_MapFeatByLocus(const string & locus,bool tag,CAnnotObject_Info & info)1655 void CTSE_Info::x_MapFeatByLocus(const string& locus, bool tag,
1656                                  CAnnotObject_Info& info)
1657 {
1658     m_LocusIndex.insert(TLocusIndex::value_type(TLocusKey(locus, tag), &info));
1659 }
1660 
1661 
x_UnmapFeatByLocus(const string & locus,bool tag,CAnnotObject_Info & info)1662 void CTSE_Info::x_UnmapFeatByLocus(const string& locus, bool tag,
1663                                    CAnnotObject_Info& info)
1664 {
1665     for ( TLocusIndex::iterator it =
1666               m_LocusIndex.lower_bound(TLocusKey(locus, tag));
1667           it != m_LocusIndex.end() &&
1668               it->first.first == locus &&
1669               it->first.second == tag;
1670           ++it ) {
1671         if ( it->second == &info ) {
1672             m_LocusIndex.erase(it);
1673             return;
1674         }
1675     }
1676 }
1677 
1678 
x_MapChunkByFeatId(TFeatIdInt id,CSeqFeatData::ESubtype subtype,TChunkId chunk_id,EFeatIdType id_type)1679 void CTSE_Info::x_MapChunkByFeatId(TFeatIdInt id,
1680                                    CSeqFeatData::ESubtype subtype,
1681                                    TChunkId chunk_id,
1682                                    EFeatIdType id_type)
1683 {
1684     SFeatIdIndex::TIndexInt& index = x_GetFeatIdIndexInt(subtype);
1685     SFeatIdIndex::TIndexInt::value_type value(id, SFeatIdInfo(id_type, chunk_id));
1686     index.insert(value);
1687 }
1688 
1689 
x_MapChunkByFeatId(TFeatIdInt id,CSeqFeatData::E_Choice type,TChunkId chunk_id,EFeatIdType id_type)1690 void CTSE_Info::x_MapChunkByFeatId(TFeatIdInt id,
1691                                    CSeqFeatData::E_Choice type,
1692                                    TChunkId chunk_id,
1693                                    EFeatIdType id_type)
1694 {
1695     CAnnotType_Index::TIndexRange range =
1696         CAnnotType_Index::GetFeatTypeRange(type);
1697     for ( size_t index = range.first; index < range.second; ++index ) {
1698         CSeqFeatData::ESubtype subtype =
1699             CAnnotType_Index::GetSubtypeForIndex(index);
1700         x_MapChunkByFeatId(id, subtype, chunk_id, id_type);
1701     }
1702 }
1703 
1704 
x_MapChunkByFeatId(TFeatIdInt id,const SAnnotTypeSelector & type,TChunkId chunk_id,EFeatIdType id_type)1705 void CTSE_Info::x_MapChunkByFeatId(TFeatIdInt id,
1706                                    const SAnnotTypeSelector& type,
1707                                    TChunkId chunk_id,
1708                                    EFeatIdType id_type)
1709 {
1710     if ( type.GetFeatSubtype() != CSeqFeatData::eSubtype_any ) {
1711         x_MapChunkByFeatId(id, type.GetFeatSubtype(), chunk_id, id_type);
1712     }
1713     else {
1714         x_MapChunkByFeatId(id, type.GetFeatType(), chunk_id, id_type);
1715     }
1716 }
1717 
1718 
x_MapChunkByFeatId(const TFeatIdStr & id,CSeqFeatData::ESubtype subtype,TChunkId chunk_id,EFeatIdType id_type)1719 void CTSE_Info::x_MapChunkByFeatId(const TFeatIdStr& id,
1720                                    CSeqFeatData::ESubtype subtype,
1721                                    TChunkId chunk_id,
1722                                    EFeatIdType id_type)
1723 {
1724     SFeatIdIndex::TIndexStr& index = x_GetFeatIdIndexStr(subtype);
1725     SFeatIdIndex::TIndexStr::value_type value(id, SFeatIdInfo(id_type, chunk_id));
1726     index.insert(value);
1727 }
1728 
1729 
x_MapChunkByFeatId(const TFeatIdStr & id,CSeqFeatData::E_Choice type,TChunkId chunk_id,EFeatIdType id_type)1730 void CTSE_Info::x_MapChunkByFeatId(const TFeatIdStr& id,
1731                                    CSeqFeatData::E_Choice type,
1732                                    TChunkId chunk_id,
1733                                    EFeatIdType id_type)
1734 {
1735     CAnnotType_Index::TIndexRange range =
1736         CAnnotType_Index::GetFeatTypeRange(type);
1737     for ( size_t index = range.first; index < range.second; ++index ) {
1738         CSeqFeatData::ESubtype subtype =
1739             CAnnotType_Index::GetSubtypeForIndex(index);
1740         x_MapChunkByFeatId(id, subtype, chunk_id, id_type);
1741     }
1742 }
1743 
1744 
x_MapChunkByFeatId(const TFeatIdStr & id,const SAnnotTypeSelector & type,TChunkId chunk_id,EFeatIdType id_type)1745 void CTSE_Info::x_MapChunkByFeatId(const TFeatIdStr& id,
1746                                    const SAnnotTypeSelector& type,
1747                                    TChunkId chunk_id,
1748                                    EFeatIdType id_type)
1749 {
1750     if ( type.GetFeatSubtype() != CSeqFeatData::eSubtype_any ) {
1751         x_MapChunkByFeatId(id, type.GetFeatSubtype(), chunk_id, id_type);
1752     }
1753     else {
1754         x_MapChunkByFeatId(id, type.GetFeatType(), chunk_id, id_type);
1755     }
1756 }
1757 
1758 
x_MapChunkByFeatId(const TFeatId & id,CSeqFeatData::ESubtype subtype,TChunkId chunk_id,EFeatIdType id_type)1759 void CTSE_Info::x_MapChunkByFeatId(const TFeatId& id,
1760                                    CSeqFeatData::ESubtype subtype,
1761                                    TChunkId chunk_id,
1762                                    EFeatIdType id_type)
1763 {
1764     if ( id.IsId() ) {
1765         x_MapChunkByFeatId(id.GetId(), subtype, chunk_id, id_type);
1766     }
1767     else {
1768         x_MapChunkByFeatId(id.GetStr(), subtype, chunk_id, id_type);
1769     }
1770 }
1771 
1772 
x_MapChunkByFeatId(const TFeatId & id,CSeqFeatData::E_Choice type,TChunkId chunk_id,EFeatIdType id_type)1773 void CTSE_Info::x_MapChunkByFeatId(const TFeatId& id,
1774                                    CSeqFeatData::E_Choice type,
1775                                    TChunkId chunk_id,
1776                                    EFeatIdType id_type)
1777 {
1778     if ( id.IsId() ) {
1779         x_MapChunkByFeatId(id.GetId(), type, chunk_id, id_type);
1780     }
1781     else {
1782         x_MapChunkByFeatId(id.GetStr(), type, chunk_id, id_type);
1783     }
1784 }
1785 
1786 
x_MapChunkByFeatId(const TFeatId & id,const SAnnotTypeSelector & type,TChunkId chunk_id,EFeatIdType id_type)1787 void CTSE_Info::x_MapChunkByFeatId(const TFeatId& id,
1788                                    const SAnnotTypeSelector& type,
1789                                    TChunkId chunk_id,
1790                                    EFeatIdType id_type)
1791 {
1792     if ( id.IsId() ) {
1793         x_MapChunkByFeatId(id.GetId(), type, chunk_id, id_type);
1794     }
1795     else {
1796         x_MapChunkByFeatId(id.GetStr(), type, chunk_id, id_type);
1797     }
1798 }
1799 
1800 
x_MapChunkByFeatType(CSeqFeatData::ESubtype subtype,TChunkId chunk_id)1801 void CTSE_Info::x_MapChunkByFeatType(CSeqFeatData::ESubtype subtype,
1802                                      TChunkId chunk_id)
1803 {
1804     m_FeatIdIndex[subtype].m_Chunks.push_back(chunk_id);
1805 }
1806 
1807 
x_MapChunkByFeatType(CSeqFeatData::E_Choice type,TChunkId chunk_id)1808 void CTSE_Info::x_MapChunkByFeatType(CSeqFeatData::E_Choice type,
1809                                      TChunkId chunk_id)
1810 {
1811     CAnnotType_Index::TIndexRange range =
1812         CAnnotType_Index::GetFeatTypeRange(type);
1813     for ( size_t index = range.first; index < range.second; ++index ) {
1814         CSeqFeatData::ESubtype subtype =
1815             CAnnotType_Index::GetSubtypeForIndex(index);
1816         x_MapChunkByFeatType(subtype, chunk_id);
1817     }
1818 }
1819 
1820 
x_MapChunkByFeatType(const SAnnotTypeSelector & type,TChunkId chunk_id)1821 void CTSE_Info::x_MapChunkByFeatType(const SAnnotTypeSelector& type,
1822                                      TChunkId chunk_id)
1823 {
1824     if ( type.GetFeatSubtype() != CSeqFeatData::eSubtype_any ) {
1825         x_MapChunkByFeatType(type.GetFeatSubtype(), chunk_id);
1826     }
1827     else {
1828         x_MapChunkByFeatType(type.GetFeatType(), chunk_id);
1829     }
1830 }
1831 
1832 
1833 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::ESubtype subtype,TFeatIdInt id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1834 CTSE_Info::x_GetFeaturesById(CSeqFeatData::ESubtype subtype,
1835                              TFeatIdInt id,
1836                              EFeatIdType id_type,
1837                              const CSeq_annot_Info* src_annot) const
1838 {
1839     TAnnotObjects objects;
1840     UpdateFeatIdIndex(subtype, id_type);
1841     if ( subtype == CSeqFeatData::eSubtype_any ) {
1842         x_AddAllFeaturesById(objects, id, id_type, src_annot);
1843     }
1844     else {
1845         x_AddFeaturesById(objects, subtype, id, id_type, src_annot);
1846     }
1847     return objects;
1848 }
1849 
1850 
1851 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::E_Choice type,TFeatIdInt id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1852 CTSE_Info::x_GetFeaturesById(CSeqFeatData::E_Choice type,
1853                              TFeatIdInt id,
1854                              EFeatIdType id_type,
1855                              const CSeq_annot_Info* src_annot) const
1856 {
1857     TAnnotObjects objects;
1858     UpdateFeatIdIndex(type, id_type);
1859     if ( type == CSeqFeatData::e_not_set ) {
1860         x_AddAllFeaturesById(objects, id, id_type, src_annot);
1861     }
1862     else {
1863         CAnnotType_Index::TIndexRange range =
1864             CAnnotType_Index::GetFeatTypeRange(type);
1865         for ( size_t index = range.first; index < range.second; ++index ) {
1866             CSeqFeatData::ESubtype subtype =
1867                 CAnnotType_Index::GetSubtypeForIndex(index);
1868             x_AddFeaturesById(objects, subtype, id, id_type, src_annot);
1869         }
1870     }
1871     return objects;
1872 }
1873 
1874 
1875 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::ESubtype subtype,const TFeatIdStr & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1876 CTSE_Info::x_GetFeaturesById(CSeqFeatData::ESubtype subtype,
1877                              const TFeatIdStr& id,
1878                              EFeatIdType id_type,
1879                              const CSeq_annot_Info* src_annot) const
1880 {
1881     TAnnotObjects objects;
1882     UpdateFeatIdIndex(subtype, id_type);
1883     if ( subtype == CSeqFeatData::eSubtype_any ) {
1884         x_AddAllFeaturesById(objects, id, id_type, src_annot);
1885     }
1886     else {
1887         x_AddFeaturesById(objects, subtype, id, id_type, src_annot);
1888     }
1889     return objects;
1890 }
1891 
1892 
1893 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::E_Choice type,const TFeatIdStr & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1894 CTSE_Info::x_GetFeaturesById(CSeqFeatData::E_Choice type,
1895                              const TFeatIdStr& id,
1896                              EFeatIdType id_type,
1897                              const CSeq_annot_Info* src_annot) const
1898 {
1899     TAnnotObjects objects;
1900     UpdateFeatIdIndex(type, id_type);
1901     if ( type == CSeqFeatData::e_not_set ) {
1902         x_AddAllFeaturesById(objects, id, id_type, src_annot);
1903     }
1904     else {
1905         CAnnotType_Index::TIndexRange range =
1906             CAnnotType_Index::GetFeatTypeRange(type);
1907         for ( size_t index = range.first; index < range.second; ++index ) {
1908             CSeqFeatData::ESubtype subtype =
1909                 CAnnotType_Index::GetSubtypeForIndex(index);
1910             x_AddFeaturesById(objects, subtype, id, id_type, src_annot);
1911         }
1912     }
1913     return objects;
1914 }
1915 
1916 
1917 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::ESubtype subtype,const TFeatId & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1918 CTSE_Info::x_GetFeaturesById(CSeqFeatData::ESubtype subtype,
1919                              const TFeatId& id,
1920                              EFeatIdType id_type,
1921                              const CSeq_annot_Info* src_annot) const
1922 {
1923     TAnnotObjects objects;
1924     if ( id.IsId() ) {
1925         x_GetFeaturesById(subtype, id.GetId(), id_type, src_annot).swap(objects);
1926     }
1927     else {
1928         x_GetFeaturesById(subtype, id.GetStr(), id_type, src_annot).swap(objects);
1929     }
1930     return objects;
1931 }
1932 
1933 
1934 CTSE_Info::TAnnotObjects
x_GetFeaturesById(CSeqFeatData::E_Choice type,const TFeatId & id,EFeatIdType id_type,const CSeq_annot_Info * src_annot) const1935 CTSE_Info::x_GetFeaturesById(CSeqFeatData::E_Choice type,
1936                              const TFeatId& id,
1937                              EFeatIdType id_type,
1938                              const CSeq_annot_Info* src_annot) const
1939 {
1940     TAnnotObjects objects;
1941     if ( id.IsId() ) {
1942         x_GetFeaturesById(type, id.GetId(), id_type, src_annot).swap(objects);
1943     }
1944     else {
1945         x_GetFeaturesById(type, id.GetStr(), id_type, src_annot).swap(objects);
1946     }
1947     return objects;
1948 }
1949 
1950 
x_GetFeaturesByLocus(const string & locus,bool tag,const CSeq_annot_Info * src_annot) const1951 CTSE_Info::TAnnotObjects CTSE_Info::x_GetFeaturesByLocus(const string& locus,
1952                                                          bool tag,
1953                                                          const CSeq_annot_Info* src_annot) const
1954 {
1955     UpdateAnnotIndex();
1956     TAnnotObjects objects;
1957     const CSeq_entry_Info* xref_tse = 0;
1958     if ( src_annot ) {
1959         xref_tse = &src_annot->GetXrefTSE();
1960         if ( xref_tse == this ) {
1961             xref_tse = 0;
1962         }
1963     }
1964     for ( TLocusIndex::const_iterator it =
1965               m_LocusIndex.lower_bound(TLocusKey(locus, tag));
1966           it != m_LocusIndex.end() &&
1967               it->first.first == locus &&
1968               it->first.second == tag;
1969           ++it ) {
1970         if ( xref_tse && xref_tse != &it->second->GetSeq_annot_Info().GetXrefTSE() ) {
1971             continue;
1972         }
1973         objects.push_back(it->second);
1974     }
1975     return objects;
1976 }
1977 
1978 
1979 CTSE_Info::TSeq_feat_Lock
x_FindSeq_feat(const CSeq_id_Handle & loc_id,TSeqPos loc_pos,const CSeq_feat & feat) const1980 CTSE_Info::x_FindSeq_feat(const CSeq_id_Handle& loc_id,
1981                           TSeqPos loc_pos,
1982                           const CSeq_feat& feat) const
1983 {
1984     TSeq_feat_Lock ret;
1985     CSeqFeatData::ESubtype subtype = feat.GetData().GetSubtype();
1986     size_t index = CAnnotType_Index::GetSubtypeIndex(subtype);
1987     TRange range(loc_pos, loc_pos);
1988     ITERATE ( TNamedAnnotObjs, it_n, m_NamedAnnotObjs ) {
1989         const SIdAnnotObjs* objs = x_GetIdObjects(it_n->second, loc_id);
1990         if ( !objs ) {
1991             continue;
1992         }
1993         if ( index < objs->x_GetRangeMapCount() &&
1994              !objs->x_RangeMapIsEmpty(index) ) {
1995             const TRangeMap& rmap = objs->x_GetRangeMap(index);
1996             for ( TRangeMap::const_iterator it(rmap.begin(range)); it; ++it ) {
1997                 const CAnnotObject_Info& annot_info =
1998                     *it->second.m_AnnotObject_Info;
1999                 if ( !annot_info.IsRegular() ) {
2000                     continue;
2001                 }
2002                 const CSeq_feat* found_feat = annot_info.GetFeatFast();
2003                 if ( found_feat == &feat ) {
2004                     ret.first.first = &annot_info.GetSeq_annot_Info();
2005                     ret.second = annot_info.GetAnnotIndex();
2006                     return ret;
2007                 }
2008             }
2009         }
2010         /*
2011         if ( subtype == CSeqFeatData::eSubtype_variation &&
2012              !objs->m_SNPSet.empty() ) {
2013 
2014         }
2015         */
2016     }
2017     return ret;
2018 }
2019 
2020 
SetBioseqUpdater(CRef<CBioseqUpdater> updater)2021 void CTSE_Info::SetBioseqUpdater(CRef<CBioseqUpdater> updater)
2022 {
2023     CFastMutexGuard guard(m_BioseqsMutex);
2024     m_BioseqUpdater = updater;
2025     set<CBioseq_Info*> seen;
2026     NON_CONST_ITERATE ( TBioseqs, it, m_Bioseqs ) {
2027         if ( seen.insert(it->second).second ) {
2028             m_BioseqUpdater->Update(*it->second);
2029         }
2030     }
2031 }
2032 
2033 
GetDescription(void) const2034 string CTSE_Info::GetDescription(void) const
2035 {
2036     string ret;
2037     if ( m_BlobId ) {
2038         ret = GetBlobId().ToString();
2039     }
2040     else {
2041         ret = NStr::PtrToString(this);
2042     }
2043     if ( GetName().IsNamed() ) {
2044         ret += '/';
2045         ret += GetName().GetName();
2046     }
2047     return ret;
2048 }
2049 
2050 
GetTopLevelObjectType(void) const2051 CTSE_Info::ETopLevelObjectType CTSE_Info::GetTopLevelObjectType(void) const
2052 {
2053     return m_TopLevelObjectType;
2054 }
2055 
2056 
GetTopLevelObjectPtr(void) const2057 const CSerialObject* CTSE_Info::GetTopLevelObjectPtr(void) const
2058 {
2059     return m_TopLevelObjectPtr.GetPointerOrNull();
2060 }
2061 
2062 
SetTopLevelObject(ETopLevelObjectType type,CSerialObject * ptr)2063 void CTSE_Info::SetTopLevelObject(ETopLevelObjectType type, CSerialObject* ptr)
2064 {
2065     m_TopLevelObjectType = type;
2066     m_TopLevelObjectPtr = ptr;
2067 }
2068 
2069 
IsTopLevelSeq_submit() const2070 bool CTSE_Info::IsTopLevelSeq_submit() const
2071 {
2072     return GetTopLevelObjectType() == CTSE_Handle::eTopLevel_Seq_submit;
2073 }
2074 
2075 
x_GetTopLevelSeq_submit() const2076 CSeq_submit& CTSE_Info::x_GetTopLevelSeq_submit() const
2077 {
2078     if ( !IsTopLevelSeq_submit() ) {
2079         NCBI_THROW(CObjMgrException, eInvalidHandle,
2080                    "CTSE_Handle::GetTopLevelSeq_submit: "
2081                    "Top level object is not Seq-submit");
2082     }
2083     CSeq_submit* submit = dynamic_cast<CSeq_submit*>(m_TopLevelObjectPtr.GetNCPointerOrNull());
2084     if ( !submit ) {
2085         NCBI_THROW(CObjMgrException, eInvalidHandle,
2086                    "CTSE_Handle::GetTopLevelSeq_submit: "
2087                    "Top level object is not Seq-submit");
2088     }
2089     return *submit;
2090 }
2091 
2092 
GetTopLevelSeq_submit() const2093 const CSeq_submit& CTSE_Info::GetTopLevelSeq_submit() const
2094 {
2095     CSeq_submit& submit = x_GetTopLevelSeq_submit();
2096     if ( IsSet() ) {
2097         const TSet& set = GetSet();
2098         // update entry/annot lists
2099         if ( set.IsSetSeq_set() && !set.GetSeq_set().empty() ) {
2100             submit.SetData().SetEntrys() = set.GetBioseq_setCore()->GetSeq_set();
2101         }
2102         else if ( set.IsSetAnnot() && !set.GetAnnot().empty() ) {
2103             submit.SetData().SetAnnots() = set.GetBioseq_setCore()->GetAnnot();
2104         }
2105         else {
2106             switch ( submit.GetData().Which() ) {
2107             case CSeq_submit::TData::e_Entrys:
2108                 submit.SetData().SetEntrys().clear();
2109                 break;
2110             case CSeq_submit::TData::e_Annots:
2111                 submit.SetData().SetAnnots().clear();
2112                 break;
2113             default:
2114                 break;
2115             }
2116         }
2117     }
2118     return submit;
2119 }
2120 
2121 
GetTopLevelSubmit_block() const2122 const CSubmit_block& CTSE_Info::GetTopLevelSubmit_block() const
2123 {
2124     return x_GetTopLevelSeq_submit().GetSub();
2125 }
2126 
2127 
SetTopLevelSubmit_block() const2128 CSubmit_block& CTSE_Info::SetTopLevelSubmit_block() const
2129 {
2130     return x_GetTopLevelSeq_submit().SetSub();
2131 }
2132 
2133 
SetTopLevelSubmit_block(CSubmit_block & sub) const2134 void CTSE_Info::SetTopLevelSubmit_block(CSubmit_block& sub) const
2135 {
2136     x_GetTopLevelSeq_submit().SetSub(sub);
2137 }
2138 
2139 
SetTopLevelObjectType(ETopLevelObjectType type)2140 void CTSE_Info::SetTopLevelObjectType(ETopLevelObjectType type)
2141 {
2142     SetTopLevelObject(type, 0);
2143 }
2144 
2145 
CTSE_SetObjectInfo(void)2146 CTSE_SetObjectInfo::CTSE_SetObjectInfo(void)
2147 {
2148 }
2149 
2150 
~CTSE_SetObjectInfo(void)2151 CTSE_SetObjectInfo::~CTSE_SetObjectInfo(void)
2152 {
2153 }
2154 
2155 
2156 
2157 END_SCOPE(objects)
2158 END_NCBI_SCOPE
2159