Ensure that an error in set_metadata does not cause the memory and disk

data to diverge
This commit is contained in:
Kovid Goyal 2013-07-30 11:46:54 +05:30
parent 82d7bd3d57
commit 2fd8022e9e

View File

@ -1094,48 +1094,52 @@ class Cache(object):
if cdata is not None: if cdata is not None:
self._set_cover({book_id: cdata}) self._set_cover({book_id: cdata})
with self.backend.conn: # Speed up set_metadata by not operating in autocommit mode try:
for field in ('rating', 'series_index', 'timestamp'): with self.backend.conn: # Speed up set_metadata by not operating in autocommit mode
val = getattr(mi, field) for field in ('rating', 'series_index', 'timestamp'):
if val is not None: val = getattr(mi, field)
protected_set_field(field, val) if val is not None:
protected_set_field(field, val)
for field in ('author_sort', 'publisher', 'series', 'tags', 'comments', for field in ('author_sort', 'publisher', 'series', 'tags', 'comments',
'languages', 'pubdate'): 'languages', 'pubdate'):
val = mi.get(field, None) val = mi.get(field, None)
if (force_changes and val is not None) or not mi.is_null(field): if (force_changes and val is not None) or not mi.is_null(field):
protected_set_field(field, val) protected_set_field(field, val)
val = mi.get('title_sort', None) val = mi.get('title_sort', None)
if (force_changes and val is not None) or not mi.is_null('title_sort'): if (force_changes and val is not None) or not mi.is_null('title_sort'):
protected_set_field('sort', val) protected_set_field('sort', val)
# identifiers will always be replaced if force_changes is True # identifiers will always be replaced if force_changes is True
mi_idents = mi.get_identifiers() mi_idents = mi.get_identifiers()
if force_changes: if force_changes:
protected_set_field('identifiers', mi_idents) protected_set_field('identifiers', mi_idents)
elif mi_idents: elif mi_idents:
identifiers = self._field_for('identifiers', book_id, default_value={}) identifiers = self._field_for('identifiers', book_id, default_value={})
for key, val in mi_idents.iteritems(): for key, val in mi_idents.iteritems():
if val and val.strip(): # Don't delete an existing identifier if val and val.strip(): # Don't delete an existing identifier
identifiers[icu_lower(key)] = val identifiers[icu_lower(key)] = val
protected_set_field('identifiers', identifiers) protected_set_field('identifiers', identifiers)
user_mi = mi.get_all_user_metadata(make_copy=False) user_mi = mi.get_all_user_metadata(make_copy=False)
fm = self.field_metadata fm = self.field_metadata
for key in user_mi.iterkeys(): for key in user_mi.iterkeys():
if (key in fm and if (key in fm and
user_mi[key]['datatype'] == fm[key]['datatype'] and user_mi[key]['datatype'] == fm[key]['datatype'] and
(user_mi[key]['datatype'] != 'text' or (user_mi[key]['datatype'] != 'text' or
user_mi[key]['is_multiple'] == fm[key]['is_multiple'])): user_mi[key]['is_multiple'] == fm[key]['is_multiple'])):
val = mi.get(key, None) val = mi.get(key, None)
if force_changes or val is not None: if force_changes or val is not None:
protected_set_field(key, val) protected_set_field(key, val)
idx = key + '_index' idx = key + '_index'
if idx in self.fields: if idx in self.fields:
extra = mi.get_extra(key) extra = mi.get_extra(key)
if extra is not None or force_changes: if extra is not None or force_changes:
protected_set_field(idx, extra) protected_set_field(idx, extra)
except:
self._reload_from_db()
raise
@write_api @write_api
def add_format(self, book_id, fmt, stream_or_path, replace=True, run_hooks=True, dbapi=None): def add_format(self, book_id, fmt, stream_or_path, replace=True, run_hooks=True, dbapi=None):