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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: reader_id1.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:41:56  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.81
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: reader_id1.cpp,v 1000.1 2004/06/01 19:41:56 gouriano Exp $
  10.  * ===========================================================================
  11.  *                            PUBLIC DOMAIN NOTICE
  12.  *               National Center for Biotechnology Information
  13.  *
  14.  *  This software/database is a "United States Government Work" under the
  15.  *  terms of the United States Copyright Act.  It was written as part of
  16.  *  the author's official duties as a United States Government employee and
  17.  *  thus cannot be copyrighted.  This software/database is freely available
  18.  *  to the public for use. The National Library of Medicine and the U.S.
  19.  *  Government have not placed any restriction on its use or reproduction.
  20.  *
  21.  *  Although all reasonable efforts have been taken to ensure the accuracy
  22.  *  and reliability of the software and data, the NLM and the U.S.
  23.  *  Government do not and cannot warrant the performance or results that
  24.  *  may be obtained by using this software or data. The NLM and the U.S.
  25.  *  Government disclaim all warranties, express or implied, including
  26.  *  warranties of performance, merchantability or fitness for any particular
  27.  *  purpose.
  28.  *
  29.  *  Please cite the author in any work or product based on this material.
  30.  *
  31.  * ===========================================================================
  32.  *
  33.  *  Author:  Anton Butanaev, Eugene Vasilchenko
  34.  *
  35.  *  File Description: Data reader from ID1
  36.  *
  37.  */
  38. #include <ncbi_pch.hpp>
  39. #include <corelib/ncbiapp.hpp>
  40. #include <corelib/ncbienv.hpp>
  41. #include <objtools/data_loaders/genbank/readers/id1/reader_id1.hpp>
  42. #include <objmgr/objmgr_exception.hpp>
  43. #include <objmgr/impl/tse_info.hpp>
  44. #include <objmgr/impl/tse_chunk_info.hpp>
  45. #include <objtools/data_loaders/genbank/reader_snp.hpp>
  46. #include <objtools/data_loaders/genbank/split_parser.hpp>
  47. #include <corelib/ncbistre.hpp>
  48. #define ID1_COLLECT_STATS
  49. #ifdef ID1_COLLECT_STATS
  50. # include <corelib/ncbitime.hpp>
  51. #endif
  52. #include <corelib/plugin_manager_impl.hpp>
  53. #include <objects/general/Dbtag.hpp>
  54. #include <objects/general/Object_id.hpp>
  55. #include <objects/seqloc/Seq_id.hpp>
  56. #include <objects/seqset/Seq_entry.hpp>
  57. #include <objects/seqset/Bioseq_set.hpp>
  58. #include <objects/seq/Seq_annot.hpp>
  59. #include <objects/id1/id1__.hpp>
  60. #include <objects/seqsplit/ID2S_Split_Info.hpp>
  61. #include <serial/enumvalues.hpp>
  62. #include <serial/iterator.hpp>
  63. #include <serial/objistrasnb.hpp>
  64. #include <serial/objostrasn.hpp>
  65. #include <serial/objostrasnb.hpp>
  66. #include <serial/serial.hpp>
  67. #include <connect/ncbi_conn_stream.hpp>
  68. #include <util/compress/reader_zlib.hpp>
  69. #include <util/stream_utils.hpp>
  70. #include <util/static_map.hpp>
  71. #include <memory>
  72. #include <iomanip>
  73. BEGIN_NCBI_SCOPE
  74. BEGIN_SCOPE(objects)
  75. #ifdef ID1_COLLECT_STATS
  76. static int resolve_id_count = 0;
  77. static double resolve_id_time = 0;
  78. static int resolve_gi_count = 0;
  79. static double resolve_gi_time = 0;
  80. static int resolve_ver_count = 0;
  81. static double resolve_ver_time = 0;
  82. static double last_object_bytes = 0;
  83. static int main_blob_count = 0;
  84. static double main_bytes = 0;
  85. static double main_time = 0;
  86. static int snp_blob_count = 0;
  87. static double snp_compressed = 0;
  88. static double snp_uncompressed = 0;
  89. static double snp_time = 0;
  90. static double snp_total_read_time = 0;
  91. static double snp_decompression_time = 0;
  92. static int s_GetCollectStatistics(void)
  93. {
  94.     const char* env = getenv("GENBANK_ID1_STATS");
  95.     if ( !env || !*env ) {
  96.         return 0;
  97.     }
  98.     try {
  99.         return NStr::StringToInt(env);
  100.     }
  101.     catch ( ... ) {
  102.         return 0;
  103.     }
  104. }
  105. #endif
  106. int CId1Reader::CollectStatistics(void)
  107. {
  108. #ifdef ID1_COLLECT_STATS
  109.     static int ret = s_GetCollectStatistics();
  110.     return ret;
  111. #else
  112.     return 0;
  113. #endif
  114. }
  115. CId1Reader::CId1Reader(TConn noConn)
  116.     : m_NoMoreConnections(false)
  117. {
  118.     
  119.     noConn=1; // limit number of simultaneous connections to one
  120. #if !defined(NCBI_THREADS)
  121.     noConn=1;
  122. #endif
  123.     try {
  124.         SetParallelLevel(noConn);
  125.     }
  126.     catch ( ... ) {
  127.         SetParallelLevel(0);
  128.         throw;
  129.     }
  130. }
  131. CId1Reader::~CId1Reader()
  132. {
  133.     SetParallelLevel(0);
  134. #ifdef ID1_COLLECT_STATS
  135.     if ( CollectStatistics() ) {
  136.         PrintStatistics();
  137.     }
  138. #endif
  139. }
  140. void CId1Reader::PrintStat(const char* type,
  141.                            size_t count,
  142.                            const char* what,
  143.                            double time)
  144. {
  145. #ifdef ID1_COLLECT_STATS
  146.     if ( !count ) {
  147.         return;
  148.     }
  149.     LOG_POST(type <<' '<<count<<' '<<what<<" in "<<
  150.              setiosflags(ios::fixed)<<
  151.              setprecision(3)<<
  152.              (time)<<" s "<<
  153.              (time*1000/count)<<" ms/one");
  154. #endif
  155. }
  156. void CId1Reader::PrintBlobStat(const char* type,
  157.                                size_t count,
  158.                                double bytes,
  159.                                double time)
  160. {
  161. #ifdef ID1_COLLECT_STATS
  162.     if ( !count ) {
  163.         return;
  164.     }
  165.     LOG_POST(type<<' '<<count<<" blobs "<<
  166.              setiosflags(ios::fixed)<<
  167.              setprecision(2)<<
  168.              (bytes/1024)<<" kB in "<<
  169.              setprecision(3)<<
  170.              (time)<<" s "<<
  171.              setprecision(2)<<
  172.              (bytes/time/1024)<<" kB/s");
  173. #endif
  174. }
  175. void CId1Reader::LogStat(const char* type, const string& name, double time)
  176. {
  177. #ifdef ID1_COLLECT_STATS
  178.     if ( CollectStatistics() <= 1 ) {
  179.         return;
  180.     }
  181.     LOG_POST(type<<' '<<name<<" in "<<
  182.              setiosflags(ios::fixed)<<
  183.              setprecision(3)<<
  184.              (time*1000)<<" ms");
  185. #endif
  186. }
  187. void CId1Reader::LogStat(const char* type,
  188.                          const string& name, const string& subkey, double time)
  189. {
  190. #ifdef ID1_COLLECT_STATS
  191.     if ( CollectStatistics() <= 1 ) {
  192.         return;
  193.     }
  194.     LOG_POST(type<<' '<<name<<" ("<<subkey<<") in "<<
  195.              setiosflags(ios::fixed)<<
  196.              setprecision(3)<<
  197.              (time*1000)<<" ms");
  198. #endif
  199. }
  200. void CId1Reader::LogStat(const char* type, const CSeq_id& id, double time)
  201. {
  202. #ifdef ID1_COLLECT_STATS
  203.     if ( CollectStatistics() <= 1 ) {
  204.         return;
  205.     }
  206.     LOG_POST(type<<' '<<id.AsFastaString()<<" in "<<
  207.              setiosflags(ios::fixed)<<
  208.              setprecision(3)<<
  209.              (time*1000)<<" ms");
  210. #endif
  211. }
  212. void CId1Reader::LogStat(const char* type,
  213.                          const CID1server_maxcomplex& maxplex, double time)
  214. {
  215. #ifdef ID1_COLLECT_STATS
  216.     if ( CollectStatistics() <= 1 ) {
  217.         return;
  218.     }
  219.     LOG_POST(type<<" TSE("<<maxplex.GetSat()<<','<<maxplex.GetEnt()<<") in "<<
  220.              setiosflags(ios::fixed)<<
  221.              setprecision(3)<<
  222.              (time*1000)<<" ms");
  223. #endif
  224. }
  225. void CId1Reader::LogStat(const char* type, int gi, double time)
  226. {
  227. #ifdef ID1_COLLECT_STATS
  228.     if ( CollectStatistics() <= 1 ) {
  229.         return;
  230.     }
  231.     LOG_POST(type<<' '<<gi<<" in "<<
  232.              setiosflags(ios::fixed)<<
  233.              setprecision(3)<<
  234.              (time*1000)<<" ms");
  235. #endif
  236. }
  237. void CId1Reader::LogBlobStat(const char* type,
  238.                              const CSeqref& seqref, double bytes, double time)
  239. {
  240. #ifdef ID1_COLLECT_STATS
  241.     if ( CollectStatistics() <= 1 ) {
  242.         return;
  243.     }
  244.     LOG_POST(type<<' '<<seqref.printTSE()<<' '<<
  245.              setiosflags(ios::fixed)<<
  246.              setprecision(2)<<
  247.              (bytes/1024)<<" kB in "<<
  248.              setprecision(3)<<
  249.              (time*1000)<<" ms "<<
  250.              setprecision(2)<<
  251.              (bytes/1024/time)<<" kB/s");
  252. #endif
  253. }
  254. void CId1Reader::PrintStatistics(void) const
  255. {
  256. #ifdef ID1_COLLECT_STATS
  257.     PrintStat("ID1 resolution: resolved",
  258.               resolve_id_count, "ids", resolve_id_time);
  259.     PrintStat("ID1 resolution: resolved",
  260.               resolve_gi_count, "gis", resolve_gi_time);
  261.     PrintStat("ID1 resolution: resolved",
  262.               resolve_ver_count, "vers", resolve_ver_time);
  263.     PrintBlobStat("ID1 non-SNP: loaded",
  264.                   main_blob_count, main_bytes, main_time);
  265.     PrintBlobStat("ID1 SNP: loaded",
  266.                   snp_blob_count, snp_compressed, snp_time);
  267.     if ( snp_blob_count ) {
  268.         LOG_POST("ID1 SNP decompression: "<<
  269.                  setiosflags(ios::fixed)<<
  270.                  setprecision(2)<<
  271.                  (snp_compressed/1024)<<" kB -> "<<
  272.                  (snp_uncompressed/1024)<<" kB, compession ratio: "<<
  273.                  setprecision(1)<<
  274.                  (snp_uncompressed/snp_compressed));
  275.         double snp_parse_time = snp_time - snp_total_read_time;
  276.         LOG_POST("ID1 SNP times: decompression : "<<
  277.                  setiosflags(ios::fixed)<<
  278.                  setprecision(3)<<
  279.                  (snp_decompression_time)<<" s, total read time: "<<
  280.                  (snp_total_read_time)<<" s, parse time: "<<
  281.                  (snp_parse_time)<<" s");
  282.     }
  283.     PrintBlobStat("ID1 total: loaded",
  284.                   main_blob_count + snp_blob_count,
  285.                   main_bytes + snp_compressed,
  286.                   main_time + snp_time);
  287. #endif
  288. }
  289. CReader::TConn CId1Reader::GetParallelLevel(void) const
  290. {
  291.     return m_Pool.size();
  292. }
  293. void CId1Reader::SetParallelLevel(TConn size)
  294. {
  295.     size_t oldSize = m_Pool.size();
  296.     for (size_t i = size; i < oldSize; ++i) {
  297.         delete m_Pool[i];
  298.         m_Pool[i] = 0;
  299.     }
  300.     m_Pool.resize(size);
  301.     for (size_t i = oldSize; i < min(1u, size); ++i) {
  302.         m_Pool[i] = x_NewConnection();
  303.     }
  304. }
  305. CConn_ServiceStream* CId1Reader::x_GetConnection(TConn conn)
  306. {
  307.     conn = conn % m_Pool.size();
  308.     CConn_ServiceStream* ret = m_Pool[conn];
  309.     if ( !ret ) {
  310.         ret = x_NewConnection();
  311.         if ( !ret ) {
  312.             NCBI_THROW(CLoaderException, eNoConnection,
  313.                        "too many connections failed: probably server is dead");
  314.         }
  315.         m_Pool[conn] = ret;
  316.     }
  317.     return ret;
  318. }
  319. void CId1Reader::Reconnect(TConn conn)
  320. {
  321.     _TRACE("Reconnect(" << conn << ")");
  322.     conn = conn % m_Pool.size();
  323.     delete m_Pool[conn];
  324.     m_Pool[conn] = 0;
  325. }
  326. CConn_ServiceStream* CId1Reader::x_NewConnection(void)
  327. {
  328.     for ( int i = 0; !m_NoMoreConnections && i < 3; ++i ) {
  329.         try {
  330.             _TRACE("CId1Reader(" << this << ")->x_NewConnection()");
  331.             string id1_svc;
  332.             {{
  333.                 CNcbiApplication* app = CNcbiApplication::Instance();
  334.                 static const char* env_var = "NCBI_SERVICE_NAME_ID1";
  335.                 if (app) { 
  336.                     id1_svc = app->GetEnvironment().Get(env_var);
  337.                 } else {
  338.                     char* s = ::getenv(env_var);
  339.                     if (s) {
  340.                         id1_svc = s;
  341.                     }
  342.                 }
  343.             }}
  344.             if ( id1_svc.empty() ) {
  345.                 id1_svc = "ID1";
  346.             }
  347.             STimeout tmout;
  348.             tmout.sec = 20;
  349.             tmout.usec = 0;
  350.             auto_ptr<CConn_ServiceStream> stream
  351.                 (new CConn_ServiceStream(id1_svc, fSERV_Any, 0, 0, &tmout));
  352.             if ( !stream->bad() ) {
  353.                 return stream.release();
  354.             }
  355.             ERR_POST("CId1Reader::x_NewConnection: cannot connect.");
  356.         }
  357.         catch ( CException& exc ) {
  358.             ERR_POST("CId1Reader::x_NewConnection: cannot connect: " <<
  359.                      exc.what());
  360.         }
  361.     }
  362.     m_NoMoreConnections = true;
  363.     return 0;
  364. }
  365. int CId1Reader::ResolveSeq_id_to_gi(const CSeq_id& seqId, TConn conn)
  366. {
  367.     CID1server_request id1_request;
  368.     id1_request.SetGetgi(const_cast<CSeq_id&>(seqId));
  369.     CID1server_back id1_reply;
  370.     x_ResolveId(id1_reply, id1_request, conn);
  371.     return id1_reply.IsGotgi()? id1_reply.GetGotgi(): 0;
  372. }
  373. typedef pair<const char*, CReader::ESatellite> TSatPair;
  374. static const TSatPair sc_SatArray[] = {
  375.     TSatPair("SNP",        CReader::eSatellite_SNP),
  376.     TSatPair("ti",         CReader::eSatellite_TRACE),
  377.     TSatPair("TR_ASSM_CH", CReader::eSatellite_TR_ASSM_CH),
  378.     TSatPair("TRACE_ASSM", CReader::eSatellite_TRACE_ASSM),
  379.     TSatPair("TRACE_CHGR", CReader::eSatellite_TRACE_CHGR)
  380. };
  381. typedef CStaticArrayMap<const char*, CReader::ESatellite, PNocase> TSatMap;
  382. static const TSatMap sc_SatMap(sc_SatArray, sizeof (sc_SatArray));
  383. void CId1Reader::ResolveSeq_id(TSeqrefs& srs, const CSeq_id& id, TConn conn)
  384. {
  385.     if ( id.IsGeneral()  &&  id.GetGeneral().GetTag().IsId() ) {
  386.         const CDbtag& dbtag = id.GetGeneral();
  387.         const CObject_id& objid = dbtag.GetTag();
  388.         int sat = 0;
  389.         int sat_key = objid.GetId();
  390.         if (sat_key != 0) {
  391.             TSatMap::const_iterator iter =
  392.                 sc_SatMap.find(dbtag.GetDb().c_str());
  393.             if (iter != sc_SatMap.end()) {
  394.                 sat = iter->second;
  395.             } else {
  396.                 try {
  397.                     sat = NStr::StringToInt(dbtag.GetDb());
  398.                 }
  399.                 catch (...) {
  400.                 }
  401.             }
  402.             if (sat != 0) {
  403.                 srs.push_back(Ref(new CSeqref(0, sat, sat_key)));
  404.                 return;
  405.             }
  406.         }
  407.     }
  408.     CReader::ResolveSeq_id(srs, id, conn);
  409. }
  410. void CId1Reader::RetrieveSeqrefs(TSeqrefs& srs, int gi, TConn conn)
  411. {
  412.     CID1server_request id1_request;
  413.     {{
  414.         CID1server_maxcomplex& blob = id1_request.SetGetblobinfo();
  415.         blob.SetMaxplex(eEntry_complexities_entry);
  416.         blob.SetGi(gi);
  417.     }}
  418.     
  419.     CID1server_back id1_reply;
  420.     x_ResolveId(id1_reply, id1_request, conn);
  421.     if ( !id1_reply.IsGotblobinfo() ) {
  422.         return;
  423.     }
  424.     const CID1blob_info& info = id1_reply.GetGotblobinfo();
  425.     if ( info.GetWithdrawn() > 0 || info.GetConfidential() > 0 ) {
  426.         LOG_POST(Warning<<"CId1Reader::RetrieveSeqrefs("<<gi<<"): "
  427.                  "gi is private");
  428.         return;
  429.     }
  430.     if ( info.GetSat() < 0 || info.GetSat_key() < 0 ) {
  431.         LOG_POST(Warning<<"CId1Reader::RetrieveSeqrefs("<<gi<<"): "
  432.                  "negative sat/satkey");
  433.         return;
  434.     }
  435.     CRef<CSeqref> ref(new CSeqref(gi, info.GetSat(), info.GetSat_key()));
  436.     ref->SetVersion(x_GetVersion(info));
  437.     srs.push_back(ref);
  438.    
  439.     if ( TrySNPSplit() ) {
  440.         if ( !info.IsSetExtfeatmask() ) {
  441.             AddSNPSeqref(srs, gi, CSeqref::fPossible);
  442.         }
  443.         else if ( info.GetExtfeatmask() & 1 ) {
  444.             AddSNPSeqref(srs, gi);
  445.         }
  446.     }
  447. }
  448. int CId1Reader::GetVersion(const CSeqref& seqref, TConn conn)
  449. {
  450.     if ( seqref.GetVersion() == 0 ) {
  451.         const_cast<CSeqref&>(seqref).SetVersion(x_GetVersion(seqref, conn));
  452.     }
  453.     return seqref.GetVersion();
  454. }
  455. int CId1Reader::x_GetVersion(const CSeqref& seqref, TConn conn)
  456. {
  457.     CID1server_request id1_request;
  458.     x_SetParams(seqref, id1_request.SetGetblobinfo(), IsSNPSeqref(seqref));
  459.     
  460.     CID1server_back    id1_reply;
  461.     x_ResolveId(id1_reply, id1_request, conn);
  462.     
  463.     if ( id1_reply.IsGotblobinfo() ) {
  464.         return x_GetVersion(id1_reply.GetGotblobinfo());
  465.     }
  466.     else {
  467.         return 1; // default non-zero version
  468.     }
  469. }
  470. void CId1Reader::x_ResolveId(CID1server_back& id1_reply,
  471.                              const CID1server_request& id1_request,
  472.                              TConn conn)
  473. {
  474. #ifdef ID1_COLLECT_STATS
  475.     CStopWatch sw;
  476.     if ( CollectStatistics() ) {
  477.         sw.Start();
  478.     }
  479. #endif
  480.     CConn_ServiceStream* stream = x_GetConnection(conn);
  481.     {{
  482.         CObjectOStreamAsnBinary out(*stream);
  483.         out << id1_request;
  484.         out.Flush();
  485.     }}
  486.     
  487.     {{
  488.         CObjectIStreamAsnBinary in(*stream);
  489.         in >> id1_reply;
  490.     }}
  491.     /*
  492.     if ( id1_reply.IsError() && id1_reply.GetError() == 0 ) {
  493.         char next_byte;
  494.         if ( CStreamUtils::Readsome(*stream, &next_byte, 1) ) {
  495.             CStreamUtils::Pushback(*stream, &next_byte, 1);
  496.             ERR_POST("Extra reply from ID1 server: ERROR 0");
  497.             CObjectIStreamAsnBinary in(*stream);
  498.             in >> id1_reply;
  499.         }
  500.     }
  501.     */
  502. #ifdef ID1_COLLECT_STATS
  503.     if ( CollectStatistics() ) {
  504.         double time = sw.Elapsed();
  505.         if ( id1_request.Which() == CID1server_request::e_Getgi ) {
  506.             LogStat("CId1Reader: resolved id", id1_request.GetGetgi(), time);
  507.             resolve_id_count++;
  508.             resolve_id_time += time;
  509.         }
  510.         else if ( id1_request.Which() == CID1server_request::e_Getblobinfo ) {
  511.             const CID1server_maxcomplex& req = id1_request.GetGetblobinfo();
  512.             if ( req.IsSetSat() ) {
  513.                 LogStat("CId1Reader: got blob version", req, time);
  514.                 resolve_ver_count++;
  515.                 resolve_ver_time += time;
  516.             }
  517.             else {
  518.                 LogStat("CId1Reader: resolved gi", req.GetGi(), time);
  519.                 resolve_gi_count++;
  520.                 resolve_gi_time += time;
  521.             }
  522.         }
  523.     }
  524. #endif
  525. }
  526. CRef<CTSE_Info> CId1Reader::GetTSEBlob(const CSeqref& seqref,
  527.                                        TConn conn)
  528. {
  529.     if ( seqref.GetFlags() & CSeqref::fPrivate ) {
  530.         NCBI_THROW(CLoaderException, ePrivateData, "gi is private");
  531.     }
  532.     CID1server_back id1_reply;
  533.     CRef<CID2S_Split_Info> split_info;
  534.     x_GetTSEBlob(id1_reply, split_info, seqref, conn);
  535.     CRef<CSeq_entry> seq_entry;
  536.     bool dead = false;
  537.     switch ( id1_reply.Which() ) {
  538.     case CID1server_back::e_Gotseqentry:
  539.         seq_entry.Reset(&id1_reply.SetGotseqentry());
  540.         break;
  541.     case CID1server_back::e_Gotdeadseqentry:
  542.         dead = true;
  543.         seq_entry.Reset(&id1_reply.SetGotdeadseqentry());
  544.         break;
  545.     case CID1server_back::e_Error:
  546.         switch ( id1_reply.GetError() ) {
  547.         case 1:
  548.             NCBI_THROW(CLoaderException, ePrivateData, "id is withdrawn");
  549.         case 2:
  550.             NCBI_THROW(CLoaderException, ePrivateData, "id is private");
  551.         case 10:
  552.             NCBI_THROW(CLoaderException, eNoData, "invalid args");
  553.         }
  554.         ERR_POST("CId1Reader::GetMainBlob: ID1server-back.error "<<
  555.                  id1_reply.GetError());
  556.         NCBI_THROW(CLoaderException, eLoaderFailed,
  557.                    "ID1server-back.error");
  558.         break;
  559.     default:
  560.         // no data
  561.         NCBI_THROW(CLoaderException, eLoaderFailed,
  562.                    "bad ID1server-back type");
  563.     }
  564.     CRef<CTSE_Info> ret(new CTSE_Info(*seq_entry, dead));
  565.     if ( split_info ) {
  566.         CSplitParser::Attach(*ret, *split_info);
  567.     }
  568.     return ret;
  569. }
  570. CRef<CSeq_annot_SNP_Info> CId1Reader::GetSNPAnnot(const CSeqref& seqref,
  571.                                                   TConn conn)
  572. {
  573.     CRef<CSeq_annot_SNP_Info> ret(new CSeq_annot_SNP_Info);
  574.     x_GetSNPAnnot(*ret, seqref, conn);
  575.     return ret;
  576. }
  577. void Id1ReaderSkipBytes(CByteSourceReader& reader, size_t to_skip)
  578. {
  579.     // skip 2 bytes of hacked header
  580.     const size_t kBufferSize = 128;
  581.     char buffer[kBufferSize];
  582.     while ( to_skip ) {
  583.         size_t cnt = reader.Read(buffer, min(to_skip, sizeof(buffer)));
  584.         if ( cnt == 0 ) {
  585.             NCBI_THROW(CEofException, eEof,
  586.                        "unexpected EOF while skipping ID1 SNP wrapper bytes");
  587.         }
  588.         to_skip -= cnt;
  589.     }
  590. }
  591. void CId1Reader::x_GetTSEBlob(CID1server_back& id1_reply,
  592.                               CRef<CID2S_Split_Info>& /*split_info*/,
  593.                               const CSeqref& seqref,
  594.                               TConn conn)
  595. {
  596. #ifdef ID1_COLLECT_STATS
  597.     CStopWatch sw;
  598.     if ( CollectStatistics() ) {
  599.         sw.Start();
  600.     }
  601.     
  602.     try {
  603. #endif
  604.         CConn_ServiceStream* stream = x_GetConnection(conn);
  605.         x_SendRequest(seqref, stream, false);
  606.         x_ReadTSEBlob(id1_reply, seqref, *stream);
  607.         
  608. #ifdef ID1_COLLECT_STATS
  609.         if ( CollectStatistics() ) {
  610.             double time = sw.Elapsed();
  611.             LogBlobStat("CId1Reader: read blob",
  612.                         seqref, last_object_bytes, time);
  613.             main_blob_count++;
  614.             main_bytes += last_object_bytes;
  615.             main_time += time;
  616.         }
  617.     }
  618.     catch ( ... ) {
  619.         if ( CollectStatistics() ) {
  620.             double time = sw.Elapsed();
  621.             LogBlobStat("CId1Reader: read fail blob",
  622.                         seqref, 0, time);
  623.             main_blob_count++;
  624.             main_time += time;
  625.         }
  626.         throw;
  627.     }
  628. #endif
  629. }
  630. void CId1Reader::x_GetSNPAnnot(CSeq_annot_SNP_Info& snp_info,
  631.                                const CSeqref& seqref,
  632.                                TConn conn)
  633. {
  634. #ifdef ID1_COLLECT_STATS
  635.     CStopWatch sw;
  636.     if ( CollectStatistics() ) {
  637.         sw.Start();
  638.     }
  639.     try {
  640. #endif
  641.         CConn_ServiceStream* stream = x_GetConnection(conn);
  642.         x_SendRequest(seqref, stream, true);
  643. #ifdef ID1_COLLECT_STATS
  644.         size_t compressed;
  645.         double decompression_time;
  646.         double total_read_time;
  647. #endif
  648.         {{
  649.             const size_t kSkipHeader = 2, kSkipFooter = 2;
  650.         
  651.             CStreamByteSourceReader src(0, stream);
  652.         
  653.             Id1ReaderSkipBytes(src, kSkipHeader);
  654.         
  655.             CNlmZipBtRdr src2(&src);
  656.         
  657.             x_ReadSNPAnnot(snp_info, seqref, src2);
  658. #ifdef ID1_COLLECT_STATS
  659.             compressed = src2.GetCompressedSize();
  660.             decompression_time = src2.GetDecompressionTime();
  661.             total_read_time = src2.GetTotalReadTime();
  662. #endif
  663.         
  664.             Id1ReaderSkipBytes(src, kSkipFooter);
  665.         }}
  666. #ifdef ID1_COLLECT_STATS
  667.         if ( CollectStatistics() ) {
  668.             double time = sw.Elapsed();
  669.             LogBlobStat("CId1Reader: read SNP blob",
  670.                         seqref, compressed, time);
  671.             snp_blob_count++;
  672.             snp_compressed += compressed;
  673.             snp_uncompressed += last_object_bytes;
  674.             snp_time += time;
  675.             snp_decompression_time += decompression_time;
  676.             snp_total_read_time += total_read_time;
  677.         }
  678.     }
  679.     catch ( ... ) {
  680.         if ( CollectStatistics() ) {
  681.             double time = sw.Elapsed();
  682.             LogBlobStat("CId1Reader: read fail SNP blob",
  683.                         seqref, 0, time);
  684.             snp_blob_count++;
  685.             snp_time += time;
  686.         }
  687.         throw;
  688.     }
  689. #endif
  690. }
  691. void CId1Reader::x_SetParams(const CSeqref& seqref,
  692.                              CID1server_maxcomplex& params,
  693.                              bool is_snp)
  694. {
  695.     bool is_external = is_snp;
  696.     bool skip_extfeat = !is_external && TrySNPSplit();
  697.     enum {
  698.         kNoExtFeat = 1<<4
  699.     };
  700.     EEntry_complexities maxplex = eEntry_complexities_entry;
  701.     if ( skip_extfeat ) {
  702.         maxplex = EEntry_complexities(int(maxplex) | kNoExtFeat);
  703.     }
  704.     params.SetMaxplex(maxplex);
  705.     params.SetGi(seqref.GetGi());
  706.     params.SetEnt(seqref.GetSatKey());
  707.     params.SetSat(NStr::IntToString(seqref.GetSat()));
  708. }
  709. int CId1Reader::x_GetVersion(const CID1blob_info& info) const
  710. {
  711.     int version = info.GetBlob_state();
  712.     if ( version < 0 ) {
  713.         version = -version;
  714.     }
  715.     if ( version == 0 ) {
  716.         // set to default: 1
  717.         // so that we will not reask version in future
  718.         version = 1;
  719.     }
  720.     return version;
  721. }
  722. void CId1Reader::x_SendRequest(const CSeqref& seqref,
  723.                                CConn_ServiceStream* stream,
  724.                                bool is_snp)
  725. {
  726.     CID1server_request id1_request;
  727.     x_SetParams(seqref, id1_request.SetGetsefromgi(), is_snp);
  728.     CObjectOStreamAsnBinary out(*stream);
  729.     out << id1_request;
  730.     out.Flush();
  731. }
  732. void CId1Reader::x_ReadTSEBlob(CID1server_back& id1_reply,
  733.                                const CSeqref& /*seqref*/,
  734.                                CNcbiIstream& stream)
  735. {
  736.     CObjectIStreamAsnBinary obj_stream(stream);
  737.     
  738.     x_ReadTSEBlob(id1_reply, obj_stream);
  739. }
  740. void CId1Reader::x_ReadTSEBlob(CID1server_back& id1_reply,
  741.                                CObjectIStream& stream)
  742. {
  743.     CReader::SetSeqEntryReadHooks(stream);
  744.     stream >> id1_reply;
  745. #ifdef ID1_COLLECT_STATS
  746.     last_object_bytes = stream.GetStreamOffset();
  747. #endif
  748. }
  749. void CId1Reader::x_ReadSNPAnnot(CSeq_annot_SNP_Info& snp_info,
  750.                                 const CSeqref& /*seqref*/,
  751.                                 CByteSourceReader& reader)
  752. {
  753.     CObjectIStreamAsnBinary in(reader);
  754.     CSeq_annot_SNP_Info_Reader::Parse(in, snp_info);
  755. #ifdef ID1_COLLECT_STATS
  756.     last_object_bytes = in.GetStreamOffset();
  757. #endif
  758. }
  759. END_SCOPE(objects)
  760. const string kId1ReaderDriverName("id1_reader");
  761. /// Class factory for ID1 reader
  762. ///
  763. /// @internal
  764. ///
  765. class CId1ReaderCF : 
  766.     public CSimpleClassFactoryImpl<objects::CReader, objects::CId1Reader>
  767. {
  768. public:
  769.     typedef 
  770.       CSimpleClassFactoryImpl<objects::CReader, objects::CId1Reader> TParent;
  771. public:
  772.     CId1ReaderCF() : TParent(kId1ReaderDriverName, 0)
  773.     {
  774.     }
  775.     ~CId1ReaderCF()
  776.     {
  777.     }
  778. };
  779. void NCBI_EntryPoint_Id1Reader(
  780.      CPluginManager<objects::CReader>::TDriverInfoList&   info_list,
  781.      CPluginManager<objects::CReader>::EEntryPointRequest method)
  782. {
  783.     CHostEntryPointImpl<CId1ReaderCF>::NCBI_EntryPointImpl(info_list, method);
  784. }
  785. END_NCBI_SCOPE
  786. /*
  787.  * $Log: reader_id1.cpp,v $
  788.  * Revision 1000.1  2004/06/01 19:41:56  gouriano
  789.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.81
  790.  *
  791.  * Revision 1.81  2004/05/21 21:42:52  gorelenk
  792.  * Added PCH ncbi_pch.hpp
  793.  *
  794.  * Revision 1.80  2004/03/16 17:49:18  vasilche
  795.  * Use enum constant for TRACE_CHGR entries
  796.  *
  797.  * Revision 1.79  2004/03/16 15:47:29  vasilche
  798.  * Added CBioseq_set_Handle and set of EditHandles
  799.  *
  800.  * Revision 1.78  2004/03/05 17:43:52  dicuccio
  801.  * Added support for satellite 31: TRACE_CHGR
  802.  *
  803.  * Revision 1.77  2004/03/03 22:59:47  ucko
  804.  * Gracefully handle CNcbiApplication::Instance returning NULL, as it
  805.  * *is* possible to use other frameworks.
  806.  *
  807.  * Revision 1.76  2004/02/19 19:24:09  vasilche
  808.  * Added conditional compilation of statistics collection code.
  809.  *
  810.  * Revision 1.75  2004/02/19 17:06:57  dicuccio
  811.  * Use sat, sat-key in seq-ref, not sat-key, sat
  812.  *
  813.  * Revision 1.74  2004/02/18 14:01:25  dicuccio
  814.  * Added new satellites for TRACE_ASSM, TR_ASSM_CH.  Added support for overloading
  815.  * the ID1 named service
  816.  *
  817.  * Revision 1.73  2004/02/04 17:47:41  kuznets
  818.  * Fixed naming of entry points
  819.  *
  820.  * Revision 1.72  2004/01/28 20:53:43  vasilche
  821.  * Added CSplitParser::Attach().
  822.  *
  823.  * Revision 1.71  2004/01/22 20:53:30  vasilche
  824.  * Fixed include path.
  825.  *
  826.  * Revision 1.70  2004/01/22 20:10:36  vasilche
  827.  * 1. Splitted ID2 specs to two parts.
  828.  * ID2 now specifies only protocol.
  829.  * Specification of ID2 split data is moved to seqsplit ASN module.
  830.  * For now they are still reside in one resulting library as before - libid2.
  831.  * As the result split specific headers are now in objects/seqsplit.
  832.  * 2. Moved ID2 and ID1 specific code out of object manager.
  833.  * Protocol is processed by corresponding readers.
  834.  * ID2 split parsing is processed by ncbi_xreader library - used by all readers.
  835.  * 3. Updated OBJMGR_LIBS correspondingly.
  836.  *
  837.  * Revision 1.69  2004/01/13 21:54:49  vasilche
  838.  * Requrrected new version
  839.  *
  840.  * Revision 1.5  2004/01/13 16:55:56  vasilche
  841.  * CReader, CSeqref and some more classes moved from xobjmgr to separate lib.
  842.  * Headers moved from include/objmgr to include/objtools/data_loaders/genbank.
  843.  *
  844.  * Revision 1.4  2003/12/30 22:14:42  vasilche
  845.  * Updated genbank loader and readers plugins.
  846.  *
  847.  * Revision 1.67  2003/12/30 16:00:24  vasilche
  848.  * Added support for new ICache (CBDB_Cache) interface.
  849.  *
  850.  * Revision 1.66  2003/12/19 19:47:44  vasilche
  851.  * Added support for TRACE data, Seq-id ::= general { db "ti", tag id NNN }.
  852.  *
  853.  * Revision 1.65  2003/12/03 14:30:02  kuznets
  854.  * Code clean up.
  855.  * Made use of driver name constant instead of immediate in-place string.
  856.  *
  857.  * Revision 1.64  2003/12/02 16:18:16  kuznets
  858.  * Added plugin manager support for CReader interface and implementaions
  859.  * (id1 reader, pubseq reader)
  860.  *
  861.  * Revision 1.63  2003/11/26 17:55:59  vasilche
  862.  * Implemented ID2 split in ID1 cache.
  863.  * Fixed loading of splitted annotations.
  864.  *
  865.  * Revision 1.62  2003/11/21 16:32:52  vasilche
  866.  * Cleaned code avoiding ERROR 0 packets.
  867.  *
  868.  * Revision 1.61  2003/11/19 15:43:03  vasilche
  869.  * Temporary fix for extra ERROR 0 packed from ID1 server.
  870.  *  CVS: ----------------------------------------------------------------------
  871.  *
  872.  * Revision 1.60  2003/11/07 16:59:01  vasilche
  873.  * Fixed stats message.
  874.  *
  875.  * Revision 1.59  2003/11/04 21:53:32  vasilche
  876.  * Check only SNP bit in extfeat field in ID1 response.
  877.  *
  878.  * Revision 1.58  2003/10/27 18:50:49  vasilche
  879.  * Detect 'private' blobs in ID1 reader.
  880.  * Avoid reconnecting after ID1 server replied with error packet.
  881.  *
  882.  * Revision 1.57  2003/10/27 15:05:41  vasilche
  883.  * Added correct recovery of cached ID1 loader if gi->sat/satkey cache is invalid.
  884.  * Added recognition of ID1 error codes: private, etc.
  885.  * Some formatting of old code.
  886.  *
  887.  * Revision 1.56  2003/10/24 13:27:40  vasilche
  888.  * Cached ID1 reader made more safe. Process errors and exceptions correctly.
  889.  * Cleaned statistics printing methods.
  890.  *
  891.  * Revision 1.55  2003/10/22 16:36:25  vasilche
  892.  * Fixed typo.
  893.  *
  894.  * Revision 1.54  2003/10/22 16:32:42  vasilche
  895.  * MSVC forces to use stream::bad() method.
  896.  *
  897.  * Revision 1.53  2003/10/22 16:12:38  vasilche
  898.  * Added CLoaderException::eNoConnection.
  899.  * Added check for 'fail' state of ID1 connection stream.
  900.  * CLoaderException::eNoConnection will be rethrown from CGBLoader.
  901.  *
  902.  * Revision 1.52  2003/10/21 16:32:50  vasilche
  903.  * Cleaned ID1 statistics messages.
  904.  * Now by setting GENBANK_ID1_STATS=1 CId1Reader collects and displays stats.
  905.  * And by setting GENBANK_ID1_STATS=2 CId1Reader logs all activities.
  906.  *
  907.  * Revision 1.51  2003/10/21 14:27:35  vasilche
  908.  * Added caching of gi -> sat,satkey,version resolution.
  909.  * SNP blobs are stored in cache in preprocessed format (platform dependent).
  910.  * Limit number of connections to GenBank servers.
  911.  * Added collection of ID1 loader statistics.
  912.  *
  913.  * Revision 1.50  2003/10/14 21:06:25  vasilche
  914.  * Fixed compression statistics.
  915.  * Disabled caching of SNP blobs.
  916.  *
  917.  * Revision 1.49  2003/10/14 18:59:55  vasilche
  918.  * Temporarily remove collection of compression statistics.
  919.  *
  920.  * Revision 1.48  2003/10/14 18:31:54  vasilche
  921.  * Added caching support for SNP blobs.
  922.  * Added statistics collection of ID1 connection.
  923.  *
  924.  * Revision 1.47  2003/10/08 14:16:13  vasilche
  925.  * Added version of blobs loaded from ID1.
  926.  *
  927.  * Revision 1.46  2003/10/01 18:08:14  kuznets
  928.  * s_SkipBytes renamed to Id1ReaderSkipBytes (made non static)
  929.  *
  930.  * Revision 1.45  2003/09/30 19:38:26  vasilche
  931.  * Added support for cached id1 reader.
  932.  *
  933.  * Revision 1.44  2003/09/30 16:22:02  vasilche
  934.  * Updated internal object manager classes to be able to load ID2 data.
  935.  * SNP blobs are loaded as ID2 split blobs - readers convert them automatically.
  936.  * Scope caches results of requests for data to data loaders.
  937.  * Optimized CSeq_id_Handle for gis.
  938.  * Optimized bioseq lookup in scope.
  939.  * Reduced object allocations in annotation iterators.
  940.  * CScope is allowed to be destroyed before other objects using this scope are
  941.  * deleted (feature iterators, bioseq handles etc).
  942.  * Optimized lookup for matching Seq-ids in CSeq_id_Mapper.
  943.  * Added 'adaptive' option to objmgr_demo application.
  944.  *
  945.  * Revision 1.43  2003/08/27 14:25:22  vasilche
  946.  * Simplified CCmpTSE class.
  947.  *
  948.  * Revision 1.42  2003/08/19 18:34:40  vasilche
  949.  * Fixed warning about enum conversion.
  950.  *
  951.  * Revision 1.41  2003/08/14 20:05:19  vasilche
  952.  * Simple SNP features are stored as table internally.
  953.  * They are recreated when needed using CFeat_CI.
  954.  *
  955.  * Revision 1.40  2003/07/24 19:28:09  vasilche
  956.  * Implemented SNP split for ID1 loader.
  957.  *
  958.  * Revision 1.39  2003/07/17 20:07:56  vasilche
  959.  * Reduced memory usage by feature indexes.
  960.  * SNP data is loaded separately through PUBSEQ_OS.
  961.  * String compression for SNP data.
  962.  *
  963.  * Revision 1.38  2003/06/02 16:06:38  dicuccio
  964.  * Rearranged src/objects/ subtree.  This includes the following shifts:
  965.  *     - src/objects/asn2asn --> arc/app/asn2asn
  966.  *     - src/objects/testmedline --> src/objects/ncbimime/test
  967.  *     - src/objects/objmgr --> src/objmgr
  968.  *     - src/objects/util --> src/objmgr/util
  969.  *     - src/objects/alnmgr --> src/objtools/alnmgr
  970.  *     - src/objects/flat --> src/objtools/flat
  971.  *     - src/objects/validator --> src/objtools/validator
  972.  *     - src/objects/cddalignview --> src/objtools/cddalignview
  973.  * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  974.  * replaces the three libmmdb? libs.
  975.  *
  976.  * Revision 1.37  2003/05/13 20:14:40  vasilche
  977.  * Catching exceptions and reconnection were moved from readers to genbank loader.
  978.  *
  979.  * Revision 1.36  2003/04/24 16:12:38  vasilche
  980.  * Object manager internal structures are splitted more straightforward.
  981.  * Removed excessive header dependencies.
  982.  *
  983.  * Revision 1.35  2003/04/15 15:30:15  vasilche
  984.  * Added include <memory> when needed.
  985.  * Removed buggy buffer in printing methods.
  986.  * Removed unnecessary include of stream_util.hpp.
  987.  *
  988.  * Revision 1.34  2003/04/15 14:24:08  vasilche
  989.  * Changed CReader interface to not to use fake streams.
  990.  *
  991.  * Revision 1.33  2003/04/07 16:56:57  vasilche
  992.  * Fixed unassigned member in ID1 request.
  993.  *
  994.  * Revision 1.32  2003/03/31 17:02:03  lavr
  995.  * Some code reformatting to [more closely] meet coding requirements
  996.  *
  997.  * Revision 1.31  2003/03/30 07:00:29  lavr
  998.  * MIPS-specific workaround for lame-designed stream read ops
  999.  *
  1000.  * Revision 1.30  2003/03/28 03:28:14  lavr
  1001.  * CId1Reader::xsgetn() added; code heavily reformatted
  1002.  *
  1003.  * Revision 1.29  2003/03/27 19:38:13  vasilche
  1004.  * Use safe NStr::IntToString() instead of sprintf().
  1005.  *
  1006.  * Revision 1.28  2003/03/03 20:34:51  vasilche
  1007.  * Added NCBI_THREADS macro - it's opposite to NCBI_NO_THREADS.
  1008.  * Avoid using _REENTRANT macro - use NCBI_THREADS instead.
  1009.  *
  1010.  * Revision 1.27  2003/03/01 22:26:56  kimelman
  1011.  * performance fixes
  1012.  *
  1013.  * Revision 1.26  2003/02/04 18:53:36  dicuccio
  1014.  * Include file clean-up
  1015.  *
  1016.  * Revision 1.25  2002/12/26 20:53:25  dicuccio
  1017.  * Minor tweaks to relieve compiler warnings in MSVC
  1018.  *
  1019.  * Revision 1.24  2002/12/26 16:39:24  vasilche
  1020.  * Object manager class CSeqMap rewritten.
  1021.  *
  1022.  * Revision 1.23  2002/11/18 19:48:43  grichenk
  1023.  * Removed "const" from datatool-generated setters
  1024.  *
  1025.  * Revision 1.22  2002/07/25 15:01:51  grichenk
  1026.  * Replaced non-const GetXXX() with SetXXX()
  1027.  *
  1028.  * Revision 1.21  2002/05/09 21:40:59  kimelman
  1029.  * MT tuning
  1030.  *
  1031.  * Revision 1.20  2002/05/06 03:28:47  vakatov
  1032.  * OM/OM1 renaming
  1033.  *
  1034.  * Revision 1.19  2002/05/03 21:28:10  ucko
  1035.  * Introduce T(Signed)SeqPos.
  1036.  *
  1037.  * Revision 1.18  2002/04/17 19:52:02  kimelman
  1038.  * fix: no gi found
  1039.  *
  1040.  * Revision 1.17  2002/04/09 16:10:56  ucko
  1041.  * Split CStrStreamBuf out into a common location.
  1042.  *
  1043.  * Revision 1.16  2002/04/08 20:52:26  butanaev
  1044.  * Added PUBSEQ reader.
  1045.  *
  1046.  * Revision 1.15  2002/03/29 02:47:05  kimelman
  1047.  * gbloader: MT scalability fixes
  1048.  *
  1049.  * Revision 1.14  2002/03/27 20:23:50  butanaev
  1050.  * Added connection pool.
  1051.  *
  1052.  * Revision 1.13  2002/03/26 23:31:08  gouriano
  1053.  * memory leaks and garbage collector fix
  1054.  *
  1055.  * Revision 1.12  2002/03/26 18:48:58  butanaev
  1056.  * Fixed bug not deleting streambuf.
  1057.  *
  1058.  * Revision 1.11  2002/03/26 17:17:02  kimelman
  1059.  * reader stream fixes
  1060.  *
  1061.  * Revision 1.10  2002/03/26 15:39:25  kimelman
  1062.  * GC fixes
  1063.  *
  1064.  * Revision 1.9  2002/03/25 18:12:48  grichenk
  1065.  * Fixed bool convertion
  1066.  *
  1067.  * Revision 1.8  2002/03/25 17:49:13  kimelman
  1068.  * ID1 failure handling
  1069.  *
  1070.  * Revision 1.7  2002/03/25 15:44:47  kimelman
  1071.  * proper logging and exception handling
  1072.  *
  1073.  * Revision 1.6  2002/03/22 21:50:21  kimelman
  1074.  * bugfix: avoid history rtequest for nonexistent sequence
  1075.  *
  1076.  * Revision 1.5  2002/03/21 19:14:54  kimelman
  1077.  * GB related bugfixes
  1078.  *
  1079.  * Revision 1.4  2002/03/21 01:34:55  kimelman
  1080.  * gbloader related bugfixes
  1081.  *
  1082.  * Revision 1.3  2002/03/20 04:50:13  kimelman
  1083.  * GB loader added
  1084.  *
  1085.  * Revision 1.2  2002/01/16 18:56:28  grichenk
  1086.  * Removed CRef<> argument from choice variant setter, updated sources to
  1087.  * use references instead of CRef<>s
  1088.  *
  1089.  * Revision 1.1  2002/01/11 19:06:22  gouriano
  1090.  * restructured objmgr
  1091.  *
  1092.  * Revision 1.7  2001/12/17 21:38:24  butanaev
  1093.  * Code cleanup.
  1094.  *
  1095.  * Revision 1.6  2001/12/13 00:19:25  kimelman
  1096.  * bugfixes:
  1097.  *
  1098.  * Revision 1.5  2001/12/12 21:46:40  kimelman
  1099.  * Compare interface fix
  1100.  *
  1101.  * Revision 1.4  2001/12/10 20:08:02  butanaev
  1102.  * Code cleanup.
  1103.  *
  1104.  * Revision 1.3  2001/12/07 21:24:59  butanaev
  1105.  * Interface development, code beautyfication.
  1106.  *
  1107.  * Revision 1.2  2001/12/07 16:43:58  butanaev
  1108.  * Fixed includes.
  1109.  *
  1110.  * Revision 1.1  2001/12/07 16:10:23  butanaev
  1111.  * Switching to new reader interfaces.
  1112.  *
  1113.  * Revision 1.3  2001/12/06 20:37:05  butanaev
  1114.  * Fixed timeout problem.
  1115.  *
  1116.  * Revision 1.2  2001/12/06 18:06:22  butanaev
  1117.  * Ported to linux.
  1118.  *
  1119.  * Revision 1.1  2001/12/06 14:35:23  butanaev
  1120.  * New streamable interfaces designed, ID1 reimplemented.
  1121.  *
  1122.  */