Browse Source

WhisperDB class split

cl-refactor
Vlad Gluhovsky 10 years ago
parent
commit
2764ca4dbb
  1. 2
      libp2p/Common.h
  2. 4
      libwhisper/Interface.h
  3. 63
      libwhisper/WhisperDB.cpp
  4. 33
      libwhisper/WhisperDB.h
  5. 45
      libwhisper/WhisperHost.cpp
  6. 1
      libwhisper/WhisperHost.h
  7. 20
      test/libwhisper/whisperDB.cpp

2
libp2p/Common.h

@ -239,6 +239,7 @@ public:
~DeadlineOps() { stop(); }
void schedule(unsigned _msInFuture, std::function<void(boost::system::error_code const&)> const& _f) { if (m_stopped) return; DEV_GUARDED(x_timers) m_timers.emplace_back(m_io, _msInFuture, _f); }
void stop() { m_stopped = true; DEV_GUARDED(x_timers) m_timers.clear(); }
protected:
@ -300,4 +301,3 @@ template <> struct hash<bi::address>
};
}

4
libwhisper/Interface.h

@ -64,15 +64,15 @@ public:
virtual ~Interface();
virtual void inject(Envelope const& _m, WhisperPeer* _from = nullptr) = 0;
virtual Topics const& fullTopics(unsigned _id) const = 0;
virtual unsigned installWatch(Topics const& _filter) = 0;
virtual void uninstallWatch(unsigned _watchId) = 0;
virtual h256s peekWatch(unsigned _watchId) const = 0;
virtual h256s checkWatch(unsigned _watchId) = 0;
virtual h256s watchMessages(unsigned _watchId) = 0;
virtual Envelope envelope(h256 _m) const = 0;
virtual void saveTopicsToDB(std::string const& _app, std::string const& _password) = 0;
virtual std::vector<unsigned> restoreTopicsFromDB(std::string const& _app, std::string const& _password) = 0;
void post(bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_topics, _ttl, _workToProve)); }
void post(Public _to, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_to, _topics, _ttl, _workToProve)); }

63
libwhisper/WhisperDB.cpp

@ -22,39 +22,30 @@
#include "WhisperDB.h"
#include <boost/filesystem.hpp>
#include <libdevcore/FileSystem.h>
#include "WhisperHost.h"
using namespace std;
using namespace dev;
using namespace dev::shh;
namespace fs = boost::filesystem;
WhisperDB::WhisperDB(DBType _t): m_type(_t)
WhisperDB::WhisperDB(string const& _type)
{
m_readOptions.verify_checksums = true;
string path = dev::getDataDir("shh");
fs::create_directories(path);
fs::permissions(path, fs::owner_all);
path.append("\\").append(_type);
leveldb::Options op;
op.create_if_missing = true;
op.max_open_files = 256;
string suffix = getTypeSuffix();
leveldb::DB* p = nullptr;
leveldb::Status status = leveldb::DB::Open(op, path + suffix, &p);
leveldb::Status status = leveldb::DB::Open(op, path, &p);
m_db.reset(p);
if (!status.ok())
BOOST_THROW_EXCEPTION(FailedToOpenLevelDB(status.ToString()));
}
string WhisperDB::getTypeSuffix()
{
switch(m_type)
{
case Messages: return "\\messages";
case Filters: return "\\filters";
}
return "\\misc";
}
string WhisperDB::lookup(dev::h256 const& _key) const
{
string ret;
@ -91,11 +82,8 @@ void WhisperDB::kill(dev::h256 const& _key)
BOOST_THROW_EXCEPTION(FailedDeleteInLevelDB(status.ToString()));
}
void WhisperDB::loadAllMessages(std::map<h256, Envelope>& o_dst)
void WhisperMessagesDB::loadAllMessages(std::map<h256, Envelope>& o_dst)
{
if (m_type != Messages)
BOOST_THROW_EXCEPTION(WrongTypeLevelDB());
leveldb::ReadOptions op;
op.fill_cache = false;
op.verify_checksums = true;
@ -150,11 +138,8 @@ void WhisperDB::loadAllMessages(std::map<h256, Envelope>& o_dst)
}
}
void WhisperDB::save(h256 const& _key, Envelope const& _e)
void WhisperMessagesDB::saveSingleMessage(h256 const& _key, Envelope const& _e)
{
if (m_type != Messages)
BOOST_THROW_EXCEPTION(WrongTypeLevelDB());
try
{
RLPStream rlp;
@ -172,3 +157,37 @@ void WhisperDB::save(h256 const& _key, Envelope const& _e)
cwarn << boost::diagnostic_information(ex);
}
}
vector<unsigned> WhisperFiltersDB::restoreTopicsFromDB(WhisperHost* _host, string const& _app)
{
vector<unsigned> ret;
h256 s = sha3(_app);
h256 h = sha3(s);
string raw = lookup(h);
bytes plain;
decryptSym(s, raw, plain);
RLP rlp(plain);
auto sz = rlp.itemCountStrict();
for (unsigned i = 0; i < sz; ++i)
{
RLP r = rlp[i];
bytesConstRef ref(r.toBytesConstRef());
Topics topics;
unsigned num = ref.size() / h256::size;
for (unsigned j = 0; j < num; ++j)
{
h256 topic(ref.data() + j * h256::size, h256::ConstructFromPointerType());
topics.push_back(topic);
}
unsigned w = _host->installWatch(topics);
ret.push_back(w);
}
return ret;
}

33
libwhisper/WhisperDB.h

@ -37,30 +37,39 @@ struct FailedInsertInLevelDB: virtual Exception { FailedInsertInLevelDB(std::str
struct FailedLookupInLevelDB: virtual Exception { FailedLookupInLevelDB(std::string const& _message): Exception(_message) {} };
struct FailedDeleteInLevelDB: virtual Exception { FailedDeleteInLevelDB(std::string const& _message): Exception(_message) {} };
class WhisperHost;
class WhisperDB
{
public:
enum DBType { Messages, Filters };
WhisperDB(DBType _t);
~WhisperDB() {}
WhisperDB(std::string const& _type);
virtual ~WhisperDB() {}
std::string lookup(dev::h256 const& _key) const;
void insert(dev::h256 const& _key, std::string const& _value);
void insert(dev::h256 const& _key, bytes const& _value);
void kill(dev::h256 const& _key);
void loadAllMessages(std::map<h256, Envelope>& o_dst);
void save(dev::h256 const& _key, Envelope const& _e);
private:
std::string getTypeSuffix();
protected:
leveldb::ReadOptions m_readOptions;
leveldb::WriteOptions m_writeOptions;
std::unique_ptr<leveldb::DB> m_db;
DBType m_type;
};
enum MetaInformation { StoreForeverFlag = 1, WatchedFlag = 2 };
class WhisperMessagesDB: public WhisperDB
{
public:
WhisperMessagesDB(): WhisperDB("messages") {}
virtual ~WhisperMessagesDB() {}
void loadAllMessages(std::map<h256, Envelope>& o_dst);
void saveSingleMessage(dev::h256 const& _key, Envelope const& _e);
};
class WhisperFiltersDB: public WhisperDB
{
public:
WhisperFiltersDB(): WhisperDB("filters") {}
virtual ~WhisperFiltersDB() {}
std::vector<unsigned> restoreTopicsFromDB(WhisperHost* _host, std::string const& _app);
};
}

45
libwhisper/WhisperHost.cpp

@ -241,13 +241,13 @@ void WhisperHost::saveMessagesToBD()
try
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
ReadGuard g(x_messages);
unsigned now = (unsigned)time(0);
for (auto const& m: m_messages)
if (m.second.expiry() > now)
if (isWatched(m.second))
db.save(m.first, m.second);
db.saveSingleMessage(m.first, m.second);
}
catch(FailedToOpenLevelDB const& ex)
{
@ -271,7 +271,7 @@ void WhisperHost::loadMessagesFromBD()
try
{
map<h256, Envelope> m;
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
db.loadAllMessages(m);
WriteGuard g(x_messages);
m_messages.swap(m);
@ -313,44 +313,11 @@ void WhisperHost::saveTopicsToDB(string const& _app, string const& _password)
rlp.swapOut(plain);
}
h256 s = sha3(_app);
h256 h = sha3(s);
bytes encrypted;
h256 s = sha3(_password);
encryptSym(s, &plain, encrypted);
h256 h = sha3(_app);
WhisperDB db(WhisperDB::Filters);
WhisperFiltersDB db;
db.insert(h, encrypted);
}
vector<unsigned> WhisperHost::restoreTopicsFromDB(string const& _app, string const& _password)
{
vector<unsigned> ret;
h256 h = sha3(_app);
WhisperDB db(WhisperDB::Filters);
string raw = db.lookup(h);
bytes plain;
h256 s = sha3(_password);
decryptSym(s, raw, plain);
RLP rlp(plain);
auto sz = rlp.itemCountStrict();
for (unsigned i = 0; i < sz; ++i)
{
RLP r = rlp[i];
bytesConstRef ref(r.toBytesConstRef());
Topics topics;
unsigned num = ref.size() / h256::size;
for (unsigned j = 0; j < num; ++j)
{
h256 topic(ref.data() + j * h256::size, h256::ConstructFromPointerType());
topics.push_back(topic);
}
unsigned w = installWatch(topics);
ret.push_back(w);
}
return ret;
}

1
libwhisper/WhisperHost.h

@ -64,7 +64,6 @@ public:
virtual h256s watchMessages(unsigned _watchId) override; ///< returns IDs of messages, which match specific watch criteria
virtual Envelope envelope(h256 _m) const override { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Envelope(); } }
virtual void saveTopicsToDB(std::string const& _app, std::string const& _password);
virtual std::vector<unsigned> restoreTopicsFromDB(std::string const& _app, std::string const& _password);
protected:
virtual void doWork() override;

20
test/libwhisper/whisperDB.cpp

@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(basic)
string const text2 = "ipsum";
h256 h1(0xBEEF);
h256 h2(0xC0FFEE);
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
db.kill(h1);
db.kill(h2);
@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(persistence)
h256 const h2(0xBADD00DE);
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
db.kill(h1);
db.kill(h2);
s = db.lookup(h1);
@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(persistence)
this_thread::sleep_for(chrono::milliseconds(20));
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
db.insert(h1, text1);
db.insert(h2, text2);
}
@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(persistence)
this_thread::sleep_for(chrono::milliseconds(20));
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
s = db.lookup(h2);
BOOST_REQUIRE(!s.compare(text2));
s = db.lookup(h1);
@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(messages)
}
}
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
unsigned x = 0;
for (auto i: m1)
@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(corruptedData)
h256 x = h256::random();
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
db.insert(x, "this is a test input, representing corrupt data");
}
@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(corruptedData)
}
{
WhisperDB db(WhisperDB::Messages);
WhisperMessagesDB db;
string s = db.lookup(x);
BOOST_REQUIRE(s.empty());
}
@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(filters)
cnote << "Testing filters saving...";
VerbosityHolder setTemporaryLevel(2);
string const app("test suite whisperDB/filters");
string const password("some pseudorandom stuff");
string const password("some pseudorandom stuff"); // todo: delete
{
p2p::Host h("Test");
@ -235,7 +235,9 @@ BOOST_AUTO_TEST_CASE(filters)
host1.setIdealPeerCount(1);
auto whost1 = host1.registerCapability(new WhisperHost());
host1.start();
auto ids = whost1->restoreTopicsFromDB(app, password);
//auto ids = whost1->restoreTopicsFromDB(app, password); // todo: delete
WhisperFiltersDB db;
auto ids = db.restoreTopicsFromDB(whost1.get(), app);
std::thread listener([&]()
{

Loading…
Cancel
Save