Gav Wood
11 years ago
17 changed files with 548 additions and 415 deletions
@ -0,0 +1,115 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file MemoryDB.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "Common.h" |
|||
#include "MemoryDB.h" |
|||
using namespace std; |
|||
using namespace eth; |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
std::map<h256, std::string> MemoryDB::get() const |
|||
{ |
|||
if (!m_enforceRefs) |
|||
return m_over; |
|||
std::map<h256, std::string> ret; |
|||
for (auto const& i: m_refCount) |
|||
if (i.second) |
|||
ret.insert(*m_over.find(i.first)); |
|||
return ret; |
|||
} |
|||
|
|||
std::string MemoryDB::lookup(h256 _h) const |
|||
{ |
|||
auto it = m_over.find(_h); |
|||
if (it != m_over.end()) |
|||
{ |
|||
if (!m_enforceRefs || (m_refCount.count(it->first) && m_refCount.at(it->first))) |
|||
return it->second; |
|||
// else if (m_enforceRefs && m_refCount.count(it->first) && !m_refCount.at(it->first))
|
|||
// cnote << "Lookup required for value with no refs. Let's hope it's in the DB." << _h.abridged();
|
|||
} |
|||
return std::string(); |
|||
} |
|||
|
|||
bool MemoryDB::exists(h256 _h) const |
|||
{ |
|||
auto it = m_over.find(_h); |
|||
if (it != m_over.end() && (!m_enforceRefs || (m_refCount.count(it->first) && m_refCount.at(it->first)))) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
void MemoryDB::insert(h256 _h, bytesConstRef _v) |
|||
{ |
|||
m_over[_h] = _v.toString(); |
|||
m_refCount[_h]++; |
|||
#if ETH_PARANOIA |
|||
dbdebug << "INST" << _h.abridged() << "=>" << m_refCount[_h]; |
|||
#endif |
|||
} |
|||
|
|||
bool MemoryDB::kill(h256 _h) |
|||
{ |
|||
if (m_refCount.count(_h)) |
|||
{ |
|||
if (m_refCount[_h] > 0) |
|||
--m_refCount[_h]; |
|||
#if ETH_PARANOIA |
|||
else |
|||
{ |
|||
// If we get to this point, then there was probably a node in the level DB which we need to remove and which we have previously
|
|||
// used as part of the memory-based MemoryDB. Nothing to be worried about *as long as the node exists in the DB*.
|
|||
dbdebug << "NOKILL-WAS" << _h.abridged(); |
|||
return false; |
|||
} |
|||
dbdebug << "KILL" << _h.abridged() << "=>" << m_refCount[_h]; |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
dbdebug << "NOKILL" << _h.abridged(); |
|||
return false; |
|||
} |
|||
#else |
|||
return true; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
void MemoryDB::purge() |
|||
{ |
|||
for (auto const& i: m_refCount) |
|||
if (!i.second) |
|||
m_over.erase(i.first); |
|||
} |
|||
|
|||
set<h256> MemoryDB::keys() const |
|||
{ |
|||
set<h256> ret; |
|||
for (auto const& i: m_refCount) |
|||
if (i.second) |
|||
ret.insert(i.first); |
|||
return ret; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,85 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file MemoryDB.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <map> |
|||
#include "Common.h" |
|||
#include "FixedHash.h" |
|||
#include "RLP.h" |
|||
#include "Log.h" |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 12; }; |
|||
|
|||
#define dbdebug clog(DBChannel) |
|||
|
|||
class MemoryDB |
|||
{ |
|||
friend class EnforceRefs; |
|||
|
|||
public: |
|||
MemoryDB() {} |
|||
|
|||
void clear() { m_over.clear(); } |
|||
std::map<h256, std::string> get() const; |
|||
|
|||
std::string lookup(h256 _h) const; |
|||
bool exists(h256 _h) const; |
|||
void insert(h256 _h, bytesConstRef _v); |
|||
bool kill(h256 _h); |
|||
void purge(); |
|||
|
|||
std::set<h256> keys() const; |
|||
|
|||
protected: |
|||
std::map<h256, std::string> m_over; |
|||
std::map<h256, uint> m_refCount; |
|||
|
|||
mutable bool m_enforceRefs = false; |
|||
}; |
|||
|
|||
class EnforceRefs |
|||
{ |
|||
public: |
|||
EnforceRefs(MemoryDB const& _o, bool _r): m_o(_o), m_r(_o.m_enforceRefs) { _o.m_enforceRefs = _r; } |
|||
~EnforceRefs() { m_o.m_enforceRefs = m_r; } |
|||
|
|||
private: |
|||
MemoryDB const& m_o; |
|||
bool m_r; |
|||
}; |
|||
|
|||
inline std::ostream& operator<<(std::ostream& _out, MemoryDB const& _m) |
|||
{ |
|||
for (auto i: _m.get()) |
|||
{ |
|||
_out << i.first << ": "; |
|||
_out << RLP(i.second); |
|||
_out << " " << toHex(i.second); |
|||
_out << std::endl; |
|||
} |
|||
return _out; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,99 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file TrieDB.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "Common.h" |
|||
#include "OverlayDB.h" |
|||
using namespace std; |
|||
using namespace eth; |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
OverlayDB::~OverlayDB() |
|||
{ |
|||
if (m_db.use_count() == 1 && m_db.get()) |
|||
cnote << "Closing state DB"; |
|||
} |
|||
|
|||
void OverlayDB::setDB(ldb::DB* _db, bool _clearOverlay) |
|||
{ |
|||
m_db = std::shared_ptr<ldb::DB>(_db); |
|||
if (_clearOverlay) |
|||
m_over.clear(); |
|||
} |
|||
|
|||
void OverlayDB::commit() |
|||
{ |
|||
if (m_db) |
|||
{ |
|||
// cnote << "Committing nodes to disk DB:";
|
|||
for (auto const& i: m_over) |
|||
{ |
|||
// cnote << i.first << "#" << m_refCount[i.first];
|
|||
if (m_refCount[i.first]) |
|||
m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size())); |
|||
} |
|||
m_over.clear(); |
|||
m_refCount.clear(); |
|||
} |
|||
} |
|||
|
|||
void OverlayDB::rollback() |
|||
{ |
|||
m_over.clear(); |
|||
m_refCount.clear(); |
|||
} |
|||
|
|||
std::string OverlayDB::lookup(h256 _h) const |
|||
{ |
|||
std::string ret = MemoryDB::lookup(_h); |
|||
if (ret.empty() && m_db) |
|||
m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); |
|||
return ret; |
|||
} |
|||
|
|||
bool OverlayDB::exists(h256 _h) const |
|||
{ |
|||
if (MemoryDB::exists(_h)) |
|||
return true; |
|||
std::string ret; |
|||
if (m_db) |
|||
m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); |
|||
return !ret.empty(); |
|||
} |
|||
|
|||
void OverlayDB::kill(h256 _h) |
|||
{ |
|||
#if ETH_PARANOIA |
|||
if (!MemoryDB::kill(_h)) |
|||
{ |
|||
std::string ret; |
|||
if (m_db) |
|||
m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); |
|||
if (ret.empty()) |
|||
cnote << "Decreasing DB node ref count below zero with no DB node. Probably have a corrupt Trie." << _h.abridged(); |
|||
} |
|||
#else |
|||
MemoryDB::kill(_h); |
|||
#endif |
|||
} |
|||
|
|||
} |
@ -0,0 +1,58 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file MemoryDB.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include "Common.h" |
|||
#include "MemoryDB.h" |
|||
#include "Log.h" |
|||
namespace ldb = leveldb; |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
class OverlayDB: public MemoryDB |
|||
{ |
|||
public: |
|||
OverlayDB(ldb::DB* _db = nullptr): m_db(_db) {} |
|||
~OverlayDB(); |
|||
|
|||
ldb::DB* db() const { return m_db.get(); } |
|||
void setDB(ldb::DB* _db, bool _clearOverlay = true); |
|||
|
|||
void commit(); |
|||
void rollback(); |
|||
|
|||
std::string lookup(h256 _h) const; |
|||
bool exists(h256 _h) const; |
|||
void kill(h256 _h); |
|||
|
|||
private: |
|||
using MemoryDB::clear; |
|||
|
|||
std::shared_ptr<ldb::DB> m_db; |
|||
|
|||
ldb::ReadOptions m_readOptions; |
|||
ldb::WriteOptions m_writeOptions; |
|||
}; |
|||
|
|||
} |
Loading…
Reference in new issue