

diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 396c37a91b..4d8cd6fdf2 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -53,7 +53,7 @@ def sanitize_file_name(name, substitute='_'): FIELD_MAP = {'id':0, 'title':1, 'authors':2, 'publisher':3, 'rating':4, 'timestamp':5, 'size':6, 'tags':7, 'comments':8, 'series':9, 'series_index':10, - 'sort':11, 'author_sort':12, 'formats':13, 'isbn':14} + 'sort':11, 'author_sort':12, 'formats':13, 'isbn':14, 'path':15} INDEX_MAP = dict(zip(FIELD_MAP.values(), FIELD_MAP.keys())) @@ -414,15 +414,39 @@ class LibraryDatabase2(LibraryDatabase): self.conn.executescript(script%dict(ltable='tags', table='tags', ltable_col='tag')) self.conn.executescript(script%dict(ltable='series', table='series', ltable_col='series')) + def upgrade_version_3(self): + ' Add path to result cache ' + self.conn.executescript(''' + DROP VIEW meta; + CREATE VIEW meta AS + SELECT id, title, + (SELECT concat(name) FROM authors WHERE authors.id IN (SELECT author from books_authors_link WHERE book=books.id)) authors, + (SELECT name FROM publishers WHERE publishers.id IN (SELECT publisher from books_publishers_link WHERE book=books.id)) publisher, + (SELECT rating FROM ratings WHERE ratings.id IN (SELECT rating from books_ratings_link WHERE book=books.id)) rating, + timestamp, + (SELECT MAX(uncompressed_size) FROM data WHERE book=books.id) size, + (SELECT concat(name) FROM tags WHERE tags.id IN (SELECT tag from books_tags_link WHERE book=books.id)) tags, + (SELECT text FROM comments WHERE book=books.id) comments, + (SELECT name FROM series WHERE series.id IN (SELECT series FROM books_series_link WHERE book=books.id)) series, + series_index, + sort, + author_sort, + (SELECT concat(format) FROM data WHERE data.book=books.id) formats, + isbn, + path + FROM books; + ''') + + def last_modified(self): ''' Return last modified time as a UTC datetime object''' return datetime.utcfromtimestamp(os.stat(self.dbpath).st_mtime) def path(self, index, index_is_id=False): 'Return the relative path to the directory containing this books files as a unicode string.' - id = index if index_is_id else self.id(index) - path = self.conn.get('SELECT path FROM books WHERE id=?', (id,), all=False).replace('/', os.sep) - return path + row = self.data._data[index] if index_is_id else self.data[index] + return row[FIELD_MAP['path']].replace('/', os.sep) + def abspath(self, index, index_is_id=False): 'Return the absolute path to the directory containing this books files as a unicode string.' @@ -496,6 +520,7 @@ class LibraryDatabase2(LibraryDatabase): self.add_format(id, format, stream, index_is_id=True, path=tpath) self.conn.execute('UPDATE books SET path=? WHERE id=?', (path, id)) self.conn.commit() + self.data.set(id, FIELD_MAP['path'], path, row_is_id=True) # Delete not needed directories if current_path and os.path.exists(spath): if normpath(spath) != normpath(tpath): @@ -650,8 +675,8 @@ class LibraryDatabase2(LibraryDatabase): ''' Removes book from the result cache and the underlying database. ''' + path = os.path.join(self.library_path, self.path(id, index_is_id=True)) self.data.remove(id) - path = os.path.join(self.library_path, self.path(id, True)) if os.path.exists(path): shutil.rmtree(path) parent = os.path.dirname(path) diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py index 9b044f478e..9cf15e2680 100644 --- a/src/calibre/library/server.py +++ b/src/calibre/library/server.py @@ -123,12 +123,11 @@ class LibraryServer(object): def get_cover(self, id, thumbnail=False): cover = self.db.cover(id, index_is_id=True, as_file=True) if cover is None: - raise cherrypy.HTTPError(404, 'no cover available for id: %d'%id) + cover = cStringIO.StringIO(server_resources['default_cover.jpg']) cherrypy.response.headers['Content-Type'] = 'image/jpeg' - path = getattr(cover, 'name', None) - if path and os.path.exists(path): - updated = datetime.utcfromtimestamp(os.stat(path).st_mtime) - cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) + path = getattr(cover, 'name', False) + updated = datetime.utcfromtimestamp(os.stat(path).st_mtime) if path and os.access(path, os.R_OK) else build_time + cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) if not thumbnail: return cover.read() try: diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py index e42efe30e2..938e5e665c 100644 --- a/src/calibre/library/sqlite.py +++ b/src/calibre/library/sqlite.py @@ -11,9 +11,12 @@ import sqlite3 as sqlite, traceback, time from sqlite3 import IntegrityError from threading import Thread from Queue import Queue +from threading import RLock from calibre.library import title_sort +global_lock = RLock() + class Concatenate(object): '''String concatenation aggregator for sqlite''' def __init__(self, sep=','): @@ -93,15 +96,16 @@ class DatabaseException(Exception): def proxy(fn): ''' Decorator to call methods on the database connection in the proxy thread ''' def run(self, *args, **kwargs): - if self.proxy.unhandled_error[0] is not None: - raise DatabaseException(*self.proxy.unhandled_error) - self.proxy.requests.put((fn.__name__, args, kwargs)) - ok, res = self.proxy.results.get() - if not ok: - if isinstance(res[0], IntegrityError): - raise IntegrityError(unicode(res[0])) - raise DatabaseException(*res) - return res + with global_lock: + if self.proxy.unhandled_error[0] is not None: + raise DatabaseException(*self.proxy.unhandled_error) + self.proxy.requests.put((fn.__name__, args, kwargs)) + ok, res = self.proxy.results.get() + if not ok: + if isinstance(res[0], IntegrityError): + raise IntegrityError(unicode(res[0])) + raise DatabaseException(*res) + return res return run diff --git a/src/calibre/library/static/gui.css b/src/calibre/library/static/gui.css index 10446d53ea..df93396786 100644 --- a/src/calibre/library/static/gui.css +++ b/src/calibre/library/static/gui.css @@ -140,8 +140,3 @@ Loading message z-index: 2; margin: 0pt; padding: 0pt; border-width: 0pt; } - -#cover_pane img { - border: solid thin black; - z-index: 10; -} diff --git a/src/calibre/library/static/gui.js b/src/calibre/library/static/gui.js index 907d82c14b..582fbe8d4d 100644 --- a/src/calibre/library/static/gui.js +++ b/src/calibre/library/static/gui.js @@ -118,6 +118,7 @@ function fetch_library_books(start, num, timeout, sort, order, search) { current_library_request = null; } + $('#cover_pane').css('visibility', 'hidden'); $('#loading').css('visibility', 'visible'); current_library_request = $.ajax({ diff --git a/src/calibre/library/static/index.html b/src/calibre/library/static/index.html index 45c902a080..19d8c42c51 100644 --- a/src/calibre/library/static/index.html +++ b/src/calibre/library/static/index.html @@ -22,7 +22,7 @@