Fix OPF backup thread

This commit is contained in:
Kovid Goyal 2010-09-26 12:17:37 -06:00
commit d6113a4d6f
3 changed files with 28 additions and 28 deletions

View File

@ -576,9 +576,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
s.exit() s.exit()
except: except:
pass pass
time.sleep(2)
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
time.sleep(2)
self.hide_windows() self.hide_windows()
return True return True

View File

@ -39,6 +39,7 @@ class MetadataBackup(Thread): # {{{
self.do_write = FunctionDispatcher(self.write) self.do_write = FunctionDispatcher(self.write)
self.get_metadata_for_dump = FunctionDispatcher(db.get_metadata_for_dump) self.get_metadata_for_dump = FunctionDispatcher(db.get_metadata_for_dump)
self.clear_dirtied = FunctionDispatcher(db.clear_dirtied) self.clear_dirtied = FunctionDispatcher(db.clear_dirtied)
self.set_dirtied = FunctionDispatcher(db.dirtied)
def stop(self): def stop(self):
self.keep_running = False self.keep_running = False
@ -68,8 +69,9 @@ class MetadataBackup(Thread): # {{{
traceback.print_exc() traceback.print_exc()
continue continue
# at this point the dirty indication is off
if mi is None: if mi is None:
self.clear_dirtied([id_])
continue continue
# Give the GUI thread a chance to do something. Python threads don't # Give the GUI thread a chance to do something. Python threads don't
@ -79,6 +81,7 @@ class MetadataBackup(Thread): # {{{
try: try:
raw = metadata_to_opf(mi) raw = metadata_to_opf(mi)
except: except:
self.set_dirtied([id_])
prints('Failed to convert to opf for id:', id_) prints('Failed to convert to opf for id:', id_)
traceback.print_exc() traceback.print_exc()
continue continue
@ -92,16 +95,11 @@ class MetadataBackup(Thread): # {{{
try: try:
self.do_write(path, raw) self.do_write(path, raw)
except: except:
self.set_dirtied([id_])
prints('Failed to write backup metadata for id:', id_, prints('Failed to write backup metadata for id:', id_,
'again, giving up') 'again, giving up')
continue continue
time.sleep(0.1) # Give the GUI thread a chance to do something
try:
self.clear_dirtied([id_])
except:
prints('Failed to clear dirtied for id:', id_)
def write(self, path, raw): def write(self, path, raw):
with open(path, 'wb') as f: with open(path, 'wb') as f:
f.write(raw) f.write(raw)

View File

@ -573,8 +573,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
The last step is clearing the indicator The last step is clearing the indicator
''' '''
for book_id in book_ids: for book_id in book_ids:
if not self.data.has_id(book_id):
continue
self.conn.execute('DELETE FROM metadata_dirtied WHERE book=?', self.conn.execute('DELETE FROM metadata_dirtied WHERE book=?',
(book_id,)) (book_id,))
# if a later exception prevents the commit, then the dirtied # if a later exception prevents the commit, then the dirtied
@ -588,9 +586,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
commit=True): commit=True):
''' '''
Write metadata for each record to an individual OPF file Write metadata for each record to an individual OPF file
:param dump_to: None or list. If list then instead of writing to file,
data is append to list
''' '''
if book_ids is None: if book_ids is None:
book_ids = [x[0] for x in self.conn.get( book_ids = [x[0] for x in self.conn.get(
@ -598,23 +593,19 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
for book_id in book_ids: for book_id in book_ids:
if not self.data.has_id(book_id): if not self.data.has_id(book_id):
continue continue
path, mi = self.get_metadata_for_dump(book_id) path, mi = self.get_metadata_for_dump(book_id,
remove_from_dirtied=remove_from_dirtied)
if path is None: if path is None:
continue continue
raw = metadata_to_opf(mi) try:
with open(path, 'wb') as f: raw = metadata_to_opf(mi)
f.write(raw) with open(path, 'wb') as f:
if remove_from_dirtied: f.write(raw)
self.conn.execute('DELETE FROM metadata_dirtied WHERE book=?', except:
(book_id,)) # Something went wrong. Put the book back on the dirty list
# if a later exception prevents the commit, then the dirtied self.dirtied([book_id])
# table will still have the book. No big deal, because the OPF
# is there and correct. We will simply do it again on next
# start
self.dirtied_cache.discard(book_id)
if commit: if commit:
self.conn.commit() self.conn.commit()
return True
def dirtied(self, book_ids, commit=True): def dirtied(self, book_ids, commit=True):
for book in book_ids: for book in book_ids:
@ -649,7 +640,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.dirtied_cache = set() self.dirtied_cache = set()
self.dirtied(book_ids) self.dirtied(book_ids)
def get_metadata_for_dump(self, idx): def get_metadata_for_dump(self, idx, remove_from_dirtied=True):
try: try:
path = os.path.join(self.abspath(idx, index_is_id=True), 'metadata.opf') path = os.path.join(self.abspath(idx, index_is_id=True), 'metadata.opf')
mi = self.get_metadata(idx, index_is_id=True) mi = self.get_metadata(idx, index_is_id=True)
@ -658,7 +649,18 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
# cover is set/removed # cover is set/removed
mi.cover = 'cover.jpg' mi.cover = 'cover.jpg'
except: except:
return (None, None) # This almost certainly means that the book has been deleted while
# the backup operation sat in the queue.
path, mi = (None, None)
try:
# clear the dirtied indicator. The user must put it back if
# something goes wrong with writing the OPF
if remove_from_dirtied:
self.clear_dirtied([idx])
except:
# No real problem. We will just do it again.
pass
return (path, mi) return (path, mi)
def get_metadata(self, idx, index_is_id=False, get_cover=False): def get_metadata(self, idx, index_is_id=False, get_cover=False):