Get rid of 'e': all unused
[novacoin.git] / src / txdb-leveldb.h
1 // Copyright (c) 2009-2012 The Bitcoin Developers.
2 // Authored by Google, Inc.
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #ifndef BITCOIN_LEVELDB_H
7 #define BITCOIN_LEVELDB_H
8
9 #include "main.h"
10
11 #include <map>
12 #include <string>
13 #include <vector>
14
15 #include <leveldb/db.h>
16 #include <leveldb/write_batch.h>
17
18 // Class that provides access to a LevelDB. Note that this class is frequently
19 // instantiated on the stack and then destroyed again, so instantiation has to
20 // be very cheap. Unfortunately that means, a CTxDB instance is actually just a
21 // wrapper around some global state.
22 //
23 // A LevelDB is a key/value store that is optimized for fast usage on hard
24 // disks. It prefers long read/writes to seeks and is based on a series of
25 // sorted key/value mapping files that are stacked on top of each other, with
26 // newer files overriding older files. A background thread compacts them
27 // together when too many files stack up.
28 //
29 // Learn more: http://code.google.com/p/leveldb/
30 class CTxDB
31 {
32 public:
33     CTxDB(const char* pszMode="r+");
34     ~CTxDB() {
35         // Note that this is not the same as Close() because it deletes only
36         // data scoped to this TxDB object.
37         delete activeBatch;
38     }
39
40     // Destroys the underlying shared global state accessed by this TxDB.
41     void Close();
42
43 private:
44     leveldb::DB *pdb;  // Points to the global instance.
45
46     // A batch stores up writes and deletes for atomic application. When this
47     // field is non-NULL, writes/deletes go there instead of directly to disk.
48     leveldb::WriteBatch *activeBatch;
49     leveldb::Options options;
50     bool fReadOnly;
51     int nVersion;
52
53 protected:
54     // Returns true and sets (value,false) if activeBatch contains the given key
55     // or leaves value alone and sets deleted = true if activeBatch contains a
56     // delete for it.
57     bool ScanBatch(const CDataStream &key, std::string *value, bool *deleted) const;
58
59     template<typename K, typename T>
60     bool Read(const K& key, T& value)
61     {
62         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
63         ssKey.reserve(1000);
64         ssKey << key;
65         std::string strValue;
66
67         bool readFromDb = true;
68         if (activeBatch) {
69             // First we must search for it in the currently pending set of
70             // changes to the db. If not found in the batch, go on to read disk.
71             bool deleted = false;
72             readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false;
73             if (deleted) {
74                 return false;
75             }
76         }
77         if (readFromDb) {
78             leveldb::Status status = pdb->Get(leveldb::ReadOptions(),
79                                               ssKey.str(), &strValue);
80             if (!status.ok()) {
81                 if (status.IsNotFound())
82                     return false;
83                 // Some unexpected error.
84                 printf("LevelDB read failure: %s\n", status.ToString().c_str());
85                 return false;
86             }
87         }
88         // Unserialize value
89         try {
90             CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(),
91                                 SER_DISK, CLIENT_VERSION);
92             ssValue >> value;
93         }
94         catch (const std::exception&) {
95             return false;
96         }
97         return true;
98     }
99
100     template<typename K, typename T>
101     bool Write(const K& key, const T& value)
102     {
103         if (fReadOnly)
104             assert(!"Write called on database in read-only mode");
105
106         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
107         ssKey.reserve(1000);
108         ssKey << key;
109         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
110         ssValue.reserve(10000);
111         ssValue << value;
112
113         if (activeBatch) {
114             activeBatch->Put(ssKey.str(), ssValue.str());
115             return true;
116         }
117         leveldb::Status status = pdb->Put(leveldb::WriteOptions(), ssKey.str(), ssValue.str());
118         if (!status.ok()) {
119             printf("LevelDB write failure: %s\n", status.ToString().c_str());
120             return false;
121         }
122         return true;
123     }
124
125     template<typename K>
126     bool Erase(const K& key)
127     {
128         if (!pdb)
129             return false;
130         if (fReadOnly)
131             assert(!"Erase called on database in read-only mode");
132
133         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
134         ssKey.reserve(1000);
135         ssKey << key;
136         if (activeBatch) {
137             activeBatch->Delete(ssKey.str());
138             return true;
139         }
140         leveldb::Status status = pdb->Delete(leveldb::WriteOptions(), ssKey.str());
141         return (status.ok() || status.IsNotFound());
142     }
143
144     template<typename K>
145     bool Exists(const K& key)
146     {
147         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
148         ssKey.reserve(1000);
149         ssKey << key;
150         std::string unused;
151
152         if (activeBatch) {
153             bool deleted;
154             if (ScanBatch(ssKey, &unused, &deleted) && !deleted) {
155                 return true;
156             }
157         }
158
159
160         leveldb::Status status = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused);
161         return status.IsNotFound() == false;
162     }
163
164
165 public:
166     bool TxnBegin();
167     bool TxnCommit();
168     bool TxnAbort()
169     {
170         delete activeBatch;
171         activeBatch = NULL;
172         return true;
173     }
174
175     bool ReadVersion(int& nVersion)
176     {
177         nVersion = 0;
178         return Read(std::string("version"), nVersion);
179     }
180
181     bool WriteVersion(int nVersion)
182     {
183         return Write(std::string("version"), nVersion);
184     }
185
186     bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
187     bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
188     bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
189     bool EraseTxIndex(const CTransaction& tx);
190     bool ContainsTx(uint256 hash);
191     bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
192     bool ReadDiskTx(uint256 hash, CTransaction& tx);
193     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
194     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
195     bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
196     bool ReadHashBestChain(uint256& hashBestChain);
197     bool WriteHashBestChain(uint256 hashBestChain);
198     bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust);
199     bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust);
200     bool ReadSyncCheckpoint(uint256& hashCheckpoint);
201     bool WriteSyncCheckpoint(uint256 hashCheckpoint);
202     bool ReadCheckpointPubKey(std::string& strPubKey);
203     bool WriteCheckpointPubKey(const std::string& strPubKey);
204     bool ReadModifierUpgradeTime(unsigned int& nUpgradeTime);
205     bool WriteModifierUpgradeTime(const unsigned int& nUpgradeTime);
206     bool LoadBlockIndex();
207 };
208
209
210 #endif // BITCOIN_DB_H