Skip to content

Commit 7be4eb5

Browse files
committed
Added libzim 9.3.0 Cache Control API support
1 parent bc954e7 commit 7be4eb5

File tree

6 files changed

+207
-0
lines changed

6 files changed

+207
-0
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Set up documentation using `mkdocs`, published on readthedocs.com (#186)
1313
- `Archive.get_random_entry()`
14+
- libzim 9.3.0 Cache Control API:
15+
- `Archive.cluster_cache_max_size`
16+
- `Archive.cluster_cache_current_size`
17+
- `Archive.dirent_cache_max_size`
18+
- `Archive.dirent_cache_current_size`
19+
- `Archive.dirent_lookup_cache_max_size`
1420

1521
### Changed
1622

libzim/libwrapper.h

+8
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ class Archive : public Wrapper<zim::Archive>
172172
FORWARD(bool, hasTitleIndex)
173173
FORWARD(bool, hasChecksum)
174174
FORWARD(bool, check)
175+
FORWARD(zim::size_type, getClusterCacheMaxSize)
176+
FORWARD(zim::size_type, getClusterCacheCurrentSize)
177+
FORWARD(void, setClusterCacheMaxSize)
178+
FORWARD(zim::size_type, getDirentCacheMaxSize)
179+
FORWARD(zim::size_type, getDirentCacheCurrentSize)
180+
FORWARD(void, setDirentCacheMaxSize)
181+
FORWARD(zim::size_type, getDirentLookupCacheMaxSize)
182+
FORWARD(void, setDirentLookupCacheMaxSize)
175183
};
176184

177185
class SearchResultSet : public Wrapper<zim::SearchResultSet>

libzim/libzim.pyx

+89
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,95 @@ cdef class Archive:
13331333
except RuntimeError as e:
13341334
raise KeyError(str(e))
13351335
1336+
@property
1337+
def cluster_cache_max_size(self) -> pyint:
1338+
"""Maximum size of the cluster cache.
1339+
1340+
Returns:
1341+
(int): maximum number of clusters stored in the cache.
1342+
"""
1343+
return self.c_archive.getClusterCacheMaxSize()
1344+
1345+
@cluster_cache_max_size.setter
1346+
def cluster_cache_max_size(self, nb_clusters: pyint):
1347+
"""Set the size of the cluster cache.
1348+
1349+
If the new size is lower than the number of currently stored clusters
1350+
some clusters will be dropped from cache to respect the new size.
1351+
1352+
Args:
1353+
nb_clusters (int): maximum number of clusters stored in the cache
1354+
"""
1355+
1356+
self.c_archive.setClusterCacheMaxSize(nb_clusters)
1357+
1358+
@property
1359+
def cluster_cache_current_size(self) -> pyint:
1360+
"""Size of the cluster cache.
1361+
1362+
Returns:
1363+
(int): number of clusters currently stored in the cache.
1364+
"""
1365+
return self.c_archive.getClusterCacheCurrentSize()
1366+
1367+
@property
1368+
def dirent_cache_max_size(self) -> pyint:
1369+
"""Maximum size of the dirent cache.
1370+
1371+
Returns:
1372+
(int): maximum number of dirents stored in the cache.
1373+
"""
1374+
return self.c_archive.getDirentCacheMaxSize()
1375+
1376+
@dirent_cache_max_size.setter
1377+
def dirent_cache_max_size(self, nb_dirents: pyint):
1378+
"""Set the size of the dirent cache.
1379+
1380+
If the new size is lower than the number of currently stored dirents
1381+
some dirents will be dropped from cache to respect the new size.
1382+
1383+
Args:
1384+
nb_dirents (int): maximum number of dirents stored in the cache.
1385+
"""
1386+
self.c_archive.setDirentCacheMaxSize(nb_dirents)
1387+
1388+
@property
1389+
def dirent_cache_current_size(self) -> pyint:
1390+
"""Size of the dirent cache.
1391+
1392+
Returns:
1393+
(int): number of dirents currently stored in the cache.
1394+
"""
1395+
return self.c_archive.getDirentCacheCurrentSize()
1396+
1397+
@property
1398+
def dirent_lookup_cache_max_size(self) -> pyint:
1399+
"""Size of the dirent lookup cache.
1400+
1401+
The returned size returns the default size or the last set size.
1402+
This may not correspond to the actual size of the dirent lookup cache.
1403+
See set_dirent_lookup_cache_max_size for more information.
1404+
1405+
Returns:
1406+
(int): maximum number of sub ranges created in the lookup cache.
1407+
"""
1408+
return self.c_archive.getDirentLookupCacheMaxSize()
1409+
1410+
@dirent_lookup_cache_max_size.setter
1411+
def dirent_lookup_cache_max_size(self, nb_ranges: pyint):
1412+
"""Set the size of the dirent lookup cache.
1413+
1414+
Contrary to other set_<foo>_cache_max_size, this method is useless
1415+
once the lookup cache is created.
1416+
The lookup cache is created at first access to a entry in the archive.
1417+
So this method must be called before any access to content (including metadata).
1418+
It is best to call this method first, just after the archive creation.
1419+
1420+
Args:
1421+
nb_ranges (int): maximum number of sub ranges created in the lookup cache.
1422+
"""
1423+
self.c_archive.setDirentLookupCacheMaxSize(nb_ranges)
1424+
13361425
def __repr__(self) -> str:
13371426
return f"{self.__class__.__name__}(filename={self.filename})"
13381427

libzim/reader.pyi

+16
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,20 @@ class Archive:
7777
def get_illustration_sizes(self) -> set[int]: ...
7878
def has_illustration(self, size: int | None = None) -> bool: ...
7979
def get_illustration_item(self, size: int | None = None) -> Item: ...
80+
@property
81+
def cluster_cache_max_size(self) -> int: ...
82+
@cluster_cache_max_size.setter
83+
def cluster_cache_max_size(self, nb_clusters: int): ...
84+
@property
85+
def cluster_cache_current_size(self) -> int: ...
86+
@property
87+
def dirent_cache_max_size(self) -> int: ...
88+
@dirent_cache_max_size.setter
89+
def dirent_cache_max_size(self, nb_dirents: int): ...
90+
@property
91+
def dirent_cache_current_size(self) -> int: ...
92+
@property
93+
def dirent_lookup_cache_max_size(self) -> int: ...
94+
@dirent_lookup_cache_max_size.setter
95+
def dirent_lookup_cache_max_size(self, nb_ranges: int): ...
8096
def __repr__(self) -> str: ...

libzim/zim.pxd

+9
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ cdef extern from "libwrapper.h" namespace "wrapper":
178178
bool hasChecksum() except +
179179
bool check() except +
180180

181+
uint64_t getClusterCacheMaxSize() except +
182+
uint64_t getClusterCacheCurrentSize() except +
183+
void setClusterCacheMaxSize(uint64_t nbClusters) except +
184+
uint64_t getDirentCacheMaxSize() except +
185+
uint64_t getDirentCacheCurrentSize() except +
186+
void setDirentCacheMaxSize(uint64_t nbDirents) except +
187+
uint64_t getDirentLookupCacheMaxSize() except +
188+
void setDirentLookupCacheMaxSize(uint64_t nbRanges) except +
189+
181190
cdef cppclass Searcher:
182191
Searcher()
183192
Searcher(const Archive& archive) except +

tests/test_libzim_reader.py

+79
Original file line numberDiff line numberDiff line change
@@ -615,3 +615,82 @@ def test_reader_get_random_entry(all_zims):
615615
zim_2 = Archive(all_zims / "example.zim")
616616
with pytest.raises(KeyError):
617617
zim_2.get_random_entry()
618+
619+
620+
@skip_if_offline
621+
@pytest.mark.parametrize(*parametrize_for(["filename"]))
622+
def test_cluster_cache(all_zims, filename):
623+
zim = Archive(all_zims / filename)
624+
default_value = 16
625+
new_value = 1
626+
empty_value = 0
627+
628+
assert zim.cluster_cache_max_size == default_value
629+
630+
zim.cluster_cache_max_size = new_value
631+
assert zim.cluster_cache_max_size == new_value
632+
633+
# test index access
634+
for index in range(0, zim.entry_count - 1):
635+
bytes(zim._get_entry_by_id(index).get_item().content)
636+
637+
assert zim.cluster_cache_current_size <= new_value
638+
639+
zim.cluster_cache_max_size = empty_value
640+
assert zim.cluster_cache_max_size == empty_value
641+
642+
for index in range(0, zim.entry_count - 1):
643+
bytes(zim._get_entry_by_id(index).get_item().content)
644+
645+
assert zim.cluster_cache_current_size == empty_value
646+
647+
648+
@skip_if_offline
649+
@pytest.mark.parametrize(*parametrize_for(["filename"]))
650+
def test_dirent_cache(all_zims, filename):
651+
zim = Archive(all_zims / filename)
652+
default_value = 512
653+
new_value = 2
654+
empty_value = 0
655+
656+
assert zim.dirent_cache_max_size == default_value
657+
658+
zim.dirent_cache_max_size = new_value
659+
assert zim.dirent_cache_max_size == new_value
660+
661+
# test index access
662+
for index in range(0, zim.entry_count - 1):
663+
bytes(zim._get_entry_by_id(index).get_item().content)
664+
665+
assert zim.dirent_cache_current_size <= new_value
666+
667+
zim.dirent_cache_max_size = empty_value
668+
assert zim.dirent_cache_max_size == empty_value
669+
assert zim.dirent_cache_current_size == empty_value
670+
671+
for index in range(0, zim.entry_count - 1):
672+
bytes(zim._get_entry_by_id(index).get_item().content)
673+
674+
assert zim.dirent_cache_current_size == empty_value
675+
676+
677+
@skip_if_offline
678+
@pytest.mark.parametrize(*parametrize_for(["filename"]))
679+
def test_dirent_lookup_cache(all_zims, filename):
680+
zim = Archive(all_zims / filename)
681+
default_value = 1024
682+
new_value = 2
683+
empty_value = 0
684+
685+
assert zim.dirent_lookup_cache_max_size == default_value
686+
687+
zim.dirent_lookup_cache_max_size = new_value
688+
assert zim.dirent_lookup_cache_max_size == new_value
689+
690+
# test index access
691+
for index in range(0, zim.entry_count - 1):
692+
bytes(zim._get_entry_by_id(index).get_item().content)
693+
694+
# setting after reading records the value but it has no use
695+
zim.dirent_lookup_cache_max_size = empty_value
696+
assert zim.dirent_lookup_cache_max_size == empty_value

0 commit comments

Comments
 (0)