/* * This file is part of the Flowee project * Copyright (c) 2012-2015 The Bitcoin Core developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dbwrapper.h" #include "util.h" #include "random.h" #include #include #include #include #include void HandleError(const leveldb::Status& status) throw(dbwrapper_error) { if (status.ok()) return; logCritical(Log::DB) << status.ToString(); if (status.IsCorruption()) throw dbwrapper_error("Database corrupted"); if (status.IsIOError()) throw dbwrapper_error("Database I/O error"); if (status.IsNotFound()) throw dbwrapper_error("Database entry missing"); throw dbwrapper_error("Unknown database error"); } static leveldb::Options GetOptions(size_t nCacheSize) { leveldb::Options options; options.block_cache = leveldb::NewLRUCache(nCacheSize / 2); options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously options.filter_policy = leveldb::NewBloomFilterPolicy(10); options.compression = leveldb::kNoCompression; options.max_open_files = 64; if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) { // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error // on corruption in later versions. options.paranoid_checks = true; } return options; } CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe) { penv = NULL; readoptions.verify_checksums = true; iteroptions.verify_checksums = true; iteroptions.fill_cache = false; syncoptions.sync = true; options = GetOptions(nCacheSize); options.create_if_missing = true; if (fMemory) { penv = leveldb::NewMemEnv(leveldb::Env::Default()); options.env = penv; } else { if (fWipe) { logCritical(Log::DB) << "Wiping LevelDB in" << path.string(); leveldb::Status result = leveldb::DestroyDB(path.string(), options); HandleError(result); } boost::system::error_code error; boost::filesystem::create_directories(path, error); logCritical(Log::DB) << "Opening LevelDB in" << path.string(); } leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); HandleError(status); logInfo(Log::DB) << "Opened LevelDB successfully"; } CDBWrapper::~CDBWrapper() { delete pdb; pdb = NULL; delete options.filter_policy; options.filter_policy = NULL; delete options.block_cache; options.block_cache = NULL; delete penv; options.env = NULL; } bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) throw(dbwrapper_error) { leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); HandleError(status); return true; } bool CDBWrapper::IsEmpty() { boost::scoped_ptr it(NewIterator()); it->SeekToFirst(); return !(it->Valid()); } CDBIterator::~CDBIterator() { delete piter; } bool CDBIterator::Valid() { return piter->Valid(); } void CDBIterator::SeekToFirst() { piter->SeekToFirst(); } void CDBIterator::Next() { piter->Next(); }