diff options
author | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-06-12 22:59:46 +0800 |
---|---|---|
committer | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-06-12 22:59:46 +0800 |
commit | ed870cef48392b5006d413b043589eb866988a87 (patch) | |
tree | b6dc781083029411b9c490eccf48aede211e5797 | |
parent | b1742a061cfe32ebd4619a8f8a91812eaaf58bc0 (diff) | |
download | pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar.gz pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar.bz2 pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar.lz pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar.xz pttbbs-ed870cef48392b5006d413b043589eb866988a87.tar.zst pttbbs-ed870cef48392b5006d413b043589eb866988a87.zip |
revise brc interface and its document.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3542 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | docs/brc.txt | 96 | ||||
-rw-r--r-- | include/proto.h | 13 | ||||
-rw-r--r-- | mbbsd/bbs.c | 2 | ||||
-rw-r--r-- | mbbsd/board.c | 13 | ||||
-rw-r--r-- | mbbsd/brc.c | 160 | ||||
-rw-r--r-- | mbbsd/var.c | 4 |
6 files changed, 153 insertions, 135 deletions
diff --git a/docs/brc.txt b/docs/brc.txt index 0a62f13c..315a1fbc 100644 --- a/docs/brc.txt +++ b/docs/brc.txt @@ -1,5 +1,6 @@ BRC documentation by scw 08/05/2003 + 06/12/2007 revised by kcwu 源起: 這篇文章主要是介紹 brc_* 的函式,這組函式是 pttbbs 用來紀錄文章已讀/未讀 @@ -17,20 +18,19 @@ BRC 是什麼?如何運作? 它的特點是用的空間極少。可以在 24k 以內的空間記下一個人在全站的文章已讀/ 未讀。當然,這樣的方法不可能真正完美,但是對於使用上已經足夠了。為什麼說是不 完美呢?這跟紀錄的儲存方式有關。 - 紀錄檔在 home/[first charactor of id]/[id]/.boardrc。檔案格式如下: + 紀錄檔在 home/[first charactor of id]/[id]/.brc2。檔案格式如下: FILE := RECORDS ; RECORDS := RECORDS RECORD | ; - RECORD := BOARD_NAME BRC_DATA ; + RECORD := BRC_BID BRC_DATA ; BRC_DATA := BRC_NUM BRC_LIST ; BRC_LIST := NUM NUM ... NUM ; (共 BRC_NUM 個 NUM) - BOARD_NAME 是 15 bytes 的板名 (#define BRC_STRLEN 15) - BRC_NUM 是對這個板的儲存量,1 byte 以 binary 方式儲存,其值 <= MAX_NUM (80) - BRC_LIST 是對這個板的紀錄,剛好有 BRC_NUM 個 4 bytes integers。 + BRC_BID 是 board bid, sizeof(brcbid_t)=2 bytes. + BRC_NUM 是對這個板的儲存量,sizeof(brcnbrd_t)=2 bytes 以 binary 方式儲存,其值 <= MAX_NUM (80) + BRC_LIST 是對這個板的紀錄,剛好有 BRC_NUM 個 sizeof(time4_t)=4 bytes integers。 另外在 24576 bytes (#define BRC_MAXSIZE 24576) 之外的資料不會被用到。 - 在下面會看到,BOARD_NAME 不用另外儲存(已經放在user的全域資料裡了),其他 - 兩項, BRC_NUM 跟 BRC_LIST 都會放在相應的全域變數中, brc_num & brc_list 。 + 在下面會看到,BRC_BID 跟 BRC_NUM 跟 BRC_LIST 都會放在相應的變數中, brc_currbid & brc_num & brc_list 。 判定一個檔案是否已經讀過的方法是在 brc_list 中搜尋檔案建立的時間,也就是 檔名 M.xxxxxxxxxx.A.yyy 中 xxxxxxxxx 的那個數字。如果這個數字有在 brc_list 中 出現就是已讀,要不如果 brc_list 中所有的數字都比這個檔案的建立時間大(也就是 @@ -40,7 +40,7 @@ BRC 是什麼?如何運作? 這樣可以看出為什麼這個方法不是真正完美但是已經足夠。不完美的原因有三個: 首先, brc_num <= 80 也就是 brc_list 最多存八十個數,這表示除了很久以前的文章 外,只會有八十篇是已讀的。第二就是所有一年前的文章都會被判為已讀。最後,如果一 - 個人看的板太多,讓 .boardrc 大小超過 BRC_MAXSIZE 有些板的紀錄就會不見( 24576 + 個人看的板太多,讓 .brc2 大小超過 BRC_MAXSIZE 有些板的紀錄就會不見( 24576 bytes 最少可以存 73 個板的資料,這還是用全部板 brc_num 都是 80 計算的)。但這 三個小缺點影響應該不大吧? @@ -48,53 +48,38 @@ BRC 實作 interface: (in proto.h) - int brc_unread(char *fname, int bnum, int *blist); + int brc_initialize(); + void brc_finalize(); + + int brc_unread(int bid, char *fname, int bnum, int *blist); 判斷一篇文章是否已讀。 傳入值:文章檔名 (fname) 以及 brc_num (bnum) 和 brc_list (blist)。 傳回值:如果由 bnum 和 blist 判斷本篇文章未讀傳回 1。 否則傳回 0。 額外效果:無。 - int brc_initial(char *boardname); + int brc_initial_board(char *boardname); 初始化在一個板的已讀未讀狀態。 傳入值:要初始化的板名。 傳回值:若找到之前的紀錄傳回新的 brc_num,否則傳回 0。 額外效果:如果傳入的看板就是目前看板會直接傳回 brc_num, 不做別的事。否則 - 本函式會先將目前的 brc data 寫入 .boardrc 中,更改 currboard ,取得 + 本函式會先將目前的 brc data 寫回 brc_buf 中,更改 currboard ,取得 currbid 和 currbrdattr 後再讀取並更新 brc_num 及 brc_list。如果在使用者 - 的 .boardrc 中沒有關於這個板的紀錄,會設定 brc_num = 1,brc_list[0] = 1 + 的 brc_buf 中沒有關於這個板的紀錄,會設定 brc_num = 1,brc_list[0] = 1 並傳回 0。 void brc_update(); - 將目前的 brc data 寫入 .boardrc 中。 + 將目前的 brc data 寫入 brc_buf 中。 額外效果:如果 brc data 未被更改或使用者權限不足則不會有動作。 void brc_addlist(char *fname); - 將文章標示為已讀。 + 將文章標示為已讀。使用前需先 brc_initial_board() 傳入值:要標示為已讀的文章檔名。 - global variables: (in var.c) - - int brc_num; - brc_list 中的有效數字個數。 - - int brc_list[BRC_MAXNUM]; - 已讀文章的存檔時間。 - - (in var.h) - extern int brc_num; - extern int brc_list[BRC_MAXNUM]; - - constant definition: (in board.c) - - #define BRC_STRLEN 15 /* Length of board name */ - 板名最大長度。 + constant definition: #define BRC_MAXSIZE 24576 - .boardrc 的有效大小。 - - #define BRC_ITEMSIZE (BRC_STRLEN + 1 + BRC_MAXNUM * sizeof( int )) - 每個 record 的最大大小。 + .brc2 的有效大小。 #define BRC_MAXNUM 80 brc_num 的最大值。 @@ -105,47 +90,34 @@ BRC 實作 brc_list 中值的下限,時間在此之前的一律當作已讀。會在 init_brdbuf 中被設 定為 login_start_time - 365 * 86400。 - static int brc_changed = 0; - 從上次讀取 .boardrc 到當時為止,brc_num 與 brc_list 是否改變過(為減少寫 - 檔的次數)。 - static char brc_buf[BRC_MAXSIZE]; - 呼叫 read_brc_buf 後 .boardrc 的前 BRC_MAXSIZE bytes 會被置入這個 buffer - 中。 + 呼叫 read_brc_buf 後 .brc2 的前 BRC_MAXSIZE bytes 會被置入這個 buffer 中。 static int brc_size; 呼叫 read_brc_buf 後 brc_buf 中的有效字元數。 - static char brc_name[BRC_STRLEN]; - 目前 brc data 的板名。 (不知道可否用 currboard 代替? by scw) + static int brc_changed = 0; + 從上次讀取 .brc2 到當時為止,brc_num 與 brc_list 是否改變過。 - static char * fn_boardrc = ".boardrc"; - brc 設定檔名。 + static int brc_currbid; - char * brc_buf_addr=brc_buf; - unused variable - - private funcions: (in board.c) + static int brc_num; + brc_list 中的有效數字個數。 + + static int brc_list[BRC_MAXNUM]; + 已讀文章的存檔時間。 + static void read_brc_buf(); - 從 .boardrc 中讀取最多 BRC_MAXSIZE bytes 並存入 brc_buf 中,將存入的字元 + 從 .brc2 中讀取最多 BRC_MAXSIZE bytes 並存入 brc_buf 中,將存入的字元 數存在 brc_size 中。 - static char * brc_getrecord(char *ptr, char *name, int *pnum, int *list); - 從 buffer 中讀取一項紀錄。 (通常在 read_brc_bufi() 之後使用) - 傳入值:ptr 為要讀取的 buffer, name, pnum, 和 list 分別寫入讀到的資料。 - 傳回值:指向讀出的 record 下一個字元的指標。 - 額外效果:name 會被存入最多 BRC_MAXLEN 個字元,為讀到的 record 的板名。 - pnum 會被存入讀到的 brc_num,list 會被寫入 *pnum 的整數,為 brc_list - 的資料。 - - static char * brc_putrecord(char *ptr, char *name, int num, int *list); + static char * brc_putrecord(char *ptr, char *endp, brcbid_t bid, brcnbrd_t num, const time4_t *list); 與 brc_getrecord() 的作用正好相反,將資料寫入 puffer 中。 - 傳入值:ptr 只向要寫入的 buffer,name, num, list 分別是要寫入的資料。 + 傳入值:ptr 指向要寫入的 buffer,bid, num, list 分別是要寫入的資料。 傳回值:指向寫入的 record 下一個字元的指標。 - 額外效果:若資料是合法的 (num > 0 && list[0] > brc_expire_time) ptr 會被 - 寫入 BRC_ITEMSIZE bytes 的資料。在 list 中比 brc_expire_time 的數字不會 - 被寫入(所以寫入的 brc_num 可能比 num 小)。 + 額外效果:若資料是合法的 (num > 0 && list[0] > brc_expire_time) 且空間足夠, + 資料會被寫入 ptr, endp 之間。 static int brc_unread_time(time_t ftime, int bnum, int *blist); 跟 brc_unread() 類似,只是傳入的是檔案建立的時間。 diff --git a/include/proto.h b/include/proto.h index c5afa9b2..eef17976 100644 --- a/include/proto.h +++ b/include/proto.h @@ -100,15 +100,16 @@ void sigfree(int); /* brc */ int brc_initialize(void); void brc_finalize(void); -int brc_unread(const char *fname, int bnum, const time4_t *blist); -int brc_unread_time(time4_t ftime, int bnum, const time4_t *blist); + +int brc_unread(int bid, const char *fname); +int brc_unread_time(int bid, time4_t ftime); int brc_initial_board(const char *boardname); -void brc_update(void); -int brc_read_record(int bid, int *num, time4_t *list); -time4_t * brc_find_record(int bid, int *num); -void brc_trunc(int bid, time4_t ftime); void brc_addlist(const char* fname); +void brc_update(void); + +void brc_toggle_all_read(int bid, int is_all_read); + /* cache */ #define demoney(money) deumoney(usernum, money) #define search_ulist(uid) search_ulistn(uid, 1) diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c index cf7ad993..ba75286c 100644 --- a/mbbsd/bbs.c +++ b/mbbsd/bbs.c @@ -303,7 +303,7 @@ readdoent(int num, fileheader_t * ent) char *mark, *title, color, special = 0, isonline = 0, recom[8]; userinfo_t *uentp; - type = brc_unread(ent->filename, brc_num, brc_list) ? '+' : ' '; + type = brc_unread(currbid, ent->filename) ? '+' : ' '; if ((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) type = (type == ' ') ? '*' : '#'; else if (currmode & MODE_BOARD || HasUserPerm(PERM_LOGINOK)) { diff --git a/mbbsd/board.c b/mbbsd/board.c index 8a228287..e9267703 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -133,9 +133,7 @@ HasBoardPerm(boardheader_t *bptr) static int check_newpost(boardstat_t * ptr) { /* Ptt 改 */ - int tbrc_num; time4_t ftime; - time4_t *tbrc_list; ptr->myattr &= ~NBRD_UNREAD; if (B_BH(ptr)->brdattr & (BRD_GROUPBOARD | BRD_SYMBOLIC)) @@ -155,8 +153,7 @@ check_newpost(boardstat_t * ptr) if (ftime > now + 10) ftime = B_LASTPOSTTIME(ptr) = now - 1; - tbrc_list = brc_find_record(ptr->bid, &tbrc_num); - if ( brc_unread_time(ftime, tbrc_num, tbrc_list) ) + if ( brc_unread_time(ptr->bid, ftime) ) ptr->myattr |= NBRD_UNREAD; return 1; @@ -451,7 +448,7 @@ unread_position(char *dirfile, boardstat_t * ptr) while (num > 0) { lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); if (read(fd, fname, FNLEN) <= 0 || - !brc_unread(fname, brc_num, brc_list)) + !brc_unread(ptr->bid, fname)) break; num -= step; if (step < 32) @@ -462,7 +459,7 @@ unread_position(char *dirfile, boardstat_t * ptr) while (num < total) { lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); if (read(fd, fname, FNLEN) <= 0 || - brc_unread(fname, brc_num, brc_list)) + brc_unread(ptr->bid, fname)) break; num++; } @@ -1129,9 +1126,9 @@ choose_board(int newflag) break; if (ch == 'v') { ptr->myattr &= ~NBRD_UNREAD; - brc_trunc(ptr->bid, now); + brc_toggle_all_read(ptr->bid, 1); } else { - brc_trunc(ptr->bid, 1); + brc_toggle_all_read(ptr->bid, 0); ptr->myattr |= NBRD_UNREAD; } show_brdlist(head, 0, newflag); diff --git a/mbbsd/brc.c b/mbbsd/brc.c index 8c4b86da..8360cedc 100644 --- a/mbbsd/brc.c +++ b/mbbsd/brc.c @@ -6,7 +6,7 @@ */ #ifndef BRC_MAXNUM -#define BRC_STRLEN 15 /* Length of board name */ +#define BRC_STRLEN 15 /* Length of board name, for old brc */ #define BRC_MAXSIZE 24576 /* Effective size of brc rc file, 8192 * 3 */ #define BRC_MAXNUM 80 /* Upper bound of brc_num, size of brc_list */ #endif @@ -26,45 +26,38 @@ typedef unsigned short brcnbrd_t; * brc_num 1 byte, binary integer * brc_list brc_num * sizeof(int) bytes, brc_num binary integer(s) */ +static char brc_initialized = 0; static time4_t brc_expire_time; /* Will be set to the time one year before login. All the files created * before then will be recognized read. */ -static int brc_changed = 0; +static int brc_changed = 0; /**< brc_list/brc_num changed */ /* The below two will be filled by read_brc_buf() and brc_update() */ static char *brc_buf = NULL; static int brc_size; static int brc_alloc; +// read records for currbid +static int brc_currbid; +static int brc_num; +static time4_t brc_list[BRC_MAXNUM]; + static char * const fn_oldboardrc = ".boardrc"; static char * const fn_brc = ".brc2"; -#if 0 -/* unused after brc2 */ -static char * -brc_getrecord(char *ptr, char *endp, brcbid_t *bid, - brcnbrd_t *pnum, time4_t *list) -{ - brcnbrd_t num; - char *tmp; - - if (ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) > endp) - return endp + 1; /* dangling, ignoring it */ - *bid = *(brcbid_t*)ptr; /* bid */ - ptr += sizeof(brcbid_t); - num = *(brcnbrd_t*)ptr; /* brc_num */ - ptr += sizeof(brcnbrd_t); - tmp = ptr + num * sizeof(time4_t); /* end of this record */ - if (tmp <= endp){ - memcpy(list, ptr, num * sizeof(time4_t)); /* brc_list */ - if (num > BRC_MAXNUM) - num = BRC_MAXNUM; - *pnum = num; - } - return tmp; -} -#endif - +/** + * find read records of bid in given buffer region + * + * @param[in] begin + * @param[in] endp + * @param bid + * @param[out] num number of records, which could be written for \a bid + * = brc_num if found + * = 0 or dangling size if not found + * + * @return address of record. \a begin <= addr < \a endp. + * 0 if not found + */ /* Returns the address of the record strictly between begin and endp with * bid equal to the parameter. Returns 0 if not found. * brcnbrd_t *num is an output parameter which will filled with brc_num @@ -97,7 +90,7 @@ brc_findrecord_in(char *begin, char *endp, brcbid_t bid, brcnbrd_t *num) return 0; } -time4_t * +static time4_t * brc_find_record(int bid, int *num) { char *p; @@ -152,11 +145,13 @@ brc_enlarge_buf(void) #endif buffer = (char*)THE_MALLOC(brc_alloc); + assert(buffer); memcpy(buffer, brc_buf, brc_alloc); free(brc_buf); brc_alloc += BRC_BLOCKSIZE; brc_buf = (char*)malloc(brc_alloc); + assert(brc_buf); memcpy(brc_buf, buffer, brc_alloc - BRC_BLOCKSIZE); #ifdef DEBUG @@ -179,6 +174,7 @@ brc_get_buf(int size){ if (brc_alloc > BRC_MAXSIZE) brc_alloc = BRC_MAXSIZE; brc_buf = (char*)malloc(brc_alloc); + assert(brc_buf); } static inline void @@ -239,10 +235,13 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, const time4_t* list) brc_changed = 0; } +/** + * write \a brc_num and \a brc_list back to \a brc_buf. + */ void brc_update(){ - if (brc_changed && cuser.userlevel && brc_num > 0) - brc_insert_record(currbid, brc_num, brc_list); + if (brc_currbid && brc_changed && cuser.userlevel && brc_num > 0) + brc_insert_record(brc_currbid, brc_num, brc_list); } /* return 1 if successfully read from old .boardrc file. @@ -314,36 +313,65 @@ read_brc_buf(void) } void +brc_release() +{ + if (brc_buf) { + free(brc_buf); + brc_buf = NULL; + } + brc_currbid = 0; + brc_num = 0; + brc_changed = 0; + brc_size = brc_alloc = 0; +} + +void brc_finalize(){ char brcfile[STRLEN]; char tmpfile[STRLEN]; - int fd; - int ok=0; + brc_update(); setuserfile(brcfile, fn_brc); snprintf(tmpfile, sizeof(tmpfile), "%s.tmp.%x", brcfile, getpid()); - if (brc_buf != NULL && - (fd = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0644)) != -1) { - if(write(fd, brc_buf, brc_size)==brc_size) - ok=1; - close(fd); + if (brc_buf != NULL) { + int fd = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd != -1) { + int ok=0; + if(write(fd, brc_buf, brc_size)==brc_size) + ok=1; + close(fd); + if(ok) + Rename(tmpfile, brcfile); + else + unlink(tmpfile); + } } - if(ok) - Rename(tmpfile, brcfile); + + brc_release(); + brc_initialized = 0; } int brc_initialize(){ - static char done = 0; - if (done) + if (brc_initialized) return 1; - done = 1; + brc_initialized = 1; brc_expire_time = login_start_time - 365 * 86400; read_brc_buf(); return 0; } -int +/** + * get the read records for bid + * + * @param bid + * @param[out] num number of record for \a bid. 1 <= \a num <= \a BRC_MAXNUM + * \a num = 1 if no records. + * @param[out] list the list of records, length \a num + * + * @return number of read record, 0 if no records + */ +static int brc_read_record(int bid, int *num, time4_t *list){ char *ptr; brcnbrd_t tnum; @@ -358,12 +386,16 @@ brc_read_record(int bid, int *num, time4_t *list){ return 0; } +/** + * @return number of records in \a boardname + */ int brc_initial_board(const char *boardname) { brc_initialize(); if (strcmp(currboard, boardname) == 0) { + assert(currbid == brc_currbid); return brc_num; } @@ -372,16 +404,17 @@ brc_initial_board(const char *boardname) if( currbid == 0 ) currbid = getbnum(DEFAULT_BOARD); assert(0<=currbid-1 && currbid-1<MAX_BOARD); + brc_currbid = currbid; currboard = bcache[currbid - 1].brdname; currbrdattr = bcache[currbid - 1].brdattr; - return brc_read_record(currbid, &brc_num, brc_list); + return brc_read_record(brc_currbid, &brc_num, brc_list); } -void +static void brc_trunc(int bid, time4_t ftime){ brc_insert_record(bid, 1, &ftime); - if ( bid == currbid ){ + if ( bid == brc_currbid ){ brc_num = 1; brc_list[0] = ftime; brc_changed = 0; @@ -389,11 +422,21 @@ brc_trunc(int bid, time4_t ftime){ } void +brc_toggle_all_read(int bid, int is_all_read) +{ + if (is_all_read) + brc_trunc(bid, now); + else + brc_trunc(bid, 1); +} + +void brc_addlist(const char *fname) { int n, i; time4_t ftime; + assert(currbid == brc_currbid); if (!cuser.userlevel) return; @@ -426,30 +469,39 @@ brc_addlist(const char *fname) } int -brc_unread_time(time4_t ftime, int bnum, const time4_t *blist) +brc_unread_time(int bid, time4_t ftime) { - int n; + int i; + int bnum; + const time4_t *blist; if (ftime <= brc_expire_time) /* too old */ return 0; + if (brc_currbid && bid == brc_currbid) { + blist = brc_list; + bnum = brc_num; + } else { + blist = brc_find_record(bid, &bnum); + } + if (bnum <= 0) return 1; - for (n = 0; n < bnum; n++) { /* using linear search */ - if (ftime > blist[n]) + for (i = 0; i < bnum; i++) { /* using linear search */ + if (ftime > blist[i]) return 1; - else if (ftime == blist[n]) + else if (ftime == blist[i]) return 0; } return 0; } int -brc_unread(const char *fname, int bnum, const time4_t *blist) +brc_unread(int bid, const char *fname) { int ftime; ftime = atoi(&fname[2]); /* this will get the time of the file created */ - return brc_unread_time(ftime, bnum, blist); + return brc_unread_time(bid, ftime); } diff --git a/mbbsd/var.c b/mbbsd/var.c index 52864a4f..39c87442 100644 --- a/mbbsd/var.c +++ b/mbbsd/var.c @@ -363,10 +363,6 @@ SHM_t *SHM; boardheader_t *bcache; userinfo_t *currutmp; -/* brc.c */ -int brc_num; -time4_t brc_list[BRC_MAXNUM]; - /* read.c */ int TagNum; /* tag's number */ int TagBoard = -1; /* TagBoard = 0 : user's mailbox */ |