LCOV - code coverage report
Current view: top level - src - leveldbwrapper.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 63 73 86.3 %
Date: 2015-10-12 22:39:14 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2014 The Bitcoin Core 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 "leveldbwrapper.h"
       6             : 
       7             : #include "util.h"
       8             : #include "random.h"
       9             : 
      10             : #include <boost/filesystem.hpp>
      11             : 
      12             : #include <leveldb/cache.h>
      13             : #include <leveldb/env.h>
      14             : #include <leveldb/filter_policy.h>
      15             : #include <memenv.h>
      16             : #include <stdint.h>
      17             : 
      18         798 : void HandleError(const leveldb::Status& status) throw(leveldb_error)
      19             : {
      20         798 :     if (status.ok())
      21         798 :         return;
      22           0 :     LogPrintf("%s\n", status.ToString());
      23           0 :     if (status.IsCorruption())
      24           0 :         throw leveldb_error("Database corrupted");
      25           0 :     if (status.IsIOError())
      26           0 :         throw leveldb_error("Database I/O error");
      27           0 :     if (status.IsNotFound())
      28           0 :         throw leveldb_error("Database entry missing");
      29           0 :     throw leveldb_error("Unknown database error");
      30             : }
      31             : 
      32             : static leveldb::Options GetOptions(size_t nCacheSize)
      33             : {
      34         244 :     leveldb::Options options;
      35         244 :     options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
      36         244 :     options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
      37         244 :     options.filter_policy = leveldb::NewBloomFilterPolicy(10);
      38         244 :     options.compression = leveldb::kNoCompression;
      39         244 :     options.max_open_files = 64;
      40             :     if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
      41             :         // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
      42             :         // on corruption in later versions.
      43         244 :         options.paranoid_checks = true;
      44             :     }
      45             :     return options;
      46             : }
      47             : 
      48        1220 : CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
      49             : {
      50         244 :     penv = NULL;
      51         244 :     readoptions.verify_checksums = true;
      52         244 :     iteroptions.verify_checksums = true;
      53         244 :     iteroptions.fill_cache = false;
      54         244 :     syncoptions.sync = true;
      55         244 :     options = GetOptions(nCacheSize);
      56         244 :     options.create_if_missing = true;
      57         244 :     if (fMemory) {
      58          52 :         penv = leveldb::NewMemEnv(leveldb::Env::Default());
      59          52 :         options.env = penv;
      60             :     } else {
      61         192 :         if (fWipe) {
      62           3 :             LogPrintf("Wiping LevelDB in %s\n", path.string());
      63           3 :             leveldb::Status result = leveldb::DestroyDB(path.string(), options);
      64           3 :             HandleError(result);
      65             :         }
      66         192 :         TryCreateDirectory(path);
      67         192 :         LogPrintf("Opening LevelDB in %s\n", path.string());
      68             :     }
      69         488 :     leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
      70         244 :     HandleError(status);
      71         244 :     LogPrintf("Opened LevelDB successfully\n");
      72             : 
      73             :     // The base-case obfuscation key, which is a noop.
      74         732 :     obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
      75             : 
      76         244 :     bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
      77             : 
      78         244 :     if (!key_exists && obfuscate && IsEmpty()) {
      79             :         // Initialize non-degenerate obfuscation if it won't upset 
      80             :         // existing, non-obfuscated data.
      81             :         std::vector<unsigned char> new_key = CreateObfuscateKey();
      82             : 
      83             :         // Write `new_key` so we don't obfuscate the key with itself
      84          64 :         Write(OBFUSCATE_KEY_KEY, new_key);
      85          64 :         obfuscate_key = new_key;
      86             : 
      87         128 :         LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), GetObfuscateKeyHex());
      88             :     }
      89             : 
      90         488 :     LogPrintf("Using obfuscation key for %s: %s\n", path.string(), GetObfuscateKeyHex());
      91         244 : }
      92             : 
      93         488 : CLevelDBWrapper::~CLevelDBWrapper()
      94             : {
      95         244 :     delete pdb;
      96         244 :     pdb = NULL;
      97         244 :     delete options.filter_policy;
      98         244 :     options.filter_policy = NULL;
      99         244 :     delete options.block_cache;
     100         244 :     options.block_cache = NULL;
     101         244 :     delete penv;
     102         244 :     options.env = NULL;
     103         244 : }
     104             : 
     105         551 : bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) throw(leveldb_error)
     106             : {
     107         551 :     leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
     108         551 :     HandleError(status);
     109        1102 :     return true;
     110             : }
     111             : 
     112             : // Prefixed with null character to avoid collisions with other keys
     113             : //
     114             : // We must use a string constructor which specifies length so that we copy
     115             : // past the null-terminator.
     116         192 : const std::string CLevelDBWrapper::OBFUSCATE_KEY_KEY("\000obfuscate_key", 14);
     117             : 
     118             : const unsigned int CLevelDBWrapper::OBFUSCATE_KEY_NUM_BYTES = 8;
     119             : 
     120             : /**
     121             :  * Returns a string (consisting of 8 random bytes) suitable for use as an 
     122             :  * obfuscating XOR key. 
     123             :  */
     124           0 : std::vector<unsigned char> CLevelDBWrapper::CreateObfuscateKey() const 
     125             : {
     126             :     unsigned char buff[OBFUSCATE_KEY_NUM_BYTES];
     127          64 :     GetRandBytes(buff, OBFUSCATE_KEY_NUM_BYTES);
     128         128 :     return std::vector<unsigned char>(&buff[0], &buff[OBFUSCATE_KEY_NUM_BYTES]);
     129             : 
     130             : }
     131             : 
     132          66 : bool CLevelDBWrapper::IsEmpty()
     133             : {
     134          66 :     boost::scoped_ptr<leveldb::Iterator> it(NewIterator());
     135          66 :     it->SeekToFirst();
     136         132 :     return !(it->Valid());
     137             : }
     138             : 
     139         421 : const std::vector<unsigned char>& CLevelDBWrapper::GetObfuscateKey() const 
     140             : { 
     141         421 :     return obfuscate_key; 
     142             : }
     143             : 
     144           0 : std::string CLevelDBWrapper::GetObfuscateKeyHex() const
     145             : { 
     146         308 :     return HexStr(obfuscate_key); 
     147         288 : }

Generated by: LCOV version 1.11