From 8c9751744ec6ff6ccea23f91f4b86e41cf472b87 Mon Sep 17 00:00:00 2001 From: chrox Date: Thu, 30 Oct 2014 11:05:22 +0800 Subject: [PATCH] fix #1064 by adding timestamp of document in cache key so that when document is modified the persistent cache will be invalidated automatically because the cache key will not be matched. There is no perfermance overhead here at all. We even don't need to check the modification time of the cache item on disk, because the name of the on disk cache is a md5sum of the cacheitem key, now the filename of the cache files contains the modification time information. If the document is modified since one rendered page is cached to disk, the cache key won't match the cache file. And the cache file will be discarded without the need to open the cache file or to check the modification time of the cache file itself. --- frontend/document/document.lua | 22 +++++++++++++++------- frontend/document/koptinterface.lua | 11 +++++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/frontend/document/document.lua b/frontend/document/document.lua index 535e09893..f274b6dda 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -1,11 +1,12 @@ +local TileCacheItem = require("document/tilecacheitem") local DrawContext = require("ffi/drawcontext") +local Configurable = require("configurable") local Blitbuffer = require("ffi/blitbuffer") -local Cache = require("cache") +local lfs = require("libs/libkoreader-lfs") local CacheItem = require("cacheitem") -local TileCacheItem = require("document/tilecacheitem") local Geom = require("ui/geometry") -local Configurable = require("configurable") local Math = require("optmath") +local Cache = require("cache") local DEBUG = require("dbg") --[[ @@ -114,6 +115,7 @@ function Document:getNativePageDimensions(pageno) end function Document:_readMetadata() + self.mod_time = lfs.attributes(self.file, "modification") self.info.number_of_pages = self._document:getPages() return true end @@ -215,8 +217,13 @@ function Document:getCoverPageImage() return nil end +function Document:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) + return "renderpg|"..self.file.."|"..self.mod_time.."|"..pageno.."|" + ..zoom.."|"..rotation.."|"..gamma.."|"..render_mode +end + function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode) - local hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode + local hash = self:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) local page_size = self:getPageDimensions(pageno, zoom, rotation) -- this will be the size we actually render local size = page_size @@ -231,12 +238,13 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode) return end -- only render required part - hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode.."|"..tostring(rect) + hash = self:getFullPageHash(pageno, zoom, rotation, gamma, render_mode).."|"..tostring(rect) size = rect end -- prepare cache item with contained blitbuffer local tile = TileCacheItem:new{ + persistent = true, size = size.w * size.h + 64, -- estimation excerpt = size, pageno = pageno, @@ -274,7 +282,7 @@ end -- a hint for the cache engine to paint a full page to the cache -- TODO: this should trigger a background operation function Document:hintPage(pageno, zoom, rotation, gamma, render_mode) - local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode + local hash_full_page = self:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) if not Cache:check(hash_full_page, TileCacheItem) then DEBUG("hinting page", pageno) self:renderPage(pageno, nil, zoom, rotation, gamma, render_mode) @@ -290,7 +298,7 @@ Draw page content to blitbuffer. @rect: visible_area inside document page --]] function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) - local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode + local hash_full_page = self:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) local hash_excerpt = hash_full_page.."|"..tostring(rect) local tile = Cache:check(hash_full_page, TileCacheItem) if not tile then diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index 2193f5e29..368a78e37 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -107,7 +107,8 @@ function KoptInterface:getContextHash(doc, pageno, bbox) local screen_size = Screen:getSize() local screen_size_hash = screen_size.w.."|"..screen_size.h local bbox_hash = bbox.x0.."|"..bbox.y0.."|"..bbox.x1.."|"..bbox.y1 - return doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..bbox_hash.."|"..screen_size_hash + return doc.file.."|"..doc.mod_time.."|"..pageno.."|" + ..doc.configurable:hash("|").."|"..bbox_hash.."|"..screen_size_hash end function KoptInterface:getPageBBox(doc, pageno) @@ -215,6 +216,7 @@ function KoptInterface:getCachedContext(doc, pageno) DEBUG("reflowed page", pageno, "fullwidth:", fullwidth, "fullheight:", fullheight) self.last_context_size = fullwidth * fullheight + 128 -- estimation Cache:insert(kctx_hash, ContextCacheItem:new{ + persistent = true, size = self.last_context_size, kctx = kc }) @@ -289,7 +291,7 @@ function KoptInterface:renderReflowedPage(doc, pageno, rect, zoom, rotation, ren end -- prepare cache item with contained blitbuffer local tile = TileCacheItem:new{ - size = fullwidth * fullheight / 2 + 64, -- estimation + size = fullwidth * fullheight + 64, -- estimation excerpt = Geom:new{ w = fullwidth, h = fullheight }, pageno = pageno, } @@ -311,7 +313,7 @@ function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, re local context_hash = self:getContextHash(doc, pageno, bbox) local renderpg_hash = "renderoptpg|"..context_hash..zoom - local cached = Cache:check(renderpg_hash) + local cached = Cache:check(renderpg_hash, TileCacheItem) if not cached then local page_size = Document.getNativePageDimensions(doc, pageno) local bbox = { @@ -329,7 +331,8 @@ function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, re local fullwidth, fullheight = kc:getPageDim() -- prepare cache item with contained blitbuffer local tile = TileCacheItem:new{ - size = fullwidth * fullheight / 2 + 64, -- estimation + persistent = true, + size = fullwidth * fullheight + 64, -- estimation excerpt = Geom:new{ x = 0, y = 0, w = fullwidth,