summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pttbbs/mbbsd/brc.c27
-rw-r--r--pttbbs/mbbsd/read.c51
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;
}