bdb_file.cpp

来自「ncbi源码」· C++ 代码 · 共 1,015 行 · 第 1/2 页

CPP
1,015
字号
/* * =========================================================================== * PRODUCTION $Log: bdb_file.cpp,v $ * PRODUCTION Revision 1000.2  2004/06/01 18:37:25  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.37 * PRODUCTION * =========================================================================== *//*  $Id: bdb_file.cpp,v 1000.2 2004/06/01 18:37:25 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anatoliy Kuznetsov * * File Description:  BDB libarary file implementations. * */#include <ncbi_pch.hpp>#include <bdb/bdb_file.hpp>#include <bdb/bdb_env.hpp>#include <bdb/bdb_trans.hpp>#include <db.h>BEGIN_NCBI_SCOPEconst char CBDB_RawFile::kDefaultDatabase[] = "_table";const int  CBDB_RawFile::kOpenFileMask      = 0664;// Auto-pointer style guard class for DB structureclass CDB_guard{public:	CDB_guard(DB** db) : m_DB(db) {}	~CDB_guard()	{ 		if (m_DB  &&  *m_DB) {            (*m_DB)->close(*m_DB, 0);            *m_DB = 0;        }	}	void release() { m_DB = 0; }private:	DB** m_DB;};///////////////////////////////////////////////////////////////////////////////  CBDB_RawFile:://CBDB_RawFile::CBDB_RawFile(EDuplicateKeys dup_keys): m_DB(0),  m_DBT_Key(0),  m_DBT_Data(0),  m_Env(0),  m_Trans(0),  m_DB_Attached(false),  m_ByteSwapped(false),  m_PageSize(0),  m_CacheSize(256 * 1024),  m_DuplicateKeys(dup_keys){    try    {        m_DBT_Key = new DBT;        m_DBT_Data = new DBT;    }    catch (...)    {        delete m_DBT_Key;        delete m_DBT_Data;        throw;    }    ::memset(m_DBT_Key,  0, sizeof(DBT));    ::memset(m_DBT_Data, 0, sizeof(DBT));}CBDB_RawFile::~CBDB_RawFile(){    x_Close(eIgnoreError);    delete m_DBT_Key;    delete m_DBT_Data;    // It's illegal to close a file involved in active transactions        if (m_Trans && (m_Trans->IsInProgress())) {        _ASSERT(0);                // If we are here we can try to communicate by throwing        // an exception. It's illegal, but situation is bad enough already                BDB_THROW(eTransInProgress,                   "Cannot close the file while transaction is in progress.");    }}void CBDB_RawFile::Close(){    x_Close(eThrowOnError);}void CBDB_RawFile::Attach(CBDB_RawFile& bdb_file){   Close();   m_DB = bdb_file.m_DB;   m_DB_Attached = true; }void CBDB_RawFile::SetEnv(CBDB_Env& env){    m_Env = &env;}DB_TXN* CBDB_RawFile::GetTxn(){    if (m_Trans)        return m_Trans->GetTxn();    return 0;}void CBDB_RawFile::x_Close(EIgnoreError close_mode){    if ( m_FileName.empty() )        return;    if (m_DB_Attached) {        m_DB = 0;        m_DB_Attached = false;    }    else    if (m_DB) {        int ret = m_DB->close(m_DB, 0);        m_DB = 0;        if (close_mode == eThrowOnError) {            BDB_CHECK(ret, m_FileName.c_str());        }    }    m_FileName.erase();    m_Database.erase();}void CBDB_RawFile::Open(const char* filename,                        const char* database,                        EOpenMode   open_mode){    if ( !m_FileName.empty() )        Close();    if (!database  ||  !*database)        database = 0; // database = kDefaultDatabase;    x_Open(filename, database, open_mode);    m_FileName = filename;    if (database)        m_Database = database;    else        m_Database = "";}void CBDB_RawFile::Reopen(EOpenMode open_mode){    _ASSERT(!m_FileName.empty());    if (m_DB_Attached) {        BDB_THROW(eInvalidOperation, "Cannot reopen attached object");    }    int ret = m_DB->close(m_DB, 0);    m_DB = 0;    BDB_CHECK(ret, m_FileName.c_str());    x_Open(m_FileName.c_str(),           !m_Database.empty() ? m_Database.c_str() : 0,           open_mode);}void CBDB_RawFile::Remove(const char* filename, const char* database){    if (!database  ||  !*database)        database = 0; // database = kDefaultDatabase;    if (m_DB_Attached) {        BDB_THROW(eInvalidOperation, "Cannot remove attached object");    }    // temporary DB is used here, because BDB remove call invalidates the    // DB argument redardless of the result.    DB* db = 0;	CDB_guard guard(&db);    int ret = db_create(&db, m_Env ? m_Env->GetEnv() : 0, 0);    BDB_CHECK(ret, 0);    ret = db->remove(db, filename, database, 0);    guard.release();    if (ret == ENOENT || ret == EINVAL)        return;  // Non existent table cannot be removed    BDB_CHECK(ret, filename);}unsigned int CBDB_RawFile::Truncate(){    _ASSERT(m_DB != 0);    u_int32_t count;    DB_TXN* txn = GetTxn();    int ret = m_DB->truncate(m_DB,                             txn,                             &count,                             0);    BDB_CHECK(ret, FileName().c_str());    return count;}void CBDB_RawFile::SetCacheSize(unsigned int cache_size){    if (m_DB) {        int ret = m_DB->set_cachesize(m_DB, 0, m_CacheSize, 1);        BDB_CHECK(ret, 0);    }    m_CacheSize = cache_size;}void CBDB_RawFile::SetTransaction(CBDB_Transaction* trans){    if (m_Trans) {        m_Trans->RemoveFile(this);    }    m_Trans = trans;    if (m_Trans) {        m_Trans->AddFile(this);    }}void CBDB_RawFile::x_RemoveTransaction(CBDB_Transaction* trans){    if (trans == m_Trans) {        m_Trans = 0;    }}void CBDB_RawFile::x_CreateDB(){    _ASSERT(m_DB == 0);    _ASSERT(!m_DB_Attached);	CDB_guard guard(&m_DB);    int ret = db_create(&m_DB, m_Env ? m_Env->GetEnv() : 0, 0);    BDB_CHECK(ret, 0);    SetCmp(m_DB);    if ( m_PageSize ) {        ret = m_DB->set_pagesize(m_DB, m_PageSize);        BDB_CHECK(ret, 0);    }    if (!m_Env) {        ret = m_DB->set_cachesize(m_DB, 0, m_CacheSize, 1);        BDB_CHECK(ret, 0);    }    if (DuplicatesAllowed()) {        ret = m_DB->set_flags(m_DB, DB_DUP);        BDB_CHECK(ret, 0);    }    guard.release();}void CBDB_RawFile::x_Open(const char* filename,                          const char* database,                          EOpenMode   open_mode){       int ret;        if (m_DB == 0) {        x_CreateDB();    }    if (open_mode == eCreate) {        Remove(filename, database);        x_Create(filename, database);    }    else {        u_int32_t open_flags;        switch (open_mode)        {        case eReadOnly:            open_flags = DB_RDONLY;            break;        case eCreate:            open_flags = DB_CREATE;            break;        default:            open_flags = 0;            break;        }        DB_TXN* txn = 0; // GetTxn();        if (m_Env) {            if (m_Env->IsTransactional()) {                open_flags |= DB_THREAD | DB_AUTO_COMMIT;            }        }        ret = m_DB->open(m_DB,                         txn,                         filename,                         database,             // database name                         DB_BTREE,                         open_flags,                         kOpenFileMask                        );        if ( ret ) {            if (open_mode == eCreate ||                 open_mode == eReadWriteCreate)            {                x_Create(filename, database);            }            else {                m_DB->close(m_DB, 0);                m_DB = 0;                BDB_CHECK(ret, filename);            }        }    } // else open_mode == Create    m_OpenMode = open_mode;    int isswapped;    ret = m_DB->get_byteswapped(m_DB, &isswapped);    BDB_CHECK(ret, filename);    m_ByteSwapped = (isswapped!=0);}void CBDB_RawFile::SetPageSize(unsigned int page_size){    _ASSERT(m_DB == 0); // we can set page size only before opening the file    if (((page_size - 1) & page_size) != 0) {        BDB_THROW(eInvalidValue, "Page size must be power of 2");    }    m_PageSize = page_size;}void CBDB_RawFile::Sync(){    int ret = m_DB->sync(m_DB, 0);    BDB_CHECK(ret, FileName().c_str());}unsigned CBDB_RawFile::CountRecs(){    DB_BTREE_STAT* stp;    int ret = m_DB->stat(m_DB, &stp, 0);    BDB_CHECK(ret, FileName().c_str());    u_int32_t rc = stp->bt_ndata;    return rc;}void CBDB_RawFile::x_Create(const char* filename, const char* database){    _ASSERT(!m_DB_Attached);    u_int32_t open_flags = DB_CREATE;    DB_TXN* txn = 0; //GetTxn();    if (m_Env) {        if (m_Env->IsTransactional()) {            open_flags |= DB_THREAD | DB_AUTO_COMMIT;        }    }    int ret = m_DB->open(m_DB,                         txn,                         filename,                         database,        // database name                         DB_BTREE,                         open_flags,                         kOpenFileMask);    if ( ret ) {        m_DB->close(m_DB, 0);        m_DB = 0;        BDB_CHECK(ret, filename);    }}DBC* CBDB_RawFile::CreateCursor(CBDB_Transaction* trans) const{    DBC* cursor;    if (!m_DB) {        BDB_THROW(eInvalidValue, "Cannot create cursor for unopen file.");    }    DB_TXN* txn = 0; // GetTxn();    if (trans) {        txn = trans->GetTxn();    }    int ret = m_DB->cursor(m_DB,                           txn,                           &cursor,                           0);    BDB_CHECK(ret, FileName().c_str());    return cursor;}/////////////////////////////////////////////////////////////////////////////////  CBDB_File:://CBDB_File::CBDB_File(EDuplicateKeys dup_keys)    : CBDB_RawFile(dup_keys),      m_KeyBuf(new CBDB_BufferManager),      m_BufsAttached(false),      m_BufsCreated(false),      m_DataBufDisabled(false),      m_LegacyString(false){}void CBDB_File::BindKey(const char* field_name,                        CBDB_Field* key_field,                        size_t      buf_size){    _ASSERT(!IsOpen());    _ASSERT(m_KeyBuf.get());    _ASSERT(key_field);    key_field->SetName(field_name);    m_KeyBuf->Bind(key_field);    if ( buf_size )        key_field->SetBufferSize(buf_size);}void CBDB_File::BindData(const char* field_name,                         CBDB_Field* data_field,                         size_t      buf_size,                         ENullable   is_nullable){    _ASSERT(!IsOpen());    _ASSERT(data_field);    data_field->SetName(field_name);    if (m_DataBuf.get() == 0) {  // data buffer is not yet created         auto_ptr<CBDB_BufferManager> dbuf(new CBDB_BufferManager);        m_DataBuf = dbuf;        m_DataBuf->SetNullable();        m_DataBuf->SetLegacyStringsCheck(m_LegacyString);    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?