txdb-leveldb.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #ifndef ECOIN_LEVELDB_H
  3. #define ECOIN_LEVELDB_H
  4. #include "main.h"
  5. #include <map>
  6. #include <string>
  7. #include <vector>
  8. #include <leveldb/db.h>
  9. #include <leveldb/write_batch.h>
  10. class CTxDB
  11. {
  12. public:
  13. CTxDB(const char* pszMode="r+");
  14. ~CTxDB() {
  15. // Note that this is not the same as Close() because it deletes only
  16. // data scoped to this TxDB object.
  17. delete activeBatch;
  18. }
  19. // Destroys the underlying shared global state accessed by this TxDB.
  20. void Close();
  21. private:
  22. leveldb::DB *pdb; // Points to the global instance.
  23. // A batch stores up writes and deletes for atomic application. When this
  24. // field is non-NULL, writes/deletes go there instead of directly to disk.
  25. leveldb::WriteBatch *activeBatch;
  26. leveldb::Options options;
  27. bool fReadOnly;
  28. int nVersion;
  29. protected:
  30. // Returns true and sets (value,false) if activeBatch contains the given key
  31. // or leaves value alone and sets deleted = true if activeBatch contains a
  32. // delete for it.
  33. bool ScanBatch(const CDataStream &key, std::string *value, bool *deleted) const;
  34. template<typename K, typename T>
  35. bool Read(const K& key, T& value)
  36. {
  37. CDataStream ssKey(SER_DISK, CLIENT_VERSION);
  38. ssKey.reserve(1000);
  39. ssKey << key;
  40. std::string strValue;
  41. bool readFromDb = true;
  42. if (activeBatch) {
  43. // First we must search for it in the currently pending set of
  44. // changes to the db. If not found in the batch, go on to read disk.
  45. bool deleted = false;
  46. readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false;
  47. if (deleted) {
  48. return false;
  49. }
  50. }
  51. if (readFromDb) {
  52. leveldb::Status status = pdb->Get(leveldb::ReadOptions(),
  53. ssKey.str(), &strValue);
  54. if (!status.ok()) {
  55. if (status.IsNotFound())
  56. return false;
  57. // Some unexpected error.
  58. printf("LevelDB read failure: %s\n", status.ToString().c_str());
  59. return false;
  60. }
  61. }
  62. // Unserialize value
  63. try {
  64. CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(),
  65. SER_DISK, CLIENT_VERSION);
  66. ssValue >> value;
  67. }
  68. catch (std::exception &e) {
  69. return false;
  70. }
  71. return true;
  72. }
  73. template<typename K, typename T>
  74. bool Write(const K& key, const T& value)
  75. {
  76. if (fReadOnly)
  77. assert(!"Write called on database in read-only mode");
  78. CDataStream ssKey(SER_DISK, CLIENT_VERSION);
  79. ssKey.reserve(1000);
  80. ssKey << key;
  81. CDataStream ssValue(SER_DISK, CLIENT_VERSION);
  82. ssValue.reserve(10000);
  83. ssValue << value;
  84. if (activeBatch) {
  85. activeBatch->Put(ssKey.str(), ssValue.str());
  86. return true;
  87. }
  88. leveldb::Status status = pdb->Put(leveldb::WriteOptions(), ssKey.str(), ssValue.str());
  89. if (!status.ok()) {
  90. printf("LevelDB write failure: %s\n", status.ToString().c_str());
  91. return false;
  92. }
  93. return true;
  94. }
  95. template<typename K>
  96. bool Erase(const K& key)
  97. {
  98. if (!pdb)
  99. return false;
  100. if (fReadOnly)
  101. assert(!"Erase called on database in read-only mode");
  102. CDataStream ssKey(SER_DISK, CLIENT_VERSION);
  103. ssKey.reserve(1000);
  104. ssKey << key;
  105. if (activeBatch) {
  106. activeBatch->Delete(ssKey.str());
  107. return true;
  108. }
  109. leveldb::Status status = pdb->Delete(leveldb::WriteOptions(), ssKey.str());
  110. return (status.ok() || status.IsNotFound());
  111. }
  112. template<typename K>
  113. bool Exists(const K& key)
  114. {
  115. CDataStream ssKey(SER_DISK, CLIENT_VERSION);
  116. ssKey.reserve(1000);
  117. ssKey << key;
  118. std::string unused;
  119. if (activeBatch) {
  120. bool deleted;
  121. if (ScanBatch(ssKey, &unused, &deleted) && !deleted) {
  122. return true;
  123. }
  124. }
  125. leveldb::Status status = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused);
  126. return status.IsNotFound() == false;
  127. }
  128. public:
  129. bool TxnBegin();
  130. bool TxnCommit();
  131. bool TxnAbort()
  132. {
  133. delete activeBatch;
  134. activeBatch = NULL;
  135. return true;
  136. }
  137. bool ReadVersion(int& nVersion)
  138. {
  139. nVersion = 0;
  140. return Read(std::string("version"), nVersion);
  141. }
  142. bool WriteVersion(int nVersion)
  143. {
  144. return Write(std::string("version"), nVersion);
  145. }
  146. bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
  147. bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
  148. bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
  149. bool EraseTxIndex(const CTransaction& tx);
  150. bool ContainsTx(uint256 hash);
  151. bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
  152. bool ReadDiskTx(uint256 hash, CTransaction& tx);
  153. bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
  154. bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
  155. bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
  156. bool ReadHashBestChain(uint256& hashBestChain);
  157. bool WriteHashBestChain(uint256 hashBestChain);
  158. bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust);
  159. bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust);
  160. bool ReadSyncCheckpoint(uint256& hashCheckpoint);
  161. bool WriteSyncCheckpoint(uint256 hashCheckpoint);
  162. bool ReadCheckpointPubKey(std::string& strPubKey);
  163. bool WriteCheckpointPubKey(const std::string& strPubKey);
  164. bool LoadBlockIndex();
  165. private:
  166. bool LoadBlockIndexGuts();
  167. };
  168. #endif // ECOIN_DB_H