forked from Tribler/tribler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupgrade.py
139 lines (115 loc) · 5.08 KB
/
upgrade.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import logging
import os
import shutil
from twisted.internet.defer import inlineCallbacks
from Tribler.Core.CacheDB.db_versions import LATEST_DB_VERSION, LOWEST_SUPPORTED_DB_VERSION
from Tribler.Core.Upgrade.db_upgrader import DBUpgrader
from Tribler.Core.Upgrade.torrent_upgrade65 import TorrentMigrator65
from Tribler.Core.simpledefs import NTFY_UPGRADER, NTFY_FINISHED, NTFY_STARTED
from Tribler.dispersy.util import call_on_reactor_thread, blocking_call_on_reactor_thread
# Database versions:
# *earlier versions are no longer supported
# 17 is used by Tribler 5.9.x - 6.0
# 18 is used by Tribler 6.1.x - 6.2.0
# 22 is used by Tribler 6.3.x
# 23 is used by Tribler 6.4
class TriblerUpgrader(object):
def __init__(self, session, db):
self._logger = logging.getLogger(self.__class__.__name__)
self.session = session
self.db = db
self.notified = False
self.is_done = False
self.failed = True
self.current_status = u"Initializing"
def run(self):
self.current_status = u"Checking Tribler version..."
if self.session.get_current_startup_config_copy().get_upgrader_enabled():
failed, has_to_upgrade = self.check_should_upgrade()
if has_to_upgrade and not failed:
self.notify_starting()
self.upgrade_database_to_current_version()
if self.failed:
self.notify_starting()
self.stash_database()
else:
# Fake the upgrade is done, because the upgrader is disabled
# for testing purposes.
self.failed = False
# TODO refactor all is_done calls with the event call back in other files
# I leave this field for now because other classes may be dependent on it.
self.is_done = True
self.notify_done()
def update_status(self, status_text):
self.current_status = status_text
def notify_starting(self):
"""
Broadcast a notification (event) that the upgrader is starting doing work
after a check has established work on the db is required.
Will only fire once.
"""
if not self.notified:
self.notified = True
self.session.notifier.notify(NTFY_UPGRADER, NTFY_STARTED, None)
def notify_done(self):
"""
Broadcast a notification (event) that the upgrader is done.
"""
self.session.notifier.notify(NTFY_UPGRADER, NTFY_FINISHED, None)
@blocking_call_on_reactor_thread
def check_should_upgrade(self):
self.failed = True
should_upgrade = False
if self.db.version > LATEST_DB_VERSION:
msg = u"The on-disk tribler database is newer than your tribler version. Your database will be backed up."
self.current_status = msg
self._logger.info(msg)
elif self.db.version < LOWEST_SUPPORTED_DB_VERSION:
msg = u"Database is too old %s < %s" % (self.db.version, LOWEST_SUPPORTED_DB_VERSION)
self.current_status = msg
elif self.db.version == LATEST_DB_VERSION:
self._logger.info(u"tribler is in the latest version, no need to upgrade")
self.failed = False
self.is_done = True
self.notify_done()
else:
should_upgrade = True
self.failed = False
return (self.failed, should_upgrade)
@call_on_reactor_thread
@inlineCallbacks
def upgrade_database_to_current_version(self):
""" Checks the database version and upgrade if it is not the latest version.
"""
try:
from Tribler.Core.leveldbstore import LevelDbStore
torrent_store = LevelDbStore(self.session.get_torrent_store_dir())
torrent_migrator = TorrentMigrator65(
self.session.get_torrent_collecting_dir(), self.session.get_state_dir(),
torrent_store=torrent_store, status_update_func=self.update_status)
yield torrent_migrator.start_migrate()
db_migrator = DBUpgrader(
self.session, self.db, torrent_store=torrent_store, status_update_func=self.update_status)
yield db_migrator.start_migrate()
# Import all the torrent files not in the database, we do this in
# case we have some unhandled torrent files left due to
# bugs/crashes, etc.
self.update_status("Recovering unregistered torrents...")
yield db_migrator.reimport_torrents()
yield torrent_store.close()
del torrent_store
self.failed = False
self.is_done = True
self.notify_done()
except Exception as e:
self._logger.exception(u"failed to upgrade: %s", e)
@call_on_reactor_thread
def stash_database(self):
self.db.close()
old_dir = os.path.dirname(self.db.sqlite_db_path)
new_dir = u'%s_backup_%d' % (old_dir, LATEST_DB_VERSION)
shutil.move(old_dir, new_dir)
os.makedirs(old_dir)
self.db.initialize()
self.is_done = True
self.notify_done()