Skip to content

Commit 24fadab

Browse files
committed
Change eviction policy to use new-style string formatting and add test for custom eviction policy
1 parent d8f79d5 commit 24fadab

2 files changed

Lines changed: 61 additions & 21 deletions

File tree

diskcache/core.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,23 +95,23 @@ def __repr__(self):
9595
' Cache (store_time)'
9696
),
9797
'get': None,
98-
'cull': 'SELECT %s FROM Cache ORDER BY store_time LIMIT ?',
98+
'cull': 'SELECT {fields} FROM Cache ORDER BY store_time LIMIT ?',
9999
},
100100
'least-recently-used': {
101101
'init': (
102102
'CREATE INDEX IF NOT EXISTS Cache_access_time ON'
103103
' Cache (access_time)'
104104
),
105-
'get': 'access_time = ((julianday("now") - 2440587.5) * 86400.0)',
106-
'cull': 'SELECT %s FROM Cache ORDER BY access_time LIMIT ?',
105+
'get': 'access_time = {now}',
106+
'cull': 'SELECT {fields} FROM Cache ORDER BY access_time LIMIT ?',
107107
},
108108
'least-frequently-used': {
109109
'init': (
110110
'CREATE INDEX IF NOT EXISTS Cache_access_count ON'
111111
' Cache (access_count)'
112112
),
113113
'get': 'access_count = access_count + 1',
114-
'cull': 'SELECT %s FROM Cache ORDER BY access_count LIMIT ?',
114+
'cull': 'SELECT {fields} FROM Cache ORDER BY access_count LIMIT ?',
115115
},
116116
}
117117

@@ -739,21 +739,20 @@ def _cull(self, now, sql, cleanup, limit=None):
739739

740740
# Evict keys by policy.
741741

742-
select_policy_template = EVICTION_POLICY[self.eviction_policy]['cull']
742+
select_policy = EVICTION_POLICY[self.eviction_policy]['cull']
743743

744-
if select_policy_template is None or self.volume() < self.size_limit:
744+
if select_policy is None or self.volume() < self.size_limit:
745745
return
746746

747-
select_policy = select_policy_template % 'filename'
748-
749-
rows = sql(select_policy, (cull_limit,)).fetchall()
747+
select_filename = select_policy.format(fields='filename', now=now)
748+
rows = sql(select_filename, (cull_limit,)).fetchall()
750749

751750
if rows:
752-
delete_policy = (
751+
delete = (
753752
'DELETE FROM Cache WHERE rowid IN (%s)'
754-
% (select_policy_template % 'rowid')
753+
% (select_policy.format(fields='rowid', now=now))
755754
)
756-
sql(delete_policy, (cull_limit,))
755+
sql(delete, (cull_limit,))
757756

758757
for filename, in rows:
759758
cleanup(filename)
@@ -868,7 +867,10 @@ def incr(self, key, delta=1, default=0):
868867

869868
columns = 'store_time = ?, value = ?'
870869
update_column = EVICTION_POLICY[self.eviction_policy]['get']
871-
columns += '' if update_column is None else ', ' + update_column
870+
871+
if update_column is not None:
872+
columns += ', ' + update_column.format(now=now)
873+
872874
update = 'UPDATE Cache SET %s WHERE rowid = ?' % columns
873875
sql(update, (now, value, rowid))
874876

@@ -918,7 +920,6 @@ def get(self, key, default=None, read=False, expire_time=False, tag=False):
918920
"""
919921
db_key, raw = self._disk.put(key)
920922
update_column = EVICTION_POLICY[self.eviction_policy]['get']
921-
update = 'UPDATE Cache SET %s WHERE rowid = ?'
922923
select = (
923924
'SELECT rowid, expire_time, tag, mode, filename, value'
924925
' FROM Cache WHERE key = ? AND raw = ?'
@@ -950,7 +951,6 @@ def get(self, key, default=None, read=False, expire_time=False, tag=False):
950951
raise
951952

952953
else: # Slow path, transaction required.
953-
954954
cache_hit = (
955955
'UPDATE Settings SET value = value + 1 WHERE key = "hits"'
956956
)
@@ -983,8 +983,11 @@ def get(self, key, default=None, read=False, expire_time=False, tag=False):
983983
if self.statistics:
984984
sql(cache_hit)
985985

986+
now = time.time()
987+
update = 'UPDATE Cache SET %s WHERE rowid = ?'
988+
986989
if update_column is not None:
987-
sql(update % update_column, (rowid,))
990+
sql(update % update_column.format(now=now), (rowid,))
988991

989992
if expire_time and tag:
990993
return (value, db_expire_time, db_tag)
@@ -1568,25 +1571,25 @@ def cull(self):
15681571

15691572
# Remove items by policy.
15701573

1571-
select_policy_template = EVICTION_POLICY[self.eviction_policy]['cull']
1574+
select_policy = EVICTION_POLICY[self.eviction_policy]['cull']
15721575

1573-
if select_policy_template is None:
1576+
if select_policy is None:
15741577
return
15751578

1576-
select_policy = select_policy_template % 'filename'
1579+
select_filename = select_policy.format(fields='filename', now=now)
15771580

15781581
try:
15791582
while self.volume() > self.size_limit:
15801583
with self._transact() as (sql, cleanup):
1581-
rows = sql(select_policy, (10,)).fetchall()
1584+
rows = sql(select_filename, (10,)).fetchall()
15821585

15831586
if not rows:
15841587
break
15851588

15861589
count += len(rows)
15871590
delete = (
15881591
'DELETE FROM Cache WHERE rowid IN (%s)'
1589-
% (select_policy_template % 'rowid')
1592+
% select_policy.format(fields='rowid', now=now)
15901593
)
15911594
sql(delete, (10,))
15921595

tests/test_core.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,43 @@ def test_rsync():
14481448
shutil.rmtree('tmp', ignore_errors=True)
14491449

14501450

1451+
@setup_cache
1452+
def test_custom_eviction_policy(cache):
1453+
dc.EVICTION_POLICY['lru-gt-1s'] = {
1454+
'init': (
1455+
'CREATE INDEX IF NOT EXISTS Cache_access_time ON'
1456+
' Cache (access_time)'
1457+
),
1458+
'get': 'access_time = {now}',
1459+
'cull': (
1460+
'SELECT {fields} FROM Cache'
1461+
' WHERE access_time < ({now} - 1)'
1462+
' ORDER BY access_time LIMIT ?'
1463+
),
1464+
}
1465+
1466+
size_limit = int(1e5)
1467+
1468+
cache.reset('eviction_policy', 'lru-gt-1s')
1469+
cache.reset('size_limit', size_limit)
1470+
1471+
for count in range(100, 150):
1472+
cache[count] = str(count) * 500
1473+
1474+
size = cache.volume()
1475+
assert size > size_limit
1476+
assert cache.cull() == 0
1477+
assert size == cache.volume()
1478+
1479+
for count in range(100, 150):
1480+
assert cache[count] == str(count) * 500
1481+
1482+
time.sleep(1.1)
1483+
1484+
assert cache.cull() == 20
1485+
assert cache.volume() < size_limit
1486+
1487+
14511488
if __name__ == '__main__':
14521489
import nose
14531490
nose.runmodule()

0 commit comments

Comments
 (0)