mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-11 15:48:05 +00:00
Deal with LevelDB errors
This commit is contained in:
parent
7851033dd6
commit
421218d304
@ -187,9 +187,9 @@ bool AppInit(int argc, char* argv[])
|
|||||||
fRet = AppInit2();
|
fRet = AppInit2();
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
PrintException(&e, "AppInit()");
|
PrintExceptionContinue(&e, "AppInit()");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintException(NULL, "AppInit()");
|
PrintExceptionContinue(NULL, "AppInit()");
|
||||||
}
|
}
|
||||||
if (!fRet)
|
if (!fRet)
|
||||||
Shutdown(NULL);
|
Shutdown(NULL);
|
||||||
|
@ -12,6 +12,18 @@
|
|||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
void HandleError(const leveldb::Status &status) throw(leveldb_error) {
|
||||||
|
if (status.ok())
|
||||||
|
return;
|
||||||
|
if (status.IsCorruption())
|
||||||
|
throw leveldb_error("Database corrupted");
|
||||||
|
if (status.IsIOError())
|
||||||
|
throw leveldb_error("Database I/O error");
|
||||||
|
if (status.IsNotFound())
|
||||||
|
throw leveldb_error("Database entry missing");
|
||||||
|
throw leveldb_error("Unknown database error");
|
||||||
|
}
|
||||||
|
|
||||||
static leveldb::Options GetOptions(size_t nCacheSize) {
|
static leveldb::Options GetOptions(size_t nCacheSize) {
|
||||||
leveldb::Options options;
|
leveldb::Options options;
|
||||||
options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
|
options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
|
||||||
@ -57,12 +69,12 @@ CLevelDB::~CLevelDB() {
|
|||||||
options.env = NULL;
|
options.env = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) {
|
bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {
|
||||||
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
|
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
printf("LevelDB write failure: %s\n", status.ToString().c_str());
|
printf("LevelDB write failure: %s\n", status.ToString().c_str());
|
||||||
|
HandleError(status);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,14 @@
|
|||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
class leveldb_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void HandleError(const leveldb::Status &status) throw(leveldb_error);
|
||||||
|
|
||||||
// Batch of changes queued to be written to a CLevelDB
|
// Batch of changes queued to be written to a CLevelDB
|
||||||
class CLevelDBBatch
|
class CLevelDBBatch
|
||||||
{
|
{
|
||||||
@ -72,7 +80,7 @@ public:
|
|||||||
CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
~CLevelDB();
|
~CLevelDB();
|
||||||
|
|
||||||
template<typename K, typename V> bool Read(const K& key, V& value) {
|
template<typename K, typename V> bool Read(const K& key, V& value) throw(leveldb_error) {
|
||||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||||
ssKey.reserve(ssKey.GetSerializeSize(key));
|
ssKey.reserve(ssKey.GetSerializeSize(key));
|
||||||
ssKey << key;
|
ssKey << key;
|
||||||
@ -84,6 +92,7 @@ public:
|
|||||||
if (status.IsNotFound())
|
if (status.IsNotFound())
|
||||||
return false;
|
return false;
|
||||||
printf("LevelDB read failure: %s\n", status.ToString().c_str());
|
printf("LevelDB read failure: %s\n", status.ToString().c_str());
|
||||||
|
HandleError(status);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
|
||||||
@ -94,13 +103,13 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) {
|
template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) {
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
batch.Write(key, value);
|
batch.Write(key, value);
|
||||||
return WriteBatch(batch, fSync);
|
return WriteBatch(batch, fSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K> bool Exists(const K& key) {
|
template<typename K> bool Exists(const K& key) throw(leveldb_error) {
|
||||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||||
ssKey.reserve(ssKey.GetSerializeSize(key));
|
ssKey.reserve(ssKey.GetSerializeSize(key));
|
||||||
ssKey << key;
|
ssKey << key;
|
||||||
@ -112,24 +121,25 @@ public:
|
|||||||
if (status.IsNotFound())
|
if (status.IsNotFound())
|
||||||
return false;
|
return false;
|
||||||
printf("LevelDB read failure: %s\n", status.ToString().c_str());
|
printf("LevelDB read failure: %s\n", status.ToString().c_str());
|
||||||
|
HandleError(status);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K> bool Erase(const K& key, bool fSync = false) {
|
template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) {
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
batch.Erase(key);
|
batch.Erase(key);
|
||||||
return WriteBatch(batch, fSync);
|
return WriteBatch(batch, fSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteBatch(CLevelDBBatch &batch, bool fSync = false);
|
bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error);
|
||||||
|
|
||||||
// not available for LevelDB; provide for compatibility with BDB
|
// not available for LevelDB; provide for compatibility with BDB
|
||||||
bool Flush() {
|
bool Flush() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync() {
|
bool Sync() throw(leveldb_error) {
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
return WriteBatch(batch, true);
|
return WriteBatch(batch, true);
|
||||||
}
|
}
|
||||||
@ -141,4 +151,3 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_LEVELDB_H
|
#endif // BITCOIN_LEVELDB_H
|
||||||
|
|
44
src/main.cpp
44
src/main.cpp
@ -800,7 +800,11 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
|
|||||||
|
|
||||||
bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs)
|
bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs);
|
return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs);
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
return state.Abort(_("System error: ") + e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
|
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
|
||||||
@ -1256,8 +1260,12 @@ bool ConnectBestBlock(CValidationState &state) {
|
|||||||
if (fRequestShutdown)
|
if (fRequestShutdown)
|
||||||
break;
|
break;
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
|
try {
|
||||||
if (!SetBestChain(state, pindexSwitch))
|
if (!SetBestChain(state, pindexSwitch))
|
||||||
return false;
|
return false;
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
return state.Abort(_("System error: ") + e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1687,7 +1695,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
|
|||||||
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
||||||
return error("ConnectBlock() : FindUndoPos failed");
|
return error("ConnectBlock() : FindUndoPos failed");
|
||||||
if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash()))
|
if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash()))
|
||||||
return state.Abort(_("Error: failed to write undo data"));
|
return state.Abort(_("Failed to write undo data"));
|
||||||
|
|
||||||
// update nUndoPos in block index
|
// update nUndoPos in block index
|
||||||
pindex->nUndoPos = pos.nPos;
|
pindex->nUndoPos = pos.nPos;
|
||||||
@ -1698,12 +1706,12 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
|
|||||||
|
|
||||||
CDiskBlockIndex blockindex(pindex);
|
CDiskBlockIndex blockindex(pindex);
|
||||||
if (!pblocktree->WriteBlockIndex(blockindex))
|
if (!pblocktree->WriteBlockIndex(blockindex))
|
||||||
return state.Abort(_("Error: failed to write block index"));
|
return state.Abort(_("Failed to write block index"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fTxIndex)
|
if (fTxIndex)
|
||||||
if (!pblocktree->WriteTxIndex(vPos))
|
if (!pblocktree->WriteTxIndex(vPos))
|
||||||
return state.Abort(_("Error: failed to write transaction index"));
|
return state.Abort(_("Failed to write transaction index"));
|
||||||
|
|
||||||
// add this block to the view's block chain
|
// add this block to the view's block chain
|
||||||
assert(view.SetBestBlock(pindex));
|
assert(view.SetBestBlock(pindex));
|
||||||
@ -1757,7 +1765,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||||||
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
|
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return state.Abort(_("Error: failed to read block"));
|
return state.Abort(_("Failed to read block"));
|
||||||
int64 nStart = GetTimeMicros();
|
int64 nStart = GetTimeMicros();
|
||||||
if (!block.DisconnectBlock(state, pindex, view))
|
if (!block.DisconnectBlock(state, pindex, view))
|
||||||
return error("SetBestBlock() : DisconnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str());
|
return error("SetBestBlock() : DisconnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str());
|
||||||
@ -1777,7 +1785,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||||||
BOOST_FOREACH(CBlockIndex *pindex, vConnect) {
|
BOOST_FOREACH(CBlockIndex *pindex, vConnect) {
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return state.Abort(_("Error: failed to read block"));
|
return state.Abort(_("Failed to read block"));
|
||||||
int64 nStart = GetTimeMicros();
|
int64 nStart = GetTimeMicros();
|
||||||
if (!block.ConnectBlock(state, pindex, view)) {
|
if (!block.ConnectBlock(state, pindex, view)) {
|
||||||
if (state.IsInvalid()) {
|
if (state.IsInvalid()) {
|
||||||
@ -1815,7 +1823,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||||||
FlushBlockFile();
|
FlushBlockFile();
|
||||||
pblocktree->Sync();
|
pblocktree->Sync();
|
||||||
if (!pcoinsTip->Flush())
|
if (!pcoinsTip->Flush())
|
||||||
return state.Abort(_("Error: failed to write to coin database"));
|
return state.Abort(_("Failed to write to coin database"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, all changes have been done to the database.
|
// At this point, all changes have been done to the database.
|
||||||
@ -1921,7 +1929,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
|
|||||||
setBlockIndexValid.insert(pindexNew);
|
setBlockIndexValid.insert(pindexNew);
|
||||||
|
|
||||||
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
|
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
|
||||||
return state.Abort(_("Error: failed to write block index"));
|
return state.Abort(_("Failed to write block index"));
|
||||||
|
|
||||||
// New best?
|
// New best?
|
||||||
if (!ConnectBestBlock(state))
|
if (!ConnectBestBlock(state))
|
||||||
@ -1936,7 +1944,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pblocktree->Flush())
|
if (!pblocktree->Flush())
|
||||||
return state.Abort(_("Error: failed to sync block index"));
|
return state.Abort(_("Failed to sync block index"));
|
||||||
|
|
||||||
uiInterface.NotifyBlocksChanged();
|
uiInterface.NotifyBlocksChanged();
|
||||||
return true;
|
return true;
|
||||||
@ -1990,7 +1998,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
|
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
|
||||||
return state.Abort(_("Error: failed to write file info"));
|
return state.Abort(_("Failed to write file info"));
|
||||||
if (fUpdatedLast)
|
if (fUpdatedLast)
|
||||||
pblocktree->WriteLastBlockFile(nLastBlockFile);
|
pblocktree->WriteLastBlockFile(nLastBlockFile);
|
||||||
|
|
||||||
@ -2008,15 +2016,15 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
|
|||||||
pos.nPos = infoLastBlockFile.nUndoSize;
|
pos.nPos = infoLastBlockFile.nUndoSize;
|
||||||
nNewSize = (infoLastBlockFile.nUndoSize += nAddSize);
|
nNewSize = (infoLastBlockFile.nUndoSize += nAddSize);
|
||||||
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
|
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
|
||||||
return state.Abort(_("Error: failed to write block info"));
|
return state.Abort(_("Failed to write block info"));
|
||||||
} else {
|
} else {
|
||||||
CBlockFileInfo info;
|
CBlockFileInfo info;
|
||||||
if (!pblocktree->ReadBlockFileInfo(nFile, info))
|
if (!pblocktree->ReadBlockFileInfo(nFile, info))
|
||||||
return state.Abort(_("Error: failed to read block info"));
|
return state.Abort(_("Failed to read block info"));
|
||||||
pos.nPos = info.nUndoSize;
|
pos.nPos = info.nUndoSize;
|
||||||
nNewSize = (info.nUndoSize += nAddSize);
|
nNewSize = (info.nUndoSize += nAddSize);
|
||||||
if (!pblocktree->WriteBlockFileInfo(nFile, info))
|
if (!pblocktree->WriteBlockFileInfo(nFile, info))
|
||||||
return state.Abort(_("Error: failed to write block info"));
|
return state.Abort(_("Failed to write block info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
|
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
|
||||||
@ -2154,6 +2162,7 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write block to history file
|
// Write block to history file
|
||||||
|
try {
|
||||||
unsigned int nBlockSize = ::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION);
|
unsigned int nBlockSize = ::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION);
|
||||||
CDiskBlockPos blockPos;
|
CDiskBlockPos blockPos;
|
||||||
if (dbp != NULL)
|
if (dbp != NULL)
|
||||||
@ -2162,9 +2171,12 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
|
|||||||
return error("AcceptBlock() : FindBlockPos failed");
|
return error("AcceptBlock() : FindBlockPos failed");
|
||||||
if (dbp == NULL)
|
if (dbp == NULL)
|
||||||
if (!WriteToDisk(blockPos))
|
if (!WriteToDisk(blockPos))
|
||||||
return state.Abort(_("Error: failed to write block"));
|
return state.Abort(_("Failed to write block"));
|
||||||
if (!AddToBlockIndex(state, blockPos))
|
if (!AddToBlockIndex(state, blockPos))
|
||||||
return error("AcceptBlock() : AddToBlockIndex failed");
|
return error("AcceptBlock() : AddToBlockIndex failed");
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
return state.Abort(_("System error: ") + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
// Relay inventory, but don't relay old inventory during initial block download
|
// Relay inventory, but don't relay old inventory during initial block download
|
||||||
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
|
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
|
||||||
@ -2432,7 +2444,7 @@ bool AbortNode(const std::string &strMessage) {
|
|||||||
fRequestShutdown = true;
|
fRequestShutdown = true;
|
||||||
strMiscWarning = strMessage;
|
strMiscWarning = strMessage;
|
||||||
printf("*** %s\n", strMessage.c_str());
|
printf("*** %s\n", strMessage.c_str());
|
||||||
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
|
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MODAL);
|
||||||
StartShutdown();
|
StartShutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2801,7 +2813,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
|||||||
int64 nStart = GetTimeMillis();
|
int64 nStart = GetTimeMillis();
|
||||||
|
|
||||||
int nLoaded = 0;
|
int nLoaded = 0;
|
||||||
{
|
try {
|
||||||
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
|
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
|
||||||
uint64 nStartByte = 0;
|
uint64 nStartByte = 0;
|
||||||
if (dbp) {
|
if (dbp) {
|
||||||
@ -2858,6 +2870,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fileIn);
|
fclose(fileIn);
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
AbortNode(_("Error: system error: ") + e.what());
|
||||||
}
|
}
|
||||||
if (nLoaded > 0)
|
if (nLoaded > 0)
|
||||||
printf("Loaded %i blocks from external file in %"PRI64d"ms\n", nLoaded, GetTimeMillis() - nStart);
|
printf("Loaded %i blocks from external file in %"PRI64d"ms\n", nLoaded, GetTimeMillis() - nStart);
|
||||||
|
Loading…
Reference in New Issue
Block a user