Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

flat-database.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2020 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef FLAT_DATABASE_H
6 #define FLAT_DATABASE_H
7 
8 #include <chainparams.h>
9 #include <clientversion.h>
10 #include <fs.h>
11 #include <hash.h>
12 #include <streams.h>
13 #include <util.h>
14 
20 template<typename T>
21 class CFlatDB
22 {
23 private:
24 
25  enum ReadResult {
26  Ok,
33  };
34 
35  fs::path pathDB;
36  std::string strFilename;
37  std::string strMagicMessage;
38 
39  bool Write(const T& objToSave)
40  {
41  // LOCK(objToSave.cs);
42 
43  int64_t nStart = GetTimeMillis();
44 
45  // serialize, checksum data up to that point, then append checksum
47  ssObj << strMagicMessage; // specific magic message for this type of object
48  ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
49  ssObj << objToSave;
50  uint256 hash = Hash(ssObj.begin(), ssObj.end());
51  ssObj << hash;
52 
53  // open output file, and associate with CAutoFile
54  FILE *file = fopen(pathDB.string().c_str(), "wb");
56  if (fileout.IsNull())
57  return error("%s: Failed to open file %s", __func__, pathDB.string());
58 
59  // Write and commit header, data
60  try {
61  fileout << ssObj;
62  }
63  catch (std::exception &e) {
64  return error("%s: Serialize or I/O error - %s", __func__, e.what());
65  }
66  fileout.fclose();
67 
68  LogPrintf("Written info to %s %dms\n", strFilename, GetTimeMillis() - nStart);
69  LogPrintf(" %s\n", objToSave.ToString());
70 
71  return true;
72  }
73 
74  ReadResult Read(T& objToLoad, bool fDryRun = false)
75  {
76  //LOCK(objToLoad.cs);
77 
78  int64_t nStart = GetTimeMillis();
79  // open input file, and associate with CAutoFile
80  FILE *file = fopen(pathDB.string().c_str(), "rb");
81  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
82  if (filein.IsNull())
83  {
84  error("%s: Failed to open file %s", __func__, pathDB.string());
85  return FileError;
86  }
87 
88  // use file size to size memory buffer
89  int fileSize = fs::file_size(pathDB);
90  int dataSize = fileSize - sizeof(uint256);
91  // Don't try to resize to a negative number if file is small
92  if (dataSize < 0)
93  dataSize = 0;
94  std::vector<unsigned char> vchData;
95  vchData.resize(dataSize);
96  uint256 hashIn;
97 
98  // read data and checksum from file
99  try {
100  filein.read((char *)vchData.data(), dataSize);
101  filein >> hashIn;
102  }
103  catch (std::exception &e) {
104  error("%s: Deserialize or I/O error - %s", __func__, e.what());
105  return HashReadError;
106  }
107  filein.fclose();
108 
109  CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
110 
111  // verify stored checksum matches input data
112  uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
113  if (hashIn != hashTmp)
114  {
115  error("%s: Checksum mismatch, data corrupted", __func__);
116  return IncorrectHash;
117  }
118 
119 
120  unsigned char pchMsgTmp[4];
121  std::string strMagicMessageTmp;
122  try {
123  // de-serialize file header (file specific magic message) and ..
124  ssObj >> strMagicMessageTmp;
125 
126  // ... verify the message matches predefined one
127  if (strMagicMessage != strMagicMessageTmp)
128  {
129  error("%s: Invalid magic message", __func__);
130  return IncorrectMagicMessage;
131  }
132 
133 
134  // de-serialize file header (network specific magic number) and ..
135  ssObj >> FLATDATA(pchMsgTmp);
136 
137  // ... verify the network matches ours
138  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
139  {
140  error("%s: Invalid network magic number", __func__);
141  return IncorrectMagicNumber;
142  }
143 
144  // de-serialize data into T object
145  ssObj >> objToLoad;
146  }
147  catch (std::exception &e) {
148  objToLoad.Clear();
149  error("%s: Deserialize or I/O error - %s", __func__, e.what());
150  return IncorrectFormat;
151  }
152 
153  LogPrintf("Loaded info from %s %dms\n", strFilename, GetTimeMillis() - nStart);
154  LogPrintf(" %s\n", objToLoad.ToString());
155  if(!fDryRun) {
156  LogPrintf("%s: Cleaning....\n", __func__);
157  objToLoad.CheckAndRemove();
158  LogPrintf(" %s\n", objToLoad.ToString());
159  }
160 
161  return Ok;
162  }
163 
164 
165 public:
166  CFlatDB(std::string strFilenameIn, std::string strMagicMessageIn)
167  {
168  pathDB = GetDataDir() / strFilenameIn;
169  strFilename = strFilenameIn;
170  strMagicMessage = strMagicMessageIn;
171  }
172 
173  bool Load(T& objToLoad)
174  {
175  LogPrintf("Reading info from %s...\n", strFilename);
176  ReadResult readResult = Read(objToLoad);
177  if (readResult == FileError)
178  LogPrintf("Missing file %s, will try to recreate\n", strFilename);
179  else if (readResult != Ok)
180  {
181  LogPrintf("Error reading %s: ", strFilename);
182  if(readResult == IncorrectFormat)
183  {
184  LogPrintf("%s: Magic is ok but data has invalid format, will try to recreate\n", __func__);
185  }
186  else {
187  LogPrintf("%s: File format is unknown or invalid, please fix it manually\n", __func__);
188  // program should exit with an error
189  return false;
190  }
191  }
192  return true;
193  }
194 
195  bool Dump(T& objToSave)
196  {
197  int64_t nStart = GetTimeMillis();
198 
199  LogPrintf("Verifying %s format...\n", strFilename);
200  T tmpObjToLoad;
201  ReadResult readResult = Read(tmpObjToLoad, true);
202 
203  // there was an error and it was not an error on file opening => do not proceed
204  if (readResult == FileError)
205  LogPrintf("Missing file %s, will try to recreate\n", strFilename);
206  else if (readResult != Ok)
207  {
208  LogPrintf("Error reading %s: ", strFilename);
209  if(readResult == IncorrectFormat)
210  LogPrintf("%s: Magic is ok but data has invalid format, will try to recreate\n", __func__);
211  else
212  {
213  LogPrintf("%s: File format is unknown or invalid, please fix it manually\n", __func__);
214  return false;
215  }
216  }
217 
218  LogPrintf("Writing info to %s...\n", strFilename);
219  Write(objToSave);
220  LogPrintf("%s dump finished %dms\n", strFilename, GetTimeMillis() - nStart);
221 
222  return true;
223  }
224 
225 };
226 
227 
228 #endif
bool Write(const T &objToSave)
Definition: flat-database.h:39
ReadResult Read(T &objToLoad, bool fDryRun=false)
Definition: flat-database.h:74
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:5
static FILE * fileout
We use boost::call_once() to make sure mutexDebugLog and vMsgsBeforeOpenLog are initialized in a thre...
Definition: util.cpp:192
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
fs::path pathDB
Definition: flat-database.h:35
#define FLATDATA(obj)
Definition: serialize.h:370
std::string strFilename
Definition: flat-database.h:36
#define LogPrintf(...)
Definition: util.h:203
bool Load(T &objToLoad)
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:84
256-bit opaque blob.
Definition: uint256.h:123
std::string strMagicMessage
Definition: flat-database.h:37
CFlatDB(std::string strFilenameIn, std::string strMagicMessageIn)
const_iterator end() const
Definition: streams.h:192
const_iterator begin() const
Definition: streams.h:190
Generic Dumping and Loading
Definition: flat-database.h:21
const CChainParams & Params()
Return the currently selected parameters.
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: utiltime.cpp:56
bool Dump(T &objToSave)
bool error(const char *fmt, const Args &... args)
Definition: util.h:222
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:928
static const int CLIENT_VERSION
dashd-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:410
Released under the MIT license