Files
MeowOS-SDK/tuku/logic/reader/page_cache.h
T
AskaEth c775f8558c fix(tuku): 评审 P2-1/P2-2——解压页与缩略图缓存互删自愈 + 大页溢出文档化
P2-1(必修):解压页缓存与缩略图 LRU 在 *.bmp 上相互踩踏
- ui/library 的 cache_prune 先按 page_cache 的共用判据 mr_cache_is_page_name
  跳过 mrpage_*,不再把 BMP 解压页算进缩略图额度或 unlink(含 Vol10.cbz 这类
  BMP 档不再出现「被缩略图 LRU 删掉 → 首页解码失败」);
- mr_cache_touch 命中时 stat 校验文件存在与大小,缺失/尺寸不符即移出索引并按
  未命中返回,调用方重新解压——外部清理/掉电残留/误删都能自愈,不再返回死路径。

P2-2(文档化一次性溢出):
- page_cache.h 与 make_room_locked 写明:单条目本身超过 32MiB 时只保留该条、
  其它全部淘汰,占用上限受页源单页 64MiB(MR_ZIP_PAGE_MAX_BYTES)约束;
  大页仍可读,不因预算拒绝落缓存。
- 新增 33MiB 页夹具(PNG 头 + 可压零填充,deflate 后仅数十 KB)与断言:
  大页可读、cache_bytes 允许超 32MiB、小页被淘汰、再来小页时大页按预算淘汰。

顺手:page_cache.h 注释包名 os.meow.picobrowser → os.meow.picbrowser(测试路径同步)。

测试:test_cbz 267 → 296 项全 PASS;run_tests.sh(zip 106)与
run_webtoon_tests.sh 全绿;交叉构建 sdk/tuku 零警告,产物静态 MIPS32r2 ELF。
2026-11-05 12:13:47 +08:00

77 lines
3.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* logic/reader/page_cache.h — 档案册解压页的磁盘缓存(纯 C,不依赖 SDK)。
*
* 为什么需要磁盘缓存:SDK 的图像解码入口只吃文件路径(meow_img_load_file_dim),
* 而 zip 里的页是压缩流。档案页源在 open(i) 时把条目解压成缓存文件,再用同一个
* 解码回调按路径解码——两种阅读模式(翻页/条漫)与目录册走完全相同的代码路径。
*
* 目录与上限(纪律):
* - 目录 = <数据目录>/cache(数据目录形如 .../MeowData/os.meow.picbrowser/data,
* 与缩略图缓存同目录;文件名统一前缀 mrpage_,与缩略图 *.bmp 互不影响);
* - 上限 = 64 页 或 32MiB,先到者触发 LRU 淘汰(按最近使用计数);
* - **单条目溢出**:某页解压后本身就超过 32MiB 时允许一次性溢出——只保留该条、
* 其它条目全部淘汰,占用上限受页源单页上限 64MiB(MR_ZIP_PAGE_MAX_BYTES)约束。
* 这样超大页仍可阅读,不会因为预算拒绝落缓存而变成永久空白页;
* - mr_cache_init() 首次成功时清掉上一进程遗留的 mrpage_*(孤儿页)
* (注意:缩略图 LRU 也必须在同一目录里跳过 mrpage_*,否则会互删);
* - 写入走 "<name>.part" + rename,进程崩溃不会留下半个缓存文件。
*
* 键 = 档案路径 + 档案 mtime/size + 条目名 + 页下标:档案被替换(mtime/size 变)或
* 同名条目重复出现时不会命中旧内容。文件名保留图片扩展名(解码入口按扩展名区分
* JPEG 的「解码期缩解」路径)。
*
* 线程:内部互斥量;可在解码线程/缩略图线程/主线程并发调用。
* 纯 C:宿主测试可直接编译(见 tuku/test/test_cbz.c)。
*/
#ifndef MR_PAGE_CACHE_H
#define MR_PAGE_CACHE_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MR_CACHE_MAX_PAGES 64
#define MR_CACHE_MAX_BYTES (32LL * 1024 * 1024)
#define MR_CACHE_PREFIX "mrpage_"
#define MR_CACHE_DIR_MAX 200
#define MR_CACHE_FILE_MAX 256
/* 数据目录 → 缓存目录(纯字符串):末尾的 "data" 段替换为 "cache"。
* 例:/…/MeowData/os.meow.picbrowser/data → /…/MeowData/os.meow.picbrowser/cache。
* 成功 0;参数非法/缓冲不足 -1。 */
int mr_cache_dir_from_data(const char *data_dir, char *out, int outsz);
/* 文件名是否属于解压页缓存(mrpage_ 前缀)。缩略图 LRU 与启动清孤儿共用这一判据,
* 保证两套缓存同目录时互不误删(P2-1)。1=解压页缓存。 */
int mr_cache_is_page_name(const char *name);
/* 建立/切换缓存目录并清孤儿。0=可用;-1=不可用(之后 store/touch 均失败)。
* 同一目录重复调用为无操作(不会删掉正在用的页)。 */
int mr_cache_init(const char *data_dir);
/* 释放索引(不删文件);测试用。可重复调用。 */
void mr_cache_shutdown(void);
int mr_cache_ready(void);
const char *mr_cache_dir(void); /* 未初始化返回空串 */
/* 计算某页缓存文件路径(不碰磁盘)。扩展名取自 entry 名(未知时 .img)。 */
int mr_cache_path(const char *archive, long long mtime, long long size,
const char *entry, int page_index, char *out, int outsz);
/* 缓存命中:文件在索引里(或磁盘上存在)则刷新 LRU 并返回 1,否则 0。 */
int mr_cache_touch(const char *path);
/* 写入缓存并纳入 LRU;1=成功。len==0 视为失败(空页没有解码价值)。 */
int mr_cache_store(const char *path, const void *data, size_t len);
/* 观测(宿主测试断言 LRU 纪律用):当前索引页数 / 字节数。 */
int mr_cache_count(void);
long long mr_cache_bytes(void);
#ifdef __cplusplus
}
#endif
#endif /* MR_PAGE_CACHE_H */