/[LeafOK_CVS]/lbbs/src/section_list.c
ViewVC logotype

Annotation of /lbbs/src/section_list.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Thu May 22 11:10:19 2025 UTC (9 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.7: +158 -6 lines
Content type: text/x-csrc
Add methods

1 sysadm 1.1 /***************************************************************************
2     section_list.c - description
3     -------------------
4     Copyright : (C) 2004-2025 by Leaflet
5     Email : leaflet@leafok.com
6     ***************************************************************************/
7    
8     /***************************************************************************
9     * *
10     * This program is free software; you can redistribute it and/or modify *
11     * it under the terms of the GNU General Public License as published by *
12     * the Free Software Foundation; either version 3 of the License, or *
13     * (at your option) any later version. *
14     * *
15     ***************************************************************************/
16    
17     #include "section_list.h"
18     #include "log.h"
19     #include "trie_dict.h"
20     #include <stdio.h>
21     #include <string.h>
22     #include <signal.h>
23     #include <unistd.h>
24     #include <stdlib.h>
25     #include <errno.h>
26 sysadm 1.7 #include <sys/param.h>
27 sysadm 1.1 #include <sys/shm.h>
28     #include <sys/ipc.h>
29    
30 sysadm 1.7 #define ARTICLE_BLOCK_PER_SHM 400 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate
31 sysadm 1.3 #define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id)
32 sysadm 1.7 #define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT)
33    
34     struct article_block_t
35     {
36     ARTICLE articles[ARTICLE_PER_BLOCK];
37     int32_t article_count;
38     struct article_block_t *p_next_block;
39     };
40     typedef struct article_block_t ARTICLE_BLOCK;
41 sysadm 1.1
42     struct article_block_shm_t
43     {
44     int shmid;
45     void *p_shm;
46     };
47     typedef struct article_block_shm_t ARTICLE_BLOCK_SHM;
48    
49 sysadm 1.7 struct article_block_pool_t
50     {
51     ARTICLE_BLOCK_SHM shm_pool[ARTICLE_BLOCK_SHM_COUNT_LIMIT];
52     int shm_count;
53     ARTICLE_BLOCK *p_block_free_list;
54     ARTICLE_BLOCK *p_block[ARTICLE_BLOCK_PER_POOL];
55     int32_t block_count;
56     };
57     typedef struct article_block_pool_t ARTICLE_BLOCK_POOL;
58    
59     static ARTICLE_BLOCK_POOL *p_article_block_pool = NULL;
60 sysadm 1.1
61 sysadm 1.7 static SECTION_LIST *p_section_list_pool = NULL;
62     static int section_list_count = 0;
63     static TRIE_NODE *p_trie_dict_section_list = NULL;
64    
65     int article_block_init(const char *filename, int block_count)
66 sysadm 1.1 {
67     int shmid;
68     int proj_id;
69     key_t key;
70     size_t size;
71     void *p_shm;
72     int i;
73 sysadm 1.7 int block_count_in_shm;
74     ARTICLE_BLOCK *p_block_in_shm;
75     ARTICLE_BLOCK **pp_block_next;
76    
77     if (p_article_block_pool != NULL)
78 sysadm 1.1 {
79 sysadm 1.7 log_error("article_block_pool already initialized\n");
80 sysadm 1.1 return -1;
81     }
82    
83 sysadm 1.7 if (block_count > ARTICLE_BLOCK_PER_POOL)
84 sysadm 1.1 {
85 sysadm 1.7 log_error("article_block_count exceed limit %d\n", ARTICLE_BLOCK_PER_POOL);
86 sysadm 1.1 return -2;
87     }
88    
89 sysadm 1.7 p_article_block_pool = calloc(1, sizeof(ARTICLE_BLOCK_POOL));
90     if (p_article_block_pool == NULL)
91 sysadm 1.1 {
92 sysadm 1.7 log_error("calloc(ARTICLE_BLOCK_POOL) OOM\n");
93 sysadm 1.1 return -2;
94     }
95    
96     // Allocate shared memory
97 sysadm 1.7 p_article_block_pool->shm_count = 0;
98     pp_block_next = &(p_article_block_pool->p_block_free_list);
99 sysadm 1.1
100 sysadm 1.7 while (block_count > 0)
101 sysadm 1.1 {
102 sysadm 1.7 block_count_in_shm = MIN(block_count, ARTICLE_BLOCK_PER_SHM);
103     block_count -= block_count_in_shm;
104 sysadm 1.1
105 sysadm 1.7 proj_id = getpid() + p_article_block_pool->shm_count;
106 sysadm 1.1 key = ftok(filename, proj_id);
107     if (key == -1)
108     {
109     log_error("ftok(%s, %d) error (%d)\n", filename, proj_id, errno);
110 sysadm 1.7 article_block_cleanup();
111 sysadm 1.1 return -3;
112     }
113    
114 sysadm 1.7 size = sizeof(shmid) + sizeof(ARTICLE_BLOCK) * (size_t)block_count_in_shm;
115 sysadm 1.1 shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
116     if (shmid == -1)
117     {
118 sysadm 1.7 log_error("shmget(shm_index = %d, size = %d) error (%d)\n", p_article_block_pool->shm_count, size, errno);
119     article_block_cleanup();
120 sysadm 1.1 return -3;
121     }
122     p_shm = shmat(shmid, NULL, 0);
123     if (p_shm == (void *)-1)
124     {
125     log_error("shmat(shmid = %d) error (%d)\n", shmid, errno);
126 sysadm 1.7 article_block_cleanup();
127 sysadm 1.1 return -3;
128     }
129    
130 sysadm 1.7 (p_article_block_pool->shm_pool + p_article_block_pool->shm_count)->shmid = shmid;
131     (p_article_block_pool->shm_pool + p_article_block_pool->shm_count)->p_shm = p_shm;
132     p_article_block_pool->shm_count++;
133 sysadm 1.1
134 sysadm 1.7 p_block_in_shm = p_shm;
135     *pp_block_next = p_block_in_shm;
136 sysadm 1.1
137 sysadm 1.7 for (i = 0; i < block_count_in_shm; i++)
138 sysadm 1.1 {
139 sysadm 1.7 if (i < block_count_in_shm - 1)
140 sysadm 1.1 {
141 sysadm 1.7 (p_block_in_shm + i)->p_next_block = (p_block_in_shm + i + 1);
142 sysadm 1.1 }
143     else
144     {
145 sysadm 1.7 (p_block_in_shm + i)->p_next_block = NULL;
146     pp_block_next = &((p_block_in_shm + i)->p_next_block);
147 sysadm 1.1 }
148     }
149     }
150    
151 sysadm 1.7 p_article_block_pool->block_count = 0;
152    
153 sysadm 1.1 return 0;
154     }
155    
156 sysadm 1.7 void article_block_cleanup(void)
157     {
158     if (p_article_block_pool != NULL)
159     {
160     for (int i = 0; i < p_article_block_pool->shm_count; i++)
161     {
162     if (shmdt((p_article_block_pool->shm_pool + i)->p_shm) == -1)
163     {
164     log_error("shmdt(shmid = %d) error (%d)\n", (p_article_block_pool->shm_pool + i)->shmid, errno);
165     }
166    
167     if (shmctl((p_article_block_pool->shm_pool + i)->shmid, IPC_RMID, NULL) == -1)
168     {
169     log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", (p_article_block_pool->shm_pool + i)->shmid, errno);
170     }
171     }
172    
173     free(p_article_block_pool);
174     p_article_block_pool = NULL;
175     }
176     }
177    
178     inline static ARTICLE_BLOCK *pop_free_article_block(void)
179     {
180     ARTICLE_BLOCK *p_block = NULL;
181    
182     if (p_article_block_pool->p_block_free_list != NULL)
183     {
184     p_block = p_article_block_pool->p_block_free_list;
185     p_article_block_pool->p_block_free_list = p_block->p_next_block;
186     p_block->p_next_block = NULL;
187     p_block->article_count = 0;
188     }
189    
190     return p_block;
191     }
192    
193     inline static void push_free_article_block(ARTICLE_BLOCK *p_block)
194 sysadm 1.1 {
195 sysadm 1.7 p_block->p_next_block = p_article_block_pool->p_block_free_list;
196     p_article_block_pool->p_block_free_list = p_block;
197     }
198    
199     int article_block_reset(void)
200     {
201     ARTICLE_BLOCK *p_block;
202    
203     if (p_article_block_pool == NULL)
204     {
205     log_error("article_block_pool not initialized\n");
206     return -1;
207     }
208 sysadm 1.1
209 sysadm 1.7 while (p_article_block_pool->block_count > 0)
210 sysadm 1.1 {
211 sysadm 1.7 p_article_block_pool->block_count--;
212     p_block = p_article_block_pool->p_block[p_article_block_pool->block_count];
213     push_free_article_block(p_block);
214 sysadm 1.1 }
215    
216 sysadm 1.7 return 0;
217     }
218    
219     ARTICLE *article_block_find_by_aid(int32_t aid)
220     {
221     ARTICLE_BLOCK *p_block;
222     int left;
223     int right;
224     int mid;
225    
226     if (p_article_block_pool == NULL)
227 sysadm 1.1 {
228 sysadm 1.7 log_error("article_block_pool not initialized\n");
229     return NULL;
230 sysadm 1.1 }
231    
232 sysadm 1.7 if (p_article_block_pool->block_count == 0) // empty
233 sysadm 1.1 {
234 sysadm 1.7 return NULL;
235 sysadm 1.1 }
236    
237 sysadm 1.7 left = 0;
238     right = p_article_block_pool->block_count;
239    
240     // aid in the range [ head aid of blocks[left], tail aid of blocks[right - 1] ]
241     while (left < right - 1)
242 sysadm 1.1 {
243 sysadm 1.7 // get block offset no less than mid value of left and right block offsets
244     mid = (left + right) / 2 + (right - left) % 2;
245    
246     if (mid >= p_article_block_pool->block_count)
247 sysadm 1.1 {
248 sysadm 1.7 log_error("block(mid = %d) is out of boundary\n", mid);
249     return NULL;
250     }
251 sysadm 1.1
252 sysadm 1.7 if (aid < p_article_block_pool->p_block[mid]->articles[0].aid)
253     {
254     right = mid;
255     }
256     else
257     {
258     left = mid;
259 sysadm 1.1 }
260 sysadm 1.7 }
261    
262     p_block = p_article_block_pool->p_block[left];
263    
264     left = 0;
265     right = p_block->article_count - 1;
266    
267     // aid in the range [ aid of articles[left], aid of articles[right] ]
268     while (left < right)
269     {
270     mid = (left + right) / 2;
271 sysadm 1.1
272 sysadm 1.7 if (aid <= p_block->articles[mid].aid)
273     {
274     right = mid;
275     }
276     else
277     {
278     left = mid + 1;
279     }
280 sysadm 1.1 }
281 sysadm 1.7
282     return (p_block->articles + left);
283 sysadm 1.1 }
284    
285 sysadm 1.7 ARTICLE *article_block_find_by_index(int index)
286 sysadm 1.1 {
287 sysadm 1.7 ARTICLE_BLOCK *p_block;
288    
289     if (p_article_block_pool == NULL)
290     {
291     log_error("article_block_pool not initialized\n");
292     return NULL;
293     }
294    
295     if (index < 0 || index / ARTICLE_PER_BLOCK >= p_article_block_pool->block_count)
296     {
297     log_error("section_data_find_article_by_index(%d) is out of boundary of block [0, %d)\n", index, p_article_block_pool->block_count);
298     return NULL;
299     }
300    
301     p_block = p_article_block_pool->p_block[index / ARTICLE_PER_BLOCK];
302 sysadm 1.1
303 sysadm 1.7 if (index % ARTICLE_PER_BLOCK >= p_block->article_count)
304 sysadm 1.1 {
305 sysadm 1.7 log_error("section_data_find_article_by_index(%d) is out of boundary of article [0, %d)\n", index, p_block->article_count);
306     return NULL;
307 sysadm 1.1 }
308    
309 sysadm 1.7 return (p_block->articles + (index % ARTICLE_PER_BLOCK));
310 sysadm 1.1 }
311    
312 sysadm 1.7 SECTION_LIST *section_list_create(const char *sname, const char *stitle, const char *master_name)
313 sysadm 1.1 {
314 sysadm 1.7 SECTION_LIST *p_section;
315    
316     if (p_section_list_pool == NULL)
317     {
318     p_section_list_pool = calloc(BBS_max_section, sizeof(SECTION_LIST));
319     if (p_section_list_pool == NULL)
320     {
321     log_error("calloc(%d SECTION_LIST) OOM\n", BBS_max_section);
322     return NULL;
323     }
324 sysadm 1.1
325 sysadm 1.7 section_list_count = 0;
326     }
327 sysadm 1.1
328 sysadm 1.7 if (p_trie_dict_section_list == NULL)
329 sysadm 1.1 {
330 sysadm 1.7 p_trie_dict_section_list = trie_dict_create();
331     if (p_trie_dict_section_list == NULL)
332     {
333     log_error("trie_dict_create() OOM\n", BBS_max_section);
334     return NULL;
335     }
336 sysadm 1.1 }
337    
338 sysadm 1.7 if (section_list_count >= BBS_max_section)
339 sysadm 1.1 {
340 sysadm 1.7 log_error("section_list_count exceed limit %d\n", BBS_max_section);
341 sysadm 1.1 return NULL;
342     }
343    
344 sysadm 1.7 p_section = p_section_list_pool + section_list_count;
345 sysadm 1.1
346     strncpy(p_section->sname, sname, sizeof(p_section->sname - 1));
347     p_section->sname[sizeof(p_section->sname - 1)] = '\0';
348    
349     strncpy(p_section->stitle, stitle, sizeof(p_section->stitle - 1));
350     p_section->stitle[sizeof(p_section->stitle - 1)] = '\0';
351    
352     strncpy(p_section->master_name, master_name, sizeof(p_section->master_name - 1));
353     p_section->master_name[sizeof(p_section->master_name - 1)] = '\0';
354    
355 sysadm 1.7 if (trie_dict_set(p_trie_dict_section_list, sname, section_list_count) != 1)
356 sysadm 1.1 {
357 sysadm 1.7 log_error("trie_dict_set(section_data, %s, %d) error\n", sname, section_list_count);
358 sysadm 1.1 return NULL;
359     }
360    
361 sysadm 1.7 section_list_reset_articles(p_section);
362    
363     section_list_count++;
364 sysadm 1.1
365     return p_section;
366     }
367    
368 sysadm 1.7 void section_list_reset_articles(SECTION_LIST *p_section)
369 sysadm 1.1 {
370 sysadm 1.7 p_section->article_count = 0;
371 sysadm 1.8 p_section->topic_count = 0;
372     p_section->visible_article_count = 0;
373     p_section->visible_topic_count = 0;
374 sysadm 1.7 p_section->p_article_head = NULL;
375     p_section->p_article_tail = NULL;
376 sysadm 1.1
377 sysadm 1.7 p_section->page_count = 0;
378 sysadm 1.8 p_section->last_page_visible_article_count = 0;
379 sysadm 1.7 }
380 sysadm 1.1
381 sysadm 1.7 void section_list_cleanup(void)
382     {
383     if (p_trie_dict_section_list != NULL)
384 sysadm 1.1 {
385 sysadm 1.7 trie_dict_destroy(p_trie_dict_section_list);
386     p_trie_dict_section_list = NULL;
387 sysadm 1.1 }
388    
389 sysadm 1.7 if (p_section_list_pool != NULL)
390 sysadm 1.1 {
391 sysadm 1.7 free(p_section_list_pool);
392     p_section_list_pool = NULL;
393 sysadm 1.1 }
394    
395 sysadm 1.7 section_list_count = 0;
396 sysadm 1.1 }
397    
398 sysadm 1.7 SECTION_LIST *section_list_find_by_name(const char *sname)
399 sysadm 1.1 {
400     int64_t index;
401    
402 sysadm 1.7 if (p_section_list_pool == NULL || p_trie_dict_section_list == NULL)
403 sysadm 1.1 {
404 sysadm 1.7 log_error("section_list not initialized\n");
405 sysadm 1.1 return NULL;
406     }
407    
408 sysadm 1.7 if (trie_dict_get(p_trie_dict_section_list, sname, &index) != 1)
409 sysadm 1.1 {
410     log_error("trie_dict_get(section_data, %s) error\n", sname);
411     return NULL;
412     }
413    
414 sysadm 1.7 return (p_section_list_pool + index);
415 sysadm 1.1 }
416    
417 sysadm 1.7 int section_list_append_article(SECTION_LIST *p_section, const ARTICLE *p_article_src)
418 sysadm 1.1 {
419     ARTICLE_BLOCK *p_block;
420     int32_t last_aid = 0;
421 sysadm 1.6 ARTICLE *p_article;
422 sysadm 1.1 ARTICLE *p_topic_head;
423     ARTICLE *p_topic_tail;
424    
425 sysadm 1.6 if (p_section == NULL || p_article_src == NULL)
426 sysadm 1.1 {
427 sysadm 1.7 log_error("section_list_append_article() NULL pointer error\n");
428 sysadm 1.1 return -1;
429     }
430    
431 sysadm 1.7 if (p_article_block_pool == NULL)
432 sysadm 1.1 {
433 sysadm 1.7 log_error("article_block_pool not initialized\n");
434 sysadm 1.1 return -1;
435     }
436    
437 sysadm 1.7 if (p_article_block_pool->block_count == 0 ||
438     p_article_block_pool->p_block[p_article_block_pool->block_count - 1]->article_count >= ARTICLE_PER_BLOCK)
439 sysadm 1.1 {
440     if ((p_block = pop_free_article_block()) == NULL)
441     {
442     log_error("pop_free_article_block() error\n");
443     return -2;
444     }
445    
446 sysadm 1.7 if (p_article_block_pool->block_count > 0)
447 sysadm 1.1 {
448 sysadm 1.7 last_aid = p_article_block_pool->p_block[p_article_block_pool->block_count - 1]->articles[ARTICLE_PER_BLOCK - 1].aid;
449 sysadm 1.1 }
450 sysadm 1.7
451     p_article_block_pool->p_block[p_article_block_pool->block_count] = p_block;
452     p_article_block_pool->block_count++;
453 sysadm 1.1 }
454     else
455     {
456 sysadm 1.7 p_block = p_article_block_pool->p_block[p_article_block_pool->block_count - 1];
457     last_aid = p_block->articles[p_block->article_count - 1].aid;
458 sysadm 1.1 }
459    
460     // AID of articles should be strictly ascending
461 sysadm 1.6 if (p_article_src->aid <= last_aid)
462 sysadm 1.1 {
463 sysadm 1.6 log_error("section_data_append_article(aid=%d) error: last_aid=%d\n", p_article_src->aid, last_aid);
464 sysadm 1.1 return -3;
465     }
466    
467 sysadm 1.7 p_article = (p_block->articles + p_block->article_count);
468     p_block->article_count++;
469     p_section->article_count++;
470    
471     // Copy article data
472     *p_article = *p_article_src;
473 sysadm 1.1
474 sysadm 1.8 if (p_article->visible)
475     {
476     p_section->visible_article_count++;
477     }
478    
479 sysadm 1.7 // Link appended article as tail node of topic bi-directional list
480     if (p_article->tid != 0)
481 sysadm 1.1 {
482 sysadm 1.7 p_topic_head = article_block_find_by_aid(p_article->tid);
483 sysadm 1.1 if (p_topic_head == NULL)
484     {
485 sysadm 1.7 log_error("search head of topic (aid=%d) error\n", p_article->tid);
486 sysadm 1.1 return -4;
487     }
488    
489 sysadm 1.6 p_topic_tail = p_topic_head->p_topic_prior;
490 sysadm 1.1 if (p_topic_tail == NULL)
491     {
492 sysadm 1.7 log_error("tail of topic (aid=%d) is NULL\n", p_article->tid);
493 sysadm 1.1 return -4;
494     }
495     }
496     else
497     {
498 sysadm 1.8 p_section->topic_count++;
499    
500     if (p_article->visible)
501     {
502     p_section->visible_topic_count++;
503     }
504    
505 sysadm 1.7 p_topic_head = p_article;
506     p_topic_tail = p_article;
507 sysadm 1.1 }
508    
509 sysadm 1.7 p_article->p_topic_prior = p_topic_tail;
510     p_article->p_topic_next = p_topic_head;
511     p_topic_head->p_topic_prior = p_article;
512     p_topic_tail->p_topic_next = p_article;
513 sysadm 1.1
514 sysadm 1.6 // Link appended article as tail node of article bi-directional list
515     if (p_section->p_article_head == NULL)
516     {
517     p_section->p_article_head = p_article;
518     p_section->p_article_tail = p_article;
519     }
520     p_article->p_prior = p_section->p_article_tail;
521     p_article->p_next = p_section->p_article_head;
522     p_section->p_article_head->p_prior = p_article;
523     p_section->p_article_tail->p_next = p_article;
524     p_section->p_article_tail = p_article;
525    
526 sysadm 1.7 // Update page
527 sysadm 1.8 if (p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0)
528 sysadm 1.1 {
529 sysadm 1.7 p_section->p_page_first_article[p_section->page_count] = p_article;
530     p_section->page_count++;
531 sysadm 1.8 p_section->last_page_visible_article_count = 0;
532 sysadm 1.1 }
533 sysadm 1.8 p_section->last_page_visible_article_count++;
534 sysadm 1.1
535 sysadm 1.7 return 0;
536 sysadm 1.2 }
537    
538 sysadm 1.7 int section_list_set_article_visible(SECTION_LIST *p_section, int32_t aid, int8_t visible)
539 sysadm 1.1 {
540     ARTICLE *p_article;
541 sysadm 1.8 ARTICLE *p_reply;
542     int affected_count = 0;
543 sysadm 1.1
544 sysadm 1.2 if (p_section == NULL)
545     {
546 sysadm 1.7 log_error("section_list_set_article_visible() NULL pointer error\n");
547 sysadm 1.2 return -2;
548     }
549    
550 sysadm 1.7 p_article = article_block_find_by_aid(aid);
551 sysadm 1.1 if (p_article == NULL)
552     {
553     return -1; // Not found
554     }
555    
556 sysadm 1.7 if (p_article->visible == visible)
557 sysadm 1.1 {
558 sysadm 1.7 return 0; // Already set
559 sysadm 1.1 }
560    
561 sysadm 1.8 if (visible == 0) // 1 -> 0
562     {
563     p_section->visible_article_count--;
564    
565     if (p_article->tid == 0)
566     {
567     p_section->visible_topic_count--;
568    
569     // Set related visible replies to invisible
570     for (p_reply = p_article->p_topic_next; p_reply->tid != 0; p_reply = p_reply->p_topic_next)
571     {
572     if (p_reply->tid != aid)
573     {
574     log_error("Inconsistent tid = %d found in reply %d of topic %d\n", p_reply->tid, p_reply->aid, aid);
575     continue;
576     }
577    
578     if (p_reply->visible == 1)
579     {
580     p_reply->visible = 0;
581     p_section->visible_article_count--;
582     affected_count++;
583     }
584     }
585     }
586     }
587     else // 0 -> 1
588     {
589     p_section->visible_article_count++;
590    
591     if (p_article->tid == 0)
592     {
593     p_section->visible_topic_count++;
594     }
595     }
596    
597 sysadm 1.7 p_article->visible = visible;
598 sysadm 1.8 affected_count++;
599    
600     return affected_count;
601     }
602    
603     ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset)
604     {
605     ARTICLE *p_article;
606     int left;
607     int right;
608     int mid;
609    
610     *p_page = -1;
611     *p_offset = -1;
612    
613     if (p_section == NULL)
614     {
615     log_error("section_list_find_article_with_offset() NULL pointer error\n");
616     return NULL;
617     }
618 sysadm 1.7
619 sysadm 1.8 if (p_section->article_count == 0) // empty
620     {
621     *p_page = 0;
622     *p_offset = 0;
623     return NULL;
624     }
625    
626     left = 0;
627     right = p_section->page_count;
628    
629     // aid in the range [ head aid of pages[left], tail aid of pages[right - 1] ]
630     while (left < right - 1)
631     {
632     // get page id no less than mid value of left page id and right page id
633     mid = (left + right) / 2 + (right - left) % 2;
634 sysadm 1.1
635 sysadm 1.8 if (mid >= p_section->page_count)
636     {
637     log_error("page id (mid = %d) is out of boundary\n", mid);
638     return NULL;
639     }
640    
641     if (aid < p_section->p_page_first_article[mid]->aid)
642     {
643     right = mid;
644     }
645     else
646     {
647     left = mid;
648     }
649     }
650    
651     *p_page = left;
652    
653     p_article = p_section->p_page_first_article[*p_page];
654    
655     // p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid
656     right = (*p_page == p_section->page_count - 1 ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid);
657    
658     // left will be the offset of article found or offset to insert
659     left = 0;
660    
661     while (1)
662     {
663     if (aid == p_article->aid) // found
664     {
665     break;
666     }
667     else if (aid < p_article->aid) // not exist
668     {
669     p_article = NULL;
670     break;
671     }
672    
673     // aid > p_article->aid
674     p_article = p_article->p_next;
675     left++;
676    
677     // over last article in the page
678     if (p_article == p_section->p_article_head || p_article->aid >= right)
679     {
680     p_article = NULL;
681     break;
682     }
683     }
684    
685     *p_offset = left;
686    
687     return p_article;
688     }
689    
690     int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid)
691     {
692     // ARTICLE *p_article;
693    
694     if (p_section == NULL)
695     {
696     log_error("section_list_calculate_page() NULL pointer error\n");
697     return -1;
698     }
699    
700     return 0;
701 sysadm 1.1 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1