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