|
|
@ -170,6 +170,14 @@ CDB::CDB(const char *pszFile, const char* pszMode) :
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool IsChainFile(std::string strFile)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (strFile == "blkindex.dat")
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CDB::Close()
|
|
|
|
void CDB::Close()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!pdb)
|
|
|
|
if (!pdb)
|
|
|
@ -183,9 +191,9 @@ void CDB::Close()
|
|
|
|
unsigned int nMinutes = 0;
|
|
|
|
unsigned int nMinutes = 0;
|
|
|
|
if (fReadOnly)
|
|
|
|
if (fReadOnly)
|
|
|
|
nMinutes = 1;
|
|
|
|
nMinutes = 1;
|
|
|
|
if (strFile == "blkindex.dat")
|
|
|
|
if (IsChainFile(strFile))
|
|
|
|
nMinutes = 2;
|
|
|
|
nMinutes = 2;
|
|
|
|
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
|
|
|
|
if (IsChainFile(strFile) && IsInitialBlockDownload())
|
|
|
|
nMinutes = 5;
|
|
|
|
nMinutes = 5;
|
|
|
|
|
|
|
|
|
|
|
|
bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
|
|
|
|
bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
|
|
|
@ -327,7 +335,7 @@ void CDBEnv::Flush(bool fShutdown)
|
|
|
|
CloseDb(strFile);
|
|
|
|
CloseDb(strFile);
|
|
|
|
printf("%s checkpoint\n", strFile.c_str());
|
|
|
|
printf("%s checkpoint\n", strFile.c_str());
|
|
|
|
dbenv.txn_checkpoint(0, 0, 0);
|
|
|
|
dbenv.txn_checkpoint(0, 0, 0);
|
|
|
|
if (strFile != "blkindex.dat" || fDetachDB) {
|
|
|
|
if (!IsChainFile(strFile) || fDetachDB) {
|
|
|
|
printf("%s detach\n", strFile.c_str());
|
|
|
|
printf("%s detach\n", strFile.c_str());
|
|
|
|
dbenv.lsn_reset(strFile.c_str(), 0);
|
|
|
|
dbenv.lsn_reset(strFile.c_str(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -529,68 +537,9 @@ CBlockIndex static * InsertBlockIndex(uint256 hash)
|
|
|
|
|
|
|
|
|
|
|
|
bool CTxDB::LoadBlockIndex()
|
|
|
|
bool CTxDB::LoadBlockIndex()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Get database cursor
|
|
|
|
if (!LoadBlockIndexGuts())
|
|
|
|
Dbc* pcursor = GetCursor();
|
|
|
|
|
|
|
|
if (!pcursor)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// Load mapBlockIndex
|
|
|
|
|
|
|
|
unsigned int fFlags = DB_SET_RANGE;
|
|
|
|
|
|
|
|
loop
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Read next record
|
|
|
|
|
|
|
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
|
|
|
|
|
|
|
if (fFlags == DB_SET_RANGE)
|
|
|
|
|
|
|
|
ssKey << make_pair(string("blockindex"), uint256(0));
|
|
|
|
|
|
|
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
|
|
|
|
|
|
|
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
|
|
|
|
|
|
|
fFlags = DB_NEXT;
|
|
|
|
|
|
|
|
if (ret == DB_NOTFOUND)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
else if (ret != 0)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Unserialize
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
string strType;
|
|
|
|
|
|
|
|
ssKey >> strType;
|
|
|
|
|
|
|
|
if (strType == "blockindex" && !fRequestShutdown)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
CDiskBlockIndex diskindex;
|
|
|
|
|
|
|
|
ssValue >> diskindex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct block index object
|
|
|
|
|
|
|
|
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
|
|
|
|
|
|
|
|
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
|
|
|
|
|
|
|
|
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
|
|
|
|
|
|
|
|
pindexNew->nFile = diskindex.nFile;
|
|
|
|
|
|
|
|
pindexNew->nBlockPos = diskindex.nBlockPos;
|
|
|
|
|
|
|
|
pindexNew->nHeight = diskindex.nHeight;
|
|
|
|
|
|
|
|
pindexNew->nVersion = diskindex.nVersion;
|
|
|
|
|
|
|
|
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
|
|
|
|
|
|
|
pindexNew->nTime = diskindex.nTime;
|
|
|
|
|
|
|
|
pindexNew->nBits = diskindex.nBits;
|
|
|
|
|
|
|
|
pindexNew->nNonce = diskindex.nNonce;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Watch for genesis block
|
|
|
|
|
|
|
|
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
|
|
|
|
|
|
|
pindexGenesisBlock = pindexNew;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!pindexNew->CheckIndex())
|
|
|
|
|
|
|
|
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
break; // if shutdown requested or finished loading block index
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} // try
|
|
|
|
|
|
|
|
catch (std::exception &e) {
|
|
|
|
|
|
|
|
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pcursor->close();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fRequestShutdown)
|
|
|
|
if (fRequestShutdown)
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
@ -756,6 +705,75 @@ bool CTxDB::LoadBlockIndex()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CTxDB::LoadBlockIndexGuts()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Get database cursor
|
|
|
|
|
|
|
|
Dbc* pcursor = GetCursor();
|
|
|
|
|
|
|
|
if (!pcursor)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load mapBlockIndex
|
|
|
|
|
|
|
|
unsigned int fFlags = DB_SET_RANGE;
|
|
|
|
|
|
|
|
loop
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Read next record
|
|
|
|
|
|
|
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
|
|
|
|
|
|
|
if (fFlags == DB_SET_RANGE)
|
|
|
|
|
|
|
|
ssKey << make_pair(string("blockindex"), uint256(0));
|
|
|
|
|
|
|
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
|
|
|
|
|
|
|
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
|
|
|
|
|
|
|
fFlags = DB_NEXT;
|
|
|
|
|
|
|
|
if (ret == DB_NOTFOUND)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
else if (ret != 0)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Unserialize
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
string strType;
|
|
|
|
|
|
|
|
ssKey >> strType;
|
|
|
|
|
|
|
|
if (strType == "blockindex" && !fRequestShutdown)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
CDiskBlockIndex diskindex;
|
|
|
|
|
|
|
|
ssValue >> diskindex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct block index object
|
|
|
|
|
|
|
|
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
|
|
|
|
|
|
|
|
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
|
|
|
|
|
|
|
|
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
|
|
|
|
|
|
|
|
pindexNew->nFile = diskindex.nFile;
|
|
|
|
|
|
|
|
pindexNew->nBlockPos = diskindex.nBlockPos;
|
|
|
|
|
|
|
|
pindexNew->nHeight = diskindex.nHeight;
|
|
|
|
|
|
|
|
pindexNew->nVersion = diskindex.nVersion;
|
|
|
|
|
|
|
|
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
|
|
|
|
|
|
|
pindexNew->nTime = diskindex.nTime;
|
|
|
|
|
|
|
|
pindexNew->nBits = diskindex.nBits;
|
|
|
|
|
|
|
|
pindexNew->nNonce = diskindex.nNonce;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Watch for genesis block
|
|
|
|
|
|
|
|
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
|
|
|
|
|
|
|
pindexGenesisBlock = pindexNew;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!pindexNew->CheckIndex())
|
|
|
|
|
|
|
|
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
break; // if shutdown requested or finished loading block index
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} // try
|
|
|
|
|
|
|
|
catch (std::exception &e) {
|
|
|
|
|
|
|
|
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pcursor->close();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|