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:
Calum Lind 2013-05-21 23:45:26 +01:00
parent 2bbc1013be
commit 2c4ef9dbb3
10 changed files with 283 additions and 229 deletions

View File

@ -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...")

View File

@ -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")
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)
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():
_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

View File

@ -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"""
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)
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:
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()

View File

@ -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"
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)
for _filepath in (filepath, filepath_bak):
log.info("Opening %s for load: %s", filename, _filepath)
try:
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)
# 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
filename = "torrents.state"
filepath = os.path.join(self.state_dir, filename)
filepath_bak = filepath + ".bak"
# 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
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
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 {}
return resume_data
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"""

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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."""

View File

@ -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

View File

@ -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")