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
@@ -28,6 +28,7 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
/* ---- ncm_cache.c 依赖的符号(核心库其他 TU 提供;此处最小内联/桩,避免链 mbedtls) ---- */
|
||||
size_t ncm_strlcpy(char *dst, const char *src, size_t sz)
|
||||
@@ -59,6 +60,12 @@ int ncm_store_mkdir_p(const char *path)
|
||||
return 0;
|
||||
}
|
||||
int ncm_store_read_cfg_int(const char *dir, const char *key, int def) { (void)dir; (void)key; return def; }
|
||||
int64_t ncm_now_ms(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return (int64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
/* ---- 工具 ---- */
|
||||
static char g_dir[512];
|
||||
@@ -285,6 +292,44 @@ int main(void)
|
||||
CHECK(stat(p, &st2) != 0, "part_remove deleted .part");
|
||||
}
|
||||
|
||||
/* ⑨ §26 孤儿半成品回收:LRU 扫描顺手续删超过 7 天的 .part/.tmp(用户不再点该曲、不续传),
|
||||
* 新鲜的在途/刚中断残体保留(写端 mtime 持续更新,不会被误删)。 */
|
||||
printf("== case 9: orphan .part/.tmp older than 7d swept by LRU scan (stage3 §26.4) ==\n");
|
||||
cleanup();
|
||||
{
|
||||
char op[600], ot[600], lp[600];
|
||||
int64_t now = ncm_now_ms() / 1000;
|
||||
int64_t old = now - 8 * 86400; /* 8 天前 */
|
||||
struct stat st;
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = old; ts[0].tv_nsec = 0; ts[1].tv_sec = old; ts[1].tv_nsec = 0;
|
||||
|
||||
/* 8 天前的 .part:应被 evict 扫描顺手删 */
|
||||
ncm_cache_path(&g_c, "orph", ".mp3", op, sizeof op);
|
||||
snprintf(op + strlen(op), sizeof op - strlen(op), ".part");
|
||||
int fd = open(op, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) { (void)!write(fd, "old", 3); close(fd); }
|
||||
utimensat(AT_FDCWD, op, ts, 0);
|
||||
|
||||
/* 8 天前的 .tmp:也应被删 */
|
||||
ncm_cache_path(&g_c, "orcht", ".mp3", ot, sizeof ot);
|
||||
snprintf(ot + strlen(ot), sizeof ot - strlen(ot), ".tmp");
|
||||
fd = open(ot, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) { (void)!write(fd, "tm", 2); close(fd); }
|
||||
utimensat(AT_FDCWD, ot, ts, 0);
|
||||
|
||||
/* 新鲜的 .part(现在):应保留(可能正在进行/刚中断,mtime 新) */
|
||||
ncm_cache_path(&g_c, "live", ".mp3", lp, sizeof lp);
|
||||
snprintf(lp + strlen(lp), sizeof lp - strlen(lp), ".part");
|
||||
fd = open(lp, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) { (void)!write(fd, "live", 4); close(fd); }
|
||||
|
||||
ncm_cache_evict(&g_c);
|
||||
CHECK(stat(op, &st) != 0, "8-day .part swept by evict scan");
|
||||
CHECK(stat(ot, &st) != 0, "8-day .tmp swept by evict scan");
|
||||
CHECK(stat(lp, &st) == 0, "fresh .part kept (inflight/resumable)");
|
||||
}
|
||||
|
||||
cleanup();
|
||||
printf("%s\n", g_fail ? "RESULT: FAIL" : "RESULT: PASS");
|
||||
return g_fail ? 1 : 0;
|
||||
|
||||
Reference in new issue
Block a user