LCOV - code coverage report
Current view: top level - src - flatdb.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 57 74 77.0 %
Date: 2025-02-23 09:33:43 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2014-2020 The Dash Core developers
       2             : // Copyright (c) 2021-2022 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef PIVX_FLATDB_H
       7             : #define PIVX_FLATDB_H
       8             : 
       9             : #include "chainparams.h"
      10             : #include "clientversion.h"
      11             : #include "fs.h"
      12             : #include "hash.h"
      13             : #include "logging.h"
      14             : #include "streams.h"
      15             : #include "utiltime.h"
      16             : #include "util/system.h"
      17             : 
      18             : /**
      19             : *   Generic Dumping and Loading
      20             : *   ---------------------------
      21             : */
      22             : 
      23             : template<typename T>
      24             : class CFlatDB
      25             : {
      26             : private:
      27             :     fs::path pathDB;
      28             :     std::string strFilename;
      29             :     std::string strMagicMessage;
      30             : 
      31             :     enum ReadResult {
      32             :         Ok,
      33             :         FileError,
      34             :         HashReadError,
      35             :         IncorrectHash,
      36             :         IncorrectMagicMessage,
      37             :         IncorrectMagicNumber,
      38             :         IncorrectFormat
      39             :     };
      40             : 
      41         770 :     bool Write(T& objToSave)
      42             :     {
      43         770 :         int64_t nStart = GetTimeMillis();
      44             : 
      45             :         // serialize, checksum data up to that point, then append checksum
      46         770 :         CDataStream ssObj(SER_DISK, CLIENT_VERSION);
      47         770 :         ssObj << strMagicMessage; // specific magic message for this type of object
      48         770 :         ssObj << Params().MessageStart(); // network specific magic number
      49         770 :         ssObj << objToSave;
      50         770 :         const uint256& hash = Hash(ssObj.begin(), ssObj.end());
      51         770 :         ssObj << hash;
      52             : 
      53             :         // open output file, and associate with CAutoFile
      54         770 :         FILE* file = fopen(pathDB.string().c_str(), "wb");
      55        1540 :         CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
      56         770 :         if (fileout.IsNull())
      57           0 :             return error("%s: Failed to open file %s", __func__, pathDB.string());
      58             : 
      59             :         // Write and commit header, data
      60             :         try {
      61         770 :             fileout << ssObj;
      62             :         }
      63           0 :         catch (std::exception &e) {
      64           0 :             return error("%s: Serialize or I/O error - %s", __func__, e.what());
      65             :         }
      66         770 :         fileout.fclose();
      67             : 
      68         770 :         LogPrintf("Written info to %s  %dms\n", strFilename, GetTimeMillis() - nStart);
      69         770 :         LogPrintf("     %s\n", objToSave.ToString());
      70         770 :         return true;
      71             :     }
      72             : 
      73         696 :     ReadResult Read(T& objToLoad)
      74             :     {
      75         696 :         int64_t nStart = GetTimeMillis();
      76             :         // open input file, and associate with CAutoFile
      77         696 :         FILE* file = fopen(pathDB.string().c_str(), "rb");
      78        1392 :         CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
      79         696 :         if (filein.IsNull()) {
      80         544 :             error("%s: Failed to open file %s", __func__, pathDB.string());
      81             :             return FileError;
      82             :         }
      83             : 
      84             :         // use file size to size memory buffer
      85         152 :         int fileSize = fs::file_size(pathDB);
      86         152 :         int dataSize = fileSize - sizeof(uint256);
      87             :         // Don't try to resize to a negative number if file is small
      88         152 :         if (dataSize < 0) dataSize = 0;
      89         696 :         std::vector<unsigned char> vchData;
      90         152 :         vchData.resize(dataSize);
      91         152 :         uint256 hashIn;
      92             : 
      93             :         // read data and checksum from file
      94             :         try {
      95         152 :             filein.read((char *)vchData.data(), dataSize);
      96         152 :             filein >> hashIn;
      97           0 :         } catch (std::exception &e) {
      98           0 :             error("%s: Deserialize or I/O error - %s", __func__, e.what());
      99             :             return HashReadError;
     100             :         }
     101         152 :         filein.fclose();
     102             : 
     103         304 :         CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
     104             : 
     105             :         // verify stored checksum matches input data
     106         152 :         uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
     107         152 :         if (hashIn != hashTmp) {
     108           0 :             error("%s: Checksum mismatch, data corrupted", __func__);
     109             :             return IncorrectHash;
     110             :         }
     111             : 
     112             :         unsigned char pchMsgTmp[4];
     113         304 :         std::string strMagicMessageTmp;
     114             :         try {
     115             :             // de-serialize file header (file specific magic message) and ..
     116         152 :             ssObj >> strMagicMessageTmp;
     117             : 
     118             :             // ... verify the message matches predefined one
     119         152 :             if (strMagicMessage != strMagicMessageTmp) {
     120           0 :                 error("%s: Invalid magic message", __func__);
     121             :                 return IncorrectMagicMessage;
     122             :             }
     123             : 
     124             :             // de-serialize file header (network specific magic number) and ..
     125         152 :             ssObj >> pchMsgTmp;
     126             : 
     127             :             // ... verify the network matches ours
     128         152 :             if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
     129           0 :                 error("%s: Invalid network magic number", __func__);
     130             :                 return IncorrectMagicNumber;
     131             :             }
     132             : 
     133             :             // de-serialize data into T object
     134         152 :             ssObj >> objToLoad;
     135           0 :         } catch (std::exception &e) {
     136           0 :             objToLoad.Clear();
     137           0 :             error("%s: Deserialize or I/O error - %s", __func__, e.what());
     138             :             return IncorrectFormat;
     139             :         }
     140             : 
     141         152 :         LogPrintf("Loaded info from %s  %dms\n", strFilename, GetTimeMillis() - nStart);
     142         152 :         LogPrintf("     %s\n", objToLoad.ToString());
     143         152 :         return Ok;
     144             :     }
     145             : public:
     146        1466 :     CFlatDB(const std::string& strFilenameIn,
     147             :             const std::string& strMagicMessageIn) :
     148             :             pathDB(GetDataDir() / strFilenameIn), strFilename(strFilenameIn),
     149        5864 :             strMagicMessage(strMagicMessageIn) {}
     150             : 
     151           0 :     fs::path GetDbPath() const { return pathDB; }
     152             : 
     153         696 :     bool Load(T& objToLoad)
     154             :     {
     155         696 :         LogPrintf("Reading info from %s...\n", strFilename);
     156         696 :         ReadResult readResult = Read(objToLoad);
     157         696 :         if (readResult == FileError) {
     158         544 :             LogPrintf("Missing file %s, will try to recreate\n", strFilename);
     159         152 :         } else if (readResult != Ok) {
     160           0 :             LogPrintf("Error reading %s: ", strFilename);
     161           0 :             if (readResult == IncorrectFormat) {
     162           0 :                 LogPrintf("%s: Magic is ok but data has invalid format, will try to recreate\n", __func__);
     163             :             } else {
     164           0 :                 LogPrintf("%s: File format is unknown or invalid, please fix it manually\n", __func__);
     165             :                 // program should exit with an error
     166           0 :                 return false;
     167             :             }
     168             :         }
     169             :         return true;
     170             :     }
     171             : 
     172         770 :     bool Dump(T& objToSave)
     173             :     {
     174         770 :         int64_t nStart = GetTimeMillis();
     175         770 :         LogPrintf("Writing info to %s...\n", strFilename);
     176         770 :         Write(objToSave);
     177         770 :         LogPrintf("%s dump finished  %dms\n", strFilename, GetTimeMillis() - nStart);
     178         770 :         return true;
     179             :     }
     180             : };
     181             : 
     182             : 
     183             : #endif // PIVX_FLATDB_H

Generated by: LCOV version 1.14