mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-09 10:03:40 +00:00
Update archiving of state file to use tarfile
This commit is contained in:
parent
596b5d5cd4
commit
45e0d10932
@ -11,7 +11,9 @@
|
|||||||
from __future__ import division, print_function, unicode_literals
|
from __future__ import division, print_function, unicode_literals
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
|
import glob
|
||||||
import locale
|
import locale
|
||||||
import logging
|
import logging
|
||||||
import numbers
|
import numbers
|
||||||
@ -20,6 +22,7 @@ import platform
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tarfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import chardet
|
import chardet
|
||||||
@ -138,6 +141,45 @@ def get_default_download_dir():
|
|||||||
return download_dir
|
return download_dir
|
||||||
|
|
||||||
|
|
||||||
|
def archive_files(arc_name, filepaths):
|
||||||
|
"""Compress a list of filepaths into timestamped tarball in config dir.
|
||||||
|
|
||||||
|
The archiving config directory is 'archive'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arc_name (str): The archive output filename (appended with timestamp).
|
||||||
|
filepaths (list): A list of the files to be archived into tarball.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The full archive filepath.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from deluge.configmanager import get_config_dir
|
||||||
|
|
||||||
|
# Set archive compression to lzma with bz2 fallback.
|
||||||
|
arc_comp = 'xz' if not PY2 else 'bz2'
|
||||||
|
|
||||||
|
archive_dir = os.path.join(get_config_dir(), 'archive')
|
||||||
|
timestamp = datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')
|
||||||
|
arc_filepath = os.path.join(archive_dir, arc_name + '-' + timestamp + '.tar.' + arc_comp)
|
||||||
|
max_num_arcs = 20
|
||||||
|
|
||||||
|
if not os.path.exists(archive_dir):
|
||||||
|
os.makedirs(archive_dir)
|
||||||
|
else:
|
||||||
|
old_arcs = glob.glob(os.path.join(archive_dir, arc_name) + '*')
|
||||||
|
if len(old_arcs) > max_num_arcs:
|
||||||
|
# TODO: Remove oldest timestamped archives.
|
||||||
|
log.warning('More than %s tarballs in config archive', max_num_arcs)
|
||||||
|
|
||||||
|
with tarfile.open(arc_filepath, 'w:' + arc_comp) as tf:
|
||||||
|
for filepath in filepaths:
|
||||||
|
tf.add(filepath, arcname=os.path.basename(filepath))
|
||||||
|
|
||||||
|
return arc_filepath
|
||||||
|
|
||||||
|
|
||||||
def windows_check():
|
def windows_check():
|
||||||
"""
|
"""
|
||||||
Checks if the current platform is Windows
|
Checks if the current platform is Windows
|
||||||
|
@ -15,7 +15,6 @@ import datetime
|
|||||||
import logging
|
import logging
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from twisted.internet import defer, reactor, threads
|
from twisted.internet import defer, reactor, threads
|
||||||
@ -24,7 +23,7 @@ from twisted.internet.task import LoopingCall
|
|||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge._libtorrent import lt
|
from deluge._libtorrent import lt
|
||||||
from deluge.common import decode_bytes, get_magnet_info
|
from deluge.common import archive_files, decode_bytes, get_magnet_info
|
||||||
from deluge.configmanager import ConfigManager, get_config_dir
|
from deluge.configmanager import ConfigManager, get_config_dir
|
||||||
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||||
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
|
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
|
||||||
@ -171,28 +170,14 @@ class TorrentManager(component.Component):
|
|||||||
def start(self):
|
def start(self):
|
||||||
# Check for old temp file to verify safe shutdown
|
# Check for old temp file to verify safe shutdown
|
||||||
if os.path.isfile(self.temp_file):
|
if os.path.isfile(self.temp_file):
|
||||||
def archive_file(filename):
|
|
||||||
"""Archives the file in 'archive' sub-directory with timestamp appended"""
|
|
||||||
filepath = os.path.join(self.state_dir, filename)
|
|
||||||
filepath_bak = 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...')
|
log.warning('Potential bad shutdown of Deluge detected, archiving torrent state files...')
|
||||||
archive_file('torrents.state')
|
arc_filepaths = []
|
||||||
archive_file('torrents.fastresume')
|
for filename in ('torrents.fastresume', 'torrents.state'):
|
||||||
else:
|
filepath = os.path.join(self.state_dir, filename)
|
||||||
|
arc_filepaths.extend([filepath, filepath + '.bak'])
|
||||||
|
archive_files('torrents_state', arc_filepaths)
|
||||||
|
os.remove(self.temp_file)
|
||||||
|
|
||||||
with open(self.temp_file, 'a'):
|
with open(self.temp_file, 'a'):
|
||||||
os.utime(self.temp_file, None)
|
os.utime(self.temp_file, None)
|
||||||
|
|
||||||
|
@ -8,16 +8,20 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import tarfile
|
||||||
|
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
from deluge.common import (VersionSplit, fdate, fpcnt, fpeer, fsize, fspeed, ftime, get_path_size, is_infohash, is_ip,
|
from deluge.common import (VersionSplit, archive_files, fdate, fpcnt, fpeer, fsize, fspeed, ftime, get_path_size,
|
||||||
is_ipv4, is_ipv6, is_magnet, is_url)
|
is_infohash, is_ip, is_ipv4, is_ipv6, is_magnet, is_url)
|
||||||
from deluge.ui.translations_util import setup_translations
|
from deluge.ui.translations_util import setup_translations
|
||||||
|
|
||||||
|
from .common import get_test_data_file, set_tmp_config_dir
|
||||||
|
|
||||||
|
|
||||||
class CommonTestCase(unittest.TestCase):
|
class CommonTestCase(unittest.TestCase):
|
||||||
def setUp(self): # NOQA
|
def setUp(self): # NOQA
|
||||||
|
self.config_dir = set_tmp_config_dir()
|
||||||
setup_translations()
|
setup_translations()
|
||||||
|
|
||||||
def tearDown(self): # NOQA
|
def tearDown(self): # NOQA
|
||||||
@ -127,3 +131,14 @@ class CommonTestCase(unittest.TestCase):
|
|||||||
for human_size, byte_size in sizes:
|
for human_size, byte_size in sizes:
|
||||||
parsed = parse_human_size(human_size)
|
parsed = parse_human_size(human_size)
|
||||||
self.assertEqual(parsed, byte_size, 'Mismatch when converting: %s' % human_size)
|
self.assertEqual(parsed, byte_size, 'Mismatch when converting: %s' % human_size)
|
||||||
|
|
||||||
|
def test_archive_files(self):
|
||||||
|
arc_filelist = [
|
||||||
|
get_test_data_file('test.torrent'),
|
||||||
|
get_test_data_file('deluge.png')]
|
||||||
|
arc_filepath = archive_files('test-arc', arc_filelist)
|
||||||
|
|
||||||
|
with tarfile.open(arc_filepath, 'r') as tar:
|
||||||
|
for tar_info in tar:
|
||||||
|
self.assertTrue(tar_info.isfile())
|
||||||
|
self.assertTrue(tar_info.name in [os.path.basename(arcf) for arcf in arc_filelist])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user