X-Git-Url: http://git.maemo.org/git/?p=feedingit;a=blobdiff_plain;f=src%2Frss_sqlite.py;h=5735de2b180dfd43d9aa28cd7c43a08dd2196a21;hp=6551d938d136cc1ddc2203ecf4afd646d51dfd34;hb=b934aa51aeced7221d9bb09061e2c9680d971dd8;hpb=892fef8d5427f1f46d76ab0d28cdc4adba4031cc diff --git a/src/rss_sqlite.py b/src/rss_sqlite.py index 6551d93..5735de2 100644 --- a/src/rss_sqlite.py +++ b/src/rss_sqlite.py @@ -81,7 +81,108 @@ update_feeds_iface = None jobs_at_start = 0 -class Feed: +class BaseObject(object): + # Columns to cache. Classes that inherit from this and use the + # cache mechanism should set this to a list of tuples, each of + # which contains two entries: the table and the column. Note that + # both are case sensitive. + cached_columns = () + + def cache_invalidate(self, table=None): + """ + Invalidate the cache. + + If table is not None, invalidate only the specified table. + Otherwise, drop the whole cache. + """ + if not hasattr(self, 'cache'): + return + + if table is None: + del self.cache + else: + if table in self.cache: + del self.cache[table] + + def lookup(self, table, column, id=None): + """ + Look up a column or value. Uses a cache for columns in + cached_columns. Note: the column is returned unsorted. + """ + if not hasattr(self, 'cache'): + self.cache = {} + + # Cache data for at most 60 seconds. + now = time.time() + try: + cache = self.cache[table] + + if time.time() - cache[None] > 60: + self.cache[table].clear() + except KeyError: + cache = None + + if (cache is None + or (table, column) not in self.cached_columns): + # The cache is empty or the caller wants a column that we + # don't cache. + if (table, column) in self.cached_columns: + do_cache = True + + self.cache[table] = cache = {} + columns = [] + for t, c in self.cached_columns: + if table == t: + cache[c] = {} + columns.append(c) + + columns.append('id') + where = "" + else: + do_cache = False + + columns = (colums,) + if id is not None: + where = "where id = '%s'" % id + else: + where = "" + + results = self.db.execute( + "SELECT %s FROM %s %s" % (','.join(columns), table, where)) + + if do_cache: + for r in results: + values = list(r) + i = values.pop() + for index, value in enumerate(values): + cache[columns[index]][i] = value + + cache[None] = now + else: + results = [] + for r in results: + if id is not None: + return values[0] + + results.append(values[0]) + + return results + else: + cache = self.cache[table] + + try: + if id is not None: + return cache[column][id] + else: + return cache[column].values() + except KeyError: + return None + +class Feed(BaseObject): + # Columns to cache. + cached_columns = (('feed', 'read'), + ('feed', 'title')) + serial_execution_lock = threading.Lock() def _getdb(self): @@ -528,6 +629,8 @@ class Feed: postFeedUpdateFunc (self.key, updateTime, etag, modified, title, *postFeedUpdateFuncArgs) + self.cache_invalidate() + def setEntryRead(self, id): self.db.execute("UPDATE feed SET read=1 WHERE id=?;", (id,) ) self.db.commit() @@ -539,21 +642,23 @@ class Feed: pass if wc().available(): mainthread.execute(doit, async=True) + self.cache_invalidate('feed') def setEntryUnread(self, id): self.db.execute("UPDATE feed SET read=0 WHERE id=?;", (id,) ) self.db.commit() + self.cache_invalidate('feed') def markAllAsRead(self): self.db.execute("UPDATE feed SET read=1 WHERE read=0;") self.db.commit() + self.cache_invalidate('feed') def isEntryRead(self, id): - read_status = self.db.execute("SELECT read FROM feed WHERE id=?;", (id,) ).fetchone()[0] - return read_status==1 # Returns True if read==1, and False if read==0 + return self.lookup('feed', 'read', id) == 1 def getTitle(self, id): - return self.db.execute("SELECT title FROM feed WHERE id=?;", (id,) ).fetchone()[0] + return self.lookup('feed', 'title', id) def getContentLink(self, id): return self.db.execute("SELECT contentLink FROM feed WHERE id=?;", (id,) ).fetchone()[0] @@ -754,7 +859,13 @@ class ArchivedArticles(Feed): pass self.removeEntry(id) -class Listing: +class Listing(BaseObject): + # Columns to cache. + cached_columns = (('feeds', 'updateTime'), + ('feeds', 'unread'), + ('feeds', 'title'), + ('categories', 'title')) + def _getdb(self): try: db = self.tls.db @@ -925,6 +1036,7 @@ class Listing: self.db.execute("UPDATE feeds SET title=(case WHEN title=='' THEN ? ELSE title END) where id=?;", (title, key)) self.db.commit() + self.cache_invalidate('feeds') self.updateUnread(key) update_server_object().ArticleCountUpdated() @@ -955,6 +1067,7 @@ class Listing: else: self.db.execute("UPDATE feeds SET title=?, url=? WHERE id=?;", (title, url, key)) self.db.commit() + self.cache_invalidate('feeds') if wc().available(): try: @@ -963,8 +1076,7 @@ class Listing: logger.debug("Feed %s (%s) unknown." % (key, title)) def getFeedUpdateTime(self, key): - update_time = self.db.execute( - "SELECT updateTime FROM feeds WHERE id=?;", (key,)).fetchone()[0] + update_time = self.lookup('feeds', 'updateTime', key) if not update_time: return "Never" @@ -998,13 +1110,14 @@ class Listing: return time.strftime("%x", time.gmtime(update_time)) def getFeedNumberOfUnreadItems(self, key): - return self.db.execute("SELECT unread FROM feeds WHERE id=?;", (key,)).fetchone()[0] + return self.lookup('feeds', 'unread', key) def getFeedTitle(self, key): - (title, url) = self.db.execute("SELECT title, url FROM feeds WHERE id=?;", (key,)).fetchone() + title = self.lookup('feeds', 'title', key) if title: return title - return url + + return self.getFeedUrl(key) def getFeedUrl(self, key): return self.db.execute("SELECT url FROM feeds WHERE id=?;", (key,)).fetchone()[0] @@ -1024,16 +1137,11 @@ class Listing: return keys def getListOfCategories(self): - rows = self.db.execute("SELECT id FROM categories ORDER BY rank;" ) - keys = [] - for row in rows: - if row[0]: - keys.append(row[0]) - return keys + return list(row[0] for row in self.db.execute( + "SELECT id FROM categories ORDER BY rank;")) def getCategoryTitle(self, id): - row = self.db.execute("SELECT title FROM categories WHERE id=?;", (id, )).fetchone() - return row[0] + return self.lookup('categories', 'title', id) def getSortedListOfKeys(self, order, onlyUnread=False, category=1): if order == "Most unread": @@ -1073,6 +1181,7 @@ class Listing: feed = self.getFeed(key) self.db.execute("UPDATE feeds SET unread=? WHERE id=?;", (feed.getNumberOfUnreadItems(), key)) self.db.commit() + self.cache_invalidate('feeds') def addFeed(self, title, url, id=None, category=1): if not id: