@ -5,7 +5,9 @@
local Cache = require ( " cache " )
local CanvasContext = require ( " document/canvascontext " )
local DataStorage = require ( " datastorage " )
local lfs = require ( " libs/libkoreader-lfs " )
local logger = require ( " logger " )
local md5 = require ( " ffi/sha2 " ) . md5
local function calcCacheMemSize ( )
local min = DGLOBAL_CACHE_SIZE_MINIMUM
@ -13,23 +15,22 @@ local function calcCacheMemSize()
local calc = Cache : _calcFreeMem ( ) * ( DGLOBAL_CACHE_FREE_PROPORTION or 0 )
return math.min ( max , math.max ( min , calc ) )
end
local cache_size = calcCacheMemSize ( )
local doccache_size = calcCacheMemSize ( )
local function computeCacheSize ( )
local mb_size = cache_size / 1024 / 1024
local mb_size = doc cache_size / 1024 / 1024
-- If we end up with a not entirely ridiculous cache size, use that...
if mb_size >= 8 then
logger.dbg ( string.format ( " Allocating a %dMB budget for the global document cache " , mb_size ) )
return cache_size
return doc cache_size
else
return nil
end
end
local function computeCacheSlots ( )
local mb_size = cache_size / 1024 / 1024
local mb_size = doc cache_size / 1024 / 1024
--- ...otherwise, effectively disable the cache by making it single slot...
if mb_size < 8 then
@ -51,4 +52,65 @@ local DocCache = Cache:new{
cache_path = DataStorage : getDataDir ( ) .. " /cache/ " ,
}
function DocCache : serialize ( doc_path )
if not self.disk_cache then
return
end
-- Calculate the current disk cache size
local cached_size = 0
local sorted_caches = { }
for _ , file in pairs ( self.cached ) do
table.insert ( sorted_caches , { file = file , time = lfs.attributes ( file , " access " ) } )
cached_size = cached_size + ( lfs.attributes ( file , " size " ) or 0 )
end
table.sort ( sorted_caches , function ( v1 , v2 ) return v1.time > v2.time end )
-- Rewind a bit in order to serialize the currently *displayed* page for the current document,
-- as the actual MRU item would be the most recently *hinted* page, which wouldn't be helpful ;).
if doc_path then
local mru_key
local mru_found = 0
for key , item in self.cache : pairs ( ) do
-- Only dump items that actually request persistence and match the current document.
if item.persistent and item.dump and item.doc_path == doc_path then
mru_key = key
mru_found = mru_found + 1
if mru_found >= ( 1 + DHINTCOUNT ) then
-- We found the right item, i.e., the *displayed* page
break
end
end
end
if mru_key then
local cache_full_path = self.cache_path .. md5 ( mru_key )
local cache_file_exists = lfs.attributes ( cache_full_path )
if not cache_file_exists then
logger.dbg ( " Dumping cache item " , mru_key )
local cache_item = self.cache : get ( mru_key )
local cache_size = cache_item : dump ( cache_full_path )
if cache_size then
cached_size = cached_size + cache_size
end
end
end
end
-- Allocate the same amount of storage to the disk cache than the memory cache
while cached_size > self.size do
-- discard the least recently used cache
local discarded = table.remove ( sorted_caches )
if discarded then
cached_size = cached_size - lfs.attributes ( discarded.file , " size " )
os.remove ( discarded.file )
else
logger.warn ( " Cache accounting is broken " )
break
end
end
-- We may have updated the disk cache's content, so refresh its state
self : refreshSnapshot ( )
end
return DocCache