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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bdb_file.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:37:25  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.37
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: bdb_file.cpp,v 1000.2 2004/06/01 18:37:25 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: Anatoliy Kuznetsov
  35.  *
  36.  * File Description:  BDB libarary file implementations.
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <bdb/bdb_file.hpp>
  41. #include <bdb/bdb_env.hpp>
  42. #include <bdb/bdb_trans.hpp>
  43. #include <db.h>
  44. BEGIN_NCBI_SCOPE
  45. const char CBDB_RawFile::kDefaultDatabase[] = "_table";
  46. const int  CBDB_RawFile::kOpenFileMask      = 0664;
  47. // Auto-pointer style guard class for DB structure
  48. class CDB_guard
  49. {
  50. public:
  51. CDB_guard(DB** db) : m_DB(db) {}
  52. ~CDB_guard()
  53. if (m_DB  &&  *m_DB) {
  54.             (*m_DB)->close(*m_DB, 0);
  55.             *m_DB = 0;
  56.         }
  57. }
  58. void release() { m_DB = 0; }
  59. private:
  60. DB** m_DB;
  61. };
  62. /////////////////////////////////////////////////////////////////////////////
  63. //  CBDB_RawFile::
  64. //
  65. CBDB_RawFile::CBDB_RawFile(EDuplicateKeys dup_keys)
  66. : m_DB(0),
  67.   m_DBT_Key(0),
  68.   m_DBT_Data(0),
  69.   m_Env(0),
  70.   m_Trans(0),
  71.   m_DB_Attached(false),
  72.   m_ByteSwapped(false),
  73.   m_PageSize(0),
  74.   m_CacheSize(256 * 1024),
  75.   m_DuplicateKeys(dup_keys)
  76. {
  77.     try
  78.     {
  79.         m_DBT_Key = new DBT;
  80.         m_DBT_Data = new DBT;
  81.     }
  82.     catch (...)
  83.     {
  84.         delete m_DBT_Key;
  85.         delete m_DBT_Data;
  86.         throw;
  87.     }
  88.     ::memset(m_DBT_Key,  0, sizeof(DBT));
  89.     ::memset(m_DBT_Data, 0, sizeof(DBT));
  90. }
  91. CBDB_RawFile::~CBDB_RawFile()
  92. {
  93.     x_Close(eIgnoreError);
  94.     delete m_DBT_Key;
  95.     delete m_DBT_Data;
  96.     // It's illegal to close a file involved in active transactions
  97.     
  98.     if (m_Trans && (m_Trans->IsInProgress())) {
  99.         _ASSERT(0);
  100.         
  101.         // If we are here we can try to communicate by throwing
  102.         // an exception. It's illegal, but situation is bad enough already
  103.         
  104.         BDB_THROW(eTransInProgress, 
  105.                   "Cannot close the file while transaction is in progress.");
  106.     }
  107. }
  108. void CBDB_RawFile::Close()
  109. {
  110.     x_Close(eThrowOnError);
  111. }
  112. void CBDB_RawFile::Attach(CBDB_RawFile& bdb_file)
  113. {
  114.    Close();
  115.    m_DB = bdb_file.m_DB;
  116.    m_DB_Attached = true; 
  117. }
  118. void CBDB_RawFile::SetEnv(CBDB_Env& env)
  119. {
  120.     m_Env = &env;
  121. }
  122. DB_TXN* CBDB_RawFile::GetTxn()
  123. {
  124.     if (m_Trans)
  125.         return m_Trans->GetTxn();
  126.     return 0;
  127. }
  128. void CBDB_RawFile::x_Close(EIgnoreError close_mode)
  129. {
  130.     if ( m_FileName.empty() )
  131.         return;
  132.     if (m_DB_Attached) {
  133.         m_DB = 0;
  134.         m_DB_Attached = false;
  135.     }
  136.     else
  137.     if (m_DB) {
  138.         int ret = m_DB->close(m_DB, 0);
  139.         m_DB = 0;
  140.         if (close_mode == eThrowOnError) {
  141.             BDB_CHECK(ret, m_FileName.c_str());
  142.         }
  143.     }
  144.     m_FileName.erase();
  145.     m_Database.erase();
  146. }
  147. void CBDB_RawFile::Open(const char* filename,
  148.                         const char* database,
  149.                         EOpenMode   open_mode)
  150. {
  151.     if ( !m_FileName.empty() )
  152.         Close();
  153.     if (!database  ||  !*database)
  154.         database = 0; // database = kDefaultDatabase;
  155.     x_Open(filename, database, open_mode);
  156.     m_FileName = filename;
  157.     if (database)
  158.         m_Database = database;
  159.     else
  160.         m_Database = "";
  161. }
  162. void CBDB_RawFile::Reopen(EOpenMode open_mode)
  163. {
  164.     _ASSERT(!m_FileName.empty());
  165.     if (m_DB_Attached) {
  166.         BDB_THROW(eInvalidOperation, "Cannot reopen attached object");
  167.     }
  168.     int ret = m_DB->close(m_DB, 0);
  169.     m_DB = 0;
  170.     BDB_CHECK(ret, m_FileName.c_str());
  171.     x_Open(m_FileName.c_str(),
  172.            !m_Database.empty() ? m_Database.c_str() : 0,
  173.            open_mode);
  174. }
  175. void CBDB_RawFile::Remove(const char* filename, const char* database)
  176. {
  177.     if (!database  ||  !*database)
  178.         database = 0; // database = kDefaultDatabase;
  179.     if (m_DB_Attached) {
  180.         BDB_THROW(eInvalidOperation, "Cannot remove attached object");
  181.     }
  182.     // temporary DB is used here, because BDB remove call invalidates the
  183.     // DB argument redardless of the result.
  184.     DB* db = 0;
  185. CDB_guard guard(&db);
  186.     int ret = db_create(&db, m_Env ? m_Env->GetEnv() : 0, 0);
  187.     BDB_CHECK(ret, 0);
  188.     ret = db->remove(db, filename, database, 0);
  189.     guard.release();
  190.     if (ret == ENOENT || ret == EINVAL)
  191.         return;  // Non existent table cannot be removed
  192.     BDB_CHECK(ret, filename);
  193. }
  194. unsigned int CBDB_RawFile::Truncate()
  195. {
  196.     _ASSERT(m_DB != 0);
  197.     u_int32_t count;
  198.     DB_TXN* txn = GetTxn();
  199.     int ret = m_DB->truncate(m_DB,
  200.                              txn,
  201.                              &count,
  202.                              0);
  203.     BDB_CHECK(ret, FileName().c_str());
  204.     return count;
  205. }
  206. void CBDB_RawFile::SetCacheSize(unsigned int cache_size)
  207. {
  208.     if (m_DB) {
  209.         int ret = m_DB->set_cachesize(m_DB, 0, m_CacheSize, 1);
  210.         BDB_CHECK(ret, 0);
  211.     }
  212.     m_CacheSize = cache_size;
  213. }
  214. void CBDB_RawFile::SetTransaction(CBDB_Transaction* trans)
  215. {
  216.     if (m_Trans) {
  217.         m_Trans->RemoveFile(this);
  218.     }
  219.     m_Trans = trans;
  220.     if (m_Trans) {
  221.         m_Trans->AddFile(this);
  222.     }
  223. }
  224. void CBDB_RawFile::x_RemoveTransaction(CBDB_Transaction* trans)
  225. {
  226.     if (trans == m_Trans) {
  227.         m_Trans = 0;
  228.     }
  229. }
  230. void CBDB_RawFile::x_CreateDB()
  231. {
  232.     _ASSERT(m_DB == 0);
  233.     _ASSERT(!m_DB_Attached);
  234. CDB_guard guard(&m_DB);
  235.     int ret = db_create(&m_DB, m_Env ? m_Env->GetEnv() : 0, 0);
  236.     BDB_CHECK(ret, 0);
  237.     SetCmp(m_DB);
  238.     if ( m_PageSize ) {
  239.         ret = m_DB->set_pagesize(m_DB, m_PageSize);
  240.         BDB_CHECK(ret, 0);
  241.     }
  242.     if (!m_Env) {
  243.         ret = m_DB->set_cachesize(m_DB, 0, m_CacheSize, 1);
  244.         BDB_CHECK(ret, 0);
  245.     }
  246.     if (DuplicatesAllowed()) {
  247.         ret = m_DB->set_flags(m_DB, DB_DUP);
  248.         BDB_CHECK(ret, 0);
  249.     }
  250.     guard.release();
  251. }
  252. void CBDB_RawFile::x_Open(const char* filename,
  253.                           const char* database,
  254.                           EOpenMode   open_mode)
  255. {   
  256.     int ret;    
  257.     if (m_DB == 0) {
  258.         x_CreateDB();
  259.     }
  260.     if (open_mode == eCreate) {
  261.         Remove(filename, database);
  262.         x_Create(filename, database);
  263.     }
  264.     else {
  265.         u_int32_t open_flags;
  266.         switch (open_mode)
  267.         {
  268.         case eReadOnly:
  269.             open_flags = DB_RDONLY;
  270.             break;
  271.         case eCreate:
  272.             open_flags = DB_CREATE;
  273.             break;
  274.         default:
  275.             open_flags = 0;
  276.             break;
  277.         }
  278.         DB_TXN* txn = 0; // GetTxn();
  279.         if (m_Env) {
  280.             if (m_Env->IsTransactional()) {
  281.                 open_flags |= DB_THREAD | DB_AUTO_COMMIT;
  282.             }
  283.         }
  284.         ret = m_DB->open(m_DB,
  285.                          txn,
  286.                          filename,
  287.                          database,             // database name
  288.                          DB_BTREE,
  289.                          open_flags,
  290.                          kOpenFileMask
  291.                         );
  292.         if ( ret ) {
  293.             if (open_mode == eCreate || 
  294.                 open_mode == eReadWriteCreate)
  295.             {
  296.                 x_Create(filename, database);
  297.             }
  298.             else {
  299.                 m_DB->close(m_DB, 0);
  300.                 m_DB = 0;
  301.                 BDB_CHECK(ret, filename);
  302.             }
  303.         }
  304.     } // else open_mode == Create
  305.     m_OpenMode = open_mode;
  306.     int isswapped;
  307.     ret = m_DB->get_byteswapped(m_DB, &isswapped);
  308.     BDB_CHECK(ret, filename);
  309.     m_ByteSwapped = (isswapped!=0);
  310. }
  311. void CBDB_RawFile::SetPageSize(unsigned int page_size)
  312. {
  313.     _ASSERT(m_DB == 0); // we can set page size only before opening the file
  314.     if (((page_size - 1) & page_size) != 0) {
  315.         BDB_THROW(eInvalidValue, "Page size must be power of 2");
  316.     }
  317.     m_PageSize = page_size;
  318. }
  319. void CBDB_RawFile::Sync()
  320. {
  321.     int ret = m_DB->sync(m_DB, 0);
  322.     BDB_CHECK(ret, FileName().c_str());
  323. }
  324. unsigned CBDB_RawFile::CountRecs()
  325. {
  326.     DB_BTREE_STAT* stp;
  327.     int ret = m_DB->stat(m_DB, &stp, 0);
  328.     BDB_CHECK(ret, FileName().c_str());
  329.     u_int32_t rc = stp->bt_ndata;
  330.     return rc;
  331. }
  332. void CBDB_RawFile::x_Create(const char* filename, const char* database)
  333. {
  334.     _ASSERT(!m_DB_Attached);
  335.     u_int32_t open_flags = DB_CREATE;
  336.     DB_TXN* txn = 0; //GetTxn();
  337.     if (m_Env) {
  338.         if (m_Env->IsTransactional()) {
  339.             open_flags |= DB_THREAD | DB_AUTO_COMMIT;
  340.         }
  341.     }
  342.     int ret = m_DB->open(m_DB,
  343.                          txn,
  344.                          filename,
  345.                          database,        // database name
  346.                          DB_BTREE,
  347.                          open_flags,
  348.                          kOpenFileMask);
  349.     if ( ret ) {
  350.         m_DB->close(m_DB, 0);
  351.         m_DB = 0;
  352.         BDB_CHECK(ret, filename);
  353.     }
  354. }
  355. DBC* CBDB_RawFile::CreateCursor(CBDB_Transaction* trans) const
  356. {
  357.     DBC* cursor;
  358.     if (!m_DB) {
  359.         BDB_THROW(eInvalidValue, "Cannot create cursor for unopen file.");
  360.     }
  361.     DB_TXN* txn = 0; // GetTxn();
  362.     if (trans) {
  363.         txn = trans->GetTxn();
  364.     }
  365.     int ret = m_DB->cursor(m_DB,
  366.                            txn,
  367.                            &cursor,
  368.                            0);
  369.     BDB_CHECK(ret, FileName().c_str());
  370.     return cursor;
  371. }
  372. /////////////////////////////////////////////////////////////////////////////
  373. //
  374. //  CBDB_File::
  375. //
  376. CBDB_File::CBDB_File(EDuplicateKeys dup_keys)
  377.     : CBDB_RawFile(dup_keys),
  378.       m_KeyBuf(new CBDB_BufferManager),
  379.       m_BufsAttached(false),
  380.       m_BufsCreated(false),
  381.       m_DataBufDisabled(false),
  382.       m_LegacyString(false)
  383. {
  384. }
  385. void CBDB_File::BindKey(const char* field_name,
  386.                         CBDB_Field* key_field,
  387.                         size_t      buf_size)
  388. {
  389.     _ASSERT(!IsOpen());
  390.     _ASSERT(m_KeyBuf.get());
  391.     _ASSERT(key_field);
  392.     key_field->SetName(field_name);
  393.     m_KeyBuf->Bind(key_field);
  394.     if ( buf_size )
  395.         key_field->SetBufferSize(buf_size);
  396. }
  397. void CBDB_File::BindData(const char* field_name,
  398.                          CBDB_Field* data_field,
  399.                          size_t      buf_size,
  400.                          ENullable   is_nullable)
  401. {
  402.     _ASSERT(!IsOpen());
  403.     _ASSERT(data_field);
  404.     data_field->SetName(field_name);
  405.     if (m_DataBuf.get() == 0) {  // data buffer is not yet created 
  406.         auto_ptr<CBDB_BufferManager> dbuf(new CBDB_BufferManager);
  407.         m_DataBuf = dbuf;
  408.         m_DataBuf->SetNullable();
  409.         m_DataBuf->SetLegacyStringsCheck(m_LegacyString);
  410.     }
  411.     m_DataBuf->Bind(data_field);
  412.     if ( buf_size )
  413.         data_field->SetBufferSize(buf_size);
  414.     if (is_nullable == eNullable)
  415.         data_field->SetNullable();
  416. }
  417. void CBDB_File::Open(const char* filename,
  418.                      const char* database,
  419.                      EOpenMode   open_mode)
  420. {
  421.     if ( IsOpen() )
  422.         Close();
  423.     CBDB_RawFile::Open(filename, database, open_mode);
  424.     x_CheckConstructBuffers();
  425.     m_DB->app_private = (void*) m_KeyBuf.get();
  426. }
  427. void CBDB_File::Reopen(EOpenMode open_mode)
  428. {
  429.     CBDB_RawFile::Reopen(open_mode);
  430.     m_DB->app_private = (void*) m_KeyBuf.get();
  431.     if ( m_DataBuf.get() ) {
  432.         m_DataBuf->SetAllNull();
  433.     }
  434.     bool byte_swapped = IsByteSwapped();
  435.     m_KeyBuf->SetByteSwapped(byte_swapped);
  436.     if (m_DataBuf.get()) {
  437.         m_DataBuf->SetByteSwapped(byte_swapped);
  438.     }
  439. }
  440. void CBDB_File::Attach(CBDB_File& db_file)
  441. {
  442.     CBDB_RawFile::Attach(db_file);
  443.     x_CheckConstructBuffers();
  444.     SetLegacyStringsCheck(db_file.m_LegacyString);
  445. }
  446. void CBDB_File::SetLegacyStringsCheck(bool value) 
  447.     m_LegacyString = value; 
  448.     if (m_KeyBuf.get()) {
  449.         m_KeyBuf->SetLegacyStringsCheck(value);
  450.     }
  451.     if (m_DataBuf.get()) {
  452.         m_DataBuf->SetLegacyStringsCheck(value);
  453.     }
  454. }
  455. EBDB_ErrCode CBDB_File::x_Fetch(unsigned int flags)
  456. {
  457.     x_StartRead();
  458.     DB_TXN* txn = GetTxn();
  459.     int ret = m_DB->get(m_DB,
  460.                         txn,
  461.                         m_DBT_Key,
  462.                         m_DBT_Data,
  463.                         flags);
  464.                         
  465.     if (ret == DB_NOTFOUND)
  466.         return eBDB_NotFound;
  467.     // Disable error reporting for custom m_DBT_data management
  468.     if (ret == ENOMEM && m_DataBufDisabled && m_DBT_Data->data == 0)
  469.         ret = 0;
  470.     BDB_CHECK(ret, FileName().c_str());
  471.     x_EndRead();
  472.     return eBDB_Ok;
  473. }
  474. EBDB_ErrCode CBDB_File::FetchForUpdate()
  475. {
  476.     return x_Fetch(DB_RMW);
  477. }
  478. DBT* CBDB_File::CloneDBT_Key()
  479. {
  480.     x_StartRead();
  481.     x_EndRead();
  482.     DBT* dbt = new DBT;
  483.     ::memset(dbt,  0, sizeof(DBT));
  484.     // Clone the "data" area (needs to be properly deleted!)
  485.     if (m_DBT_Key->size) {
  486.         dbt->size = m_DBT_Key->size;
  487.         unsigned char* p = (unsigned char*)malloc(dbt->size);
  488.         ::memcpy(p, m_DBT_Key->data, m_DBT_Key->size);
  489.         dbt->data = p;
  490.     }
  491.     return dbt;
  492. }
  493. void CBDB_File::DestroyDBT_Clone(DBT* dbt)
  494. {
  495.     unsigned char* p = (unsigned char*)dbt->data;
  496.     free(p);
  497.     delete dbt;
  498. }
  499. EBDB_ErrCode CBDB_File::Insert(EAfterWrite write_flag)
  500. {
  501.     CheckNullDataConstraint();
  502.     unsigned int flags;
  503.     if (DuplicatesAllowed()) {
  504.         flags = 0;
  505.     } else {
  506.         flags = /*DB_NODUPDATA |*/ DB_NOOVERWRITE;
  507.     }
  508.     return x_Write(flags, write_flag);
  509. }
  510. EBDB_ErrCode CBDB_File::UpdateInsert(EAfterWrite write_flag)
  511. {
  512.     CheckNullDataConstraint();
  513.     return x_Write(0, write_flag);
  514. }
  515. EBDB_ErrCode CBDB_File::Delete(EIgnoreError on_error)
  516. {
  517.     m_KeyBuf->PrepareDBT_ForWrite(m_DBT_Key);
  518.     DB_TXN* txn = GetTxn();
  519.     int ret = m_DB->del(m_DB,
  520.                         txn,
  521.                         m_DBT_Key,
  522.                         0);
  523.     if (on_error != eIgnoreError) {
  524.         BDB_CHECK(ret, FileName().c_str());
  525.     }
  526.     Discard();
  527.     return eBDB_Ok;
  528. }
  529. void CBDB_File::Discard()
  530. {
  531.     m_KeyBuf->ArrangePtrsUnpacked();
  532.     if ( m_DataBuf.get() ) {
  533.         m_DataBuf->ArrangePtrsUnpacked();
  534.         m_DataBuf->SetAllNull();
  535.     }
  536. }
  537. void CBDB_File::SetCmp(DB* db)
  538. {
  539.     BDB_CompareFunction func = m_KeyBuf->GetCompareFunction();
  540.     _ASSERT(func);
  541.     int ret = db->set_bt_compare(db, func);
  542.     BDB_CHECK(ret, 0);
  543. }
  544. CBDB_File::TUnifiedFieldIndex 
  545. CBDB_File::GetFieldIdx(const string& name) const
  546. {
  547.     int fidx = 0;
  548.     if (m_KeyBuf.get()) {
  549.         fidx = m_KeyBuf->GetFieldIndex(name);
  550.         if (fidx >= 0) {    //  field name found
  551.             return BDB_GetUFieldIdx(fidx, true /*key*/);
  552.         }
  553.     }
  554.     if (m_DataBuf.get()) {
  555.         fidx = m_DataBuf->GetFieldIndex(name);
  556.         if (fidx >= 0) {    //  field name found
  557.             return BDB_GetUFieldIdx(fidx, false /*non-key*/);
  558.         }
  559.     }
  560.     return 0;
  561. }
  562. const CBDB_Field& CBDB_File::GetField(TUnifiedFieldIndex idx) const
  563. {
  564.     _ASSERT(idx != 0);
  565.     const CBDB_BufferManager* buffer;
  566.     if (idx < 0) { // key buffer
  567.         idx = -idx;
  568.         --idx;
  569.         buffer = m_KeyBuf.get();
  570.     } else {  // data buffer
  571.         --idx;
  572.         buffer = m_DataBuf.get();
  573.     }
  574.     _ASSERT(buffer);
  575.     const CBDB_Field& fld = buffer->GetField(idx);
  576.     return fld;
  577. }
  578. CBDB_Field& CBDB_File::GetField(TUnifiedFieldIndex idx)
  579. {
  580.     _ASSERT(idx != 0);
  581.     CBDB_BufferManager* buffer;
  582.     if (idx < 0) {     // key buffer
  583.         idx = -idx;
  584.         --idx;
  585.         buffer = m_KeyBuf.get();
  586.     } else {          // data buffer
  587.         --idx;
  588.         buffer = m_DataBuf.get();
  589.     }
  590.     _ASSERT(buffer);
  591.     CBDB_Field& fld = buffer->GetField(idx);
  592.     return fld;
  593. }
  594. EBDB_ErrCode CBDB_File::ReadCursor(DBC* dbc, unsigned int bdb_flag)
  595. {
  596.     x_StartRead();
  597.     if (m_DataBufDisabled) {
  598.         m_DBT_Data->size  = 0;
  599.         m_DBT_Data->flags = 0;
  600.         m_DBT_Data->data  = 0;        
  601.     }
  602.     int ret = dbc->c_get(dbc,
  603.                          m_DBT_Key,
  604.                          m_DBT_Data,
  605.                          bdb_flag);
  606.     if (ret == DB_NOTFOUND)
  607.         return eBDB_NotFound;
  608.     BDB_CHECK(ret, FileName().c_str());
  609.     x_EndRead();
  610.     return eBDB_Ok;
  611. }
  612. EBDB_ErrCode CBDB_File::WriteCursor(DBC* dbc, unsigned int bdb_flag, 
  613.                                     EAfterWrite write_flag)
  614. {
  615.     CheckNullDataConstraint();
  616.     return x_Write(bdb_flag, write_flag, dbc);
  617. }
  618. EBDB_ErrCode CBDB_File::DeleteCursor(DBC* dbc, EIgnoreError on_error)
  619. {
  620.     int ret = dbc->c_del(dbc,0);
  621.     if (on_error != CBDB_File::eIgnoreError) {
  622.         BDB_CHECK(ret, FileName().c_str());
  623.     }
  624.     return eBDB_Ok;
  625. }
  626. void CBDB_File::x_CheckConstructBuffers()
  627. {
  628.     if (!m_BufsAttached  &&  !m_BufsCreated) {
  629.         m_KeyBuf->Construct();
  630.         if ( m_DataBuf.get() ) {
  631. m_DataBuf->Construct();
  632.             m_DataBuf->SetAllNull();
  633. }
  634.         m_BufsCreated = 1;
  635.     }
  636. }
  637. void CBDB_File::x_StartRead()
  638. {
  639.     m_KeyBuf->Pack();
  640.     m_KeyBuf->PrepareDBT_ForRead(m_DBT_Key);
  641.     if (!m_DataBufDisabled) {
  642.         if ( m_DataBuf.get() ) {
  643.             m_DataBuf->PrepareDBT_ForRead(m_DBT_Data);
  644.         }
  645.         else {
  646.             m_DBT_Data->size  = 0;
  647.             m_DBT_Data->flags = 0;
  648.             m_DBT_Data->data  = 0;
  649.         }
  650.     }
  651. }
  652. void CBDB_File::x_EndRead()
  653. {
  654.     m_KeyBuf->SetDBT_Size(m_DBT_Key->size);
  655.     m_KeyBuf->ArrangePtrsPacked();
  656.     if ( m_DataBuf.get() ) {
  657.         m_DataBuf->SetDBT_Size(m_DBT_Data->size);
  658.         m_DataBuf->ArrangePtrsPacked();
  659.     }
  660. }
  661. EBDB_ErrCode CBDB_File::x_Write(unsigned int flags, 
  662.                                 EAfterWrite write_flag, 
  663.                                 DBC * dbc)
  664. {
  665.     m_KeyBuf->PrepareDBT_ForWrite(m_DBT_Key);
  666.     if (!m_DataBufDisabled) {
  667.         if ( m_DataBuf.get() ) {
  668.             m_DataBuf->PrepareDBT_ForWrite(m_DBT_Data);
  669.         }
  670.     }
  671.     int ret=0;
  672.     if(dbc) {
  673.         ret = dbc->c_put(dbc,
  674.                          m_DBT_Key,
  675.                          m_DBT_Data,
  676.                          flags
  677.             );
  678.         
  679.     } else {
  680.         DB_TXN* txn = GetTxn();
  681.     
  682.         ret = m_DB->put(m_DB,
  683.                         txn,
  684.                         m_DBT_Key,
  685.                         m_DBT_Data,
  686.                         flags
  687.             );
  688.     }
  689.     
  690.     if (ret == DB_KEYEXIST)
  691.         return eBDB_KeyDup;
  692.     BDB_CHECK(ret, FileName().c_str());
  693.     if (write_flag == eDiscardData) {
  694.         Discard();
  695.     }
  696.     return eBDB_Ok;
  697. }
  698. /////////////////////////////////////////////////////////////////////////////
  699. //
  700. //  CBDB_IdFile::
  701. //
  702. CBDB_IdFile::CBDB_IdFile() 
  703. : CBDB_File()
  704. {
  705.     BindKey("id", &IdKey);
  706. }
  707. void CBDB_IdFile::SetCmp(DB* db)
  708. {
  709.     int ret = db->set_bt_compare(db, BDB_IntCompare);
  710.     BDB_CHECK(ret, 0);
  711. }
  712. END_NCBI_SCOPE
  713. /*
  714.  * ===========================================================================
  715.  * $Log: bdb_file.cpp,v $
  716.  * Revision 1000.2  2004/06/01 18:37:25  gouriano
  717.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.37
  718.  *
  719.  * Revision 1.37  2004/05/17 20:55:11  gorelenk
  720.  * Added include of PCH ncbi_pch.hpp
  721.  *
  722.  * Revision 1.36  2004/05/06 18:18:14  rotmistr
  723.  * Cursor Update/Delete implemented
  724.  *
  725.  * Revision 1.35  2004/03/12 15:08:36  kuznets
  726.  * Removed unnecessary DB_NODUPDATA flag (db->put)
  727.  *
  728.  * Revision 1.34  2004/03/08 13:32:43  kuznets
  729.  * Code clean-up
  730.  *
  731.  * Revision 1.33  2004/02/13 15:01:02  kuznets
  732.  * + methods working with TUnifiedFieldIndex
  733.  *
  734.  * Revision 1.32  2004/02/11 17:56:20  kuznets
  735.  * Assign legacy strings checking flag when attaching to a file
  736.  *
  737.  * Revision 1.31  2003/12/29 13:23:53  kuznets
  738.  * Added support for transaction protected cursors.
  739.  *
  740.  * Revision 1.30  2003/12/22 18:57:02  kuznets
  741.  * Minor implementation changes: DBT size passed to underlying buffer
  742.  * manager in order to better detect c-strings.
  743.  *
  744.  * Revision 1.29  2003/12/16 13:43:35  kuznets
  745.  * + CBDB_RawFile::x_RemoveTransaction
  746.  *
  747.  * Revision 1.28  2003/12/12 19:12:21  kuznets
  748.  * Fixed bug in transactional file opening
  749.  *
  750.  * Revision 1.27  2003/12/12 14:09:12  kuznets
  751.  * Changed file opening code to work correct in transactional environment.
  752.  *
  753.  * Revision 1.26  2003/12/10 19:14:08  kuznets
  754.  * Added support of berkeley db transactions
  755.  *
  756.  * Revision 1.25  2003/10/15 18:11:00  kuznets
  757.  * Several functions(Close, Delete) received optional parameter to ignore
  758.  * errors (if any).
  759.  *
  760.  * Revision 1.24  2003/09/17 18:18:21  kuznets
  761.  * Fixed some memory allocation bug in key cloning.
  762.  *
  763.  * Revision 1.23  2003/09/16 20:17:40  kuznets
  764.  * CBDB_File: added methods to clone (and then destroy) DBT Key.
  765.  *
  766.  * Revision 1.22  2003/09/12 18:06:13  kuznets
  767.  * Commenented out usage of the default sub-database name when no name is supplied.
  768.  * When "database" argument is NULL BerkeleyDB create files of a slightly less-complex
  769.  * structure which should have positive effect on performance and may cure some
  770.  * problems.
  771.  *
  772.  * Revision 1.21  2003/09/11 16:34:35  kuznets
  773.  * Implemented byte-order independence.
  774.  *
  775.  * Revision 1.20  2003/08/27 20:02:57  kuznets
  776.  * Added DB_ENV support
  777.  *
  778.  * Revision 1.19  2003/07/23 20:21:43  kuznets
  779.  * Implemented new improved scheme for setting BerkeleyDB comparison function.
  780.  * When table has non-segmented key the simplest(and fastest) possible function
  781.  * is assigned (automatically without reloading CBDB_File::SetCmp function).
  782.  *
  783.  * Revision 1.18  2003/07/23 18:08:48  kuznets
  784.  * SetCacheSize function implemented
  785.  *
  786.  * Revision 1.17  2003/07/22 19:21:19  kuznets
  787.  * Implemented support of attachable berkeley db files
  788.  *
  789.  * Revision 1.16  2003/07/22 15:15:02  kuznets
  790.  * + RawFile::CountRecs() function
  791.  *
  792.  * Revision 1.15  2003/07/21 18:33:28  kuznets
  793.  * Fixed bug with duplicate key tables
  794.  *
  795.  * Revision 1.14  2003/07/18 20:11:32  kuznets
  796.  * Implemented ReadWrite or Create open mode.
  797.  *
  798.  * Revision 1.13  2003/07/16 13:33:33  kuznets
  799.  * Added error condition if cursor is created on unopen file.
  800.  *
  801.  * Revision 1.12  2003/07/09 14:29:24  kuznets
  802.  * Added support of files with duplicate access keys. (DB_DUP mode)
  803.  *
  804.  * Revision 1.11  2003/07/02 17:55:35  kuznets
  805.  * Implementation modifications to eliminated direct dependency from <db.h>
  806.  *
  807.  * Revision 1.10  2003/06/25 16:35:56  kuznets
  808.  * Bug fix: data file gets created even if eCreate flag was not specified.
  809.  *
  810.  * Revision 1.9  2003/06/10 20:08:27  kuznets
  811.  * Fixed function names.
  812.  *
  813.  * Revision 1.8  2003/05/27 18:43:45  kuznets
  814.  * Fixed some compilation problems with GCC 2.95
  815.  *
  816.  * Revision 1.7  2003/05/09 13:44:57  kuznets
  817.  * Fixed a bug in cursors based on BLOB storage
  818.  *
  819.  * Revision 1.6  2003/05/05 20:15:32  kuznets
  820.  * Added CBDB_BLobFile
  821.  *
  822.  * Revision 1.5  2003/05/02 14:11:59  kuznets
  823.  * + UpdateInsert method
  824.  *
  825.  * Revision 1.4  2003/04/30 20:25:42  kuznets
  826.  * Bug fix
  827.  *
  828.  * Revision 1.3  2003/04/29 19:07:22  kuznets
  829.  * Cosmetics..
  830.  *
  831.  * Revision 1.2  2003/04/28 14:51:55  kuznets
  832.  * #include directives changed to conform the NCBI policy
  833.  *
  834.  * Revision 1.1  2003/04/24 16:34:30  kuznets
  835.  * Initial revision
  836.  *
  837.  * ===========================================================================
  838.  */