Skip to content

Commit

Permalink
Merge pull request #3308 from xoriole/Checks_for_db_errors
Browse files Browse the repository at this point in the history
Startup checks for LevelDB and SQLite database errors
  • Loading branch information
devos50 authored Jan 17, 2018
2 parents ecdb112 + 159ae92 commit b1aabe5
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Tribler/Core/APIImplementation/LaunchManyCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,14 @@ def register(self, session, sesslock):
if self.session.get_torrent_store():
from Tribler.Core.leveldbstore import LevelDbStore
self.torrent_store = LevelDbStore(self.session.get_torrent_store_dir())
if not self.torrent_store.get_db():
raise RuntimeError("Torrent store (leveldb) is None which should not normally happen")

if self.session.get_enable_metadata():
from Tribler.Core.leveldbstore import LevelDbStore
self.metadata_store = LevelDbStore(self.session.get_metadata_store_dir())
if not self.metadata_store.get_db():
raise RuntimeError("Metadata store (leveldb) is None which should not normally happen")

# torrent collecting: RemoteTorrentHandler
if self.session.get_torrent_collecting():
Expand Down
7 changes: 7 additions & 0 deletions Tribler/Core/CacheDB/sqlitecachedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ def _open_connection(self):

cursor = self.get_cursor()

# Check integrity of the database
check_response, = self.execute(u"PRAGMA quick_check").next()
if check_response != 'ok':
msg = u"Quick integrity check of database failed"
self._logger.error(msg)
raise CorruptedDatabaseError(msg)

# apply pragma
page_size, = next(cursor.execute(u"PRAGMA page_size"))
if page_size < 8192:
Expand Down
3 changes: 3 additions & 0 deletions Tribler/Core/leveldbstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ def __init__(self, store_dir):
self._writeback_lc.clock = self._reactor
self._writeback_lc.start(WRITEBACK_PERIOD)

def get_db(self):
return self._db

def __getitem__(self, key):
try:
return self._pending_torrents[key]
Expand Down
1 change: 1 addition & 0 deletions Tribler/Test/Core/test_launch_many_cores.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from nose.tools import raises

from twisted.internet.defer import Deferred

from Tribler.Core import NoDispersyRLock
Expand Down
18 changes: 17 additions & 1 deletion Tribler/Test/Core/test_sqlitecachedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from nose.tools import raises
from twisted.internet.defer import inlineCallbacks

from Tribler.Test.Core.base_test import TriblerCoreTest
from Tribler.Test.Core.base_test import TriblerCoreTest, MockObject
from Tribler.Core.CacheDB.sqlitecachedb import SQLiteCacheDB, DB_SCRIPT_NAME, CorruptedDatabaseError
from Tribler.dispersy.util import blocking_call_on_reactor_thread

Expand Down Expand Up @@ -115,6 +115,22 @@ def test_no_version_info_in_database(self):
os.path.join(self.SQLITE_SCRIPTS_DIR, "script1.sql"))
sqlite_test_2.initialize()

@blocking_call_on_reactor_thread
@raises(CorruptedDatabaseError)
def test_integrity_check_failed(self):
sqlite_test_2 = SQLiteCacheDB(os.path.join(self.session_base_dir, "test_db.db"),
os.path.join(self.SQLITE_SCRIPTS_DIR, "script1.sql"))

def execute(sql):
if sql == u"PRAGMA quick_check":
db_response = MockObject()
db_response.next = lambda: ("Error: database disk image is malformed", )
return db_response

sqlite_test_2.execute = execute
sqlite_test_2.initialize()


@blocking_call_on_reactor_thread
def test_clean_db(self):
sqlite_test_2 = SQLiteCacheDB(os.path.join(self.session_base_dir, "test_db.db"), self.tribler_db_script)
Expand Down

0 comments on commit b1aabe5

Please sign in to comment.