Speed up restoring original format by doing a rename rather than a copy and re-add. Fixes #1839733 [Restore pre conversion originals very slow](https://bugs.launchpad.net/calibre/+bug/1839733)

This commit is contained in:
Kovid Goyal 2019-08-11 19:23:50 +05:30
parent 91a0659a9c
commit 5d1379fbec
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 23 additions and 21 deletions

View File

@ -1341,6 +1341,16 @@ class DB(object):
def has_format(self, book_id, fmt, fname, path):
return self.format_abspath(book_id, fmt, fname, path) is not None
def is_format_accessible(self, book_id, fmt, fname, path):
fpath = self.format_abspath(book_id, fmt, fname, path)
return fpath and os.access(fpath, os.R_OK | os.W_OK)
def rename_format_file(self, book_id, src_fname, src_fmt, dest_fname, dest_fmt, path):
src_path = self.format_abspath(book_id, src_fmt, src_fname, path)
dest_path = self.format_abspath(book_id, dest_fmt, dest_fname, path)
atomic_rename(src_path, dest_path)
return os.path.getsize(dest_path)
def remove_formats(self, remove_map):
paths = []
for book_id, removals in iteritems(remove_map):

View File

@ -795,18 +795,24 @@ class Cache(object):
nfmt = 'ORIGINAL_'+fmt
return self.add_format(book_id, nfmt, fmtfile, run_hooks=False)
@api
@write_api
def restore_original_format(self, book_id, original_fmt):
''' Restore the specified format from the previously saved
ORIGINAL_FORMAT, if any. Return True on success. The ORIGINAL_FORMAT is
deleted after a successful restore. '''
original_fmt = original_fmt.upper()
fmtfile = self.format(book_id, original_fmt, as_file=True)
if fmtfile is not None:
fmt = original_fmt.partition('_')[2]
with fmtfile:
self.add_format(book_id, fmt, fmtfile, run_hooks=False)
self.remove_formats({book_id:(original_fmt,)})
try:
ofmt_name = self.fields['formats'].format_fname(book_id, original_fmt)
path = self._field_for('path', book_id).replace('/', os.sep)
except Exception:
return False
if self.backend.is_format_accessible(book_id, original_fmt, ofmt_name, path):
self.add_format(book_id, fmt, BytesIO(), run_hooks=False)
fmt_name = self.fields['formats'].format_fname(book_id, fmt)
file_size = self.backend.rename_format_file(book_id, ofmt_name, original_fmt, fmt_name, fmt, path)
self.fields['formats'].table.update_fmt(book_id, fmt, fmt_name, file_size, self.backend)
self._remove_formats({book_id:(original_fmt,)})
return True
return False

View File

@ -793,20 +793,6 @@ class LegacyTest(BaseTest):
self.assertEqual(ndb.new_api.field_for('#series_index', 1), 9)
# }}}
def test_legacy_original_fmt(self): # {{{
db, ndb = self.init_old(), self.init_legacy()
run_funcs(self, db, ndb, (
('original_fmt', 1, 'FMT1'),
('save_original_format', 1, 'FMT1'),
('original_fmt', 1, 'FMT1'),
('restore_original_format', 1, 'ORIGINAL_FMT1'),
('original_fmt', 1, 'FMT1'),
('%formats', 1, True),
))
db.close()
# }}}
def test_legacy_saved_search(self): # {{{
' Test legacy saved search API '
db, ndb = self.init_old(), self.init_legacy()