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