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 + -
显示快捷键?