Get rid of fTrickle parameter.
[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 (std::exception &e) {
95             (void)e;
96             return false;
97         }
98         return true;
99     }
100
101     template<typename K, typename T>
102     bool Write(const K& key, const T& value)
103     {
104         if (fReadOnly)
105             assert(!"Write called on database in read-only mode");
106
107         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
108         ssKey.reserve(1000);
109         ssKey << key;
110         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
111         ssValue.reserve(10000);
112         ssValue << value;
113
114         if (activeBatch) {
115             activeBatch->Put(ssKey.str(), ssValue.str());
116             return true;
117         }
118         leveldb::Status status = pdb->Put(leveldb::WriteOptions(), ssKey.str(), ssValue.str());
119         if (!status.ok()) {
120             printf("LevelDB write failure: %s\n", status.ToString().c_str());
121             return false;
122         }
123         return true;
124     }
125
126     template<typename K>
127     bool Erase(const K& key)
128     {
129         if (!pdb)
130             return false;
131         if (fReadOnly)
132             assert(!"Erase called on database in read-only mode");
133
134         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
135         ssKey.reserve(1000);
136         ssKey << key;
137         if (activeBatch) {
138             activeBatch->Delete(ssKey.str());
139             return true;
140         }
141         leveldb::Status status = pdb->Delete(leveldb::WriteOptions(), ssKey.str());
142         return (status.ok() || status.IsNotFound());
143     }
144
145     template<typename K>
146     bool Exists(const K& key)
147     {
148         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
149         ssKey.reserve(1000);
150         ssKey << key;
151         std::string unused;
152
153         if (activeBatch) {
154             bool deleted;
155             if (ScanBatch(ssKey, &unused, &deleted) && !deleted) {
156                 return true;
157             }
158         }
159
160
161         leveldb::Status status = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused);
162         return status.IsNotFound() == false;
163     }
164
165
166 public:
167     bool TxnBegin();
168     bool TxnCommit();
169     bool TxnAbort()
170     {
171         delete activeBatch;
172         activeBatch = NULL;
173         return true;
174     }
175
176     bool ReadVersion(int& nVersion)
177     {
178         nVersion = 0;
179         return Read(std::string("version"), nVersion);
180     }
181
182     bool WriteVersion(int nVersion)
183     {
184         return Write(std::string("version"), nVersion);
185     }
186
187     bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
188     bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
189     bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
190     bool EraseTxIndex(const CTransaction& tx);
191     bool ContainsTx(uint256 hash);
192     bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
193     bool ReadDiskTx(uint256 hash, CTransaction& tx);
194     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
195     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
196     bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
197     bool ReadHashBestChain(uint256& hashBestChain);
198     bool WriteHashBestChain(uint256 hashBestChain);
199     bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust);
200     bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust);
201     bool ReadSyncCheckpoint(uint256& hashCheckpoint);
202     bool WriteSyncCheckpoint(uint256 hashCheckpoint);
203     bool ReadCheckpointPubKey(std::string& strPubKey);
204     bool WriteCheckpointPubKey(const std::string& strPubKey);
205     bool ReadModifierUpgradeTime(unsigned int& nUpgradeTime);
206     bool WriteModifierUpgradeTime(const unsigned int& nUpgradeTime);
207     bool LoadBlockIndex();
208 };
209
210
211 #endif // BITCOIN_DB_H