280 歌单链路三修:开A→开B 竞态防串(5194 串数据) + 92/200 批边界 Load Failed + 歌单列表盘缓存 + 孤儿 .part 回收
ncm_app(REPORT §26, ncm 158ec367 未部署留主会话): - 打开时快照 plid+代次:appstate_playlist_begin/open_gen/open_idx/reset + appstate_load_playlist_songs_ctx(快照 pl 不读 g_st.playlists[],detail 结果落 staging 锁内原子发布,代次/目标不匹配判 NCM_ERR_STALE 不写全局);playlist_tick 过期丢弃 + appstate_playlist_reset 清窗口防串。修 5194「我喜欢的音乐」3 首/串数据。 - appstate_song_ensure_range fill-and-continue:bn<m 部分返回/单批网络失败非致命 (记 NCM_ERR_NOTFOUND/r2),已物化保留+占位行;worker 首屏 track_ids_count>0 降级非致命(snack)。修 92/200 首歌单点开整页 Load Failed。 - 歌单列表盘缓存 <data_dir>/playlists.bin(magic+ver+ts+数组):home_reload 先缓存 秒渲 + 后台静默刷新,刷新失败有数据不置错态。修返回首页卡 LOADING(275 遗留)。 - 孤儿 .part/.tmp:evict/total_bytes LRU 扫描顺续删 mtime>7 天(in-flight mtime 新鲜安全)。 验证:新 bench/playlist_race_sim(竞态防串/批边界/非致命/盘缓存/reset)+cache_evict_sim case9(7 天回收)+window/pagination/search/stream_sim 零回归+test_ncm_core host+mipsel PASS;build_ncm.sh -Wall -Wextra 0 warning(text 978354/bss 1496484);0 真实请求。 遗留:appstate_logout 未联动删 playlists.bin;g_st.playlists[] 快照拷贝仍有极小交错窗。
This commit is contained in:
1 parent
d8eeef5c57
commit
f0b73e119d
11 files changed
+744
-48
No files matched your search
@@ -20,6 +20,10 @@
|
||||
#define MAX_LIMIT_GB 100
|
||||
#define MAX_ENTRIES 4096
|
||||
|
||||
/* §26 孤儿半成品回收:.tmp/.part 不进 LRU 池(防在播文件误删),但长期不续传的残体占磁盘。
|
||||
* LRU 扫描时顺手判 mtime——超过此天数的孤儿 .part/.tmp 惰性删除(in-flight 下载 mtime 新鲜安全)。 */
|
||||
#define NCM_ORPHAN_PART_DAYS 7
|
||||
|
||||
typedef struct entry {
|
||||
char name[256];
|
||||
uint64_t size;
|
||||
@@ -169,10 +173,21 @@ int ncm_cache_evict(const ncm_cache_t *c) {
|
||||
if (!ents) { closedir(d); return NCM_ERR_OOM; }
|
||||
int n = 0;
|
||||
uint64_t total = 0;
|
||||
int64_t orphan_cutoff = (int64_t)time(NULL) - (int64_t)NCM_ORPHAN_PART_DAYS * 86400;
|
||||
struct dirent *e;
|
||||
while ((e = readdir(d)) && n < MAX_ENTRIES) {
|
||||
if (strncmp(e->d_name, "song_", 5) != 0) continue;
|
||||
if (is_partial_name(e->d_name)) continue; /* 阶段3:.tmp/.part 归写者管理域,不淘汰 */
|
||||
if (is_partial_name(e->d_name)) { /* 阶段3:.tmp/.part 归写者管理域,不进 LRU 池 */
|
||||
/* §26 顺手续删:超过 7 天的孤儿 .part/.tmp(用户不再点该曲、不续传)惰性删除。
|
||||
* 在播/刚中断的 .tmp/.part mtime 新鲜(写端持续更新),不会被误删。 */
|
||||
char pb[NCM_CACHE_DIR_MAX + NAME_MAX + 8];
|
||||
snprintf(pb, sizeof pb, "%s/%s", c->dir, e->d_name);
|
||||
struct stat sb;
|
||||
if (stat(pb, &sb) == 0 && S_ISREG(sb.st_mode) &&
|
||||
(int64_t)sb.st_mtim.tv_sec < orphan_cutoff)
|
||||
unlink(pb);
|
||||
continue;
|
||||
}
|
||||
char p[NCM_CACHE_DIR_MAX + NAME_MAX + 8];
|
||||
snprintf(p, sizeof p, "%s/%s", c->dir, e->d_name);
|
||||
struct stat st;
|
||||
@@ -307,10 +322,20 @@ uint64_t ncm_cache_total_bytes(const ncm_cache_t *c) {
|
||||
DIR *d = opendir(c->dir);
|
||||
if (!d) return 0;
|
||||
uint64_t total = 0;
|
||||
int64_t orphan_cutoff = (int64_t)time(NULL) - (int64_t)NCM_ORPHAN_PART_DAYS * 86400;
|
||||
struct dirent *e;
|
||||
while ((e = readdir(d))) {
|
||||
if (strncmp(e->d_name, "song_", 5) != 0) continue;
|
||||
if (is_partial_name(e->d_name)) continue; /* 阶段3:半成品不计入池占用 */
|
||||
if (is_partial_name(e->d_name)) { /* 阶段3:半成品不计入池占用 */
|
||||
/* §26 顺手续删:超过 7 天的孤儿 .part/.tmp 惰性删除。 */
|
||||
char pb[NCM_CACHE_DIR_MAX + NAME_MAX + 8];
|
||||
snprintf(pb, sizeof pb, "%s/%s", c->dir, e->d_name);
|
||||
struct stat sb;
|
||||
if (stat(pb, &sb) == 0 && S_ISREG(sb.st_mode) &&
|
||||
(int64_t)sb.st_mtim.tv_sec < orphan_cutoff)
|
||||
unlink(pb);
|
||||
continue;
|
||||
}
|
||||
char p[NCM_CACHE_DIR_MAX + NAME_MAX + 8];
|
||||
snprintf(p, sizeof p, "%s/%s", c->dir, e->d_name);
|
||||
struct stat st;
|
||||
|
||||
@@ -31,6 +31,7 @@ enum {
|
||||
NCM_ERR_AUTH = -13, /* 未登录/鉴权失败 */
|
||||
NCM_ERR_LIMIT = -14, /* 超出上限级 */
|
||||
NCM_ERR_VIP = -15, /* VIP 专享(fee 门槛命中,未发 song_url 请求,§20) */
|
||||
NCM_ERR_STALE = -16, /* 异步结果过期(打开歌单 A 未完→打开 B,A 的迟到结果被丢弃,§26) */
|
||||
};
|
||||
|
||||
/* ---------- 常用尺寸 ---------- */
|
||||
|
||||
Reference in new issue
Block a user