Line data Source code
1 : // Copyright (c) 2012-2014 The Bitcoin developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include "dbwrapper.h" 6 : 7 : #include <leveldb/cache.h> 8 : #include <leveldb/env.h> 9 : #include <leveldb/filter_policy.h> 10 : #include <memenv.h> 11 : #include <stdint.h> 12 : 13 : 14 2781 : static void SetMaxOpenFiles(leveldb::Options *options) { 15 : // On most platforms the default setting of max_open_files (which is 1000) 16 : // is optimal. On Windows using a large file count is OK because the handles 17 : // do not interfere with select() loops. On 64-bit Unix hosts this value is 18 : // also OK, because up to that amount LevelDB will use an mmap 19 : // implementation that does not use extra file descriptors (the fds are 20 : // closed after being mapped). 21 : // 22 : // Increasing the value beyond the default is dangerous because LevelDB will 23 : // fall back to a non-mmap implementation when the file count is too large. 24 : // On 32-bit Unix host we should decrease the value because the handles use 25 : // up real fds, and we want to avoid fd exhaustion issues. 26 : // 27 : // See PR #12495 for further discussion. 28 : 29 2781 : int default_open_files = options->max_open_files; 30 : #ifndef WIN32 31 2781 : if (sizeof(void*) < 8) { 32 : options->max_open_files = 64; 33 : } 34 : #endif 35 2781 : LogPrint(BCLog::LEVELDB, "LevelDB using max_open_files=%d (default=%d)\n", 36 : options->max_open_files, default_open_files); 37 2781 : } 38 : 39 2781 : static leveldb::Options GetOptions(size_t nCacheSize) 40 : { 41 2781 : leveldb::Options options; 42 2781 : options.block_cache = leveldb::NewLRUCache(nCacheSize / 2); 43 2781 : options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously 44 2781 : options.filter_policy = leveldb::NewBloomFilterPolicy(10); 45 2781 : options.compression = leveldb::kNoCompression; 46 2781 : if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) { 47 : // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error 48 : // on corruption in later versions. 49 2781 : options.paranoid_checks = true; 50 : } 51 2781 : SetMaxOpenFiles(&options); 52 2781 : return options; 53 : } 54 : 55 2781 : CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, int nVersion) 56 : { 57 2781 : penv = nullptr; 58 2781 : readoptions.verify_checksums = true; 59 2781 : iteroptions.verify_checksums = true; 60 2781 : iteroptions.fill_cache = false; 61 2781 : syncoptions.sync = true; 62 2781 : options = GetOptions(nCacheSize); 63 2781 : options.create_if_missing = true; 64 2781 : this->nVersion = nVersion; 65 2781 : if (fMemory) { 66 1010 : penv = leveldb::NewMemEnv(leveldb::Env::Default()); 67 1010 : options.env = penv; 68 : } else { 69 1771 : if (fWipe) { 70 23 : LogPrintf("Wiping LevelDB in %s\n", path.string()); 71 46 : leveldb::Status result = leveldb::DestroyDB(path.string(), options); 72 23 : dbwrapper_private::HandleError(result); 73 : } 74 1771 : TryCreateDirectories(path); 75 1771 : LogPrintf("Opening LevelDB in %s\n", path.string()); 76 : } 77 2781 : leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); 78 2781 : dbwrapper_private::HandleError(status); 79 2781 : LogPrintf("Opened LevelDB successfully\n"); 80 2781 : } 81 : 82 5562 : CDBWrapper::~CDBWrapper() 83 : { 84 2781 : delete pdb; 85 2781 : pdb = nullptr; 86 2781 : delete options.filter_policy; 87 2781 : options.filter_policy = nullptr; 88 2781 : delete options.block_cache; 89 2781 : options.block_cache = nullptr; 90 2781 : delete penv; 91 2781 : options.env = nullptr; 92 2781 : } 93 : 94 28159 : bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) 95 : { 96 28159 : leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); 97 28159 : dbwrapper_private::HandleError(status); 98 28159 : return true; 99 : } 100 : 101 0 : bool CDBWrapper::IsEmpty() 102 : { 103 0 : std::unique_ptr<CDBIterator> it(NewIterator()); 104 0 : it->SeekToFirst(); 105 0 : return !(it->Valid()); 106 : } 107 : 108 4933 : CDBIterator::~CDBIterator() { delete piter; } 109 254380 : bool CDBIterator::Valid() { return piter->Valid(); } 110 0 : void CDBIterator::SeekToFirst() { piter->SeekToFirst(); } 111 248518 : void CDBIterator::Next() { piter->Next(); } 112 : 113 : 114 : namespace dbwrapper_private { 115 : 116 30963 : void HandleError(const leveldb::Status& status) 117 : { 118 30963 : if (status.ok()) 119 30963 : return; 120 0 : LogPrintf("%s\n", status.ToString()); 121 0 : if (status.IsCorruption()) 122 0 : throw dbwrapper_error("Database corrupted"); 123 0 : if (status.IsIOError()) 124 0 : throw dbwrapper_error("Database I/O error"); 125 0 : if (status.IsNotFound()) 126 0 : throw dbwrapper_error("Database entry missing"); 127 0 : throw dbwrapper_error("Unknown database error"); 128 : } 129 : 130 : };