|
|
@ -164,8 +164,6 @@ void CDB::Close() |
|
|
|
unsigned int nMinutes = 0; |
|
|
|
unsigned int nMinutes = 0; |
|
|
|
if (fReadOnly) |
|
|
|
if (fReadOnly) |
|
|
|
nMinutes = 1; |
|
|
|
nMinutes = 1; |
|
|
|
if (strFile == "addr.dat") |
|
|
|
|
|
|
|
nMinutes = 2; |
|
|
|
|
|
|
|
if (strFile == "blkindex.dat") |
|
|
|
if (strFile == "blkindex.dat") |
|
|
|
nMinutes = 2; |
|
|
|
nMinutes = 2; |
|
|
|
if (strFile == "blkindex.dat" && IsInitialBlockDownload()) |
|
|
|
if (strFile == "blkindex.dat" && IsInitialBlockDownload()) |
|
|
@ -310,7 +308,7 @@ void DBFlush(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" && strFile != "addr.dat") || fDetachDB) { |
|
|
|
if (strFile != "blkindex.dat" || 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); |
|
|
|
} |
|
|
|
} |
|
|
@ -737,65 +735,96 @@ bool CTxDB::LoadBlockIndex() |
|
|
|
// CAddrDB
|
|
|
|
// CAddrDB
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
bool CAddrDB::WriteAddrman(const CAddrMan& addrman) |
|
|
|
|
|
|
|
|
|
|
|
CAddrDB::CAddrDB() |
|
|
|
{ |
|
|
|
{ |
|
|
|
return Write(string("addrman"), addrman); |
|
|
|
pathAddr = GetDataDir() / "peers.dat"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CAddrDB::LoadAddresses() |
|
|
|
bool CAddrDB::Write(const CAddrMan& addr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (Read(string("addrman"), addrman)) |
|
|
|
// Generate random temporary filename
|
|
|
|
{ |
|
|
|
unsigned short randv = 0; |
|
|
|
printf("Loaded %i addresses\n", addrman.size()); |
|
|
|
RAND_bytes((unsigned char *)&randv, sizeof(randv)); |
|
|
|
return true; |
|
|
|
std::string tmpfn = strprintf("peers.dat.%04x", randv); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// serialize addresses, checksum data up to that point, then append csum
|
|
|
|
|
|
|
|
CDataStream ssPeers(SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
ssPeers << FLATDATA(pchMessageStart); |
|
|
|
|
|
|
|
ssPeers << addr; |
|
|
|
|
|
|
|
uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); |
|
|
|
|
|
|
|
ssPeers << hash; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// open temp output file, and associate with CAutoFile
|
|
|
|
|
|
|
|
boost::filesystem::path pathTmp = GetDataDir() / tmpfn; |
|
|
|
|
|
|
|
FILE *file = fopen(pathTmp.string().c_str(), "wb"); |
|
|
|
|
|
|
|
CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
if (!fileout) |
|
|
|
|
|
|
|
return error("CAddrman::Write() : open failed"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Write and commit header, data
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
fileout << ssPeers; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
catch (std::exception &e) { |
|
|
|
// Read pre-0.6 addr records
|
|
|
|
return error("CAddrman::Write() : I/O error"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
FileCommit(fileout); |
|
|
|
|
|
|
|
fileout.fclose(); |
|
|
|
|
|
|
|
|
|
|
|
vector<CAddress> vAddr; |
|
|
|
// replace existing peers.dat, if any, with new peers.dat.XXXX
|
|
|
|
vector<vector<unsigned char> > vDelete; |
|
|
|
if (!RenameOver(pathTmp, pathAddr)) |
|
|
|
|
|
|
|
return error("CAddrman::Write() : Rename-into-place failed"); |
|
|
|
|
|
|
|
|
|
|
|
// Get cursor
|
|
|
|
return true; |
|
|
|
Dbc* pcursor = GetCursor(); |
|
|
|
} |
|
|
|
if (!pcursor) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loop |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Read next record
|
|
|
|
|
|
|
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
int ret = ReadAtCursor(pcursor, ssKey, ssValue); |
|
|
|
|
|
|
|
if (ret == DB_NOTFOUND) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
else if (ret != 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Unserialize
|
|
|
|
bool CAddrDB::Read(CAddrMan& addr) |
|
|
|
string strType; |
|
|
|
{ |
|
|
|
ssKey >> strType; |
|
|
|
// open input file, and associate with CAutoFile
|
|
|
|
if (strType == "addr") |
|
|
|
FILE *file = fopen(pathAddr.string().c_str(), "rb"); |
|
|
|
{ |
|
|
|
CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION); |
|
|
|
CAddress addr; |
|
|
|
if (!filein) |
|
|
|
ssValue >> addr; |
|
|
|
return error("CAddrman::Read() : open failed"); |
|
|
|
vAddr.push_back(addr); |
|
|
|
|
|
|
|
} |
|
|
|
// use file size to size memory buffer
|
|
|
|
|
|
|
|
int fileSize = GetFilesize(filein); |
|
|
|
|
|
|
|
int dataSize = fileSize - sizeof(uint256); |
|
|
|
|
|
|
|
vector<unsigned char> vchData; |
|
|
|
|
|
|
|
vchData.resize(dataSize); |
|
|
|
|
|
|
|
uint256 hashIn; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// read data and checksum from file
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
filein.read((char *)&vchData[0], dataSize); |
|
|
|
|
|
|
|
filein >> hashIn; |
|
|
|
} |
|
|
|
} |
|
|
|
pcursor->close(); |
|
|
|
catch (std::exception &e) { |
|
|
|
|
|
|
|
return error("CAddrman::Read() 2 : I/O error or stream data corrupted"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
filein.fclose(); |
|
|
|
|
|
|
|
|
|
|
|
addrman.Add(vAddr, CNetAddr("0.0.0.0")); |
|
|
|
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); |
|
|
|
printf("Loaded %i addresses\n", addrman.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Note: old records left; we ran into hangs-on-startup
|
|
|
|
// verify stored checksum matches input data
|
|
|
|
// bugs for some users who (we think) were running after
|
|
|
|
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); |
|
|
|
// an unclean shutdown.
|
|
|
|
if (hashIn != hashTmp) |
|
|
|
|
|
|
|
return error("CAddrman::Read() : checksum mismatch; data corrupted"); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
// de-serialize address data
|
|
|
|
} |
|
|
|
unsigned char pchMsgTmp[4]; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
ssPeers >> FLATDATA(pchMsgTmp); |
|
|
|
|
|
|
|
ssPeers >> addr; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (std::exception &e) { |
|
|
|
|
|
|
|
return error("CAddrman::Read() : I/O error or stream data corrupted"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool LoadAddresses() |
|
|
|
// finally, verify the network matches ours
|
|
|
|
{ |
|
|
|
if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp))) |
|
|
|
return CAddrDB("cr+").LoadAddresses(); |
|
|
|
return error("CAddrman::Read() : invalid network magic number"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|