]> Git Repo - VerusCoin.git/blob - src/leveldbwrapper.h
boost: split stream classes out of serialize.h
[VerusCoin.git] / src / leveldbwrapper.h
1 // Copyright (c) 2012-2013 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #ifndef BITCOIN_LEVELDBWRAPPER_H
6 #define BITCOIN_LEVELDBWRAPPER_H
7
8 #include "serialize.h"
9 #include "streams.h"
10 #include "util.h"
11 #include "version.h"
12
13 #include <boost/filesystem/path.hpp>
14
15 #include <leveldb/db.h>
16 #include <leveldb/write_batch.h>
17
18 class leveldb_error : public std::runtime_error
19 {
20 public:
21     leveldb_error(const std::string& msg) : std::runtime_error(msg) {}
22 };
23
24 void HandleError(const leveldb::Status& status) throw(leveldb_error);
25
26 // Batch of changes queued to be written to a CLevelDBWrapper
27 class CLevelDBBatch
28 {
29     friend class CLevelDBWrapper;
30
31 private:
32     leveldb::WriteBatch batch;
33
34 public:
35     template <typename K, typename V>
36     void Write(const K& key, const V& value)
37     {
38         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
39         ssKey.reserve(ssKey.GetSerializeSize(key));
40         ssKey << key;
41         leveldb::Slice slKey(&ssKey[0], ssKey.size());
42
43         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
44         ssValue.reserve(ssValue.GetSerializeSize(value));
45         ssValue << value;
46         leveldb::Slice slValue(&ssValue[0], ssValue.size());
47
48         batch.Put(slKey, slValue);
49     }
50
51     template <typename K>
52     void Erase(const K& key)
53     {
54         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
55         ssKey.reserve(ssKey.GetSerializeSize(key));
56         ssKey << key;
57         leveldb::Slice slKey(&ssKey[0], ssKey.size());
58
59         batch.Delete(slKey);
60     }
61 };
62
63 class CLevelDBWrapper
64 {
65 private:
66     // custom environment this database is using (may be NULL in case of default environment)
67     leveldb::Env* penv;
68
69     // database options used
70     leveldb::Options options;
71
72     // options used when reading from the database
73     leveldb::ReadOptions readoptions;
74
75     // options used when iterating over values of the database
76     leveldb::ReadOptions iteroptions;
77
78     // options used when writing to the database
79     leveldb::WriteOptions writeoptions;
80
81     // options used when sync writing to the database
82     leveldb::WriteOptions syncoptions;
83
84     // the database itself
85     leveldb::DB* pdb;
86
87 public:
88     CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
89     ~CLevelDBWrapper();
90
91     template <typename K, typename V>
92     bool Read(const K& key, V& value) const throw(leveldb_error)
93     {
94         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
95         ssKey.reserve(ssKey.GetSerializeSize(key));
96         ssKey << key;
97         leveldb::Slice slKey(&ssKey[0], ssKey.size());
98
99         std::string strValue;
100         leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
101         if (!status.ok()) {
102             if (status.IsNotFound())
103                 return false;
104             LogPrintf("LevelDB read failure: %s\n", status.ToString());
105             HandleError(status);
106         }
107         try {
108             CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
109             ssValue >> value;
110         } catch (const std::exception&) {
111             return false;
112         }
113         return true;
114     }
115
116     template <typename K, typename V>
117     bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error)
118     {
119         CLevelDBBatch batch;
120         batch.Write(key, value);
121         return WriteBatch(batch, fSync);
122     }
123
124     template <typename K>
125     bool Exists(const K& key) const throw(leveldb_error)
126     {
127         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
128         ssKey.reserve(ssKey.GetSerializeSize(key));
129         ssKey << key;
130         leveldb::Slice slKey(&ssKey[0], ssKey.size());
131
132         std::string strValue;
133         leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
134         if (!status.ok()) {
135             if (status.IsNotFound())
136                 return false;
137             LogPrintf("LevelDB read failure: %s\n", status.ToString());
138             HandleError(status);
139         }
140         return true;
141     }
142
143     template <typename K>
144     bool Erase(const K& key, bool fSync = false) throw(leveldb_error)
145     {
146         CLevelDBBatch batch;
147         batch.Erase(key);
148         return WriteBatch(batch, fSync);
149     }
150
151     bool WriteBatch(CLevelDBBatch& batch, bool fSync = false) throw(leveldb_error);
152
153     // not available for LevelDB; provide for compatibility with BDB
154     bool Flush()
155     {
156         return true;
157     }
158
159     bool Sync() throw(leveldb_error)
160     {
161         CLevelDBBatch batch;
162         return WriteBatch(batch, true);
163     }
164
165     // not exactly clean encapsulation, but it's easiest for now
166     leveldb::Iterator* NewIterator()
167     {
168         return pdb->NewIterator(iteroptions);
169     }
170 };
171
172 #endif // BITCOIN_LEVELDBWRAPPER_H
This page took 0.032332 seconds and 4 git commands to generate.