From 878061317ebee6fbf2b977a2cb7b918e2aea6e08 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Wed, 2 Oct 2013 20:03:32 -0300 Subject: [PATCH] leveldb repair for torrents --- libtorrent/src/storage.cpp | 36 +++++++++++++++++++++++++----------- src/leveldb.cpp | 20 ++++++++++++++++++++ src/leveldb.h | 5 +++++ 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 66f2b84a..9d900ef2 100644 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -540,10 +540,17 @@ namespace libtorrent std::string postStr(static_cast(bufs[0].iov_base), bufs[0].iov_len); - if( Write(std::make_pair('p', slot), postStr) ) { - return postStr.size(); - } else { - return -1; + int tries = 2; + while( tries-- ) { + try { + if( Write(std::make_pair('p', slot), postStr) ) { + return postStr.size(); + } else { + return -1; + } + } catch( leveldb_error &e ) { + RepairDB(); + } } } @@ -572,13 +579,20 @@ namespace libtorrent TORRENT_ASSERT(num_bufs == 1); TORRENT_ASSERT(offset == 0); - std::string postStr; - if( Read(std::make_pair('p', slot), postStr) ) { - TORRENT_ASSERT(bufs[0].iov_len >= postStr.size()); - memcpy(bufs[0].iov_base, postStr.data(), postStr.size()); - return postStr.size(); - } else { - return 0; + int tries = 2; + while( tries-- ) { + try { + std::string postStr; + if( Read(std::make_pair('p', slot), postStr) ) { + TORRENT_ASSERT(bufs[0].iov_len >= postStr.size()); + memcpy(bufs[0].iov_base, postStr.data(), postStr.size()); + return postStr.size(); + } else { + return 0; + } + } catch( leveldb_error &e ) { + RepairDB(); + } } } diff --git a/src/leveldb.cpp b/src/leveldb.cpp index e66f8514..f95367d1 100644 --- a/src/leveldb.cpp +++ b/src/leveldb.cpp @@ -35,6 +35,8 @@ static leveldb::Options GetOptions(size_t nCacheSize) { } CLevelDB::CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe) { + m_path = path.string(); + m_nCacheSize = nCacheSize; penv = NULL; readoptions.verify_checksums = true; iteroptions.verify_checksums = true; @@ -79,3 +81,21 @@ bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) } return true; } + +void CLevelDB::RepairDB() +{ + printf("CLevelDB::RepairDB trying to repair...\n"); + delete pdb; + pdb = NULL; + + leveldb::Status status; + + status = leveldb::RepairDB(m_path, options); + if (!status.ok()) + throw std::runtime_error(strprintf("CLevelDB(): error RepairDB %s", status.ToString().c_str())); + + status = leveldb::DB::Open(options, m_path, &pdb); + if (!status.ok()) + throw std::runtime_error(strprintf("CLevelDB(): error opening database environment %s", status.ToString().c_str())); + printf("Repaired and reopened LevelDB successfully\n"); +} diff --git a/src/leveldb.h b/src/leveldb.h index 79262edb..ebf9e558 100644 --- a/src/leveldb.h +++ b/src/leveldb.h @@ -76,6 +76,9 @@ private: // the database itself leveldb::DB *pdb; + std::string m_path; + size_t m_nCacheSize; + public: CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); ~CLevelDB(); @@ -148,6 +151,8 @@ public: leveldb::Iterator *NewIterator() { return pdb->NewIterator(iteroptions); } + + void RepairDB(); }; #endif // BITCOIN_LEVELDB_H