Fixup saving and loading state files
* All state files have a backup created before saving * The backup will now be used if saving or loading fails * GTKUI state files stored in new gtkui_state dir and common load/save functions created * Detects bad shutdown and archives timestamped state files in separate config directory.
This commit is contained in:
parent
2bbc1013be
commit
2c4ef9dbb3
|
@ -486,8 +486,8 @@ what is currently in the config and it could not convert the value
|
|||
|
||||
# Make a backup of the old config
|
||||
try:
|
||||
log.debug("Backing up old config file to %s~", filename)
|
||||
shutil.move(filename, filename + "~")
|
||||
log.debug("Backing up old config file to %s.bak", filename)
|
||||
shutil.move(filename, filename + ".bak")
|
||||
except Exception, e:
|
||||
log.warning("Unable to backup old config...")
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ class AuthManager(component.Component):
|
|||
def update(self):
|
||||
auth_file = configmanager.get_config_dir("auth")
|
||||
# Check for auth file and create if necessary
|
||||
if not os.path.exists(auth_file):
|
||||
if not os.path.isfile(auth_file):
|
||||
log.info("Authfile not found, recreating it.")
|
||||
self.__load_auth_file()
|
||||
return
|
||||
|
@ -192,36 +192,40 @@ class AuthManager(component.Component):
|
|||
return True
|
||||
|
||||
def write_auth_file(self):
|
||||
old_auth_file = configmanager.get_config_dir("auth")
|
||||
new_auth_file = old_auth_file + '.new'
|
||||
bak_auth_file = old_auth_file + '.bak'
|
||||
# Let's first create a backup
|
||||
if os.path.exists(old_auth_file):
|
||||
shutil.copy2(old_auth_file, bak_auth_file)
|
||||
filename = "auth"
|
||||
filepath = os.path.join(configmanager,get_config_dir(), filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
try:
|
||||
fd = open(new_auth_file, "w")
|
||||
if os.path.isfile(filepath):
|
||||
log.info("Creating backup of %s at: %s", filename, filepath_bak)
|
||||
shutil.copy2(filepath, filepath_bak)
|
||||
except IOError as ex:
|
||||
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
|
||||
else:
|
||||
log.info("Saving the %s at: %s", filename, filepath)
|
||||
try:
|
||||
with open(filepath, "wb") as _file:
|
||||
for account in self.__auth.values():
|
||||
fd.write(
|
||||
"%(username)s:%(password)s:%(authlevel_int)s\n" %
|
||||
account.data()
|
||||
)
|
||||
fd.flush()
|
||||
os.fsync(fd.fileno())
|
||||
fd.close()
|
||||
os.rename(new_auth_file, old_auth_file)
|
||||
except:
|
||||
# Something failed, let's restore the previous file
|
||||
if os.path.exists(bak_auth_file):
|
||||
os.rename(bak_auth_file, old_auth_file)
|
||||
_file.write("%(username)s:%(password)s:%(authlevel_int)s\n" % account.data())
|
||||
_file.flush()
|
||||
os.fsync(_file.fileno())
|
||||
except (IOError) as ex:
|
||||
log.error("Unable to save %s: %s", filename, ex)
|
||||
if os.path.isfile(filepath_bak):
|
||||
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
|
||||
shutil.move(filepath_bak, filepath)
|
||||
|
||||
self.__load_auth_file()
|
||||
|
||||
def __load_auth_file(self):
|
||||
save_and_reload = False
|
||||
auth_file = configmanager.get_config_dir("auth")
|
||||
filename = "auth"
|
||||
auth_file = configmanager.get_config_dir(filename)
|
||||
auth_file_bak = auth_file + ".bak"
|
||||
|
||||
# Check for auth file and create if necessary
|
||||
if not os.path.exists(auth_file):
|
||||
if not os.path.isfile(auth_file):
|
||||
create_localclient_account()
|
||||
return self.__load_auth_file()
|
||||
|
||||
|
@ -232,10 +236,20 @@ class AuthManager(component.Component):
|
|||
# File didn't change, no need for re-parsing's
|
||||
return
|
||||
|
||||
# Load the auth file into a dictionary: {username: Account(...)}
|
||||
f = open(auth_file, "r").readlines()
|
||||
for _filepath in (auth_file, auth_file_bak):
|
||||
log.info("Opening %s for load: %s", filename, _filepath)
|
||||
try:
|
||||
with open(_filepath, "rb") as _file:
|
||||
file_data = _file.readlines()
|
||||
except (IOError), ex:
|
||||
log.warning("Unable to load %s: %s", _filepath, ex)
|
||||
file_data = []
|
||||
else:
|
||||
log.info("Successfully loaded %s: %s", filename, _filepath)
|
||||
break
|
||||
|
||||
for line in f:
|
||||
# Load the auth file into a dictionary: {username: Account(...)}
|
||||
for line in file_data:
|
||||
line = line.strip()
|
||||
if line.startswith("#") or not line:
|
||||
# This line is a comment or empty
|
||||
|
|
|
@ -38,6 +38,7 @@ from deluge._libtorrent import lt
|
|||
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
import base64
|
||||
import logging
|
||||
import threading
|
||||
|
@ -50,7 +51,7 @@ import twisted.web.error
|
|||
from deluge.httpdownloader import download_file
|
||||
from deluge import path_chooser_common
|
||||
|
||||
import deluge.configmanager
|
||||
from deluge.configmanager import ConfigManager, get_config_dir
|
||||
import deluge.common
|
||||
import deluge.component as component
|
||||
from deluge.event import *
|
||||
|
@ -120,7 +121,7 @@ class Core(component.Component):
|
|||
self.new_release = None
|
||||
|
||||
# Get the core config
|
||||
self.config = deluge.configmanager.ConfigManager("core.conf")
|
||||
self.config = ConfigManager("core.conf")
|
||||
self.config.save()
|
||||
|
||||
# If there was an interface value from the command line, use it, but
|
||||
|
@ -153,19 +154,46 @@ class Core(component.Component):
|
|||
|
||||
def __save_session_state(self):
|
||||
"""Saves the libtorrent session state"""
|
||||
filename = "session.state"
|
||||
filepath = get_config_dir(filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
try:
|
||||
session_state = deluge.configmanager.get_config_dir("session.state")
|
||||
open(session_state, "wb").write(lt.bencode(self.session.save_state()))
|
||||
except Exception, e:
|
||||
log.warning("Failed to save lt state: %s", e)
|
||||
if os.path.isfile(filepath):
|
||||
log.info("Creating backup of %s at: %s", filename, filepath_bak)
|
||||
shutil.copy2(filepath, filepath_bak)
|
||||
except IOError as ex:
|
||||
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
|
||||
else:
|
||||
log.info("Saving the %s at: %s", filename, filepath)
|
||||
try:
|
||||
with open(filepath, "wb") as _file:
|
||||
_file.write(lt.bencode(self.session.save_state()))
|
||||
_file.flush()
|
||||
os.fsync(_file.fileno())
|
||||
except (IOError, EOFError) as ex:
|
||||
log.error("Unable to save %s: %s", filename, ex)
|
||||
if os.path.isfile(filepath_bak):
|
||||
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
|
||||
shutil.move(filepath_bak, filepath)
|
||||
|
||||
def __load_session_state(self):
|
||||
"""Loads the libtorrent session state"""
|
||||
filename = "session.state"
|
||||
filepath = get_config_dir(filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
for _filepath in (filepath, filepath_bak):
|
||||
log.info("Opening %s for load: %s", filename, _filepath)
|
||||
try:
|
||||
session_state = deluge.configmanager.get_config_dir("session.state")
|
||||
self.session.load_state(lt.bdecode(open(session_state, "rb").read()))
|
||||
except Exception, e:
|
||||
log.warning("Failed to load lt state: %s", e)
|
||||
with open(_filepath, "rb") as _file:
|
||||
state = lt.bdecode(_file.read())
|
||||
except (IOError, EOFError, RuntimeError), ex:
|
||||
log.warning("Unable to load %s: %s", _filepath, ex)
|
||||
else:
|
||||
log.info("Successfully loaded %s: %s", filename, _filepath)
|
||||
self.session.load_state(state)
|
||||
return
|
||||
|
||||
def get_new_release(self):
|
||||
log.debug("get_new_release")
|
||||
|
@ -679,7 +707,7 @@ class Core(component.Component):
|
|||
log.exception(e)
|
||||
return
|
||||
|
||||
f = open(os.path.join(deluge.configmanager.get_config_dir(), "plugins", filename), "wb")
|
||||
f = open(os.path.join(get_config_dir(), "plugins", filename), "wb")
|
||||
f.write(filedump)
|
||||
f.close()
|
||||
component.get("CorePluginManager").scan_for_plugins()
|
||||
|
|
|
@ -144,8 +144,9 @@ class TorrentManager(component.Component):
|
|||
self.config = ConfigManager("core.conf")
|
||||
|
||||
# Make sure the state folder has been created
|
||||
if not os.path.exists(os.path.join(get_config_dir(), "state")):
|
||||
os.makedirs(os.path.join(get_config_dir(), "state"))
|
||||
self.state_dir = os.path.join(get_config_dir(), "state")
|
||||
if not os.path.exists(self.state_dir):
|
||||
os.makedirs(self.state_dir)
|
||||
|
||||
# Create the torrents dict { torrent_id: Torrent }
|
||||
self.torrents = {}
|
||||
|
@ -212,6 +213,34 @@ class TorrentManager(component.Component):
|
|||
# Get the pluginmanager reference
|
||||
self.plugins = component.get("CorePluginManager")
|
||||
|
||||
# Check for temp file
|
||||
self.temp_file = os.path.join(self.state_dir, ".safe_state_check")
|
||||
if os.path.isfile(self.temp_file):
|
||||
def archive_file(filename):
|
||||
import datetime
|
||||
filepath = os.path.join(self.state_dir, filename)
|
||||
filepath_bak = state_filepath + ".bak"
|
||||
archive_dir = os.path.join(get_config_dir(), "archive")
|
||||
if not os.path.exists(archive_dir):
|
||||
os.makedirs(archive_dir)
|
||||
|
||||
for _filepath in (filepath, filepath_bak):
|
||||
timestamp = datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')
|
||||
archive_filepath = os.path.join(archive_dir, filename + "-" + timestamp)
|
||||
try:
|
||||
shutil.copy2(_filepath, archive_filepath)
|
||||
except IOError:
|
||||
log.error("Unable to archive: %s", filename)
|
||||
else:
|
||||
log.info("Archive of %s successful: %s", filename, archive_filepath)
|
||||
|
||||
log.warning("Potential bad shutdown of Deluge detected, archiving torrent state files...")
|
||||
archive_file("torrents.state")
|
||||
archive_file("torrents.fastresume")
|
||||
else:
|
||||
with file(self.temp_file, 'a'):
|
||||
os.utime(self.temp_file, None)
|
||||
|
||||
# Run the old state upgrader before loading state
|
||||
deluge.core.oldstateupgrader.OldStateUpgrader()
|
||||
|
||||
|
@ -246,7 +275,13 @@ class TorrentManager(component.Component):
|
|||
# Stop the status cleanup LoopingCall here
|
||||
self.torrents[key].prev_status_cleanup_loop.stop()
|
||||
|
||||
return self.save_resume_data(self.torrents.keys())
|
||||
def remove_temp_file(result):
|
||||
if result and os.path.isfile(self.temp_file):
|
||||
os.remove(self.temp_file)
|
||||
|
||||
d = self.save_resume_data(self.torrents.keys())
|
||||
d.addCallback(remove_temp_file)
|
||||
return d
|
||||
|
||||
def update(self):
|
||||
for torrent_id, torrent in self.torrents.items():
|
||||
|
@ -301,8 +336,7 @@ class TorrentManager(component.Component):
|
|||
"""Returns an entry with the resume data or None"""
|
||||
fastresume = ""
|
||||
try:
|
||||
_file = open(os.path.join(get_config_dir(), "state",
|
||||
torrent_id + ".fastresume"), "rb")
|
||||
_file = open(os.path.join(self.state_dir, torrent_id + ".fastresume"), "rb")
|
||||
fastresume = _file.read()
|
||||
_file.close()
|
||||
except IOError, e:
|
||||
|
@ -312,8 +346,7 @@ class TorrentManager(component.Component):
|
|||
|
||||
def legacy_delete_resume_data(self, torrent_id):
|
||||
"""Deletes the .fastresume file"""
|
||||
path = os.path.join(get_config_dir(), "state",
|
||||
torrent_id + ".fastresume")
|
||||
path = os.path.join(self.state_dir, torrent_id + ".fastresume")
|
||||
log.debug("Deleting fastresume file: %s", path)
|
||||
try:
|
||||
os.remove(path)
|
||||
|
@ -501,9 +534,7 @@ class TorrentManager(component.Component):
|
|||
# Write the .torrent file to the state directory
|
||||
if filedump:
|
||||
try:
|
||||
save_file = open(os.path.join(get_config_dir(), "state",
|
||||
torrent.torrent_id + ".torrent"),
|
||||
"wb")
|
||||
save_file = open(os.path.join(self.state_dir, torrent.torrent_id + ".torrent"), "wb")
|
||||
save_file.write(filedump)
|
||||
save_file.close()
|
||||
except IOError, e:
|
||||
|
@ -546,10 +577,7 @@ class TorrentManager(component.Component):
|
|||
# Get the torrent data from the torrent file
|
||||
try:
|
||||
log.debug("Attempting to open %s for add.", torrent_id)
|
||||
_file = open(
|
||||
os.path.join(
|
||||
get_config_dir(), "state", torrent_id + ".torrent"),
|
||||
"rb")
|
||||
_file = open(os.path.join(self.state_dir, torrent_id + ".torrent"), "rb")
|
||||
filedump = lt.bdecode(_file.read())
|
||||
_file.close()
|
||||
except (IOError, RuntimeError), e:
|
||||
|
@ -636,16 +664,24 @@ class TorrentManager(component.Component):
|
|||
|
||||
def load_state(self):
|
||||
"""Load the state of the TorrentManager from the torrents.state file"""
|
||||
state = TorrentManagerState()
|
||||
filename = "torrents.state"
|
||||
filepath = os.path.join(self.state_dir, filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
for _filepath in (filepath, filepath_bak):
|
||||
log.info("Opening %s for load: %s", filename, _filepath)
|
||||
try:
|
||||
log.debug("Opening torrent state file for load.")
|
||||
state_file = open(
|
||||
os.path.join(get_config_dir(), "state", "torrents.state"), "rb")
|
||||
state = cPickle.load(state_file)
|
||||
state_file.close()
|
||||
except (EOFError, IOError, Exception, cPickle.UnpicklingError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
with open(_filepath, "rb") as _file:
|
||||
state = cPickle.load(_file)
|
||||
except (IOError, EOFError, cPickle.UnpicklingError), ex:
|
||||
log.warning("Unable to load %s: %s", _filepath, ex)
|
||||
state = None
|
||||
else:
|
||||
log.info("Successfully loaded %s: %s", filename, _filepath)
|
||||
break
|
||||
|
||||
if state is None:
|
||||
state = TorrentManagerState()
|
||||
|
||||
# Try to use an old state
|
||||
try:
|
||||
|
@ -727,28 +763,29 @@ class TorrentManager(component.Component):
|
|||
)
|
||||
state.torrents.append(torrent_state)
|
||||
|
||||
filename = "torrents.state"
|
||||
filepath = os.path.join(self.state_dir, filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
try:
|
||||
if os.path.isfile(filepath):
|
||||
log.info("Creating backup of %s at: %s", filename, filepath_bak)
|
||||
shutil.copy2(filepath, filepath_bak)
|
||||
except IOError as ex:
|
||||
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
|
||||
else:
|
||||
log.info("Saving the %s at: %s", filename, filepath)
|
||||
try:
|
||||
with open(filepath, "wb") as _file:
|
||||
# Pickle the TorrentManagerState object
|
||||
try:
|
||||
log.debug("Saving torrent state file.")
|
||||
state_file = open(os.path.join(get_config_dir(),
|
||||
"state", "torrents.state.new"), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.flush()
|
||||
os.fsync(state_file.fileno())
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
return True
|
||||
|
||||
# We have to move the 'torrents.state.new' file to 'torrents.state'
|
||||
try:
|
||||
shutil.move(
|
||||
os.path.join(get_config_dir(), "state", "torrents.state.new"),
|
||||
os.path.join(get_config_dir(), "state", "torrents.state"))
|
||||
except IOError:
|
||||
log.warning("Unable to save state file.")
|
||||
return True
|
||||
|
||||
cPickle.dump(state, _file)
|
||||
_file.flush()
|
||||
os.fsync(_file.fileno())
|
||||
except (IOError, cPickle.PicklingError) as ex:
|
||||
log.error("Unable to save %s: %s", filename, ex)
|
||||
if os.path.isfile(filepath_bak):
|
||||
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
|
||||
shutil.move(filepath_bak, filepath)
|
||||
# We return True so that the timer thread will continue
|
||||
return True
|
||||
|
||||
|
@ -760,7 +797,6 @@ class TorrentManager(component.Component):
|
|||
:returns: A Deferred whose callback will be invoked when save is complete
|
||||
:rtype: twisted.internet.defer.Deferred
|
||||
"""
|
||||
|
||||
if torrent_ids is None:
|
||||
torrent_ids = (t[0] for t in self.torrents.iteritems() if t[1].handle.need_save_resume_data())
|
||||
|
||||
|
@ -779,43 +815,63 @@ class TorrentManager(component.Component):
|
|||
|
||||
def on_all_resume_data_finished(result):
|
||||
if result:
|
||||
self.save_resume_data_file()
|
||||
if self.save_resume_data_file():
|
||||
return True
|
||||
|
||||
return DeferredList(deferreds).addBoth(on_all_resume_data_finished)
|
||||
|
||||
def load_resume_data_file(self):
|
||||
resume_data = {}
|
||||
try:
|
||||
log.debug("Opening torrents fastresume file for load.")
|
||||
fastresume_file = open(os.path.join(get_config_dir(), "state",
|
||||
"torrents.fastresume"), "rb")
|
||||
resume_data = lt.bdecode(fastresume_file.read())
|
||||
fastresume_file.close()
|
||||
except (EOFError, IOError, Exception), e:
|
||||
log.warning("Unable to load fastresume file: %s", e)
|
||||
filename = "torrents.fastresume"
|
||||
filepath = os.path.join(self.state_dir, filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
old_data_filepath = os.path.join(get_config_dir(), filename)
|
||||
|
||||
for _filepath in (filepath, filepath_bak, old_data_filepath):
|
||||
log.info("Opening %s for load: %s", filename, _filepath)
|
||||
try:
|
||||
with open(_filepath, "rb") as _file:
|
||||
resume_data = lt.bdecode(_file.read())
|
||||
except (IOError, EOFError, RuntimeError), ex:
|
||||
log.warning("Unable to load %s: %s", _filepath, ex)
|
||||
resume_data = None
|
||||
else:
|
||||
log.info("Successfully loaded %s: %s", filename, _filepath)
|
||||
break
|
||||
# If the libtorrent bdecode doesn't happen properly, it will return None
|
||||
# so we need to make sure we return a {}
|
||||
if resume_data is None:
|
||||
return {}
|
||||
|
||||
else:
|
||||
return resume_data
|
||||
|
||||
def save_resume_data_file(self):
|
||||
"""
|
||||
Saves the resume data file with the contents of self.resume_data.
|
||||
"""
|
||||
path = os.path.join(get_config_dir(), "state", "torrents.fastresume")
|
||||
filename = "torrents.fastresume"
|
||||
filepath = os.path.join(self.state_dir, filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
try:
|
||||
log.debug("Saving fastresume file: %s", path)
|
||||
fastresume_file = open(path, "wb")
|
||||
fastresume_file.write(lt.bencode(self.resume_data))
|
||||
fastresume_file.flush()
|
||||
os.fsync(fastresume_file.fileno())
|
||||
fastresume_file.close()
|
||||
except IOError:
|
||||
log.warning("Error trying to save fastresume file")
|
||||
if os.path.isfile(filepath):
|
||||
log.info("Creating backup of %s at: %s", filename, filepath_bak)
|
||||
shutil.copy2(filepath, filepath_bak)
|
||||
except IOError as ex:
|
||||
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
|
||||
else:
|
||||
log.info("Saving the %s at: %s", filename, filepath)
|
||||
try:
|
||||
with open(filepath, "wb") as _file:
|
||||
_file.write(lt.bencode(self.session.save_state()))
|
||||
_file.flush()
|
||||
os.fsync(_file.fileno())
|
||||
except (IOError, EOFError) as ex:
|
||||
log.error("Unable to save %s: %s", filename, ex)
|
||||
if os.path.isfile(filepath_bak):
|
||||
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
|
||||
shutil.move(filepath_bak, filepath)
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_queue_position(self, torrent_id):
|
||||
"""Get queue position of torrent"""
|
||||
|
|
|
@ -41,6 +41,8 @@ import pygtk
|
|||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import logging
|
||||
import cPickle
|
||||
import shutil
|
||||
|
||||
import deluge.component as component
|
||||
import deluge.common
|
||||
|
@ -264,3 +266,53 @@ def associate_magnet_links(overwrite=False):
|
|||
log.error("Unable to register Deluge as default magnet uri handler.")
|
||||
return False
|
||||
return False
|
||||
|
||||
def save_pickled_state_file(filename, state):
|
||||
"""Save a file in the config directory and creates a backup
|
||||
filename: Filename to be saved to config
|
||||
state: The data to be pickled and written to file
|
||||
"""
|
||||
from deluge.configmanager import get_config_dir
|
||||
filepath = os.path.join(get_config_dir(), "gtkui_state", filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
|
||||
try:
|
||||
if os.path.isfile(filepath):
|
||||
log.info("Creating backup of %s at: %s", filename, filepath_bak)
|
||||
shutil.copy2(filepath, filepath_bak)
|
||||
except IOError as ex:
|
||||
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
|
||||
else:
|
||||
log.info("Saving the %s at: %s", filename, filepath)
|
||||
try:
|
||||
with open(filepath, "wb") as _file:
|
||||
# Pickle the state object
|
||||
cPickle.dump(state, _file)
|
||||
_file.flush()
|
||||
os.fsync(_file.fileno())
|
||||
except (IOError, EOFError, cPickle.PicklingError) as ex:
|
||||
log.error("Unable to save %s: %s", filename, ex)
|
||||
if os.path.isfile(filepath_bak):
|
||||
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
|
||||
shutil.move(filepath_bak, filepath)
|
||||
|
||||
def load_pickled_state_file(filename):
|
||||
"""Loads a file from the config directory, attempting backup if original fails to load.
|
||||
filename: Filename to be loaded from config
|
||||
returns unpickled state
|
||||
"""
|
||||
from deluge.configmanager import get_config_dir
|
||||
filepath = os.path.join(get_config_dir(), "gtkui_state", filename)
|
||||
filepath_bak = filepath + ".bak"
|
||||
old_data_filepath = os.path.join(get_config_dir(), filename)
|
||||
|
||||
for _filepath in (filepath, filepath_bak, old_data_filepath):
|
||||
log.info("Opening %s for load: %s", filename, _filepath)
|
||||
try:
|
||||
with open(_filepath, "rb") as _file:
|
||||
state = cPickle.load(_file)
|
||||
except (IOError, cPickle.UnpicklingError), ex:
|
||||
log.warning("Unable to load %s: %s", _filepath, ex)
|
||||
else:
|
||||
log.info("Successfully loaded %s: %s", filename, _filepath)
|
||||
return state
|
||||
|
|
|
@ -38,15 +38,14 @@ import gtk
|
|||
import gtk.gdk
|
||||
import gobject
|
||||
import os.path
|
||||
import cPickle
|
||||
import logging
|
||||
import cPickle
|
||||
|
||||
from deluge.ui.gtkui.torrentdetails import Tab
|
||||
from deluge.ui.client import client
|
||||
import deluge.configmanager
|
||||
import deluge.component as component
|
||||
import deluge.common
|
||||
import common
|
||||
from deluge.ui.gtkui.common import reparent_iter, save_pickled_state_file, load_pickled_state_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -242,7 +241,6 @@ class FilesTab(Tab):
|
|||
getattr(widget, attr)()
|
||||
|
||||
def save_state(self):
|
||||
filename = "files_tab.state"
|
||||
# Get the current sort order of the view
|
||||
column_id, sort_order = self.treestore.get_sort_column_id()
|
||||
|
||||
|
@ -259,30 +257,10 @@ class FilesTab(Tab):
|
|||
"width": column.get_width()
|
||||
}
|
||||
|
||||
# Get the config location for saving the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
|
||||
try:
|
||||
log.debug("Saving FilesTab state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
save_pickled_state_file("files_tab.state", state)
|
||||
|
||||
def load_state(self):
|
||||
filename = "files_tab.state"
|
||||
# Get the config location for loading the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
state = None
|
||||
|
||||
try:
|
||||
log.debug("Loading FilesTab state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "rb")
|
||||
state = cPickle.load(state_file)
|
||||
state_file.close()
|
||||
except (EOFError, IOError, AttributeError, cPickle.UnpicklingError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
state = load_pickled_state_file("files_tabs.state")
|
||||
|
||||
if state == None:
|
||||
return
|
||||
|
@ -807,14 +785,14 @@ class FilesTab(Tab):
|
|||
return
|
||||
if new_folder_iter:
|
||||
# This means that a folder by this name already exists
|
||||
common.reparent_iter(self.treestore, self.treestore.iter_children(old_folder_iter), new_folder_iter)
|
||||
reparent_iter(self.treestore, self.treestore.iter_children(old_folder_iter), new_folder_iter)
|
||||
else:
|
||||
parent = old_folder_iter_parent
|
||||
for ns in new_split[:-1]:
|
||||
parent = self.treestore.append(parent, [ns + "/", 0, "", 0, 0, -1, gtk.STOCK_DIRECTORY])
|
||||
|
||||
self.treestore[old_folder_iter][0] = new_split[-1] + "/"
|
||||
common.reparent_iter(self.treestore, old_folder_iter, parent)
|
||||
reparent_iter(self.treestore, old_folder_iter, parent)
|
||||
|
||||
# We need to check if the old_folder_iter_parent no longer has children
|
||||
# and if so, we delete it
|
||||
|
|
|
@ -40,6 +40,7 @@ gobject.set_prgname("deluge")
|
|||
from twisted.internet import gtk2reactor
|
||||
reactor = gtk2reactor.install()
|
||||
|
||||
import os
|
||||
import gtk
|
||||
import sys
|
||||
import logging
|
||||
|
@ -71,14 +72,13 @@ from queuedtorrents import QueuedTorrents
|
|||
from addtorrentdialog import AddTorrentDialog
|
||||
from deluge.ui.sessionproxy import SessionProxy
|
||||
import dialogs
|
||||
import common
|
||||
|
||||
import deluge.configmanager
|
||||
from deluge.ui.gtkui.common import associate_magnet_links
|
||||
from deluge.configmanager import ConfigManager, get_config_dir
|
||||
import deluge.common
|
||||
import deluge.error
|
||||
|
||||
from deluge.ui.ui import _UI
|
||||
|
||||
|
||||
class Gtk(_UI):
|
||||
|
||||
help = """Starts the Deluge GTK+ interface"""
|
||||
|
@ -90,6 +90,7 @@ class Gtk(_UI):
|
|||
super(Gtk, self).start()
|
||||
GtkUI(self.args)
|
||||
|
||||
|
||||
def start():
|
||||
Gtk().start()
|
||||
|
||||
|
@ -152,6 +153,7 @@ DEFAULT_PREFS = {
|
|||
"focus_main_window_on_add": True,
|
||||
}
|
||||
|
||||
|
||||
class GtkUI(object):
|
||||
def __init__(self, args):
|
||||
self.daemon_bps = (0,0,0)
|
||||
|
@ -192,10 +194,14 @@ class GtkUI(object):
|
|||
|
||||
# Attempt to register a magnet URI handler with gconf, but do not overwrite
|
||||
# if already set by another program.
|
||||
common.associate_magnet_links(False)
|
||||
associate_magnet_links(False)
|
||||
|
||||
# Make sure gtkui.conf has at least the defaults set
|
||||
self.config = deluge.configmanager.ConfigManager("gtkui.conf", DEFAULT_PREFS)
|
||||
self.config = ConfigManager("gtkui.conf", DEFAULT_PREFS)
|
||||
|
||||
# Make sure the gtkui state folder has been created
|
||||
if not os.path.exists(os.path.join(get_config_dir(), "gtkui_state")):
|
||||
os.makedirs(os.path.join(get_config_dir(), "gtkui_state"))
|
||||
|
||||
# We need to check on exit if it was started in classic mode to ensure we
|
||||
# shutdown the daemon.
|
||||
|
@ -370,7 +376,7 @@ Please see the details below for more information."), details=traceback.format_e
|
|||
if self.config["autostart_localhost"] and host in ("localhost", "127.0.0.1"):
|
||||
log.debug("Autostarting localhost:%s", host)
|
||||
try_connect = client.start_daemon(
|
||||
port, deluge.configmanager.get_config_dir()
|
||||
port, get_config_dir()
|
||||
)
|
||||
log.debug("Localhost started: %s", try_connect)
|
||||
if not try_connect:
|
||||
|
|
|
@ -34,19 +34,13 @@
|
|||
#
|
||||
#
|
||||
|
||||
|
||||
import cPickle
|
||||
import os.path
|
||||
import logging
|
||||
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import gettext
|
||||
|
||||
from deluge.configmanager import ConfigManager
|
||||
import deluge.configmanager
|
||||
import deluge.common
|
||||
from deluge.ui.gtkui.common import save_pickled_state_file, load_pickled_state_file
|
||||
|
||||
from gobject import signal_new, SIGNAL_RUN_LAST, TYPE_NONE
|
||||
from gtk import gdk
|
||||
|
@ -333,34 +327,11 @@ class ListView:
|
|||
state.append(self.create_column_state(column, counter))
|
||||
|
||||
state += self.removed_columns_state
|
||||
|
||||
# Get the config location for saving the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
|
||||
try:
|
||||
log.debug("Saving ListView state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
save_pickled_state_file(filename, state)
|
||||
|
||||
def load_state(self, filename):
|
||||
"""Load the listview state from filename."""
|
||||
# Get the config location for loading the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
state = None
|
||||
|
||||
try:
|
||||
log.debug("Loading ListView state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "rb")
|
||||
state = cPickle.load(state_file)
|
||||
state_file.close()
|
||||
except (EOFError, IOError, cPickle.UnpicklingError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
|
||||
# Keep the state in self.state so we can access it as we add new columns
|
||||
self.state = state
|
||||
self.state = load_pickled_state_file(filename)
|
||||
|
||||
def set_treeview(self, treeview_widget):
|
||||
"""Set the treeview widget that this listview uses."""
|
||||
|
|
|
@ -36,16 +36,15 @@
|
|||
import gtk
|
||||
import logging
|
||||
import os.path
|
||||
import cPickle
|
||||
from itertools import izip
|
||||
|
||||
from deluge.ui.client import client
|
||||
import deluge.configmanager
|
||||
import deluge.component as component
|
||||
import deluge.common
|
||||
from deluge.ui.gtkui.listview import cell_data_speed as cell_data_speed
|
||||
from deluge.ui.gtkui.torrentdetails import Tab
|
||||
from deluge.ui.countries import COUNTRIES
|
||||
from deluge.ui.gtkui.common import save_pickled_state_file, load_pickled_state_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -171,7 +170,6 @@ class PeersTab(Tab):
|
|||
self.torrent_id = None
|
||||
|
||||
def save_state(self):
|
||||
filename = "peers_tab.state"
|
||||
# Get the current sort order of the view
|
||||
column_id, sort_order = self.liststore.get_sort_column_id()
|
||||
|
||||
|
@ -187,31 +185,10 @@ class PeersTab(Tab):
|
|||
"position": index,
|
||||
"width": column.get_width()
|
||||
}
|
||||
|
||||
# Get the config location for saving the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
|
||||
try:
|
||||
log.debug("Saving FilesTab state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
save_pickled_state_file("peers_tab.state", state)
|
||||
|
||||
def load_state(self):
|
||||
filename = "peers_tab.state"
|
||||
# Get the config location for loading the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
state = None
|
||||
|
||||
try:
|
||||
log.debug("Loading PeersTab state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "rb")
|
||||
state = cPickle.load(state_file)
|
||||
state_file.close()
|
||||
except (EOFError, IOError, AttributeError, cPickle.UnpicklingError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
state = load_pickled_state_file("peers_tabs.state")
|
||||
|
||||
if state == None:
|
||||
return
|
||||
|
|
|
@ -37,15 +37,11 @@
|
|||
"""The torrent details component shows info about the selected torrent."""
|
||||
|
||||
import gtk
|
||||
import os
|
||||
import os.path
|
||||
import cPickle
|
||||
import logging
|
||||
|
||||
import deluge.component as component
|
||||
from deluge.ui.client import client
|
||||
from deluge.configmanager import ConfigManager
|
||||
import deluge.configmanager
|
||||
from deluge.ui.gtkui.common import save_pickled_state_file, load_pickled_state_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -411,8 +407,6 @@ class TorrentDetails(component.Component):
|
|||
|
||||
def save_state(self):
|
||||
"""We save the state, which is basically the tab_index list"""
|
||||
filename = "tabs.state"
|
||||
|
||||
#Update the visiblity status of all tabs
|
||||
#Leave tabs we dont know anything about it the state as they
|
||||
#might come from a plugin
|
||||
|
@ -423,29 +417,7 @@ class TorrentDetails(component.Component):
|
|||
log.debug("Set to %s %d" % self.state[i])
|
||||
state = self.state
|
||||
|
||||
# Get the config location for saving the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
|
||||
try:
|
||||
log.debug("Saving TorrentDetails state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
save_pickled_state_file("tabs.state", state)
|
||||
|
||||
def load_state(self):
|
||||
filename = "tabs.state"
|
||||
# Get the config location for loading the state file
|
||||
config_location = deluge.configmanager.get_config_dir()
|
||||
state = None
|
||||
|
||||
try:
|
||||
log.debug("Loading TorrentDetails state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "rb")
|
||||
state = cPickle.load(state_file)
|
||||
state_file.close()
|
||||
except (EOFError, IOError, cPickle.UnpicklingError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
|
||||
return state
|
||||
return load_pickled_state_file("tabs.state")
|
||||
|
|
Loading…
Reference in New Issue