diff options
-rw-r--r-- | pttbbs/mbbsd/brc.c | 27 | ||||
-rw-r--r-- | pttbbs/mbbsd/read.c | 51 |
2 files changed, 63 insertions, 15 deletions
diff --git a/pttbbs/mbbsd/brc.c b/pttbbs/mbbsd/brc.c index 8f7bf5ba..096d2a72 100644 --- a/pttbbs/mbbsd/brc.c +++ b/pttbbs/mbbsd/brc.c @@ -652,9 +652,11 @@ brc_unread(int bid, const char *fname, time4_t modified) * forward == 1: 往更新的文章找 (往下找) * * 假設: blist[] 是按照 .create 由大而小往後排序好的. + * blist[] 最後一個是 .create = 1 (see brc_read_record()) * - * Return: 0 -- 沒有任何已讀的文章 - * 1 -- 找到已讀文章, 並將該文章放在 result 中傳回. + * Return: -1 -- 沒有任何已讀文章的紀錄 + * 0 -- 找不到任何已讀的文章 + * 1 -- 找到已讀文章, 並將該文章放在 result 中傳回. */ int brc_search_read(int bid, time4_t ftime, int forward, time4_t *result) @@ -672,18 +674,25 @@ brc_search_read(int bid, time4_t ftime, int forward, time4_t *result) blist = brc_find_record(bid, &bnum); } + if( bnum == 0 || !blist || + ( bnum == 1 && blist[0].create == 1 ) ) { + // 本版沒有已讀文章紀錄 (有可能是太久沒看, 已讀文章列表被丟棄, 或是 + // 從來就沒有進來過這個版 ...). + return -1; + } + // [0].create is the biggest. // 首先要找到 ftime 所在的區間, 然後再視 forward 的值來取前後的已讀文章. for( i = 0; i < bnum; i++ ) { /* using linear search */ if( ftime > blist[i].create ) { if( forward ) { if( i ) { - goto return_older; + goto return_newer; } else { return 0; } } else { - // 回傳此篇已讀文章 + // 回傳此篇為已讀文章 if( result ) *result = blist[i].create; return 1; } @@ -691,25 +700,25 @@ brc_search_read(int bid, time4_t ftime, int forward, time4_t *result) // 游標所在的檔案本身就是已讀過 else if( ftime == blist[i].create ) { if( forward && i ) { - goto return_older; - } else if( !forward && (i + 1) < bnum ) { goto return_newer; + } else if( !forward && (i + 1) < bnum ) { + goto return_older; } return 0; } } // 區間落在最後一個的後面 (更早之前的文章) if ( forward && i ) { - goto return_older; + goto return_newer; } return 0; -return_older: +return_newer: // 回傳後一篇已讀文章 if( result ) *result = blist[i - 1].create; return 1; -return_newer: +return_older: // 回傳前一篇已讀文章 if( result ) *result = blist[i + 1].create; return 1; diff --git a/pttbbs/mbbsd/read.c b/pttbbs/mbbsd/read.c index 50e24561..c9d19805 100644 --- a/pttbbs/mbbsd/read.c +++ b/pttbbs/mbbsd/read.c @@ -349,24 +349,63 @@ search_read(const int bid, const keeploc_t * locmem, int stypen) int fd = -1; int forward = (stypen & RS_FORWARD) ? 1 : 0; time4_t ftime, result; + int ret; + int step = forward ? 1 : -1; if( last_line <= 1 ) return pos; - /* First load the timestamp of article where cursor pointing to */ + /* First load the timestamp of article where cursor points to */ +reload_fh: rk = get_record_keep(currdirect, &fh, sizeof(fileheader_t), pos, &fd); - if( fd < 0 || rk < 0) return pos; - ftime = atoi( &fh.filename[2] ); + if( fd < 0 || rk < 0 ) return pos; + if( rk == 0 /* EOF */ ) { + /* 如果是置底文章, 則要將 ftime 設定成最大 (代表比最後一篇還要新) */ + ftime = 2147483647; + } else { +#ifdef SAFE_ARTICLE_DELETE + if (fh.filename[0] == '.' || fh.owner[0] == '-') { + /* 游標所在文章已被刪除, 跳過, 往下找下一篇文章 */ + close(fd); + pos += step; + goto reload_fh; + } +#endif + ftime = atoi( &fh.filename[2] ); + } /* given the ftime to resolve the read article */ - if( brc_search_read(bid, ftime, forward, &result ) ) { + ret = brc_search_read(bid, ftime, forward, &result ); + if( ret < 0 ) { + /* No read record is found. Try to traverse from last article to + * the first until a read article is found (via brc_unread()). + * Note that this is O(n) since the brc_unread() returns at + * either (ftime <= brc_expire_time) or (bnum <= 0). + */ + int i; + + for( i = last_line; i >= 0; --i ) { + rk = get_record_keep(currdirect, &fh, sizeof(fileheader_t), i, &fd); + if( fd < 0 || rk < 0) goto out; + if( 0 == brc_unread( bid, fh.filename, 0 ) ) { + pos = i; + goto out; + } + } + } else if( ret ) { + /* yes we found the read article and stored in result. */ int i; - int step = forward ? 1 : -1; /* find out the position for the article result */ for( i = pos; i >= 0 && i <= last_line; i += step ) { rk = get_record_keep(currdirect, &fh, sizeof(fileheader_t), i, &fd); if( fd < 0 || rk < 0) goto out; - if (atoi( &fh.filename[2] ) == result ) { +#ifdef SAFE_ARTICLE_DELETE + if (fh.filename[0] == '.' || fh.owner[0] == '-') { + /* 這篇文章已被刪除, 跳過, 試試下一篇 */ + continue; + } +#endif + if( atoi( &fh.filename[2] ) == result ) { pos = i; goto out; } |