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

Diff of /lbbs/src/section_list.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.5 by sysadm, Wed May 21 09:18:17 2025 UTC Revision 1.15 by sysadm, Sat May 24 03:41:34 2025 UTC
# Line 23  Line 23 
23  #include <unistd.h>  #include <unistd.h>
24  #include <stdlib.h>  #include <stdlib.h>
25  #include <errno.h>  #include <errno.h>
26    #include <sys/param.h>
27  #include <sys/shm.h>  #include <sys/shm.h>
28  #include <sys/ipc.h>  #include <sys/ipc.h>
29    
30  // ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT should be  #define ARTICLE_BLOCK_PER_SHM 400                 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate
 // no less than BBS_article_block_limit_per_section * BBS_max_section,  
 // in order to allocate enough memory for blocks  
 #define ARTICLE_BLOCK_PER_SHM 400 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate  
31  #define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id)  #define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id)
32    #define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT)
33    
34    #define CALCULATE_PAGE_THRESHOLD 100 // Adjust to tune performance of move topic
35    
36    #define SID_STR_LEN 5 // 32-bit + NULL
37    
38    struct article_block_t
39    {
40            ARTICLE articles[ARTICLE_PER_BLOCK];
41            int32_t article_count;
42            struct article_block_t *p_next_block;
43    };
44    typedef struct article_block_t ARTICLE_BLOCK;
45    
46  struct article_block_shm_t  struct article_block_shm_t
47  {  {
# Line 39  struct article_block_shm_t Line 50  struct article_block_shm_t
50  };  };
51  typedef struct article_block_shm_t ARTICLE_BLOCK_SHM;  typedef struct article_block_shm_t ARTICLE_BLOCK_SHM;
52    
53  static ARTICLE_BLOCK_SHM *p_article_block_shm_pool;  struct article_block_pool_t
54  static int article_block_shm_count;  {
55  static ARTICLE_BLOCK *p_article_block_free_list;          ARTICLE_BLOCK_SHM shm_pool[ARTICLE_BLOCK_SHM_COUNT_LIMIT];
56            int shm_count;
57  static SECTION_DATA *p_section_data_pool;          ARTICLE_BLOCK *p_block_free_list;
58  static int section_data_count;          ARTICLE_BLOCK *p_block[ARTICLE_BLOCK_PER_POOL];
59  static TRIE_NODE *p_trie_dict_section_data;          int32_t block_count;
60    };
61    typedef struct article_block_pool_t ARTICLE_BLOCK_POOL;
62    
63    static ARTICLE_BLOCK_POOL *p_article_block_pool = NULL;
64    
65    static int section_list_pool_shmid;
66    static SECTION_LIST *p_section_list_pool = NULL;
67    static int section_list_count = 0;
68    static TRIE_NODE *p_trie_dict_section_by_name = NULL;
69    static TRIE_NODE *p_trie_dict_section_by_sid = NULL;
70    
71  int section_data_pool_init(const char *filename, int article_block_count)  int article_block_init(const char *filename, int block_count)
72  {  {
73          int shmid;          int shmid;
74          int proj_id;          int proj_id;
# Line 55  int section_data_pool_init(const char *f Line 76  int section_data_pool_init(const char *f
76          size_t size;          size_t size;
77          void *p_shm;          void *p_shm;
78          int i;          int i;
79          int article_block_count_in_shm;          int block_count_in_shm;
80          ARTICLE_BLOCK *p_article_block_in_shm;          ARTICLE_BLOCK *p_block_in_shm;
81          ARTICLE_BLOCK **pp_article_block_next;          ARTICLE_BLOCK **pp_block_next;
   
         if (p_article_block_shm_pool != NULL ||  
                 p_article_block_free_list != NULL ||  
                 p_section_data_pool != NULL ||  
                 p_trie_dict_section_data != NULL)  
         {  
                 log_error("section_data_pool already initialized\n");  
                 return -1;  
         }  
82    
83          if (article_block_count > ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT)          if (p_article_block_pool != NULL)
84          {          {
85                  log_error("article_block_count exceed limit %d\n", ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT);                  log_error("article_block_pool already initialized\n");
86                  return -2;                  return -1;
         }  
   
         p_article_block_shm_pool = calloc((size_t)article_block_count / ARTICLE_BLOCK_PER_SHM + 1, sizeof(ARTICLE_BLOCK_SHM));  
         if (p_article_block_shm_pool == NULL)  
         {  
                 log_error("calloc(%d ARTICLE_BLOCK_SHM) OOM\n", article_block_count / ARTICLE_BLOCK_PER_SHM + 1);  
                 return -2;  
87          }          }
88    
89          p_section_data_pool = calloc(BBS_max_section, sizeof(SECTION_DATA));          if (block_count > ARTICLE_BLOCK_PER_POOL)
         if (p_section_data_pool == NULL)  
90          {          {
91                  log_error("calloc(%d SECTION_DATA) OOM\n", BBS_max_section);                  log_error("article_block_count exceed limit %d\n", ARTICLE_BLOCK_PER_POOL);
92                  return -2;                  return -2;
93          }          }
         section_data_count = 0;  
94    
95          p_trie_dict_section_data = trie_dict_create();          p_article_block_pool = calloc(1, sizeof(ARTICLE_BLOCK_POOL));
96          if (p_trie_dict_section_data == NULL)          if (p_article_block_pool == NULL)
97          {          {
98                  log_error("trie_dict_create() OOM\n", BBS_max_section);                  log_error("calloc(ARTICLE_BLOCK_POOL) OOM\n");
99                  return -2;                  return -2;
100          }          }
101    
102          // Allocate shared memory          // Allocate shared memory
103          article_block_shm_count = 0;          p_article_block_pool->shm_count = 0;
104          pp_article_block_next = &p_article_block_free_list;          pp_block_next = &(p_article_block_pool->p_block_free_list);
105    
106          while (article_block_count > 0)          while (block_count > 0)
107          {          {
108                  article_block_count_in_shm =                  block_count_in_shm = MIN(block_count, ARTICLE_BLOCK_PER_SHM);
109                          (article_block_count < ARTICLE_BLOCK_PER_SHM ? article_block_count : ARTICLE_BLOCK_PER_SHM);                  block_count -= block_count_in_shm;
                 article_block_count -= article_block_count_in_shm;  
110    
111                  proj_id = getpid() + article_block_shm_count;                  proj_id = getpid() + p_article_block_pool->shm_count;
112                  key = ftok(filename, proj_id);                  key = ftok(filename, proj_id);
113                  if (key == -1)                  if (key == -1)
114                  {                  {
115                          log_error("ftok(%s, %d) error (%d)\n", filename, proj_id, errno);                          log_error("ftok(%s, %d) error (%d)\n", filename, proj_id, errno);
116                          section_data_pool_cleanup();                          article_block_cleanup();
117                          return -3;                          return -3;
118                  }                  }
119    
120                  size = sizeof(shmid) + sizeof(ARTICLE_BLOCK) * (size_t)article_block_count_in_shm;                  size = sizeof(shmid) + sizeof(ARTICLE_BLOCK) * (size_t)block_count_in_shm;
121                  shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);                  shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
122                  if (shmid == -1)                  if (shmid == -1)
123                  {                  {
124                          log_error("shmget(shm_index = %d, size = %d) error (%d)\n", article_block_shm_count, size, errno);                          log_error("shmget(shm_index = %d, size = %d) error (%d)\n", p_article_block_pool->shm_count, size, errno);
125                          section_data_pool_cleanup();                          article_block_cleanup();
126                          return -3;                          return -3;
127                  }                  }
128                  p_shm = shmat(shmid, NULL, 0);                  p_shm = shmat(shmid, NULL, 0);
129                  if (p_shm == (void *)-1)                  if (p_shm == (void *)-1)
130                  {                  {
131                          log_error("shmat(shmid = %d) error (%d)\n", shmid, errno);                          log_error("shmat(shmid = %d) error (%d)\n", shmid, errno);
132                          section_data_pool_cleanup();                          article_block_cleanup();
133                          return -3;                          return -3;
134                  }                  }
135    
136                  (p_article_block_shm_pool + article_block_shm_count)->shmid = shmid;                  (p_article_block_pool->shm_pool + p_article_block_pool->shm_count)->shmid = shmid;
137                  (p_article_block_shm_pool + article_block_shm_count)->p_shm = p_shm;                  (p_article_block_pool->shm_pool + p_article_block_pool->shm_count)->p_shm = p_shm;
138                  article_block_shm_count++;                  p_article_block_pool->shm_count++;
139    
140                  p_article_block_in_shm = p_shm;                  p_block_in_shm = p_shm;
141                  *pp_article_block_next = p_article_block_in_shm;                  *pp_block_next = p_block_in_shm;
142    
143                  for (i = 0; i < article_block_count_in_shm; i++)                  for (i = 0; i < block_count_in_shm; i++)
144                  {                  {
145                          if (i < article_block_count_in_shm - 1)                          if (i < block_count_in_shm - 1)
146                          {                          {
147                                  (p_article_block_in_shm + i)->p_next_block = (p_article_block_in_shm + i + 1);                                  (p_block_in_shm + i)->p_next_block = (p_block_in_shm + i + 1);
148                          }                          }
149                          else                          else
150                          {                          {
151                                  (p_article_block_in_shm + i)->p_next_block = NULL;                                  (p_block_in_shm + i)->p_next_block = NULL;
152                                  pp_article_block_next = &((p_article_block_in_shm + i)->p_next_block);                                  pp_block_next = &((p_block_in_shm + i)->p_next_block);
153                          }                          }
154                  }                  }
155          }          }
156    
157            p_article_block_pool->block_count = 0;
158    
159          return 0;          return 0;
160  }  }
161    
162  void section_data_pool_cleanup(void)  void article_block_cleanup(void)
163  {  {
164          int i;          if (p_article_block_pool != NULL)
165            {
166                    for (int i = 0; i < p_article_block_pool->shm_count; i++)
167                    {
168                            if (shmdt((p_article_block_pool->shm_pool + i)->p_shm) == -1)
169                            {
170                                    log_error("shmdt(shmid = %d) error (%d)\n", (p_article_block_pool->shm_pool + i)->shmid, errno);
171                            }
172    
173          if (p_trie_dict_section_data != NULL)                          if (shmctl((p_article_block_pool->shm_pool + i)->shmid, IPC_RMID, NULL) == -1)
174                            {
175                                    log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", (p_article_block_pool->shm_pool + i)->shmid, errno);
176                            }
177                    }
178    
179                    free(p_article_block_pool);
180                    p_article_block_pool = NULL;
181            }
182    }
183    
184    inline static ARTICLE_BLOCK *pop_free_article_block(void)
185    {
186            ARTICLE_BLOCK *p_block = NULL;
187    
188            if (p_article_block_pool->p_block_free_list != NULL)
189            {
190                    p_block = p_article_block_pool->p_block_free_list;
191                    p_article_block_pool->p_block_free_list = p_block->p_next_block;
192                    p_block->p_next_block = NULL;
193                    p_block->article_count = 0;
194            }
195    
196            return p_block;
197    }
198    
199    inline static void push_free_article_block(ARTICLE_BLOCK *p_block)
200    {
201            p_block->p_next_block = p_article_block_pool->p_block_free_list;
202            p_article_block_pool->p_block_free_list = p_block;
203    }
204    
205    int article_block_reset(void)
206    {
207            ARTICLE_BLOCK *p_block;
208    
209            if (p_article_block_pool == NULL)
210            {
211                    log_error("article_block_pool not initialized\n");
212                    return -1;
213            }
214    
215            while (p_article_block_pool->block_count > 0)
216          {          {
217                  trie_dict_destroy(p_trie_dict_section_data);                  p_article_block_pool->block_count--;
218                  p_trie_dict_section_data = NULL;                  p_block = p_article_block_pool->p_block[p_article_block_pool->block_count];
219                  section_data_count = 0;                  push_free_article_block(p_block);
220          }          }
221    
222          if (p_section_data_pool != NULL)          return 0;
223    }
224    
225    ARTICLE *article_block_find_by_aid(int32_t aid)
226    {
227            ARTICLE_BLOCK *p_block;
228            int left;
229            int right;
230            int mid;
231    
232            if (p_article_block_pool == NULL)
233          {          {
234                  free(p_section_data_pool);                  log_error("article_block_pool not initialized\n");
235                  p_section_data_pool = NULL;                  return NULL;
236          }          }
237    
238          if (p_article_block_free_list != NULL)          if (p_article_block_pool->block_count == 0) // empty
239          {          {
240                  p_article_block_free_list = NULL;                  return NULL;
241          }          }
242    
243          if (p_article_block_shm_pool != NULL)          left = 0;
244            right = p_article_block_pool->block_count;
245    
246            // aid in the range [ head aid of blocks[left], tail aid of blocks[right - 1] ]
247            while (left < right - 1)
248          {          {
249                  for (i = 0; i < article_block_shm_count; i++)                  // get block offset no less than mid value of left and right block offsets
250                    mid = (left + right) / 2 + (right - left) % 2;
251    
252                    if (mid >= p_article_block_pool->block_count)
253                  {                  {
254                          if (shmdt((p_article_block_shm_pool + i)->p_shm) == -1)                          log_error("block(mid = %d) is out of boundary\n", mid);
255                          {                          return NULL;
256                                  log_error("shmdt(shmid = %d) error (%d)\n", (p_article_block_shm_pool + i)->shmid, errno);                  }
                         }  
257    
258                          if (shmctl((p_article_block_shm_pool + i)->shmid, IPC_RMID, NULL) == -1)                  if (aid < p_article_block_pool->p_block[mid]->articles[0].aid)
259                          {                  {
260                                  log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", (p_article_block_shm_pool + i)->shmid, errno);                          right = mid;
                         }  
261                  }                  }
262                    else
263                    {
264                            left = mid;
265                    }
266            }
267    
268            p_block = p_article_block_pool->p_block[left];
269    
270            left = 0;
271            right = p_block->article_count - 1;
272    
273            // aid in the range [ aid of articles[left], aid of articles[right] ]
274            while (left < right)
275            {
276                    mid = (left + right) / 2;
277    
278                  p_article_block_shm_pool = NULL;                  if (aid <= p_block->articles[mid].aid)
279                  article_block_shm_count = 0;                  {
280                            right = mid;
281                    }
282                    else
283                    {
284                            left = mid + 1;
285                    }
286          }          }
287    
288            return (p_block->articles + left);
289  }  }
290    
291  inline static ARTICLE_BLOCK *pop_free_article_block(void)  ARTICLE *article_block_find_by_index(int index)
292    {
293            ARTICLE_BLOCK *p_block;
294    
295            if (p_article_block_pool == NULL)
296            {
297                    log_error("article_block_pool not initialized\n");
298                    return NULL;
299            }
300    
301            if (index < 0 || index / ARTICLE_PER_BLOCK >= p_article_block_pool->block_count)
302            {
303                    log_error("article_block_find_by_index(%d) is out of boundary of block [0, %d)\n", index, p_article_block_pool->block_count);
304                    return NULL;
305            }
306    
307            p_block = p_article_block_pool->p_block[index / ARTICLE_PER_BLOCK];
308    
309            if (index % ARTICLE_PER_BLOCK >= p_block->article_count)
310            {
311                    log_error("article_block_find_by_index(%d) is out of boundary of article [0, %d)\n", index, p_block->article_count);
312                    return NULL;
313            }
314    
315            return (p_block->articles + (index % ARTICLE_PER_BLOCK));
316    }
317    
318    extern int section_list_pool_init(const char *filename)
319  {  {
320          ARTICLE_BLOCK *p_article_block = NULL;          int shmid;
321            int proj_id;
322            key_t key;
323            size_t size;
324            void *p_shm;
325    
326          if (p_article_block_free_list != NULL)          if (p_section_list_pool == NULL || p_trie_dict_section_by_name == NULL || p_trie_dict_section_by_sid == NULL)
327          {          {
328                  p_article_block = p_article_block_free_list;                  section_list_pool_cleanup();
                 p_article_block_free_list = p_article_block_free_list->p_next_block;  
329          }          }
330    
331          return p_article_block;          p_section_list_pool = calloc(BBS_max_section, sizeof(SECTION_LIST));
332            if (p_section_list_pool == NULL)
333            {
334                    log_error("calloc(%d SECTION_LIST) OOM\n", BBS_max_section);
335                    return -1;
336            }
337    
338            proj_id = (int)(time(NULL) % getpid());
339            key = ftok(filename, proj_id);
340            if (key == -1)
341            {
342                    log_error("ftok(%s, %d) error (%d)\n", filename, proj_id, errno);
343                    return -3;
344            }
345    
346            size = sizeof(shmid) + sizeof(SECTION_LIST) * BBS_max_section;
347            shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
348            if (shmid == -1)
349            {
350                    log_error("shmget(section_list_pool, size = %d) error (%d)\n", size, errno);
351                    return -3;
352            }
353            p_shm = shmat(shmid, NULL, 0);
354            if (p_shm == (void *)-1)
355            {
356                    log_error("shmat(shmid = %d) error (%d)\n", shmid, errno);
357                    return -3;
358            }
359    
360            section_list_pool_shmid = shmid;
361            p_section_list_pool = p_shm;
362            section_list_count = 0;
363    
364            p_trie_dict_section_by_name = trie_dict_create();
365            if (p_trie_dict_section_by_name == NULL)
366            {
367                    log_error("trie_dict_create() OOM\n", BBS_max_section);
368                    return -2;
369            }
370    
371            p_trie_dict_section_by_sid = trie_dict_create();
372            if (p_trie_dict_section_by_sid == NULL)
373            {
374                    log_error("trie_dict_create() OOM\n", BBS_max_section);
375                    return -2;
376            }
377    
378            return 0;
379  }  }
380    
381  inline static void push_free_article_block(ARTICLE_BLOCK *p_article_block)  inline static void sid_to_str(int32_t sid, char *p_sid_str)
382  {  {
383          p_article_block->p_next_block = p_article_block_free_list;          uint32_t u_sid;
384          p_article_block_free_list = p_article_block;          int i;
385    
386            u_sid = (uint32_t)sid;
387            for (i = 0; i < SID_STR_LEN - 1; i++)
388            {
389                    p_sid_str[i] = (char)(u_sid % 255 + 1);
390                    u_sid /= 255;
391            }
392            p_sid_str[i] = '\0';
393  }  }
394    
395  SECTION_DATA *section_data_create(const char *sname, const char *stitle, const char *master_name)  SECTION_LIST *section_list_create(int32_t sid, const char *sname, const char *stitle, const char *master_name)
396  {  {
397          SECTION_DATA *p_section;          SECTION_LIST *p_section;
398          int index;          char sid_str[SID_STR_LEN];
399    
400          if (p_section_data_pool == NULL || p_trie_dict_section_data == NULL)          if (p_section_list_pool == NULL || p_trie_dict_section_by_name == NULL || p_trie_dict_section_by_sid == NULL)
401          {          {
402                  log_error("section_data not initialized\n");                  log_error("session_list_pool not initialized\n");
403                  return NULL;                  return NULL;
404          }          }
405    
406          if (section_data_count >= BBS_max_section)          if (section_list_count >= BBS_max_section)
407          {          {
408                  log_error("section_data_count exceed limit %d\n", BBS_max_section);                  log_error("section_list_count exceed limit %d >= %d\n", section_list_count, BBS_max_section);
409                  return NULL;                  return NULL;
410          }          }
411    
412          index = section_data_count;          sid_to_str(sid, sid_str);
413          p_section = p_section_data_pool + index;  
414            p_section = p_section_list_pool + section_list_count;
415    
416            p_section->sid = sid;
417    
418          strncpy(p_section->sname, sname, sizeof(p_section->sname - 1));          strncpy(p_section->sname, sname, sizeof(p_section->sname - 1));
419          p_section->sname[sizeof(p_section->sname - 1)] = '\0';          p_section->sname[sizeof(p_section->sname - 1)] = '\0';
# Line 245  SECTION_DATA *section_data_create(const Line 424  SECTION_DATA *section_data_create(const
424          strncpy(p_section->master_name, master_name, sizeof(p_section->master_name - 1));          strncpy(p_section->master_name, master_name, sizeof(p_section->master_name - 1));
425          p_section->master_name[sizeof(p_section->master_name - 1)] = '\0';          p_section->master_name[sizeof(p_section->master_name - 1)] = '\0';
426    
427          p_section->p_head_block = NULL;          if (trie_dict_set(p_trie_dict_section_by_name, sname, section_list_count) != 1)
428          p_section->p_tail_block = NULL;          {
429          p_section->block_count = 0;                  log_error("trie_dict_set(section, %s, %d) error\n", sname, section_list_count);
430          p_section->article_count = 0;                  return NULL;
431          p_section->delete_count = 0;          }
432    
433          if (trie_dict_set(p_trie_dict_section_data, sname, index) != 1)          if (trie_dict_set(p_trie_dict_section_by_sid, sid_str, section_list_count) != 1)
434          {          {
435                  log_error("trie_dict_set(section_data, %s, %d) error\n", sname, index);                  log_error("trie_dict_set(section, %d, %d) error\n", sid, section_list_count);
436                    log_std("Debug %x %x %x %x\n", sid_str[0], sid_str[1], sid_str[2], sid_str[3]);
437                  return NULL;                  return NULL;
438          }          }
439    
440          section_data_count++;          section_list_reset_articles(p_section);
441    
442            section_list_count++;
443    
444          return p_section;          return p_section;
445  }  }
446    
447  int section_data_free_block(SECTION_DATA *p_section)  void section_list_reset_articles(SECTION_LIST *p_section)
448  {  {
449          ARTICLE_BLOCK *p_block;          p_section->article_count = 0;
450            p_section->topic_count = 0;
451            p_section->visible_article_count = 0;
452            p_section->visible_topic_count = 0;
453            p_section->p_article_head = NULL;
454            p_section->p_article_tail = NULL;
455    
456          if (p_section == NULL)          p_section->page_count = 0;
457            p_section->last_page_visible_article_count = 0;
458    }
459    
460    void section_list_pool_cleanup(void)
461    {
462            if (p_trie_dict_section_by_name != NULL)
463          {          {
464                  log_error("section_data_free_block() NULL pointer error\n");                  trie_dict_destroy(p_trie_dict_section_by_name);
465                  return -1;                  p_trie_dict_section_by_name = NULL;
466          }          }
467    
468          if (p_section_data_pool == NULL)          if (p_trie_dict_section_by_sid != NULL)
469          {          {
470                  log_error("section_data not initialized\n");                  trie_dict_destroy(p_trie_dict_section_by_sid);
471                  return -1;                  p_trie_dict_section_by_sid = NULL;
472          }          }
473    
474          while (p_section->p_head_block != NULL)          if (p_section_list_pool != NULL)
475          {          {
476                  p_block = p_section->p_head_block;                  if (shmdt(p_section_list_pool) == -1)
477                  p_section->p_head_block = p_block->p_next_block;                  {
478                  push_free_article_block(p_block);                          log_error("shmdt(shmid = %d) error (%d)\n", section_list_pool_shmid, errno);
479                    }
480                    p_section_list_pool = NULL;
481    
482                    if (shmctl(section_list_pool_shmid, IPC_RMID, NULL) == -1)
483                    {
484                            log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", section_list_pool_shmid, errno);
485                    }
486          }          }
487    
488          p_section->p_tail_block = NULL;          section_list_count = 0;
489          p_section->block_count = 0;  }
         p_section->article_count = 0;  
         p_section->delete_count = 0;  
490    
491          return 0;  SECTION_LIST *section_list_find_by_name(const char *sname)
492    {
493            int64_t index;
494    
495            if (p_section_list_pool == NULL || p_trie_dict_section_by_name == NULL)
496            {
497                    log_error("section_list not initialized\n");
498                    return NULL;
499            }
500    
501            if (trie_dict_get(p_trie_dict_section_by_name, sname, &index) != 1)
502            {
503                    log_error("trie_dict_get(section, %s) error\n", sname);
504                    return NULL;
505            }
506    
507            return (p_section_list_pool + index);
508  }  }
509    
510  SECTION_DATA *section_data_find_section_by_name(const char *sname)  SECTION_LIST *section_list_find_by_sid(int32_t sid)
511  {  {
512          int64_t index;          int64_t index;
513            char sid_str[SID_STR_LEN];
514    
515          if (p_section_data_pool == NULL || p_trie_dict_section_data == NULL)          if (p_section_list_pool == NULL || p_trie_dict_section_by_sid == NULL)
516          {          {
517                  log_error("section_data not initialized\n");                  log_error("section_list not initialized\n");
518                  return NULL;                  return NULL;
519          }          }
520    
521          if (trie_dict_get(p_trie_dict_section_data, sname, &index) != 1)          sid_to_str(sid, sid_str);
522    
523            if (trie_dict_get(p_trie_dict_section_by_sid, sid_str, &index) != 1)
524          {          {
525                  log_error("trie_dict_get(section_data, %s) error\n", sname);                  log_error("trie_dict_get(section, %d) error\n", sid);
526                  return NULL;                  return NULL;
527          }          }
528    
529          return (p_section_data_pool + index);          return (p_section_list_pool + index);
530  }  }
531    
532  int section_data_append_article(SECTION_DATA *p_section, const ARTICLE *p_article)  int section_list_append_article(SECTION_LIST *p_section, const ARTICLE *p_article_src)
533  {  {
534          ARTICLE_BLOCK *p_block;          ARTICLE_BLOCK *p_block;
535          int32_t last_aid = 0;          int32_t last_aid = 0;
536            ARTICLE *p_article;
537          ARTICLE *p_topic_head;          ARTICLE *p_topic_head;
538          ARTICLE *p_topic_tail;          ARTICLE *p_topic_tail;
539    
540          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article_src == NULL)
541          {          {
542                  log_error("section_data_append_article() NULL pointer error\n");                  log_error("section_list_append_article() NULL pointer error\n");
543                  return -1;                  return -1;
544          }          }
545    
546          if (p_section_data_pool == NULL)          if (p_article_block_pool == NULL)
547          {          {
548                  log_error("section_data not initialized\n");                  log_error("article_block_pool not initialized\n");
549                  return -1;                  return -1;
550          }          }
551    
552          if (p_section->p_tail_block == NULL || p_section->p_tail_block->article_count >= BBS_article_limit_per_block)          if (p_section->sid != p_article_src->sid)
553          {          {
554                  if (p_section->block_count >= BBS_article_block_limit_per_section)                  log_error("section_list_append_article() error: section sid %d != article sid %d\n", p_section->sid, p_article_src->sid);
555                  {                  return -2;
556                          log_error("section block count %d reach limit\n", p_section->block_count);          }
                         return -2;  
                 }  
557    
558            if (p_section->article_count >= BBS_article_limit_per_section)
559            {
560                    log_error("section_list_append_article() error: article_count reach limit in section %d\n", p_section->sid);
561                    return -2;
562            }
563    
564            if (p_article_block_pool->block_count == 0 ||
565                    p_article_block_pool->p_block[p_article_block_pool->block_count - 1]->article_count >= ARTICLE_PER_BLOCK)
566            {
567                  if ((p_block = pop_free_article_block()) == NULL)                  if ((p_block = pop_free_article_block()) == NULL)
568                  {                  {
569                          log_error("pop_free_article_block() error\n");                          log_error("pop_free_article_block() error\n");
570                          return -2;                          return -2;
571                  }                  }
572    
573                  p_block->article_count = 0;                  if (p_article_block_pool->block_count > 0)
                 p_block->p_next_block = NULL;  
   
                 if (p_section->p_tail_block == NULL)  
                 {  
                         p_section->p_head_block = p_block;  
                         last_aid = 0;  
                 }  
                 else  
574                  {                  {
575                          p_section->p_tail_block->p_next_block = p_block;                          last_aid = p_article_block_pool->p_block[p_article_block_pool->block_count - 1]->articles[ARTICLE_PER_BLOCK - 1].aid;
                         last_aid = p_section->p_tail_block->articles[BBS_article_limit_per_block - 1].aid;  
576                  }                  }
577                  p_section->p_tail_block = p_block;  
578                  p_section->p_block[p_section->block_count] = p_block;                  p_article_block_pool->p_block[p_article_block_pool->block_count] = p_block;
579                  p_section->block_count++;                  p_article_block_pool->block_count++;
580          }          }
581          else          else
582          {          {
583                  p_block = p_section->p_tail_block;                  p_block = p_article_block_pool->p_block[p_article_block_pool->block_count - 1];
584                  last_aid = p_block->articles[p_block->article_count - 1].aid;                  last_aid = p_block->articles[p_block->article_count - 1].aid;
585          }          }
586    
587          // AID of articles should be strictly ascending          // AID of articles should be strictly ascending
588          if (p_article->aid <= last_aid)          if (p_article_src->aid <= last_aid)
589          {          {
590                  log_error("section_data_append_article(aid=%d) error: last_aid=%d\n", p_article->aid, last_aid);                  log_error("section_list_append_article(aid=%d) error: last_aid=%d\n", p_article_src->aid, last_aid);
591                  return -3;                  return -3;
592          }          }
593    
594          if (p_block->article_count == 0)          p_article = (p_block->articles + p_block->article_count);
595            p_block->article_count++;
596            p_section->article_count++;
597    
598            // Copy article data
599            *p_article = *p_article_src;
600    
601            if (p_article->visible)
602          {          {
603                  p_section->block_head_aid[p_section->block_count - 1] = p_article->aid;                  p_section->visible_article_count++;
604          }          }
605    
606            // Link appended article as tail node of topic bi-directional list
607          if (p_article->tid != 0)          if (p_article->tid != 0)
608          {          {
609                  p_topic_head = section_data_find_article_by_aid(p_section, p_article->tid);                  p_topic_head = article_block_find_by_aid(p_article->tid);
610                  if (p_topic_head == NULL)                  if (p_topic_head == NULL)
611                  {                  {
612                          log_error("search head of topic (aid=%d) error\n", p_article->tid);                          log_error("search head of topic (aid=%d) error\n", p_article->tid);
613                          return -4;                          return -4;
614                  }                  }
615    
616                  p_topic_tail = section_data_find_article_by_aid(p_section, p_topic_head->prior_aid);                  p_topic_tail = p_topic_head->p_topic_prior;
617                  if (p_topic_tail == NULL)                  if (p_topic_tail == NULL)
618                  {                  {
619                          log_error("search tail of topic (aid=%d) error\n", p_topic_head->prior_aid);                          log_error("tail of topic (aid=%d) is NULL\n", p_article->tid);
620                          return -4;                          return -4;
621                  }                  }
622          }          }
623          else          else
624          {          {
625                  p_topic_head = &(p_block->articles[p_block->article_count]);                  p_section->topic_count++;
626                  p_topic_tail = p_topic_head;  
627                    if (p_article->visible)
628                    {
629                            p_section->visible_topic_count++;
630                    }
631    
632                    p_topic_head = p_article;
633                    p_topic_tail = p_article;
634          }          }
635    
636          // Copy article data          p_article->p_topic_prior = p_topic_tail;
637          p_block->articles[p_block->article_count] = *p_article;          p_article->p_topic_next = p_topic_head;
638            p_topic_head->p_topic_prior = p_article;
639            p_topic_tail->p_topic_next = p_article;
640    
641          // Link appended article as tail node of topic bi-directional list;          // Link appended article as tail node of article bi-directional list
642          p_block->articles[p_block->article_count].prior_aid = p_topic_tail->aid;          if (p_section->p_article_head == NULL)
643          p_block->articles[p_block->article_count].next_aid = p_topic_head->aid;          {
644          p_topic_head->prior_aid = p_article->aid;                  p_section->p_article_head = p_article;
645          p_topic_tail->next_aid = p_article->aid;                  p_section->p_article_tail = p_article;
646            }
647            p_article->p_prior = p_section->p_article_tail;
648            p_article->p_next = p_section->p_article_head;
649            p_section->p_article_head->p_prior = p_article;
650            p_section->p_article_tail->p_next = p_article;
651            p_section->p_article_tail = p_article;
652    
653          p_block->article_count++;          // Update page
654          p_section->article_count++;          if ((p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0) ||
655                    p_section->article_count == 1)
656            {
657                    p_section->p_page_first_article[p_section->page_count] = p_article;
658                    p_section->page_count++;
659                    p_section->last_page_visible_article_count = 0;
660            }
661    
662            if (p_article->visible)
663            {
664                    p_section->last_page_visible_article_count++;
665            }
666    
667          return 0;          return 0;
668  }  }
669    
670  ARTICLE *section_data_find_article_by_aid(SECTION_DATA *p_section, int32_t aid)  int section_list_set_article_visible(SECTION_LIST *p_section, int32_t aid, int8_t visible)
671    {
672            ARTICLE *p_article;
673            ARTICLE *p_reply;
674            int affected_count = 0;
675    
676            if (p_section == NULL)
677            {
678                    log_error("section_list_set_article_visible() NULL pointer error\n");
679                    return -2;
680            }
681    
682            p_article = article_block_find_by_aid(aid);
683            if (p_article == NULL)
684            {
685                    return -1; // Not found
686            }
687    
688            if (p_section->sid != p_article->sid)
689            {
690                    log_error("section_list_set_article_visible() error: section sid %d != article sid %d\n", p_section->sid, p_article->sid);
691                    return -2;
692            }
693    
694            if (p_article->visible == visible)
695            {
696                    return 0; // Already set
697            }
698    
699            if (visible == 0) // 1 -> 0
700            {
701                    p_section->visible_article_count--;
702    
703                    if (p_article->tid == 0)
704                    {
705                            p_section->visible_topic_count--;
706    
707                            // Set related visible replies to invisible
708                            for (p_reply = p_article->p_topic_next; p_reply->tid != 0; p_reply = p_reply->p_topic_next)
709                            {
710                                    if (p_reply->tid != aid)
711                                    {
712                                            log_error("Inconsistent tid = %d found in reply %d of topic %d\n", p_reply->tid, p_reply->aid, aid);
713                                            continue;
714                                    }
715    
716                                    if (p_reply->visible == 1)
717                                    {
718                                            p_reply->visible = 0;
719                                            p_section->visible_article_count--;
720                                            affected_count++;
721                                    }
722                            }
723                    }
724            }
725            else // 0 -> 1
726            {
727                    p_section->visible_article_count++;
728    
729                    if (p_article->tid == 0)
730                    {
731                            p_section->visible_topic_count++;
732                    }
733            }
734    
735            p_article->visible = visible;
736            affected_count++;
737    
738            return affected_count;
739    }
740    
741    ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset, ARTICLE **pp_next)
742  {  {
743          ARTICLE *p_article;          ARTICLE *p_article;
         ARTICLE_BLOCK *p_block;  
744          int left;          int left;
745          int right;          int right;
746          int mid;          int mid;
747    
748            *p_page = -1;
749            *p_offset = -1;
750            *pp_next = NULL;
751    
752          if (p_section == NULL)          if (p_section == NULL)
753          {          {
754                  log_error("section_data_find_article_by_aid() NULL pointer error\n");                  log_error("section_list_find_article_with_offset() NULL pointer error\n");
755                  return NULL;                  return NULL;
756          }          }
757    
758          if (p_section->block_count == 0) // empty section          if (p_section->article_count == 0) // empty
759          {          {
760                    *p_page = 0;
761                    *p_offset = 0;
762                  return NULL;                  return NULL;
763          }          }
764    
765          left = 0;          left = 0;
766          right = p_section->block_count;          right = p_section->page_count;
767    
768          // aid in the range [ head aid of blocks[left], tail aid of blocks[right - 1] ]          // aid in the range [ head aid of pages[left], tail aid of pages[right - 1] ]
769          while (left < right - 1)          while (left < right - 1)
770          {          {
771                  // get block offset no less than mid value of left and right block offsets                  // get page id no less than mid value of left page id and right page id
772                  mid = (left + right) / 2 + (right - left) % 2;                  mid = (left + right) / 2 + (right - left) % 2;
773                    
774                  if (mid >= BBS_article_block_limit_per_section)                  if (mid >= p_section->page_count)
775                  {                  {
776                          log_error("block_m(%d) is out of boundary\n", mid);                          log_error("page id (mid = %d) is out of boundary\n", mid);
777                          return NULL;                          return NULL;
778                  }                  }
779    
780                  if (aid < p_section->block_head_aid[mid])                  if (aid < p_section->p_page_first_article[mid]->aid)
781                  {                  {
782                          right = mid;                          right = mid;
783                  }                  }
# Line 461  ARTICLE *section_data_find_article_by_ai Line 787  ARTICLE *section_data_find_article_by_ai
787                  }                  }
788          }          }
789    
790          p_block = p_section->p_block[left];          *p_page = left;
791    
792            p_article = p_section->p_page_first_article[*p_page];
793    
794            // p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid
795            right = (*p_page == MAX(0, p_section->page_count - 1) ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid);
796    
797            // left will be the offset of article found or offset to insert
798          left = 0;          left = 0;
         right = p_block->article_count - 1;  
799    
800          // aid in the range [ aid of articles[left], aid of articles[right] ]          while (aid > p_article->aid)
         while (left < right)  
801          {          {
802                  mid = (left + right) / 2;                  p_article = p_article->p_next;
803                    left++;
804    
805                  if (aid <= p_block->articles[mid].aid)                  if (aid == p_article->aid)
806                  {                  {
807                          right = mid;                          *pp_next = p_article->p_next;
808                            break;
809                  }                  }
810                  else  
811                    // over last article in the page
812                    if (p_article == p_section->p_article_head || p_article->aid >= right)
813                  {                  {
814                          left = mid + 1;                          *pp_next = (p_article == p_section->p_article_head ? p_section->p_article_head : p_section->p_page_first_article[*p_page + 1]);
815                            *p_offset = left;
816                            return NULL; // not found
817                  }                  }
818          }          }
819    
820          p_article = &(p_block->articles[left]);          if (aid < p_article->aid)
821            {
822                    *pp_next = p_article;
823                    p_article = NULL; // not found
824            }
825            else // aid == p_article->aid
826            {
827                    *pp_next = p_article->p_next;
828            }
829    
830            *p_offset = left;
831    
832          return p_article;          return p_article;
833  }  }
834    
835  ARTICLE *section_data_find_article_by_index(SECTION_DATA *p_section, int index)  int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid)
836  {  {
837          ARTICLE *p_article;          ARTICLE *p_article;
838          ARTICLE_BLOCK *p_block;          ARTICLE *p_next;
839            int32_t page;
840            int32_t offset;
841            int visible_article_count;
842            int page_head_set;
843    
844          if (p_section == NULL)          if (p_section == NULL)
845          {          {
846                  log_error("section_data_find_article_by_index() NULL pointer error\n");                  log_error("section_list_calculate_page() NULL pointer error\n");
847                  return NULL;                  return -1;
848          }          }
849    
850          if (index < 0 || index >= p_section->article_count)          if (p_section->article_count == 0) // empty
851          {          {
852                  log_error("section_data_find_article_by_index(%d) is out of boundary [0, %d)\n", index, p_section->article_count);                  p_section->page_count = 0;
853                  return NULL;                  p_section->last_page_visible_article_count = 0;
854    
855                    return 0;
856          }          }
857    
858          p_block = p_section->p_block[index / BBS_article_limit_per_block];          if (start_aid > 0)
859          p_article = &(p_block->articles[index % BBS_article_limit_per_block]);          {
860                    p_article = article_block_find_by_aid(start_aid);
861                    if (p_article == NULL)
862                    {
863                            return -1; // Not found
864                    }
865    
866          return p_article;                  if (p_section->sid != p_article->sid)
867                    {
868                            log_error("section_list_calculate_page() error: section sid %d != start article sid %d\n", p_section->sid, p_article->sid);
869                            return -2;
870                    }
871    
872                    p_article = section_list_find_article_with_offset(p_section, start_aid, &page, &offset, &p_next);
873                    if (p_article == NULL)
874                    {
875                            if (page < 0)
876                            {
877                                    return -1;
878                            }
879                            log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n",
880                                              start_aid, p_section->sid);
881                            return -2;
882                    }
883    
884                    if (offset > 0)
885                    {
886                            p_article = p_section->p_page_first_article[page];
887                    }
888            }
889            else
890            {
891                    p_article = p_section->p_article_head;
892                    page = 0;
893                    offset = 0;
894            }
895    
896            visible_article_count = 0;
897            page_head_set = 0;
898    
899            do
900            {
901                    if (!page_head_set && visible_article_count == 0)
902                    {
903                            p_section->p_page_first_article[page] = p_article;
904                            page_head_set = 1;
905                    }
906    
907                    if (p_article->visible)
908                    {
909                            visible_article_count++;
910                    }
911    
912                    p_article = p_article->p_next;
913    
914                    // skip remaining invisible articles
915                    while (p_article->visible == 0 && p_article != p_section->p_article_head)
916                    {
917                            p_article = p_article->p_next;
918                    }
919    
920                    if (visible_article_count >= BBS_article_limit_per_page && p_article != p_section->p_article_head)
921                    {
922                            page++;
923                            visible_article_count = 0;
924                            page_head_set = 0;
925    
926                            if (page >= BBS_article_limit_per_section / BBS_article_limit_per_page && p_article != p_section->p_article_head)
927                            {
928                                    log_error("Count of page exceed limit in section %d\n", p_section->sid);
929                                    break;
930                            }
931                    }
932            } while (p_article != p_section->p_article_head);
933    
934            p_section->page_count = page + (visible_article_count > 0 ? 1 : 0);
935            p_section->last_page_visible_article_count = visible_article_count;
936    
937            return 0;
938  }  }
939    
940  int section_data_mark_del_article(SECTION_DATA *p_section, int32_t aid)  int article_count_of_topic(int32_t aid)
941  {  {
942          ARTICLE *p_article;          ARTICLE *p_article;
943            int article_count;
944    
945          if (p_section == NULL)          p_article = article_block_find_by_aid(aid);
946            if (p_article == NULL)
947          {          {
948                  log_error("section_data_mark_del_article() NULL pointer error\n");                  return 0; // Not found
949            }
950    
951            article_count = 0;
952    
953            do
954            {
955                    if (p_article->tid != 0 && p_article->tid != aid)
956                    {
957                            log_error("article_count_of_topic(%d) error: article %d not linked to the topic\n", aid, p_article->aid);
958                            break;
959                    }
960    
961                    article_count++;
962                    p_article = p_article->p_topic_next;
963            } while (p_article->aid != aid);
964    
965            return article_count;
966    }
967    
968    int section_list_move_topic(SECTION_LIST *p_section_src, SECTION_LIST *p_section_dest, int32_t aid)
969    {
970            ARTICLE *p_article;
971            ARTICLE *p_next;
972            int32_t page;
973            int32_t offset;
974            int32_t move_article_count;
975            int32_t dest_article_count_old;
976            int32_t last_unaffected_aid_src;
977            int32_t first_inserted_aid_dest;
978            int move_counter;
979    
980            if (p_section_dest == NULL)
981            {
982                    log_error("section_list_move_topic() NULL pointer error\n");
983                    return -1;
984            }
985    
986            if ((p_article = article_block_find_by_aid(aid)) == NULL)
987            {
988                    log_error("section_list_move_topic() error: article %d not found in block\n", aid);
989                  return -2;                  return -2;
990          }          }
991    
992          p_article = section_data_find_article_by_aid(p_section, aid);          if (p_section_src->sid != p_article->sid)
         if (p_article == NULL)  
993          {          {
994                  return -1; // Not found                  log_error("section_list_move_topic() error: src section sid %d != article %d sid %d\n",
995                                      p_section_src->sid, p_article->aid, p_article->sid);
996                    return -2;
997            }
998    
999            if (p_article->tid != 0)
1000            {
1001                    log_error("section_list_move_topic(aid = %d) error: article is not head of topic, tid = %d\n", aid, p_article->tid);
1002                    return -2;
1003            }
1004    
1005            last_unaffected_aid_src = (p_article == p_section_src->p_article_head ? 0 : p_article->p_prior->aid);
1006    
1007            move_article_count = article_count_of_topic(aid);
1008            if (move_article_count <= 0)
1009            {
1010                    log_error("section_list_count_of_topic_articles(aid = %d) <= 0\n", aid);
1011                    return -2;
1012            }
1013    
1014            if (p_section_dest->article_count + move_article_count > BBS_article_limit_per_section)
1015            {
1016                    log_error("section_list_move_topic() error: article_count %d reach limit in section %d\n",
1017                                      p_section_dest->article_count + move_article_count, p_section_dest->sid);
1018                    return -3;
1019          }          }
1020    
1021          if (p_article->visible == 0)          dest_article_count_old = p_section_dest->article_count;
1022            move_counter = 0;
1023            first_inserted_aid_dest = p_article->aid;
1024    
1025            do
1026          {          {
1027                  return 0; // Already deleted                  if (p_section_src->sid != p_article->sid)
1028                    {
1029                            log_error("section_list_move_topic() error: src section sid %d != article %d sid %d\n",
1030                                              p_section_src->sid, p_article->aid, p_article->sid);
1031                            return -2;
1032                    }
1033    
1034                    // Remove from bi-directional article list of src section
1035                    if (p_section_src->p_article_head == p_article)
1036                    {
1037                            p_section_src->p_article_head = p_article->p_next;
1038                    }
1039                    if (p_section_src->p_article_tail == p_article)
1040                    {
1041                            p_section_src->p_article_tail = p_article->p_prior;
1042                    }
1043                    if (p_section_src->p_article_head == p_article) // || p_section_src->p_article_tail == p_article
1044                    {
1045                            p_section_src->p_article_head = NULL;
1046                            p_section_src->p_article_tail = NULL;
1047                    }
1048    
1049                    p_article->p_prior->p_next = p_article->p_next;
1050                    p_article->p_next->p_prior = p_article->p_prior;
1051    
1052                    // Update sid of article
1053                    p_article->sid = p_section_dest->sid;
1054    
1055                    if (section_list_find_article_with_offset(p_section_dest, p_article->aid, &page, &offset, &p_next) != NULL)
1056                    {
1057                            log_error("section_list_move_topic() error: article %d already in section %d\n", p_article->aid, p_section_dest->sid);
1058                            return -4;
1059                    }
1060    
1061                    // Insert into bi-directional article list of dest section
1062                    if (p_next == NULL) // empty section
1063                    {
1064                            p_section_dest->p_article_head = p_article;
1065                            p_section_dest->p_article_tail = p_article;
1066                            p_article->p_prior = p_article;
1067                            p_article->p_next = p_article;
1068                    }
1069                    else
1070                    {
1071                            if (p_section_dest->p_article_head == p_next)
1072                            {
1073                                    if (p_article->aid < p_next->aid)
1074                                    {
1075                                            p_section_dest->p_article_head = p_article;
1076                                    }
1077                                    else // p_article->aid > p_next->aid
1078                                    {
1079                                            p_section_dest->p_article_tail = p_article;
1080                                    }
1081                            }
1082    
1083                            p_article->p_prior = p_next->p_prior;
1084                            p_article->p_next = p_next;
1085                            p_next->p_prior->p_next = p_article;
1086                            p_next->p_prior = p_article;
1087                    }
1088    
1089                    // Update article / topic counter of src / desc section
1090                    p_section_src->article_count--;
1091                    p_section_dest->article_count++;
1092                    if (p_article->tid == 0)
1093                    {
1094                            p_section_src->topic_count--;
1095                            p_section_dest->topic_count++;
1096                    }
1097    
1098                    // Update visible article / topic counter of src / desc section
1099                    if (p_article->visible)
1100                    {
1101                            p_section_src->visible_article_count--;
1102                            p_section_dest->visible_article_count++;
1103                            if (p_article->tid == 0)
1104                            {
1105                                    p_section_src->visible_topic_count--;
1106                                    p_section_dest->visible_topic_count++;
1107                            }
1108                    }
1109    
1110                    // Update page for empty dest section
1111                    if (p_section_dest->article_count == 1)
1112                    {
1113                            p_section_dest->p_page_first_article[0] = p_article;
1114                            p_section_dest->page_count = 1;
1115                            p_section_dest->last_page_visible_article_count = (p_article->visible ? 1 : 0);
1116                    }
1117    
1118                    p_article = p_article->p_topic_next;
1119    
1120                    move_counter++;
1121                    if (move_counter % CALCULATE_PAGE_THRESHOLD == 0)
1122                    {
1123                            // Re-calculate pages of desc section
1124                            if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
1125                            {
1126                                    log_error("section_list_calculate_page(dest section = %d, aid = %d) error\n",
1127                                                      p_section_dest->sid, first_inserted_aid_dest);
1128                            }
1129    
1130                            first_inserted_aid_dest = p_article->aid;
1131                    }
1132            } while (p_article->aid != aid);
1133    
1134            if (p_section_dest->article_count - dest_article_count_old != move_article_count)
1135            {
1136                    log_error("section_list_move_topic() error: count of moved articles %d != %d\n",
1137                                      p_section_dest->article_count - dest_article_count_old, move_article_count);
1138          }          }
1139    
1140          p_article->visible = 0;          // Re-calculate pages of src section
1141          p_section->delete_count++;          if (section_list_calculate_page(p_section_src, last_unaffected_aid_src) < 0)
1142            {
1143                    log_error("section_list_calculate_page(src section = %d, aid = %d) error at aid = %d\n",
1144                                      p_section_src->sid, last_unaffected_aid_src, aid);
1145            }
1146    
1147            if (move_counter % CALCULATE_PAGE_THRESHOLD != 0)
1148            {
1149                    // Re-calculate pages of desc section
1150                    if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
1151                    {
1152                            log_error("section_list_calculate_page(dest section = %d, aid = %d) error\n",
1153                                              p_section_dest->sid, first_inserted_aid_dest);
1154                    }
1155            }
1156    
1157          return 1;          return move_article_count;
1158  }  }


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

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