bdb_blobcache.cpp

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

CPP
1,387
字号
/* * =========================================================================== * PRODUCTION $Log: bdb_blobcache.cpp,v $ * PRODUCTION Revision 1000.5  2004/06/01 18:37:14  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.54 * PRODUCTION * =========================================================================== *//*  $Id: bdb_blobcache.cpp,v 1000.5 2004/06/01 18:37:14 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 BLOB cache implementation. * */#include <ncbi_pch.hpp>#include <corelib/ncbitime.hpp>#include <corelib/ncbifile.hpp>#include <corelib/ncbi_process.hpp>#include <corelib/plugin_manager_impl.hpp>#include <bdb/bdb_blobcache.hpp>#include <bdb/bdb_cursor.hpp>#include <bdb/bdb_trans.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbitime.hpp>BEGIN_NCBI_SCOPE// Mutex to sync cache requests coming from different threads// All requests are protected with one mutexDEFINE_STATIC_FAST_MUTEX(x_BDB_BLOB_CacheMutex);// Mutex to sync int cache requests coming from different threads// All requests are protected with one mutex/*DEFINE_STATIC_FAST_MUTEX(x_BDB_IntCacheMutex);*/static const unsigned int s_WriterBufferSize = 256 * 1024;/*static void s_MakeOverflowFileName(string& buf,                                   const string& path,                                    const string& blob_key,                                   int           version){    buf = path + blob_key + '_' + NStr::IntToString(version) + ".ov_";}*/		static void s_MakeOverflowFileName(string& buf,                                   const string& path,                                    const string& key,                                   int           version,                                   const string& subkey){    buf = path + key + '_'               + NStr::IntToString(version) + '_' + subkey + ".ov_";}struct SCacheDescr{    string    key;    int       version;    string    subkey;    int       overflow;    SCacheDescr(string x_key,                int    x_version,                string x_subkey,                int    x_overflow)    : key(x_key),      version(x_version),      subkey(x_subkey),      overflow(x_overflow)    {}    SCacheDescr() {}};class CBDB_CacheIReader : public IReader{public:    CBDB_CacheIReader(CBDB_BLobStream* blob_stream)    : m_BlobStream(blob_stream),      m_OverflowFile(0),      m_Buffer(0)    {}    CBDB_CacheIReader(CNcbiIfstream* overflow_file)    : m_BlobStream(0),      m_OverflowFile(overflow_file),      m_Buffer(0)    {}    CBDB_CacheIReader(unsigned char* buf, size_t buf_size)    : m_BlobStream(0),      m_OverflowFile(0),      m_Buffer(buf),      m_BufferPtr(buf),      m_BufferSize(buf_size)    {    }    virtual ~CBDB_CacheIReader()    {        delete m_BlobStream;        delete m_OverflowFile;        delete[] m_Buffer;    }    virtual ERW_Result Read(void*   buf,                             size_t  count,                            size_t* bytes_read)    {        if (count == 0)            return eRW_Success;        // Check if BLOB is memory based...        if (m_Buffer) {            if (m_BufferSize == 0) {                *bytes_read = 0;                return eRW_Eof;            }            *bytes_read = min(count, m_BufferSize);            ::memcpy(buf, m_BufferPtr, *bytes_read);            m_BufferPtr += *bytes_read;            m_BufferSize -= *bytes_read;            return eRW_Success;        }        // Check if BLOB is file based...        if (m_OverflowFile) {            CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);            m_OverflowFile->read((char*)buf, count);            *bytes_read = m_OverflowFile->gcount();            if (*bytes_read == 0) {                return eRW_Eof;            }            return eRW_Success;        }                // Reading from the BDB stream        size_t br;        {{        CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);        m_BlobStream->Read(buf, count, &br);        }}        if (bytes_read)            *bytes_read = br;                if (br == 0)             return eRW_Eof;        return eRW_Success;    }    virtual ERW_Result PendingCount(size_t* count)    {        if ( m_Buffer ) {            *count = m_BufferSize;            return eRW_Success;        }        else if ( m_OverflowFile ) {            *count = m_OverflowFile->good()? 1: 0;            return eRW_Success;        }        else if (m_BlobStream) {            *count = m_BlobStream->PendingCount();            return eRW_Success;        }        *count = 0;        return eRW_Error;    }private:    CBDB_CacheIReader(const CBDB_CacheIReader&);    CBDB_CacheIReader& operator=(const CBDB_CacheIReader&);private:    CBDB_BLobStream* m_BlobStream;    CNcbiIfstream*   m_OverflowFile;    unsigned char*   m_Buffer;    unsigned char*   m_BufferPtr;    size_t           m_BufferSize;};class CBDB_CacheIWriter : public IWriter{public:    CBDB_CacheIWriter(const char*         path,                      const string&       blob_key,                      int                 version,                      const string&       subkey,                      CBDB_BLobStream*    blob_stream,                      SCacheDB&           blob_db,                      SCache_AttrDB&      attr_db,                      int                 stamp_subkey)    : m_Path(path),      m_BlobKey(blob_key),      m_Version(version),      m_SubKey(subkey),      m_BlobStream(blob_stream),      m_BlobDB(blob_db),      m_AttrDB(attr_db),      m_Buffer(0),      m_BytesInBuffer(0),      m_OverflowFile(0),      m_StampSubKey(stamp_subkey)    {        m_Buffer = new unsigned char[s_WriterBufferSize];    }    virtual ~CBDB_CacheIWriter()    {        // Dumping the buffer        CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);        CBDB_Transaction trans(*m_AttrDB.GetEnv());        m_AttrDB.SetTransaction(&trans);        m_BlobDB.SetTransaction(&trans);        if (m_Buffer) {            _TRACE("LC: Dumping BDB BLOB size=" << m_BytesInBuffer);            m_BlobStream->SetTransaction(&trans);            m_BlobStream->Write(m_Buffer, m_BytesInBuffer);            m_BlobDB.Sync();            delete[] m_Buffer;        }        delete m_BlobStream;        m_AttrDB.key = m_BlobKey.c_str();        m_AttrDB.version = m_Version;        m_AttrDB.subkey = m_StampSubKey ? m_SubKey : "";        m_AttrDB.overflow = 0;        CTime time_stamp(CTime::eCurrent);        m_AttrDB.time_stamp = (unsigned)time_stamp.GetTimeT();        if (m_OverflowFile) {            m_AttrDB.overflow = 1;            delete m_OverflowFile;        }        m_AttrDB.UpdateInsert();        m_AttrDB.Sync();        trans.Commit();        m_AttrDB.GetEnv()->TransactionCheckpoint();    }    virtual ERW_Result Write(const void* buf, size_t count,                             size_t* bytes_written = 0)    {        *bytes_written = 0;        if (count == 0)            return eRW_Success;        CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);        unsigned int new_buf_length = m_BytesInBuffer + count;        if (m_Buffer) {            // Filling the buffer while we can            if (new_buf_length <= s_WriterBufferSize) {                ::memcpy(m_Buffer + m_BytesInBuffer, buf, count);                m_BytesInBuffer = new_buf_length;                *bytes_written = count;                return eRW_Success;            } else {                // Buffer overflow. Writing to file.                OpenOverflowFile();                if (m_OverflowFile) {                    if (m_BytesInBuffer) {                        m_OverflowFile->write((char*)m_Buffer,                                               m_BytesInBuffer);                    }                    delete[] m_Buffer;                    m_Buffer = 0;                    m_BytesInBuffer = 0;                }            }        }        if (m_OverflowFile) {            m_OverflowFile->write((char*)buf, count);            if ( m_OverflowFile->good() ) {                *bytes_written = count;                return eRW_Success;            }        }        return eRW_Error;    }    /// Flush pending data (if any) down to output device.    virtual ERW_Result Flush(void)    {        // Dumping the buffer        CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);        CBDB_Transaction trans(*m_AttrDB.GetEnv());        m_AttrDB.SetTransaction(&trans);        m_BlobDB.SetTransaction(&trans);        if (m_Buffer) {            _TRACE("LC: Dumping BDB BLOB size=" << m_BytesInBuffer);            m_BlobStream->SetTransaction(&trans);            m_BlobStream->Write(m_Buffer, m_BytesInBuffer);            delete[] m_Buffer;            m_Buffer = 0;            m_BytesInBuffer = 0;        }        m_BlobDB.Sync();        if ( m_OverflowFile ) {            m_OverflowFile->flush();            if ( m_OverflowFile->bad() ) {                return eRW_Error;            }        }        trans.Commit();        m_AttrDB.GetEnv()->TransactionCheckpoint();        return eRW_Success;    }private:    void OpenOverflowFile()    {        string path;        s_MakeOverflowFileName(path, m_Path, m_BlobKey, m_Version, m_SubKey);        _TRACE("LC: Making overflow file " << path);        m_OverflowFile =            new CNcbiOfstream(path.c_str(),                               IOS_BASE::out |                               IOS_BASE::trunc |                               IOS_BASE::binary);        if (!m_OverflowFile->is_open()) {            ERR_POST("LC Error:Cannot create overflow file " << path);            delete m_OverflowFile;            m_OverflowFile = 0;        }    }private:    CBDB_CacheIWriter(const CBDB_CacheIWriter&);    CBDB_CacheIWriter& operator=(const CBDB_CacheIWriter&);private:    const char*           m_Path;    string                m_BlobKey;    int                   m_Version;    string                m_SubKey;    CBDB_BLobStream*      m_BlobStream;    SCacheDB&             m_BlobDB;    SCache_AttrDB&        m_AttrDB;    unsigned char*        m_Buffer;    unsigned int          m_BytesInBuffer;    CNcbiOfstream*        m_OverflowFile;    int                   m_StampSubKey;};CBDB_Cache::CBDB_Cache(): m_PidGuard(0),  m_Env(0),  m_CacheDB(0),  m_CacheAttrDB(0),  m_VersionFlag(eDropOlder){    m_TimeStampFlag = fTimeStampOnRead |                       fExpireLeastFrequentlyUsed |                      fPurgeOnStartup;}CBDB_Cache::~CBDB_Cache(){    Close();}void CBDB_Cache::Open(const char* cache_path,                       const char* cache_name,                      ELockMode lm,                       unsigned int cache_ram_size){    {{        CFastMutexGuard guard(x_BDB_BLOB_CacheMutex);    Close();    m_Path = CDirEntry::AddTrailingPathSeparator(cache_path);    // Make sure our directory exists    {{        CDir dir(m_Path);        if ( !dir.Exists() ) {            dir.Create();        }    }}    string lock_file = string("lcs_") + string(cache_name) + string(".pid");    string lock_file_path = m_Path + lock_file;    switch (lm)    {    case ePidLock:        m_PidGuard = new CPIDGuard(lock_file_path, m_Path);        break;    case eNoLock:        break;    default:        break;    }    m_Env = new CBDB_Env();

⌨️ 快捷键说明

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