src/objtools/data_loaders/genbank/cache/reader_cache.cpp

Go to the documentation of this file.
00001 /*  $Id: reader_cache.cpp 163689 2009-06-17 21:18:36Z vasilche $
00002  * ===========================================================================
00003  *                            PUBLIC DOMAIN NOTICE
00004  *               National Center for Biotechnology Information
00005  *
00006  *  This software/database is a "United States Government Work" under the
00007  *  terms of the United States Copyright Act.  It was written as part of
00008  *  the author's official duties as a United States Government employee and
00009  *  thus cannot be copyrighted.  This software/database is freely available
00010  *  to the public for use. The National Library of Medicine and the U.S.
00011  *  Government have not placed any restriction on its use or reproduction.
00012  *
00013  *  Although all reasonable efforts have been taken to ensure the accuracy
00014  *  and reliability of the software and data, the NLM and the U.S.
00015  *  Government do not and cannot warrant the performance or results that
00016  *  may be obtained by using this software or data. The NLM and the U.S.
00017  *  Government disclaim all warranties, express or implied, including
00018  *  warranties of performance, merchantability or fitness for any particular
00019  *  purpose.
00020  *
00021  *  Please cite the author in any work or product based on this material.
00022  *
00023  * ===========================================================================
00024  *
00025  *  Author:  Eugene Vasilchenko, Anatoliy Kuznetsov
00026  *
00027  *  File Description: Cached extension of data reader from ID1
00028  *
00029  */
00030 #include <ncbi_pch.hpp>
00031 #include <objtools/data_loaders/genbank/cache/reader_cache.hpp>
00032 #include <objtools/data_loaders/genbank/cache/reader_cache_entry.hpp>
00033 #include <objtools/data_loaders/genbank/cache/reader_cache_params.h>
00034 #include <objtools/data_loaders/genbank/readers.hpp> // for entry point
00035 #include <objtools/data_loaders/genbank/dispatcher.hpp>
00036 #include <objtools/data_loaders/genbank/request_result.hpp>
00037 #include <objtools/data_loaders/genbank/gbloader.hpp>
00038 
00039 #include <corelib/ncbitime.hpp>
00040 #include <corelib/rwstream.hpp>
00041 #include <corelib/plugin_manager_store.hpp>
00042 
00043 #include <util/cache/icache.hpp>
00044 
00045 #include <objmgr/objmgr_exception.hpp>
00046 #include <objmgr/impl/tse_split_info.hpp>
00047 #include <objmgr/impl/tse_chunk_info.hpp>
00048 #include <objmgr/annot_selector.hpp>
00049 
00050 #include <serial/objistrasnb.hpp>       // for reading Seq-ids
00051 #include <serial/serial.hpp>            // for reading Seq-ids
00052 #include <objects/seqloc/Seq_id.hpp>    // for reading Seq-ids
00053 
00054 #define FIX_BAD_ID2S_REPLY_DATA 1
00055 
00056 BEGIN_NCBI_SCOPE
00057 BEGIN_SCOPE(objects)
00058 
00059 const int    SCacheInfo::IDS_MAGIC = 0x32fd0105;
00060 
00061 string SCacheInfo::GetBlobKey(const CBlob_id& blob_id)
00062 {
00063     CNcbiOstrstream oss;
00064     oss << blob_id.GetSat();
00065     if ( blob_id.GetSubSat() != 0 ) {
00066         oss << '.' << blob_id.GetSubSat();
00067     }
00068     oss << '-' << blob_id.GetSatKey();
00069     return CNcbiOstrstreamToString(oss);
00070 }
00071 
00072 
00073 string SCacheInfo::GetIdKey(int gi)
00074 {
00075     return NStr::IntToString(gi);
00076 }
00077 
00078 
00079 string SCacheInfo::GetIdKey(const CSeq_id& id)
00080 {
00081     return id.IsGi()? GetIdKey(id.GetGi()): id.AsFastaString();
00082 }
00083 
00084 
00085 string SCacheInfo::GetIdKey(const CSeq_id_Handle& id)
00086 {
00087     return id.IsGi()? GetIdKey(id.GetGi()): id.AsString();
00088 }
00089 
00090 
00091 static const size_t kHashLimit = 100;
00092 
00093 
00094 void SCacheInfo::GetBlob_idsSubkey(const SAnnotSelector* sel,
00095                                    string& subkey,
00096                                    string& true_subkey)
00097 {
00098     if ( !sel ) {
00099         subkey = "blobs";
00100         return;
00101     }
00102     const SAnnotSelector::TNamedAnnotAccessions& accs =
00103         sel->GetNamedAnnotAccessions();
00104     if ( accs.empty() ) {
00105         subkey = "blobs";
00106         return;
00107     }
00108 
00109     CNcbiOstrstream str;
00110     str << "blobs";
00111     size_t total_size = 0;
00112     ITERATE ( SAnnotSelector::TNamedAnnotAccessions, it, accs ) {
00113         total_size += 1+it->size();
00114     }
00115     bool add_hash = total_size > kHashLimit;
00116     if ( add_hash ) {
00117         size_t hash = 5381;
00118         ITERATE ( SAnnotSelector::TNamedAnnotAccessions, it, accs ) {
00119             hash = hash*17 + it->size();
00120             ITERATE ( string, i, *it ) {
00121                 hash = hash*17 + (*i & 0xff);
00122             }
00123         }
00124         str << ";#" << hex << hash << dec;
00125     }
00126     ITERATE ( SAnnotSelector::TNamedAnnotAccessions, it,
00127               sel->GetNamedAnnotAccessions() ) {
00128         str << ';';
00129         str << *it;
00130     }
00131     if ( add_hash ) {
00132         true_subkey = CNcbiOstrstreamToString(str);
00133         subkey = true_subkey.substr(0, kHashLimit);
00134     }
00135     else {
00136         subkey = CNcbiOstrstreamToString(str);
00137     }
00138 }
00139 
00140 
00141 const char* SCacheInfo::GetGiSubkey(void)
00142 {
00143     return "gi4";
00144 }
00145 
00146 
00147 const char* SCacheInfo::GetAccVerSubkey(void)
00148 {
00149     return "accver";
00150 }
00151 
00152 
00153 const char* SCacheInfo::GetLabelSubkey(void)
00154 {
00155     return "label";
00156 }
00157 
00158 
00159 const char* SCacheInfo::GetSeq_idsSubkey(void)
00160 {
00161     return "ids4";
00162 }
00163 
00164 
00165 const char* SCacheInfo::GetBlobVersionSubkey(void)
00166 {
00167     return "ver4";
00168 }
00169 
00170 
00171 string SCacheInfo::GetBlobSubkey(int chunk_id)
00172 {
00173     if ( chunk_id == kMain_ChunkId )
00174         return kEmptyStr;
00175     else
00176         return NStr::IntToString(chunk_id);
00177 }
00178 
00179 
00180 /////////////////////////////////////////////////////////////////////////////
00181 // CCacheHolder
00182 /////////////////////////////////////////////////////////////////////////////
00183 
00184 CCacheHolder::CCacheHolder(void)
00185     : m_BlobCache(0), m_IdCache(0)
00186 {
00187 }
00188 
00189 
00190 CCacheHolder::~CCacheHolder(void)
00191 {
00192     SetIdCache(0);
00193     SetBlobCache(0);
00194 }
00195 
00196 
00197 void CCacheHolder::SetIdCache(ICache* id_cache)
00198 {
00199     m_IdCache = id_cache;
00200 }
00201 
00202 
00203 void CCacheHolder::SetBlobCache(ICache* blob_cache)
00204 {
00205     m_BlobCache = blob_cache;
00206 }
00207 
00208 
00209 /////////////////////////////////////////////////////////////////////////
00210 
00211 
00212 CCacheReader::CCacheReader(void)
00213 {
00214     SetMaximumConnections(1);
00215 }
00216 
00217 
00218 void CCacheReader::x_AddConnectionSlot(TConn /*conn*/)
00219 {
00220 }
00221 
00222 
00223 void CCacheReader::x_RemoveConnectionSlot(TConn /*conn*/)
00224 {
00225     SetIdCache(0);
00226     SetBlobCache(0);
00227 }
00228 
00229 
00230 void CCacheReader::x_DisconnectAtSlot(TConn /*conn*/)
00231 {
00232 }
00233 
00234 
00235 void CCacheReader::x_ConnectAtSlot(TConn /*conn*/)
00236 {
00237 }
00238 
00239 
00240 int CCacheReader::GetRetryCount(void) const
00241 {
00242     return 2;
00243 }
00244 
00245 
00246 bool CCacheReader::MayBeSkippedOnErrors(void) const
00247 {
00248     return true;
00249 }
00250 
00251 
00252 int CCacheReader::GetMaximumConnectionsLimit(void) const
00253 {
00254     return 1;
00255 }
00256 
00257 
00258 //////////////////////////////////////////////////////////////////
00259 
00260 
00261 namespace {
00262     class CParseBuffer {
00263     public:
00264         CParseBuffer(ICache* cache,
00265                      const string& key, int version, const string& subkey);
00266 
00267         bool Found(void) const
00268             {
00269                 return m_Descr.blob_found;
00270             }
00271         bool Done(void) const
00272             {
00273                 if ( m_Ptr ) {
00274                     return m_Size == 0;
00275                 }
00276                 else {
00277                     return x_Eof();
00278                 }
00279             }
00280 
00281         Uint4 ParseUint4(void)
00282             {
00283                 const char* ptr = x_NextBytes(4);
00284                 return ((ptr[0]&0xff)<<24)|((ptr[1]&0xff)<<16)|
00285                     ((ptr[2]&0xff)<<8)|(ptr[3]&0xff);
00286             }
00287         Int4 ParseInt4(void)
00288             {
00289                 return ParseUint4();
00290             }
00291         string ParseString(void);
00292         string FullString(void);
00293         
00294     protected:
00295         bool x_Eof(void) const;
00296         const char* x_NextBytes(size_t size);
00297         
00298     private:
00299         CParseBuffer(const CParseBuffer&);
00300         void operator=(const CParseBuffer&);
00301 
00302         char m_Buffer[4096];
00303         ICache::SBlobAccessDescr m_Descr;
00304         const char* m_Ptr;
00305         size_t m_Size;
00306     };
00307 
00308     CParseBuffer::CParseBuffer(ICache* cache,
00309                                const string& key,
00310                                int version,
00311                                const string& subkey)
00312         : m_Descr(m_Buffer, sizeof(m_Buffer)), m_Ptr(0), m_Size(0)
00313     {
00314         cache->GetBlobAccess(key, version, subkey, &m_Descr);
00315         if ( !m_Descr.reader.get() ) {
00316             m_Ptr = m_Descr.buf;
00317             m_Size = m_Descr.blob_size;
00318         }
00319     }
00320     
00321     string CParseBuffer::ParseString(void)
00322     {
00323         string ret;
00324         size_t size = ParseUint4();
00325         if ( m_Ptr ) {
00326             ret.assign(x_NextBytes(size), size);
00327         }
00328         else {
00329             ret.reserve(size);
00330             while ( size ) {
00331                 size_t count = min(size, sizeof(m_Buffer));
00332                 ret.assign(x_NextBytes(count), count);
00333                 size -= count;
00334             }
00335         }
00336         return ret;
00337     }
00338 
00339     string CParseBuffer::FullString(void)
00340     {
00341         string ret;
00342         if ( m_Ptr ) {
00343             ret.assign(m_Ptr, m_Size);
00344             m_Ptr += m_Size;
00345             m_Size = 0;
00346         }
00347         else {
00348             for ( ;; ) {
00349                 size_t count = 0;
00350                 if ( m_Descr.reader->Read(m_Buffer, sizeof(m_Buffer), &count) != eRW_Success ) {
00351                     break;
00352                 }
00353                 ret.append(m_Buffer, count);
00354             }
00355         }
00356         return ret;
00357     }
00358     
00359     const char* CParseBuffer::x_NextBytes(size_t size)
00360     {
00361         const char* ret = m_Ptr;
00362         if ( ret ) {
00363             if ( m_Size >= size ) {
00364                 m_Ptr = ret + size;
00365                 m_Size -= size;
00366                 return ret;
00367             }
00368         }
00369         else if ( size <= sizeof(m_Buffer) ) {
00370             char* buf = m_Buffer;
00371             while ( size ) {
00372                 size_t count = 0;
00373                 if ( m_Descr.reader->Read(buf, size, &count) != eRW_Success ) {
00374                     break;
00375                 }
00376                 buf += count;
00377                 size -= count;
00378             }
00379             if ( size == 0 ) {
00380                 return m_Buffer;
00381             }
00382         }
00383         NCBI_THROW(CLoaderException, eLoaderFailed,
00384                    "parse buffer overflow");
00385     }
00386 
00387     bool CParseBuffer::x_Eof(void) const
00388     {
00389         char buffer[1];
00390         size_t count;
00391         return m_Descr.reader->Read(buffer, 1, &count) == eRW_Eof;
00392     }
00393 }
00394 
00395 
00396 
00397 bool CCacheReader::LoadStringSeq_ids(CReaderRequestResult& result,
00398                                      const string& seq_id)
00399 {
00400     if ( !m_IdCache ) {
00401         return false;
00402     }
00403 
00404     CLoadLockSeq_ids ids(result, seq_id);
00405     return ReadSeq_ids(result, seq_id, ids);
00406 }
00407 
00408 
00409 bool CCacheReader::LoadSeq_idSeq_ids(CReaderRequestResult& result,
00410                                      const CSeq_id_Handle& seq_id)
00411 {
00412     if ( !m_IdCache ) {
00413         return false;
00414     }
00415 
00416     CLoadLockSeq_ids ids(result, seq_id);
00417     return ReadSeq_ids(result, GetIdKey(seq_id), ids);
00418 }
00419 
00420 
00421 bool CCacheReader::LoadSeq_idGi(CReaderRequestResult& result,
00422                                 const CSeq_id_Handle& seq_id)
00423 {
00424     if ( !m_IdCache ) {
00425         return false;
00426     }
00427 
00428     CLoadLockSeq_ids ids(result, seq_id);
00429     if ( !ids->IsLoadedGi() ) {
00430         CParseBuffer str(m_IdCache, GetIdKey(seq_id), 0, GetGiSubkey());
00431         if ( str.Found() ) {
00432             int gi = str.ParseInt4();
00433             if ( str.Done() ) {
00434                 ids->SetLoadedGi(gi);
00435                 return true;
00436             }
00437         }
00438     }
00439     return false;
00440 }
00441 
00442 
00443 bool CCacheReader::LoadSeq_idAccVer(CReaderRequestResult& result,
00444                                     const CSeq_id_Handle& seq_id)
00445 {
00446     if ( !m_IdCache ) {
00447         return false;
00448     }
00449 
00450     CLoadLockSeq_ids ids(result, seq_id);
00451     if ( !ids->IsLoadedAccVer() ) {
00452         CParseBuffer str(m_IdCache, GetIdKey(seq_id), 0, GetAccVerSubkey());
00453         if ( str.Found() ) {
00454             string data = str.FullString();
00455             CSeq_id_Handle acch;
00456             if ( !data.empty() ) {
00457                 CSeq_id id(data);
00458                 acch = CSeq_id_Handle::GetHandle(id);
00459             }
00460             ids->SetLoadedAccVer(acch);
00461             return true;
00462         }
00463     }
00464     return false;
00465 }
00466 
00467 
00468 bool CCacheReader::LoadSeq_idLabel(CReaderRequestResult& result,
00469                                    const CSeq_id_Handle& seq_id)
00470 {
00471     if ( !m_IdCache ) {
00472         return false;
00473     }
00474 
00475     CLoadLockSeq_ids ids(result, seq_id);
00476     if ( !ids->IsLoadedLabel() ) {
00477         CParseBuffer str(m_IdCache, GetIdKey(seq_id), 0, GetLabelSubkey());
00478         if ( str.Found() ) {
00479             ids->SetLoadedLabel(str.FullString());
00480             return true;
00481         }
00482     }
00483     return false;
00484 }
00485 
00486 
00487 bool CCacheReader::ReadSeq_ids(CReaderRequestResult& result,
00488                                const string& key,
00489                                CLoadLockSeq_ids& ids)
00490 {
00491     if ( !m_IdCache ) {
00492         return false;
00493     }
00494 
00495     if ( ids.IsLoaded() ) {
00496         return true;
00497     }
00498 
00499     CLoadInfoSeq_ids::TSeq_ids seq_ids;
00500     {{
00501         CConn conn(result, this);
00502         auto_ptr<IReader> reader
00503             (m_IdCache->GetReadStream(key, 0, GetSeq_idsSubkey()));
00504         if ( !reader.get() ) {
00505             conn.Release();
00506             return false;
00507         }
00508         CRStream r_stream(reader.get());
00509         CObjectIStreamAsnBinary obj_stream(r_stream);
00510         size_t count = static_cast<CObjectIStream&>(obj_stream).ReadUint4();
00511         for ( size_t i = 0; i < count; ++i ) {
00512             CSeq_id id;
00513             obj_stream >> id;
00514             seq_ids.push_back(CSeq_id_Handle::GetHandle(id));
00515         }
00516         conn.Release();
00517     }}
00518     ids->m_Seq_ids.swap(seq_ids);
00519     ids.SetLoaded();
00520     return true;
00521 }
00522 
00523 
00524 bool CCacheReader::LoadSeq_idBlob_ids(CReaderRequestResult& result,
00525                                       const CSeq_id_Handle& seq_id,
00526                                       const SAnnotSelector* sel)
00527 {
00528     if ( !m_IdCache ) {
00529         return false;
00530     }
00531 
00532     CLoadLockBlob_ids ids(result, seq_id, sel);
00533     if( ids.IsLoaded() ) {
00534         return true;
00535     }
00536     
00537     string subkey, true_subkey;
00538     GetBlob_idsSubkey(sel, subkey, true_subkey);
00539     CParseBuffer str(m_IdCache, GetIdKey(seq_id), 0, subkey);
00540     if ( str.Found() ) {
00541         if ( str.ParseInt4() != IDS_MAGIC ) {
00542             return false;
00543         }
00544         ids->clear();
00545         ids->SetState(str.ParseUint4());
00546         size_t blob_count = str.ParseUint4();
00547         for ( size_t i = 0; i < blob_count; ++i ) {
00548             CBlob_id id;
00549             id.SetSat(str.ParseUint4());
00550             id.SetSubSat(str.ParseUint4());
00551             id.SetSatKey(str.ParseUint4());
00552             CBlob_Info info(str.ParseUint4());
00553             size_t name_count = str.ParseUint4();
00554             for ( size_t j = 0; j < name_count; ++j ) {
00555                 info.AddNamedAnnotName(str.ParseString());
00556             }
00557             ids.AddBlob_id(id, info);
00558         }
00559         if ( !true_subkey.empty() && str.ParseString() != true_subkey ) {
00560             ids->clear();
00561             return false;
00562         }
00563         ids.SetLoaded();
00564         if ( !str.Done() ) {
00565             ids->clear();
00566             return false;
00567         }
00568     }
00569     return true;
00570 }
00571 
00572 
00573 bool CCacheReader::LoadBlobVersion(CReaderRequestResult& result,
00574                                    const TBlobId& blob_id)
00575 {
00576     if ( !m_IdCache ) {
00577         return false;
00578     }
00579     
00580     CParseBuffer str(m_IdCache, GetBlobKey(blob_id), 0, GetBlobVersionSubkey());
00581     if ( str.Found() ) {
00582         int version = str.ParseInt4();
00583         if ( str.Done() ) {
00584             SetAndSaveBlobVersion(result, blob_id, version);
00585             return true;
00586         }
00587     }
00588     return false;
00589 }
00590 
00591 
00592 bool CCacheReader::LoadBlob(CReaderRequestResult& result,
00593                             const TBlobId& blob_id)
00594 {
00595     return LoadChunk(result, blob_id, CProcessor::kMain_ChunkId);
00596 }
00597 
00598 
00599 bool CCacheReader::LoadChunk(CReaderRequestResult& result,
00600                              const TBlobId& blob_id,
00601                              TChunkId chunk_id)
00602 {
00603     if ( !m_BlobCache ) {
00604         return false;
00605     }
00606 
00607     CLoadLockBlob blob(result, blob_id);
00608     if ( CProcessor::IsLoaded(blob_id, chunk_id, blob) ) {
00609         return true;
00610     }
00611 
00612     string key = GetBlobKey(blob_id);
00613     string subkey = GetBlobSubkey(chunk_id);
00614     if ( !blob.IsSetBlobVersion() ) {
00615         {{
00616             CConn conn(result, this);
00617             if ( !m_BlobCache->HasBlobs(key, subkey) ) {
00618                 conn.Release();
00619                 return false;
00620             }
00621         }}
00622         m_Dispatcher->LoadBlobVersion(result, blob_id);
00623         if ( !blob.IsSetBlobVersion() ) {
00624             return false;
00625         }
00626     }
00627     TBlobVersion version = blob.GetBlobVersion();
00628 
00629     CConn conn(result, this);
00630     auto_ptr<IReader> reader(m_BlobCache->GetReadStream(key, version, subkey));
00631     if ( !reader.get() ) {
00632         conn.Release();
00633         return false;
00634     }
00635 
00636     CRStream stream(reader.get());
00637     int processor_type = ReadInt(stream);
00638     const CProcessor& processor =
00639         m_Dispatcher->GetProcessor(CProcessor::EType(processor_type));
00640     if ( processor_type != processor.GetType() ) {
00641         NCBI_THROW_FMT(CLoaderException, eLoaderFailed,
00642                        "CCacheReader::LoadChunk: "
00643                        "invalid processor type: "<<processor_type);
00644     }
00645     int processor_magic = ReadInt(stream);
00646     if ( processor_magic != int(processor.GetMagic()) ) {
00647         NCBI_THROW_FMT(CLoaderException, eLoaderFailed,
00648                        "CCacheReader::LoadChunk: "
00649                        "invalid processor magic number: "<<processor_magic);
00650     }
00651     processor.ProcessStream(result, blob_id, chunk_id, stream);
00652     conn.Release();
00653     return true;
00654 }
00655 
00656 
00657 struct SPluginParams
00658 {
00659     typedef SCacheInfo::TParams TParams;
00660 
00661     struct SDefaultValue {
00662         const char* name;
00663         const char* value;
00664     };
00665 
00666 
00667     static
00668     TParams* FindSubNode(TParams* params, const string& name)
00669     {
00670         if ( params ) {
00671             for ( TParams::TNodeList_I it = params->SubNodeBegin();
00672                   it != params->SubNodeEnd(); ++it ) {
00673                 if ( NStr::CompareNocase((*it)->GetKey(), name) == 0 ) {
00674                     return static_cast<TParams*>(*it);
00675                 }
00676             }
00677         }
00678         return 0;
00679     }
00680 
00681 
00682     static
00683     const TParams* FindSubNode(const TParams* params,
00684                                const string& name)
00685     {
00686         if ( params ) {
00687             for ( TParams::TNodeList_CI it = params->SubNodeBegin();
00688                   it != params->SubNodeEnd(); ++it ) {
00689                 if ( NStr::CompareNocase((*it)->GetKey(), name) == 0 ) {
00690                     return static_cast<const TParams*>(*it);
00691                 }
00692             }
00693         }
00694         return 0;
00695     }
00696 
00697 
00698     static
00699     TParams* SetSubNode(TParams* params,
00700                         const string& name,
00701                         const char* default_value = "")
00702     {
00703         _ASSERT(!name.empty());
00704         TParams* node = FindSubNode(params, name);
00705         if ( !node ) {
00706             node = params->AddNode(TParams::TValueType(name, default_value));
00707         }
00708         return node;
00709     }
00710 
00711 
00712     static
00713     TParams* SetSubSection(TParams* params, const string& name)
00714     {
00715         return SetSubNode(params, name, "");
00716     }
00717 
00718 
00719     static
00720     const string& SetDefaultValue(TParams* params,
00721                                   const string& name,
00722                                   const char* value)
00723     {
00724         return SetSubNode(params, name, value)->GetValue().value;
00725     }
00726 
00727 
00728     static
00729     const string& SetDefaultValue(TParams* params, const SDefaultValue& value)
00730     {
00731         return SetDefaultValue(params, value.name, value.value);
00732     }
00733 
00734 
00735     static
00736     void SetDefaultValues(TParams* params, const SDefaultValue* values)
00737     {
00738         for ( ; values->name; ++values ) {
00739             SetDefaultValue(params, *values);
00740         }
00741     }
00742 
00743 };
00744 
00745 
00746 static
00747 bool IsDisabledCache(const SCacheInfo::TParams* params)
00748 {
00749     const SCacheInfo::TParams* driver =
00750         SPluginParams::FindSubNode(params,
00751             NCBI_GBLOADER_READER_CACHE_PARAM_DRIVER);
00752     if ( driver ) {
00753         if ( driver->GetValue().value.empty() ) {
00754             // driver is set empty, it means no cache
00755             return true;
00756         }
00757     }
00758     return false;
00759 }
00760 
00761 
00762 static
00763 SCacheInfo::TParams* GetDriverParams(SCacheInfo::TParams* params)
00764 {
00765     const string& driver_name =
00766         SPluginParams::SetDefaultValue(params,
00767                         NCBI_GBLOADER_READER_CACHE_PARAM_DRIVER,
00768                         "bdb");
00769     return SPluginParams::SetSubSection(params, driver_name);
00770 }
00771 
00772 
00773 static
00774 SCacheInfo::TParams*
00775 GetCacheParamsCopy(const SCacheInfo::TParams* src_params,
00776                    const char* section_name)
00777 {
00778     const SCacheInfo::TParams* src_section =
00779         SPluginParams::FindSubNode(src_params, section_name);
00780     if ( IsDisabledCache(src_section) ) {
00781         // no cache
00782         return 0;
00783     }
00784     if ( src_section ) {
00785         // make a copy of params
00786         return new SCacheInfo::TParams(*src_section);
00787     }
00788     else {
00789         // new param tree, if section is absent
00790         return new SCacheInfo::TParams();
00791     }
00792 }
00793 
00794 static const SPluginParams::SDefaultValue s_DefaultParams[] = {
00795     { "path", ".genbank_cache" },
00796     { "keep_versions", "all" },
00797     { "write_sync", "no" },
00798     { "mem_size", "20M" },
00799     { "log_file_max", "20M" },
00800     { "purge_batch_sleep", "500" }, // .5 sec
00801     { "purge_thread_delay", "3600" }, // 1 hour
00802     { "purge_clean_log", "16" },
00803     { 0, 0 }
00804 };
00805 static const SPluginParams::SDefaultValue s_DefaultIdParams[] = {
00806     { "name", "ids" },
00807     { "timeout", "172800" }, // 2 days
00808     { "timestamp", "subkey check_expiration" /* purge_on_startup"*/ },
00809     { "page_size", "small" },
00810     { 0, 0}
00811 };
00812 static const SPluginParams::SDefaultValue s_DefaultBlobParams[] = {
00813     { "name", "blobs" },
00814     { "timeout", "432000" }, // 5 days
00815     { "timestamp", "onread expire_not_used" /* purge_on_startup"*/ },
00816     { 0, 0 }
00817 };
00818 static const SPluginParams::SDefaultValue s_DefaultReaderParams[] = {
00819     { "purge_thread", "yes" },
00820     { 0, 0 }
00821 };
00822 static const SPluginParams::SDefaultValue s_DefaultWriterParams[] = {
00823     { "purge_thread", "no" },
00824     { 0, 0 }
00825 };
00826 
00827 SCacheInfo::TParams*
00828 GetCacheParams(const SCacheInfo::TParams* src_params,
00829                 SCacheInfo::EReaderOrWriter reader_or_writer,
00830                 SCacheInfo::EIdOrBlob id_or_blob)
00831 {
00832     const char* section_name;
00833     if ( id_or_blob == SCacheInfo::eIdCache ) {
00834         section_name = NCBI_GBLOADER_READER_CACHE_PARAM_ID_SECTION;
00835     }
00836     else {
00837         section_name = NCBI_GBLOADER_READER_CACHE_PARAM_BLOB_SECTION;
00838     }
00839     auto_ptr<SCacheInfo::TParams> section
00840         (GetCacheParamsCopy(src_params, section_name));
00841     if ( !section.get() ) {
00842         // disabled
00843         return 0;
00844     }
00845     // fill driver section with default values
00846     SCacheInfo::TParams* driver_params = GetDriverParams(section.get());
00847     SPluginParams::SetDefaultValues(driver_params, s_DefaultParams);
00848     if ( id_or_blob == SCacheInfo::eIdCache ) {
00849         SPluginParams::SetDefaultValues(driver_params, s_DefaultIdParams);
00850     }
00851     else {
00852         SPluginParams::SetDefaultValues(driver_params, s_DefaultBlobParams);
00853     }
00854     if ( reader_or_writer == SCacheInfo::eCacheReader ) {
00855         SPluginParams::SetDefaultValues(driver_params, s_DefaultReaderParams);
00856     }
00857     else {
00858         SPluginParams::SetDefaultValues(driver_params, s_DefaultWriterParams);
00859     }
00860     return section.release();
00861 }
00862 
00863 
00864 ICache* SCacheInfo::CreateCache(const TParams* params,
00865                                 EReaderOrWriter reader_or_writer,
00866                                 EIdOrBlob id_or_blob)
00867 {
00868     auto_ptr<TParams> cache_params
00869         (GetCacheParams(params, reader_or_writer, id_or_blob));
00870     if ( !cache_params.get() ) {
00871         return 0;
00872     }
00873     typedef CPluginManager<ICache> TCacheManager;
00874     CRef<TCacheManager> manager(CPluginManagerGetter<ICache>::Get());
00875     _ASSERT(manager);
00876     return manager->CreateInstanceFromKey
00877         (cache_params.get(), NCBI_GBLOADER_READER_CACHE_PARAM_DRIVER);
00878 }
00879 
00880 
00881 void CCacheReader::InitializeCache(CReaderCacheManager& cache_manager,
00882                                    const TPluginManagerParamTree* params)
00883 {
00884     const TPluginManagerParamTree* reader_params = params ?
00885         params->FindNode(NCBI_GBLOADER_READER_CACHE_DRIVER_NAME) : 0;
00886     ICache* id_cache = 0;
00887     ICache* blob_cache = 0;
00888     auto_ptr<TParams> id_params
00889         (GetCacheParams(reader_params, eCacheReader, eIdCache));
00890     auto_ptr<TParams> blob_params
00891         (GetCacheParams(reader_params, eCacheReader, eBlobCache));
00892     _ASSERT(id_params.get());
00893     _ASSERT(blob_params.get());
00894     const TParams* share_id_param =
00895         id_params->FindNode(NCBI_GBLOADER_WRITER_CACHE_PARAM_SHARE);
00896     bool share_id = !share_id_param  ||
00897         NStr::StringToBool(share_id_param->GetValue().value);
00898     const TParams* share_blob_param =
00899         blob_params->FindNode(NCBI_GBLOADER_WRITER_CACHE_PARAM_SHARE);
00900     bool share_blob = !share_blob_param  ||
00901         NStr::StringToBool(share_blob_param->GetValue().value);
00902     if (share_id  ||  share_blob) {
00903         if ( share_id ) {
00904             ICache* cache = cache_manager.
00905                 FindCache(CReaderCacheManager::fCache_Id,
00906                           id_params.get());
00907             if ( cache ) {
00908                 _ASSERT(!id_cache);
00909                 id_cache = cache;
00910             }
00911         }
00912         if ( share_blob ) {
00913             ICache* cache = cache_manager.
00914                 FindCache(CReaderCacheManager::fCache_Blob,
00915                           blob_params.get());
00916             if ( cache ) {
00917                 _ASSERT(!blob_cache);
00918                 blob_cache = cache;
00919             }
00920         }
00921     }
00922     if ( !id_cache ) {
00923         id_cache = CreateCache(reader_params, eCacheReader, eIdCache);
00924         if ( id_cache ) {
00925             cache_manager.RegisterCache(*id_cache,
00926                 CReaderCacheManager::fCache_Id);
00927         }
00928     }
00929     if ( !blob_cache ) {
00930         blob_cache = CreateCache(reader_params, eCacheReader, eBlobCache);
00931         if ( blob_cache ) {
00932             cache_manager.RegisterCache(*blob_cache,
00933                 CReaderCacheManager::fCache_Blob);
00934         }
00935     }
00936     SetIdCache(id_cache);
00937     SetBlobCache(blob_cache);
00938 }
00939 
00940 
00941 void CCacheReader::ResetCache(void)
00942 {
00943     SetIdCache(0);
00944     SetBlobCache(0);
00945 }
00946 
00947 
00948 END_SCOPE(objects)
00949 
00950 
00951 /// Class factory for Cache reader
00952 ///
00953 /// @internal
00954 ///
00955 using namespace objects;
00956 
00957 class CCacheReaderCF :
00958     public CSimpleClassFactoryImpl<CReader, CCacheReader>
00959 {
00960     typedef CSimpleClassFactoryImpl<CReader, CCacheReader> TParent;
00961 public:
00962     CCacheReaderCF()
00963         : TParent(NCBI_GBLOADER_READER_CACHE_DRIVER_NAME, 0)
00964         {
00965         }
00966     ~CCacheReaderCF()
00967         {
00968         }
00969 
00970 
00971     CReader*
00972     CreateInstance(const string& driver  = kEmptyStr,
00973                    CVersionInfo version = NCBI_INTERFACE_VERSION(CReader),
00974                    const TPluginManagerParamTree* params = 0) const
00975     {
00976         if ( !driver.empty()  &&  driver != m_DriverName ) {
00977             return 0;
00978         }
00979         if ( !version.Match(NCBI_INTERFACE_VERSION(CReader)) ) {
00980             return 0;
00981         }
00982         return new CCacheReader;
00983     }
00984 };
00985 
00986 
00987 void NCBI_EntryPoint_CacheReader(
00988      CPluginManager<CReader>::TDriverInfoList&   info_list,
00989      CPluginManager<CReader>::EEntryPointRequest method)
00990 {
00991     CHostEntryPointImpl<CCacheReaderCF>::NCBI_EntryPointImpl(info_list,
00992                                                              method);
00993 }
00994 
00995 
00996 void NCBI_EntryPoint_xreader_cache(
00997      CPluginManager<CReader>::TDriverInfoList&   info_list,
00998      CPluginManager<CReader>::EEntryPointRequest method)
00999 {
01000     NCBI_EntryPoint_CacheReader(info_list, method);
01001 }
01002 
01003 
01004 void GenBankReaders_Register_Cache(void)
01005 {
01006     RegisterEntryPoint<CReader>(NCBI_EntryPoint_CacheReader);
01007 }
01008 
01009 
01010 END_NCBI_SCOPE
01011 
01012 

Generated on Sun Dec 6 22:41:16 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:21:12 2009 by modify_doxy.py rev. 173732