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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seqdboidlist.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:46:51  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seqdboidlist.cpp,v 1000.1 2004/06/01 19:46:51 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Kevin Bealer
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include <corelib/ncbistr.hpp>
  39. #include "seqdboidlist.hpp"
  40. #include "seqdbfile.hpp"
  41. BEGIN_NCBI_SCOPE
  42. CSeqDBOIDList::CSeqDBOIDList(CSeqDBVolSet & volset, bool use_mmap)
  43.     : m_NumOIDs (0),
  44.       m_Bits    (0),
  45.       m_BitEnd  (0)
  46. {
  47.     _ASSERT( volset.HasMask() );
  48.     
  49.     if (volset.HasSimpleMask()) {
  50.         x_Setup( volset.GetSimpleMask(), use_mmap );
  51.     } else {
  52.         x_Setup( volset, use_mmap );
  53.     }
  54. }
  55. CSeqDBOIDList::~CSeqDBOIDList()
  56. {
  57. }
  58. void CSeqDBOIDList::x_Setup(const string  & filename,
  59.                             bool            use_mmap)
  60. {
  61.     m_RawFile.Reset( new CSeqDBRawFile(m_MemPool, use_mmap) );
  62.     
  63.     m_RawFile->Open(filename);
  64.     m_RawFile->ReadSwapped(& m_NumOIDs);
  65.     
  66.     Uint4 file_length = (Uint4) m_RawFile->GetFileLength();
  67.     
  68.     m_Bits   = (unsigned char*) m_RawFile->GetRegion(sizeof(Int4), file_length);
  69.     m_BitEnd = m_Bits + file_length - sizeof(Int4);
  70. }
  71. // The general rule I am following in these methods is to use byte
  72. // computations except during actual looping.
  73. void CSeqDBOIDList::x_Setup(CSeqDBVolSet & volset, bool use_mmap)
  74. {
  75.     _ASSERT(volset.HasMask() && (! volset.HasSimpleMask()));
  76.     
  77.     // First, get the memory space, clear it.
  78.     
  79.     // Pad memory space to word boundary.
  80.     
  81.     Uint4 num_oids = volset.GetNumSeqs();
  82.     Uint4 byte_length = ((num_oids + 31) / 32) * 4;
  83.     
  84.     m_Bits   = (TUC*) m_MemPool.Alloc(byte_length);
  85.     m_BitEnd = m_Bits + byte_length;
  86.     
  87.     memset((void*) m_Bits, 0, byte_length);
  88.     
  89.     // Then get the list of filenames and offsets to overlay onto it.
  90.     
  91.     for(Uint4 i = 0; i < volset.GetNumVols(); i++) {
  92.         bool         all_oids (false);
  93.         list<string> mask_files;
  94.         Uint4        oid_start(0);
  95.         Uint4        oid_end  (0);
  96.         
  97.         volset.GetMaskFiles(i, all_oids, mask_files, oid_start, oid_end);
  98.         
  99.         if (all_oids) {
  100.             x_SetBitRange(oid_start, oid_end);
  101.         } else {
  102.             // For each file, copy bits into array.
  103.             
  104.             for(list<string>::iterator mask_iter = mask_files.begin();
  105.                 mask_iter != mask_files.end();
  106.                 ++mask_iter) {
  107.                 
  108.                 x_OrFileBits(*mask_iter, oid_start, oid_end, use_mmap);
  109.             }
  110.         }
  111.     }
  112.     
  113.     m_NumOIDs = num_oids;
  114.     
  115.     while(m_NumOIDs && (! x_IsSet(m_NumOIDs - 1))) {
  116.         -- m_NumOIDs;
  117.     }
  118.     
  119.     if (seqdb_debug_class & debug_oid) {
  120.         cout << "x_Setup: Dumping OID map data." << endl;
  121.     
  122.         unsigned cnt = 0;
  123.     
  124.         cout << hex;
  125.     
  126.         for(TCUC * bp = m_Bits; bp < m_BitEnd; bp ++) {
  127.             unsigned int ubp = (unsigned int)(*bp);
  128.         
  129.             if (ubp >= 16) {
  130.                 cout << ubp << " ";
  131.             } else {
  132.                 cout << "0" << ubp << " ";
  133.             }
  134.         
  135.             cnt++;
  136.         
  137.             if (cnt == 32) {
  138.                 cout << "n";
  139.                 cnt = 0;
  140.             }
  141.         }
  142.     
  143.         cout << dec << "n" << endl;
  144.     }
  145. }
  146. // oid_end is not used - it could be.  One use would be to trim the
  147. // "incoming bits" to that length; specifically, to assume that the
  148. // file may contain nonzero "junk data" after the official end point.
  149. //
  150. // This implies that two oid sets share the oid mask file, but one
  151. // used a smaller subset of that file.  That really should never
  152. // happen; it would be so unlikely for that optimization to "buy
  153. // anything" that the code would almost certainly never be written
  154. // that way.  For this reason, I have not yet implemented trimming.
  155. void CSeqDBOIDList::x_OrFileBits(const string & mask_fname,
  156.                                  Uint4          oid_start,
  157.                                  Uint4          /*oid_end*/,
  158.                                  bool           use_mmap)
  159. {
  160.     // Open file and get pointers
  161.     
  162.     TCUC* bitmap = 0;
  163.     TCUC* bitend = 0;
  164.     
  165.     CSeqDBMemPool mempool;
  166.     CSeqDBRawFile volmask(mempool, use_mmap);
  167.     
  168.     {
  169.         Uint4 num_oids = 0;
  170.         
  171.         volmask.Open(mask_fname);
  172.         volmask.ReadSwapped(& num_oids);
  173.         
  174.         Uint4 file_length = (Uint4) volmask.GetFileLength();
  175.         
  176.         // Cast forces signed/unsigned conversion.
  177.         
  178.         bitmap = (TCUC*) volmask.GetRegion(sizeof(Int4), file_length);
  179.         //bitend = bitmap + file_length - sizeof(Int4);
  180.         bitend = bitmap + (((num_oids + 31) / 32) * 4);
  181.     }
  182.     
  183.     // Fold bitmap/bitend into m_Bits/m_BitEnd at bit offset oid_start.
  184.     
  185.     
  186.     if (0 == (oid_start & 31)) {
  187.         // If the new data is "word aligned", we can use a fast algorithm.
  188.         
  189.         TCUC * srcp = bitmap;
  190.         TUC  * locp = m_Bits + (oid_start / 8);
  191.         TUC  * endp = locp + (bitend-bitmap);
  192.         
  193.         _ASSERT(endp <= m_BitEnd);
  194.         
  195.         Uint4 * wsrcp = (Uint4*) srcp;
  196.         Uint4 * wlocp = (Uint4*) locp;
  197.         Uint4 * wendp = wlocp + ((bitend - bitmap) / 4);
  198.         
  199.         while(wlocp < wendp) {
  200.             *wlocp++ |= *wsrcp++;
  201.         }
  202.         
  203.         srcp = (TCUC*) wsrcp;
  204.         locp = (unsigned char*) wlocp;
  205.         
  206.         while(locp < endp) {
  207.             *locp++ |= *(srcp++);
  208.         }
  209.     } else if (0 == (oid_start & 7)) {
  210.         // If the new data is "byte aligned", we can use a less fast algorithm.
  211.         
  212.         TCUC * srcp = bitmap;
  213.         TUC  * locp = m_Bits + (oid_start / 8);
  214.         TUC  * endp = locp + (bitend-bitmap);
  215.         
  216.         _ASSERT(endp <= m_BitEnd);
  217.         
  218.         while(locp < endp) {
  219.             *locp++ |= *srcp++;
  220.         }
  221.     } else {
  222.         // Otherwise... we have to use a slower, byte splicing algorithm.
  223.         
  224.         Uint4 Rshift = oid_start & 7;
  225.         Uint4 Lshift = 8 - Rshift;
  226.         
  227.         TCUC * srcp = bitmap;
  228.         TUC  * locp = m_Bits + (oid_start / 8);
  229.         TUC  * endp = locp + (bitend-bitmap);
  230.         
  231.         _ASSERT(endp <= m_BitEnd);
  232.         
  233.         TCUC * endp2 = endp - 1;
  234.         
  235.         // This loop iterates over the source bytes.  Each byte is
  236.         // split over two destination bytes.
  237.         
  238.         while(locp < endp2) {
  239.             // Store left half of source char in one location.
  240.             TCUC source = *srcp;
  241.             *locp |= (source >> Rshift);
  242.             locp++;
  243.             
  244.             // Store right half of source in the next location.
  245.             *locp |= (source << Lshift);
  246.             srcp++;
  247.         }
  248.     }
  249. }
  250. void CSeqDBOIDList::x_SetBitRange(Uint4          oid_start,
  251.                                   Uint4          oid_end)
  252. {
  253.     // Set bits at the front and back, closing to a range of full-byte
  254.     // addresses.
  255.     
  256.     while((oid_start & 0x7) && (oid_start < oid_end)) {
  257.         x_SetBit(oid_start);
  258.         ++oid_start;
  259.     }
  260.     
  261.     while((oid_end & 0x7) && (oid_start < oid_end)) {
  262.         x_SetBit(oid_end - 1);
  263.         --oid_end;
  264.     }
  265.     
  266.     if (oid_start < oid_end) {
  267.         TUC * bp_start = m_Bits + (oid_start >> 3);
  268.         TUC * bp_end   = m_Bits + (oid_end   >> 3);
  269.         
  270.         _ASSERT(bp_end   <= m_BitEnd);
  271.         _ASSERT(bp_start <  bp_end);
  272.         
  273.         memset(bp_start, 0xFF, (bp_end - bp_start));
  274.     }
  275. }
  276. void CSeqDBOIDList::x_SetBit(TOID oid)
  277. {
  278.     TUC * bp = m_Bits + (oid >> 3);
  279.     
  280.     Int4 bitnum = (oid & 7);
  281.     
  282.     if (bp < m_BitEnd) {
  283.         *bp |= (0x80 >> bitnum);
  284.     }
  285. }
  286. bool CSeqDBOIDList::x_IsSet(TOID oid) const
  287. {
  288.     TCUC * bp = m_Bits + (oid >> 3);
  289.     
  290.     Int4 bitnum = (oid & 7);
  291.     
  292.     if (bp < m_BitEnd) {
  293.         if (*bp & (0x80 >> bitnum)) {
  294.             return true;
  295.         }
  296.     }
  297.     
  298.     return false;
  299. }
  300. bool CSeqDBOIDList::x_FindNext(TOID & oid) const
  301. {
  302.     // If the specified OID is valid, use it.
  303.     
  304.     if (x_IsSet(oid)) {
  305.         return true;
  306.     }
  307.     
  308.     // OPTIONAL portion
  309.     
  310.     Uint4 whole_word_oids = m_NumOIDs & -32;
  311.     
  312.     while(oid < whole_word_oids) {
  313.         if (x_IsSet(oid)) {
  314.             return true;
  315.         }
  316.         
  317.         oid ++;
  318.         
  319.         if ((oid & 31) == 0) {
  320.             const Uint4 * bp = ((const Uint4*) m_Bits + (oid             >> 5));
  321.             const Uint4 * ep = ((const Uint4*) m_Bits + (whole_word_oids >> 5));
  322.             
  323.             while((bp < ep) && (0 == *bp)) {
  324.                 ++ bp;
  325.                 oid += 32;
  326.             }
  327.         }
  328.     }
  329.     
  330.     // END of OPTIONAL portion
  331.     
  332.     while(oid < m_NumOIDs) {
  333.         if (x_IsSet(oid)) {
  334.             return true;
  335.         }
  336.         
  337.         oid++;
  338.     }
  339.     
  340.     return false;
  341. }
  342. END_NCBI_SCOPE