/[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.63 by sysadm, Thu Nov 20 10:20:51 2025 UTC Revision 1.67 by sysadm, Sat Jan 3 10:27:14 2026 UTC
# Line 3  Line 3 
3   * section_list   * section_list
4   *   - data models and basic operations of section and article   *   - data models and basic operations of section and article
5   *   *
6   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>   * Copyright (C) 2004-2026  Leaflet <leaflet@leafok.com>
7   */   */
8    
9  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
# Line 41  enum _section_list_constant_t Line 41  enum _section_list_constant_t
41  {  {
42          SECTION_TRY_LOCK_WAIT_TIME = 1, // second          SECTION_TRY_LOCK_WAIT_TIME = 1, // second
43          SECTION_TRY_LOCK_TIMES = 10,          SECTION_TRY_LOCK_TIMES = 10,
44            SECTION_DEAD_LOCK_TIMEOUT = 15, // second
45    
46          ARTICLE_BLOCK_PER_SHM = 1000,           // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate          ARTICLE_BLOCK_PER_SHM = 1000,           // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate
47          ARTICLE_BLOCK_SHM_COUNT_LIMIT = 80, // limited by length (8-bit) of proj_id in ftok(path, proj_id)          ARTICLE_BLOCK_SHM_COUNT_LIMIT = 80, // limited by length (8-bit) of proj_id in ftok(path, proj_id)
# Line 80  static ARTICLE_BLOCK_POOL *p_article_blo Line 81  static ARTICLE_BLOCK_POOL *p_article_blo
81  static char section_list_shm_name[FILE_NAME_LEN];  static char section_list_shm_name[FILE_NAME_LEN];
82  SECTION_LIST_POOL *p_section_list_pool = NULL;  SECTION_LIST_POOL *p_section_list_pool = NULL;
83    
84    #ifndef HAVE_SYSTEM_V
85    static int section_list_reset_lock(SECTION_LIST *p_section);
86    #endif
87    
88  int article_block_init(const char *filename, int block_count)  int article_block_init(const char *filename, int block_count)
89  {  {
90          char filepath[FILE_PATH_LEN];          char filepath[FILE_PATH_LEN];
# Line 93  int article_block_init(const char *filen Line 98  int article_block_init(const char *filen
98    
99          if (p_article_block_pool != NULL)          if (p_article_block_pool != NULL)
100          {          {
101                  log_error("article_block_pool already initialized\n");                  log_error("article_block_pool already initialized");
102                  return -1;                  return -1;
103          }          }
104    
105          if (block_count <= 0 || block_count > ARTICLE_BLOCK_PER_POOL)          if (block_count <= 0 || block_count > ARTICLE_BLOCK_PER_POOL)
106          {          {
107                  log_error("article_block_count exceed limit %d\n", ARTICLE_BLOCK_PER_POOL);                  log_error("article_block_count exceed limit %d", ARTICLE_BLOCK_PER_POOL);
108                  return -2;                  return -2;
109          }          }
110    
# Line 113  int article_block_init(const char *filen Line 118  int article_block_init(const char *filen
118    
119          if (shm_unlink(filepath) == -1 && errno != ENOENT)          if (shm_unlink(filepath) == -1 && errno != ENOENT)
120          {          {
121                  log_error("shm_unlink(%s) error (%d)\n", filepath, errno);                  log_error("shm_unlink(%s) error (%d)", filepath, errno);
122                  return -2;                  return -2;
123          }          }
124    
125          if ((fd = shm_open(filepath, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)          if ((fd = shm_open(filepath, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
126          {          {
127                  log_error("shm_open(%s) error (%d)\n", filepath, errno);                  log_error("shm_open(%s) error (%d)", filepath, errno);
128                  return -2;                  return -2;
129          }          }
130          if (ftruncate(fd, (off_t)size) == -1)          if (ftruncate(fd, (off_t)size) == -1)
131          {          {
132                  log_error("ftruncate(size=%d) error (%d)\n", size, errno);                  log_error("ftruncate(size=%d) error (%d)", size, errno);
133                  close(fd);                  close(fd);
134                  return -2;                  return -2;
135          }          }
# Line 132  int article_block_init(const char *filen Line 137  int article_block_init(const char *filen
137          p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);          p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
138          if (p_shm == MAP_FAILED)          if (p_shm == MAP_FAILED)
139          {          {
140                  log_error("mmap() error (%d)\n", errno);                  log_error("mmap() error (%d)", errno);
141                  close(fd);                  close(fd);
142                  return -2;                  return -2;
143          }          }
144    
145          if (close(fd) < 0)          if (close(fd) < 0)
146          {          {
147                  log_error("close(fd) error (%d)\n", errno);                  log_error("close(fd) error (%d)", errno);
148                  return -1;                  return -1;
149          }          }
150    
# Line 159  int article_block_init(const char *filen Line 164  int article_block_init(const char *filen
164    
165                  if (shm_unlink(filepath) == -1 && errno != ENOENT)                  if (shm_unlink(filepath) == -1 && errno != ENOENT)
166                  {                  {
167                          log_error("shm_unlink(%s) error (%d)\n", filepath, errno);                          log_error("shm_unlink(%s) error (%d)", filepath, errno);
168                          return -2;                          return -2;
169                  }                  }
170    
171                  if ((fd = shm_open(filepath, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)                  if ((fd = shm_open(filepath, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
172                  {                  {
173                          log_error("shm_open(%s) error (%d)\n", filepath, errno);                          log_error("shm_open(%s) error (%d)", filepath, errno);
174                          return -2;                          return -2;
175                  }                  }
176                  if (ftruncate(fd, (off_t)size) == -1)                  if (ftruncate(fd, (off_t)size) == -1)
177                  {                  {
178                          log_error("ftruncate(size=%d) error (%d)\n", size, errno);                          log_error("ftruncate(size=%d) error (%d)", size, errno);
179                          close(fd);                          close(fd);
180                          return -2;                          return -2;
181                  }                  }
# Line 178  int article_block_init(const char *filen Line 183  int article_block_init(const char *filen
183                  p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);                  p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
184                  if (p_shm == MAP_FAILED)                  if (p_shm == MAP_FAILED)
185                  {                  {
186                          log_error("mmap() error (%d)\n", errno);                          log_error("mmap() error (%d)", errno);
187                          close(fd);                          close(fd);
188                          return -2;                          return -2;
189                  }                  }
190    
191                  if (close(fd) < 0)                  if (close(fd) < 0)
192                  {                  {
193                          log_error("close(fd) error (%d)\n", errno);                          log_error("close(fd) error (%d)", errno);
194                          return -1;                          return -1;
195                  }                  }
196    
# Line 230  void article_block_cleanup(void) Line 235  void article_block_cleanup(void)
235    
236                  if (shm_unlink(filepath) == -1 && errno != ENOENT)                  if (shm_unlink(filepath) == -1 && errno != ENOENT)
237                  {                  {
238                          log_error("shm_unlink(%s) error (%d)\n", filepath, errno);                          log_error("shm_unlink(%s) error (%d)", filepath, errno);
239                  }                  }
240          }          }
241    
# Line 238  void article_block_cleanup(void) Line 243  void article_block_cleanup(void)
243    
244          if (shm_unlink(filepath) == -1 && errno != ENOENT)          if (shm_unlink(filepath) == -1 && errno != ENOENT)
245          {          {
246                  log_error("shm_unlink(%s) error (%d)\n", filepath, errno);                  log_error("shm_unlink(%s) error (%d)", filepath, errno);
247          }          }
248    
249          detach_article_block_shm();          detach_article_block_shm();
# Line 246  void article_block_cleanup(void) Line 251  void article_block_cleanup(void)
251    
252  int set_article_block_shm_readonly(void)  int set_article_block_shm_readonly(void)
253  {  {
254          int i;          // int i;
255    
256          if (p_article_block_pool == NULL)          if (p_article_block_pool == NULL)
257          {          {
258                  log_error("article_block_pool not initialized\n");                  log_error("article_block_pool not initialized");
259                  return -1;                  return -1;
260          }          }
261    
262          for (i = 0; i < p_article_block_pool->shm_count; i++)          // for (i = 0; i < p_article_block_pool->shm_count; i++)
263          {          // {
264                  if ((p_article_block_pool->shm_pool + i)->p_shm != NULL &&          //      if ((p_article_block_pool->shm_pool + i)->p_shm != NULL &&
265                          mprotect((p_article_block_pool->shm_pool + i)->p_shm, (p_article_block_pool->shm_pool + i)->shm_size, PROT_READ) < 0)          //              mprotect((p_article_block_pool->shm_pool + i)->p_shm, (p_article_block_pool->shm_pool + i)->shm_size, PROT_READ) < 0)
266                  {          //      {
267                          log_error("mprotect() error (%d)\n", errno);          //              log_error("mprotect() error (%d)", errno);
268                          return -2;          //              return -2;
269                  }          //      }
270          }          // }
271    
272          if (p_article_block_pool != NULL &&          if (p_article_block_pool != NULL &&
273                  mprotect(p_article_block_pool, p_article_block_pool->shm_size, PROT_READ) < 0)                  mprotect(p_article_block_pool, p_article_block_pool->shm_size, PROT_READ) < 0)
274          {          {
275                  log_error("mprotect() error (%d)\n", errno);                  log_error("mprotect() error (%d)", errno);
276                  return -3;                  return -3;
277          }          }
278    
# Line 286  int detach_article_block_shm(void) Line 291  int detach_article_block_shm(void)
291                  if ((p_article_block_pool->shm_pool + i)->p_shm != NULL &&                  if ((p_article_block_pool->shm_pool + i)->p_shm != NULL &&
292                          munmap((p_article_block_pool->shm_pool + i)->p_shm, (p_article_block_pool->shm_pool + i)->shm_size) < 0)                          munmap((p_article_block_pool->shm_pool + i)->p_shm, (p_article_block_pool->shm_pool + i)->shm_size) < 0)
293                  {                  {
294                          log_error("munmap() error (%d)\n", errno);                          log_error("munmap() error (%d)", errno);
295                          return -2;                          return -2;
296                  }                  }
297          }          }
298    
299          if (p_article_block_pool != NULL && munmap(p_article_block_pool, p_article_block_pool->shm_size) < 0)          if (p_article_block_pool != NULL && munmap(p_article_block_pool, p_article_block_pool->shm_size) < 0)
300          {          {
301                  log_error("munmap() error (%d)\n", errno);                  log_error("munmap() error (%d)", errno);
302                  return -3;                  return -3;
303          }          }
304    
# Line 329  int article_block_reset(void) Line 334  int article_block_reset(void)
334    
335          if (p_article_block_pool == NULL)          if (p_article_block_pool == NULL)
336          {          {
337                  log_error("article_block_pool not initialized\n");                  log_error("article_block_pool not initialized");
338                  return -1;                  return -1;
339          }          }
340    
# Line 352  ARTICLE *article_block_find_by_aid(int32 Line 357  ARTICLE *article_block_find_by_aid(int32
357    
358          if (p_article_block_pool == NULL)          if (p_article_block_pool == NULL)
359          {          {
360                  log_error("article_block_pool not initialized\n");                  log_error("article_block_pool not initialized");
361                  return NULL;                  return NULL;
362          }          }
363    
# Line 414  ARTICLE *article_block_find_by_index(int Line 419  ARTICLE *article_block_find_by_index(int
419    
420          if (p_article_block_pool == NULL)          if (p_article_block_pool == NULL)
421          {          {
422                  log_error("article_block_pool not initialized\n");                  log_error("article_block_pool not initialized");
423                  return NULL;                  return NULL;
424          }          }
425    
426          if (index < 0 || index / BBS_article_count_per_block >= p_article_block_pool->block_count)          if (index < 0 || index / BBS_article_count_per_block >= p_article_block_pool->block_count)
427          {          {
428                  log_error("article_block_find_by_index(%d) is out of boundary of block [0, %d)\n", index, p_article_block_pool->block_count);                  log_error("article_block_find_by_index(%d) is out of boundary of block [0, %d)", index, p_article_block_pool->block_count);
429                  return NULL;                  return NULL;
430          }          }
431    
# Line 428  ARTICLE *article_block_find_by_index(int Line 433  ARTICLE *article_block_find_by_index(int
433    
434          if (index % BBS_article_count_per_block >= p_block->article_count)          if (index % BBS_article_count_per_block >= p_block->article_count)
435          {          {
436                  log_error("article_block_find_by_index(%d) is out of boundary of article [0, %d)\n", index, p_block->article_count);                  log_error("article_block_find_by_index(%d) is out of boundary of article [0, %d)", index, p_block->article_count);
437                  return NULL;                  return NULL;
438          }          }
439    
# Line 463  extern int section_list_init(const char Line 468  extern int section_list_init(const char
468    
469          if (shm_unlink(section_list_shm_name) == -1 && errno != ENOENT)          if (shm_unlink(section_list_shm_name) == -1 && errno != ENOENT)
470          {          {
471                  log_error("shm_unlink(%s) error (%d)\n", section_list_shm_name, errno);                  log_error("shm_unlink(%s) error (%d)", section_list_shm_name, errno);
472                  return -2;                  return -2;
473          }          }
474    
475          if ((fd = shm_open(section_list_shm_name, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)          if ((fd = shm_open(section_list_shm_name, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
476          {          {
477                  log_error("shm_open(%s) error (%d)\n", section_list_shm_name, errno);                  log_error("shm_open(%s) error (%d)", section_list_shm_name, errno);
478                  return -2;                  return -2;
479          }          }
480          if (ftruncate(fd, (off_t)size) == -1)          if (ftruncate(fd, (off_t)size) == -1)
481          {          {
482                  log_error("ftruncate(size=%d) error (%d)\n", size, errno);                  log_error("ftruncate(size=%d) error (%d)", size, errno);
483                  close(fd);                  close(fd);
484                  return -2;                  return -2;
485          }          }
# Line 482  extern int section_list_init(const char Line 487  extern int section_list_init(const char
487          p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);          p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
488          if (p_shm == MAP_FAILED)          if (p_shm == MAP_FAILED)
489          {          {
490                  log_error("mmap() error (%d)\n", errno);                  log_error("mmap() error (%d)", errno);
491                  close(fd);                  close(fd);
492                  return -2;                  return -2;
493          }          }
494    
495          if (close(fd) < 0)          if (close(fd) < 0)
496          {          {
497                  log_error("close(fd) error (%d)\n", errno);                  log_error("close(fd) error (%d)", errno);
498                  return -1;                  return -1;
499          }          }
500    
# Line 503  extern int section_list_init(const char Line 508  extern int section_list_init(const char
508          {          {
509                  if (sem_init(&(p_section_list_pool->sem[i]), 1, 1) == -1)                  if (sem_init(&(p_section_list_pool->sem[i]), 1, 1) == -1)
510                  {                  {
511                          log_error("sem_init(sem[%d]) error (%d)\n", i, errno);                          log_error("sem_init(sem[%d]) error (%d)", i, errno);
512                          return -3;                          return -3;
513                  }                  }
514    
# Line 515  extern int section_list_init(const char Line 520  extern int section_list_init(const char
520          key = ftok(filename, proj_id);          key = ftok(filename, proj_id);
521          if (key == -1)          if (key == -1)
522          {          {
523                  log_error("ftok(%s, %d) error (%d)\n", filename, proj_id, errno);                  log_error("ftok(%s, %d) error (%d)", filename, proj_id, errno);
524                  return -3;                  return -3;
525          }          }
526    
# Line 523  extern int section_list_init(const char Line 528  extern int section_list_init(const char
528          semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600);          semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600);
529          if (semid == -1)          if (semid == -1)
530          {          {
531                  log_error("semget(section_list_pool_sem, size = %d) error (%d)\n", size, errno);                  log_error("semget(section_list_pool_sem, size = %d) error (%d)", size, errno);
532                  return -3;                  return -3;
533          }          }
534    
# Line 533  extern int section_list_init(const char Line 538  extern int section_list_init(const char
538          {          {
539                  if (semctl(semid, i, SETVAL, arg) == -1)                  if (semctl(semid, i, SETVAL, arg) == -1)
540                  {                  {
541                          log_error("semctl(section_list_pool_sem, SETVAL) error (%d)\n", errno);                          log_error("semctl(section_list_pool_sem, SETVAL) error (%d)", errno);
542                          return -3;                          return -3;
543                  }                  }
544          }          }
# Line 544  extern int section_list_init(const char Line 549  extern int section_list_init(const char
549          p_section_list_pool->p_trie_dict_section_by_name = trie_dict_create();          p_section_list_pool->p_trie_dict_section_by_name = trie_dict_create();
550          if (p_section_list_pool->p_trie_dict_section_by_name == NULL)          if (p_section_list_pool->p_trie_dict_section_by_name == NULL)
551          {          {
552                  log_error("trie_dict_create() OOM\n", BBS_max_section);                  log_error("trie_dict_create() OOM", BBS_max_section);
553                  return -2;                  return -2;
554          }          }
555    
556          p_section_list_pool->p_trie_dict_section_by_sid = trie_dict_create();          p_section_list_pool->p_trie_dict_section_by_sid = trie_dict_create();
557          if (p_section_list_pool->p_trie_dict_section_by_sid == NULL)          if (p_section_list_pool->p_trie_dict_section_by_sid == NULL)
558          {          {
559                  log_error("trie_dict_create() OOM\n", BBS_max_section);                  log_error("trie_dict_create() OOM", BBS_max_section);
560                  return -2;                  return -2;
561          }          }
562    
# Line 580  void section_list_cleanup(void) Line 585  void section_list_cleanup(void)
585  #ifdef HAVE_SYSTEM_V  #ifdef HAVE_SYSTEM_V
586          if (semctl(p_section_list_pool->semid, 0, IPC_RMID) == -1)          if (semctl(p_section_list_pool->semid, 0, IPC_RMID) == -1)
587          {          {
588                  log_error("semctl(semid = %d, IPC_RMID) error (%d)\n", p_section_list_pool->semid, errno);                  log_error("semctl(semid = %d, IPC_RMID) error (%d)", p_section_list_pool->semid, errno);
589          }          }
590  #else  #else
591          for (int i = 0; i <= BBS_max_section; i++)          for (int i = 0; i <= BBS_max_section; i++)
592          {          {
593                  if (sem_destroy(&(p_section_list_pool->sem[i])) == -1)                  if (sem_destroy(&(p_section_list_pool->sem[i])) == -1)
594                  {                  {
595                          log_error("sem_destroy(sem[%d]) error (%d)\n", i, errno);                          log_error("sem_destroy(sem[%d]) error (%d)", i, errno);
596                  }                  }
597          }          }
598  #endif  #endif
# Line 596  void section_list_cleanup(void) Line 601  void section_list_cleanup(void)
601    
602          if (shm_unlink(section_list_shm_name) == -1 && errno != ENOENT)          if (shm_unlink(section_list_shm_name) == -1 && errno != ENOENT)
603          {          {
604                  log_error("shm_unlink(%s) error (%d)\n", section_list_shm_name, errno);                  log_error("shm_unlink(%s) error (%d)", section_list_shm_name, errno);
605          }          }
606  }  }
607    
# Line 604  int set_section_list_shm_readonly(void) Line 609  int set_section_list_shm_readonly(void)
609  {  {
610          if (p_section_list_pool == NULL)          if (p_section_list_pool == NULL)
611          {          {
612                  log_error("p_section_list_pool not initialized\n");                  log_error("p_section_list_pool not initialized");
613                  return -1;                  return -1;
614          }          }
615    
616          if (p_section_list_pool != NULL &&          if (p_section_list_pool != NULL &&
617                  mprotect(p_section_list_pool, p_section_list_pool->shm_size, PROT_READ) < 0)                  mprotect(p_section_list_pool, p_section_list_pool->shm_size, PROT_READ) < 0)
618          {          {
619                  log_error("mprotect() error (%d)\n", errno);                  log_error("mprotect() error (%d)", errno);
620                  return -2;                  return -2;
621          }          }
622    
# Line 622  int detach_section_list_shm(void) Line 627  int detach_section_list_shm(void)
627  {  {
628          if (p_section_list_pool != NULL && munmap(p_section_list_pool, p_section_list_pool->shm_size) < 0)          if (p_section_list_pool != NULL && munmap(p_section_list_pool, p_section_list_pool->shm_size) < 0)
629          {          {
630                  log_error("munmap() error (%d)\n", errno);                  log_error("munmap() error (%d)", errno);
631                  return -1;                  return -1;
632          }          }
633    
# Line 652  SECTION_LIST *section_list_create(int32_ Line 657  SECTION_LIST *section_list_create(int32_
657    
658          if (p_section_list_pool == NULL)          if (p_section_list_pool == NULL)
659          {          {
660                  log_error("session_list_pool not initialized\n");                  log_error("session_list_pool not initialized");
661                  return NULL;                  return NULL;
662          }          }
663    
664          if (p_section_list_pool->section_count >= BBS_max_section)          if (p_section_list_pool->section_count >= BBS_max_section)
665          {          {
666                  log_error("section_count reach limit %d >= %d\n", p_section_list_pool->section_count, BBS_max_section);                  log_error("section_count reach limit %d >= %d", p_section_list_pool->section_count, BBS_max_section);
667                  return NULL;                  return NULL;
668          }          }
669    
# Line 680  SECTION_LIST *section_list_create(int32_ Line 685  SECTION_LIST *section_list_create(int32_
685    
686          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_name, sname, p_section_list_pool->section_count) != 1)          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_name, sname, p_section_list_pool->section_count) != 1)
687          {          {
688                  log_error("trie_dict_set(section, %s, %d) error\n", sname, p_section_list_pool->section_count);                  log_error("trie_dict_set(section, %s, %d) error", sname, p_section_list_pool->section_count);
689                  return NULL;                  return NULL;
690          }          }
691    
692          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_sid, sid_str, p_section_list_pool->section_count) != 1)          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_sid, sid_str, p_section_list_pool->section_count) != 1)
693          {          {
694                  log_error("trie_dict_set(section, %d, %d) error\n", sid, p_section_list_pool->section_count);                  log_error("trie_dict_set(section, %d, %d) error", sid, p_section_list_pool->section_count);
695                  return NULL;                  return NULL;
696          }          }
697    
# Line 703  int section_list_update(SECTION_LIST *p_ Line 708  int section_list_update(SECTION_LIST *p_
708    
709          if (p_section == NULL || sname == NULL || stitle == NULL || master_list == NULL)          if (p_section == NULL || sname == NULL || stitle == NULL || master_list == NULL)
710          {          {
711                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
712                  return -1;                  return -1;
713          }          }
714    
# Line 720  int section_list_update(SECTION_LIST *p_ Line 725  int section_list_update(SECTION_LIST *p_
725    
726          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_name, sname, index) < 0)          if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_name, sname, index) < 0)
727          {          {
728                  log_error("trie_dict_set(section, %s, %d) error\n", sname, index);                  log_error("trie_dict_set(section, %s, %d) error", sname, index);
729                  return -2;                  return -2;
730          }          }
731    
# Line 749  SECTION_LIST *section_list_find_by_name( Line 754  SECTION_LIST *section_list_find_by_name(
754    
755          if (p_section_list_pool == NULL)          if (p_section_list_pool == NULL)
756          {          {
757                  log_error("section_list not initialized\n");                  log_error("section_list not initialized");
758                  return NULL;                  return NULL;
759          }          }
760    
761          ret = trie_dict_get(p_section_list_pool->p_trie_dict_section_by_name, sname, &index);          ret = trie_dict_get(p_section_list_pool->p_trie_dict_section_by_name, sname, &index);
762          if (ret < 0)          if (ret < 0)
763          {          {
764                  log_error("trie_dict_get(section, %s) error\n", sname);                  log_error("trie_dict_get(section, %s) error", sname);
765                  return NULL;                  return NULL;
766          }          }
767          else if (ret == 0)          else if (ret == 0)
# Line 775  SECTION_LIST *section_list_find_by_sid(i Line 780  SECTION_LIST *section_list_find_by_sid(i
780    
781          if (p_section_list_pool == NULL)          if (p_section_list_pool == NULL)
782          {          {
783                  log_error("section_list not initialized\n");                  log_error("section_list not initialized");
784                  return NULL;                  return NULL;
785          }          }
786    
# Line 784  SECTION_LIST *section_list_find_by_sid(i Line 789  SECTION_LIST *section_list_find_by_sid(i
789          ret = trie_dict_get(p_section_list_pool->p_trie_dict_section_by_sid, sid_str, &index);          ret = trie_dict_get(p_section_list_pool->p_trie_dict_section_by_sid, sid_str, &index);
790          if (ret < 0)          if (ret < 0)
791          {          {
792                  log_error("trie_dict_get(section, %d) error\n", sid);                  log_error("trie_dict_get(section, %d) error", sid);
793                  return NULL;                  return NULL;
794          }          }
795          else if (ret == 0)          else if (ret == 0)
# Line 805  int section_list_append_article(SECTION_ Line 810  int section_list_append_article(SECTION_
810    
811          if (p_section == NULL || p_article_src == NULL)          if (p_section == NULL || p_article_src == NULL)
812          {          {
813                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
814                  return -1;                  return -1;
815          }          }
816    
817          if (p_article_block_pool == NULL)          if (p_article_block_pool == NULL)
818          {          {
819                  log_error("article_block_pool not initialized\n");                  log_error("article_block_pool not initialized");
820                  return -1;                  return -1;
821          }          }
822    
823          if (p_section->sid != p_article_src->sid)          if (p_section->sid != p_article_src->sid)
824          {          {
825                  log_error("section_list_append_article() error: section sid %d != article sid %d\n", p_section->sid, p_article_src->sid);                  log_error("section_list_append_article() error: section sid %d != article sid %d", p_section->sid, p_article_src->sid);
826                  return -2;                  return -2;
827          }          }
828    
829          if (p_section->article_count >= BBS_article_limit_per_section)          if (p_section->article_count >= BBS_article_limit_per_section)
830          {          {
831                  log_error("section_list_append_article() error: article_count reach limit in section %d\n", p_section->sid);                  log_error("section_list_append_article() error: article_count reach limit in section %d", p_section->sid);
832                  return -2;                  return -2;
833          }          }
834    
# Line 832  int section_list_append_article(SECTION_ Line 837  int section_list_append_article(SECTION_
837          {          {
838                  if ((p_block = pop_free_article_block()) == NULL)                  if ((p_block = pop_free_article_block()) == NULL)
839                  {                  {
840                          log_error("pop_free_article_block() error\n");                          log_error("pop_free_article_block() error");
841                          return -2;                          return -2;
842                  }                  }
843    
# Line 853  int section_list_append_article(SECTION_ Line 858  int section_list_append_article(SECTION_
858          // AID of articles should be strictly ascending          // AID of articles should be strictly ascending
859          if (p_article_src->aid <= last_aid)          if (p_article_src->aid <= last_aid)
860          {          {
861                  log_error("section_list_append_article(aid=%d) error: last_aid=%d\n", p_article_src->aid, last_aid);                  log_error("section_list_append_article(aid=%d) error: last_aid=%d", p_article_src->aid, last_aid);
862                  return -3;                  return -3;
863          }          }
864    
# Line 875  int section_list_append_article(SECTION_ Line 880  int section_list_append_article(SECTION_
880                  p_topic_head = article_block_find_by_aid(p_article->tid);                  p_topic_head = article_block_find_by_aid(p_article->tid);
881                  if (p_topic_head == NULL)                  if (p_topic_head == NULL)
882                  {                  {
883                          log_error("search head of topic (aid=%d) error\n", p_article->tid);                          log_error("search head of topic (aid=%d) error", p_article->tid);
884                          return -4;                          return -4;
885                  }                  }
886    
887                  p_topic_tail = p_topic_head->p_topic_prior;                  p_topic_tail = p_topic_head->p_topic_prior;
888                  if (p_topic_tail == NULL)                  if (p_topic_tail == NULL)
889                  {                  {
890                          log_error("tail of topic (aid=%d) is NULL\n", p_article->tid);                          log_error("tail of topic (aid=%d) is NULL", p_article->tid);
891                          return -4;                          return -4;
892                  }                  }
893          }          }
# Line 932  int section_list_append_article(SECTION_ Line 937  int section_list_append_article(SECTION_
937    
938          if (p_article->ontop && section_list_update_article_ontop(p_section, p_article) < 0)          if (p_article->ontop && section_list_update_article_ontop(p_section, p_article) < 0)
939          {          {
940                  log_error("section_list_update_article_ontop(sid=%d, aid=%d) error\n",                  log_error("section_list_update_article_ontop(sid=%d, aid=%d) error",
941                                    p_section->sid, p_article->aid);                                    p_section->sid, p_article->aid);
942                  return -5;                  return -5;
943          }          }
# Line 948  int section_list_set_article_visible(SEC Line 953  int section_list_set_article_visible(SEC
953    
954          if (p_section == NULL)          if (p_section == NULL)
955          {          {
956                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
957                  return -1;                  return -1;
958          }          }
959    
# Line 960  int section_list_set_article_visible(SEC Line 965  int section_list_set_article_visible(SEC
965    
966          if (p_section->sid != p_article->sid)          if (p_section->sid != p_article->sid)
967          {          {
968                  log_error("Inconsistent section sid %d != article sid %d\n", p_section->sid, p_article->sid);                  log_error("Inconsistent section sid %d != article sid %d", p_section->sid, p_article->sid);
969                  return -2;                  return -2;
970          }          }
971    
# Line 975  int section_list_set_article_visible(SEC Line 980  int section_list_set_article_visible(SEC
980    
981                  if (user_article_cnt_inc(p_article->uid, -1) < 0)                  if (user_article_cnt_inc(p_article->uid, -1) < 0)
982                  {                  {
983                          log_error("user_article_cnt_inc(uid=%d, -1) error\n", p_article->uid);                          log_error("user_article_cnt_inc(uid=%d, -1) error", p_article->uid);
984                  }                  }
985    
986                  if (p_article->tid == 0)                  if (p_article->tid == 0)
# Line 987  int section_list_set_article_visible(SEC Line 992  int section_list_set_article_visible(SEC
992                          {                          {
993                                  if (p_reply->tid != aid)                                  if (p_reply->tid != aid)
994                                  {                                  {
995                                          log_error("Inconsistent tid = %d found in reply %d of topic %d\n", p_reply->tid, p_reply->aid, aid);                                          log_error("Inconsistent tid = %d found in reply %d of topic %d", p_reply->tid, p_reply->aid, aid);
996                                          continue;                                          continue;
997                                  }                                  }
998    
# Line 999  int section_list_set_article_visible(SEC Line 1004  int section_list_set_article_visible(SEC
1004    
1005                                          if (user_article_cnt_inc(p_reply->uid, -1) < 0)                                          if (user_article_cnt_inc(p_reply->uid, -1) < 0)
1006                                          {                                          {
1007                                                  log_error("user_article_cnt_inc(uid=%d, -1) error\n", p_reply->uid);                                                  log_error("user_article_cnt_inc(uid=%d, -1) error", p_reply->uid);
1008                                          }                                          }
1009                                  }                                  }
1010                          }                          }
# Line 1016  int section_list_set_article_visible(SEC Line 1021  int section_list_set_article_visible(SEC
1021    
1022                  if (user_article_cnt_inc(p_article->uid, 1) < 0)                  if (user_article_cnt_inc(p_article->uid, 1) < 0)
1023                  {                  {
1024                          log_error("user_article_cnt_inc(uid=%d, 1) error\n", p_article->uid);                          log_error("user_article_cnt_inc(uid=%d, 1) error", p_article->uid);
1025                  }                  }
1026          }          }
1027    
# Line 1026  int section_list_set_article_visible(SEC Line 1031  int section_list_set_article_visible(SEC
1031          return affected_count;          return affected_count;
1032  }  }
1033    
1034    int section_list_set_article_excerption(SECTION_LIST *p_section, int32_t aid, int8_t excerption)
1035    {
1036            ARTICLE *p_article;
1037    
1038            if (p_section == NULL)
1039            {
1040                    log_error("NULL pointer error");
1041                    return -1;
1042            }
1043    
1044            p_article = article_block_find_by_aid(aid);
1045            if (p_article == NULL)
1046            {
1047                    return -1; // Not found
1048            }
1049    
1050            if (p_section->sid != p_article->sid)
1051            {
1052                    log_error("Inconsistent section sid %d != article sid %d", p_section->sid, p_article->sid);
1053                    return -2;
1054            }
1055    
1056            if (p_article->excerption == excerption)
1057            {
1058                    return 0; // Already set
1059            }
1060    
1061            p_article->excerption = excerption;
1062    
1063            return 1;
1064    }
1065    
1066  int section_list_update_article_ontop(SECTION_LIST *p_section, ARTICLE *p_article)  int section_list_update_article_ontop(SECTION_LIST *p_section, ARTICLE *p_article)
1067  {  {
1068          int i;          int i;
1069    
1070          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
1071          {          {
1072                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1073                  return -1;                  return -1;
1074          }          }
1075    
1076          if (p_section->sid != p_article->sid)          if (p_section->sid != p_article->sid)
1077          {          {
1078                  log_error("Inconsistent section sid %d != article sid %d\n", p_section->sid, p_article->sid);                  log_error("Inconsistent section sid %d != article sid %d", p_section->sid, p_article->sid);
1079                  return -2;                  return -2;
1080          }          }
1081    
# Line 1048  int section_list_update_article_ontop(SE Line 1085  int section_list_update_article_ontop(SE
1085                  {                  {
1086                          if (p_section->p_ontop_articles[i]->aid == p_article->aid)                          if (p_section->p_ontop_articles[i]->aid == p_article->aid)
1087                          {                          {
1088                                  log_error("Inconsistent state found: article %d already ontop in section %d\n", p_article->aid, p_section->sid);                                  log_error("Inconsistent state found: article %d already ontop in section %d", p_article->aid, p_section->sid);
1089                                  return 0;                                  return 0;
1090                          }                          }
1091                          else if (p_section->p_ontop_articles[i]->aid > p_article->aid)                          else if (p_section->p_ontop_articles[i]->aid > p_article->aid)
# Line 1093  int section_list_update_article_ontop(SE Line 1130  int section_list_update_article_ontop(SE
1130                  }                  }
1131                  if (i == p_section->ontop_article_count) // not found                  if (i == p_section->ontop_article_count) // not found
1132                  {                  {
1133                          log_error("Inconsistent state found: article %d not ontop in section %d\n", p_article->aid, p_section->sid);                          log_error("Inconsistent state found: article %d not ontop in section %d", p_article->aid, p_section->sid);
1134                          return 0;                          return 0;
1135                  }                  }
1136    
# Line 1112  int section_list_page_count_with_ontop(S Line 1149  int section_list_page_count_with_ontop(S
1149    
1150          if (p_section == NULL)          if (p_section == NULL)
1151          {          {
1152                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1153                  return -1;                  return -1;
1154          }          }
1155    
# Line 1132  int section_list_page_article_count_with Line 1169  int section_list_page_article_count_with
1169  {  {
1170          if (p_section == NULL)          if (p_section == NULL)
1171          {          {
1172                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1173                  return -1;                  return -1;
1174          }          }
1175    
# Line 1162  ARTICLE *section_list_find_article_with_ Line 1199  ARTICLE *section_list_find_article_with_
1199    
1200          if (p_section == NULL)          if (p_section == NULL)
1201          {          {
1202                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1203                  return NULL;                  return NULL;
1204          }          }
1205    
# Line 1248  int section_list_calculate_page(SECTION_ Line 1285  int section_list_calculate_page(SECTION_
1285    
1286          if (p_section == NULL)          if (p_section == NULL)
1287          {          {
1288                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1289                  return -1;                  return -1;
1290          }          }
1291    
# Line 1270  int section_list_calculate_page(SECTION_ Line 1307  int section_list_calculate_page(SECTION_
1307    
1308                  if (p_section->sid != p_article->sid)                  if (p_section->sid != p_article->sid)
1309                  {                  {
1310                          log_error("section_list_calculate_page() error: section sid %d != start article sid %d\n", p_section->sid, p_article->sid);                          log_error("section_list_calculate_page() error: section sid %d != start article sid %d", p_section->sid, p_article->sid);
1311                          return -2;                          return -2;
1312                  }                  }
1313    
# Line 1281  int section_list_calculate_page(SECTION_ Line 1318  int section_list_calculate_page(SECTION_
1318                          {                          {
1319                                  return -1;                                  return -1;
1320                          }                          }
1321                          log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n",                          log_error("section_list_calculate_page() aid = %d not found in section sid = %d",
1322                                            start_aid, p_section->sid);                                            start_aid, p_section->sid);
1323                          return -2;                          return -2;
1324                  }                  }
# Line 1330  int section_list_calculate_page(SECTION_ Line 1367  int section_list_calculate_page(SECTION_
1367    
1368                          if (page >= BBS_article_limit_per_section / BBS_article_limit_per_page && p_article != p_section->p_article_head)                          if (page >= BBS_article_limit_per_section / BBS_article_limit_per_page && p_article != p_section->p_article_head)
1369                          {                          {
1370                                  log_error("Count of page exceed limit in section %d\n", p_section->sid);                                  log_error("Count of page exceed limit in section %d", p_section->sid);
1371                                  break;                                  break;
1372                          }                          }
1373                  }                  }
# Line 1384  int article_count_of_topic(int32_t aid) Line 1421  int article_count_of_topic(int32_t aid)
1421          {          {
1422                  if (p_article->tid != 0 && p_article->tid != aid)                  if (p_article->tid != 0 && p_article->tid != aid)
1423                  {                  {
1424                          log_error("article_count_of_topic(%d) error: article %d not linked to the topic\n", aid, p_article->aid);                          log_error("article_count_of_topic(%d) error: article %d not linked to the topic", aid, p_article->aid);
1425                          break;                          break;
1426                  }                  }
1427    
# Line 1409  int section_list_move_topic(SECTION_LIST Line 1446  int section_list_move_topic(SECTION_LIST
1446    
1447          if (p_section_src == NULL || p_section_dest == NULL)          if (p_section_src == NULL || p_section_dest == NULL)
1448          {          {
1449                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1450                  return -1;                  return -1;
1451          }          }
1452    
1453          if (p_section_src->sid == p_section_dest->sid)          if (p_section_src->sid == p_section_dest->sid)
1454          {          {
1455                  log_error("section_list_move_topic() src and dest section are the same\n");                  log_error("section_list_move_topic() src and dest section are the same");
1456                  return -1;                  return -1;
1457          }          }
1458    
1459          if ((p_article = article_block_find_by_aid(aid)) == NULL)          if ((p_article = article_block_find_by_aid(aid)) == NULL)
1460          {          {
1461                  log_error("article_block_find_by_aid(aid = %d) error: article not found\n", aid);                  log_error("article_block_find_by_aid(aid = %d) error: article not found", aid);
1462                  return -2;                  return -2;
1463          }          }
1464    
1465          if (p_section_src->sid != p_article->sid)          if (p_section_src->sid != p_article->sid)
1466          {          {
1467                  log_error("section_list_move_topic() error: src section sid %d != article %d sid %d\n",                  log_error("section_list_move_topic() error: src section sid %d != article %d sid %d",
1468                                    p_section_src->sid, p_article->aid, p_article->sid);                                    p_section_src->sid, p_article->aid, p_article->sid);
1469                  return -2;                  return -2;
1470          }          }
1471    
1472          if (p_article->tid != 0)          if (p_article->tid != 0)
1473          {          {
1474                  log_error("section_list_move_topic(aid = %d) error: article is not head of topic, tid = %d\n", aid, p_article->tid);                  log_error("section_list_move_topic(aid = %d) error: article is not head of topic, tid = %d", aid, p_article->tid);
1475                  return -2;                  return -2;
1476          }          }
1477    
# Line 1443  int section_list_move_topic(SECTION_LIST Line 1480  int section_list_move_topic(SECTION_LIST
1480          move_article_count = article_count_of_topic(aid);          move_article_count = article_count_of_topic(aid);
1481          if (move_article_count <= 0)          if (move_article_count <= 0)
1482          {          {
1483                  log_error("article_count_of_topic(aid = %d) <= 0\n", aid);                  log_error("article_count_of_topic(aid = %d) <= 0", aid);
1484                  return -2;                  return -2;
1485          }          }
1486    
1487          if (p_section_dest->article_count + move_article_count > BBS_article_limit_per_section)          if (p_section_dest->article_count + move_article_count > BBS_article_limit_per_section)
1488          {          {
1489                  log_error("section_list_move_topic() error: article_count %d reach limit in section %d\n",                  log_error("section_list_move_topic() error: article_count %d reach limit in section %d",
1490                                    p_section_dest->article_count + move_article_count, p_section_dest->sid);                                    p_section_dest->article_count + move_article_count, p_section_dest->sid);
1491                  return -3;                  return -3;
1492          }          }
# Line 1462  int section_list_move_topic(SECTION_LIST Line 1499  int section_list_move_topic(SECTION_LIST
1499          {          {
1500                  if (p_section_src->sid != p_article->sid)                  if (p_section_src->sid != p_article->sid)
1501                  {                  {
1502                          log_error("section_list_move_topic() warning: src section sid %d != article %d sid %d\n",                          log_error("section_list_move_topic() warning: src section sid %d != article %d sid %d",
1503                                            p_section_src->sid, p_article->aid, p_article->sid);                                            p_section_src->sid, p_article->aid, p_article->sid);
1504                          p_article = p_article->p_topic_next;                          p_article = p_article->p_topic_next;
1505                          continue;                          continue;
# Line 1491  int section_list_move_topic(SECTION_LIST Line 1528  int section_list_move_topic(SECTION_LIST
1528    
1529                  if (section_list_find_article_with_offset(p_section_dest, p_article->aid, &page, &offset, &p_next) != NULL)                  if (section_list_find_article_with_offset(p_section_dest, p_article->aid, &page, &offset, &p_next) != NULL)
1530                  {                  {
1531                          log_error("section_list_move_topic() warning: article %d already in section %d\n", p_article->aid, p_section_dest->sid);                          log_error("section_list_move_topic() warning: article %d already in section %d", p_article->aid, p_section_dest->sid);
1532                          p_article = p_article->p_topic_next;                          p_article = p_article->p_topic_next;
1533                          continue;                          continue;
1534                  }                  }
# Line 1561  int section_list_move_topic(SECTION_LIST Line 1598  int section_list_move_topic(SECTION_LIST
1598                          // Re-calculate pages of desc section                          // Re-calculate pages of desc section
1599                          if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)                          if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
1600                          {                          {
1601                                  log_error("section_list_calculate_page(dest section = %d, aid = %d) error\n",                                  log_error("section_list_calculate_page(dest section = %d, aid = %d) error",
1602                                                    p_section_dest->sid, first_inserted_aid_dest);                                                    p_section_dest->sid, first_inserted_aid_dest);
1603                          }                          }
1604    
# Line 1571  int section_list_move_topic(SECTION_LIST Line 1608  int section_list_move_topic(SECTION_LIST
1608    
1609          if (p_section_dest->article_count - dest_article_count_old != move_article_count)          if (p_section_dest->article_count - dest_article_count_old != move_article_count)
1610          {          {
1611                  log_error("section_list_move_topic() warning: count of moved articles %d != %d\n",                  log_error("section_list_move_topic() warning: count of moved articles %d != %d",
1612                                    p_section_dest->article_count - dest_article_count_old, move_article_count);                                    p_section_dest->article_count - dest_article_count_old, move_article_count);
1613          }          }
1614    
1615          // Re-calculate pages of src section          // Re-calculate pages of src section
1616          if (section_list_calculate_page(p_section_src, last_unaffected_aid_src) < 0)          if (section_list_calculate_page(p_section_src, last_unaffected_aid_src) < 0)
1617          {          {
1618                  log_error("section_list_calculate_page(src section = %d, aid = %d) error at aid = %d\n",                  log_error("section_list_calculate_page(src section = %d, aid = %d) error at aid = %d",
1619                                    p_section_src->sid, last_unaffected_aid_src, aid);                                    p_section_src->sid, last_unaffected_aid_src, aid);
1620          }          }
1621    
# Line 1587  int section_list_move_topic(SECTION_LIST Line 1624  int section_list_move_topic(SECTION_LIST
1624                  // Re-calculate pages of desc section                  // Re-calculate pages of desc section
1625                  if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)                  if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
1626                  {                  {
1627                          log_error("section_list_calculate_page(dest section = %d, aid = %d) error\n",                          log_error("section_list_calculate_page(dest section = %d, aid = %d) error",
1628                                            p_section_dest->sid, first_inserted_aid_dest);                                            p_section_dest->sid, first_inserted_aid_dest);
1629                  }                  }
1630          }          }
# Line 1601  int get_section_index(SECTION_LIST *p_se Line 1638  int get_section_index(SECTION_LIST *p_se
1638    
1639          if (p_section_list_pool == NULL)          if (p_section_list_pool == NULL)
1640          {          {
1641                  log_error("get_section_index() error: uninitialized\n");                  log_error("get_section_index() error: uninitialized");
1642                  return -1;                  return -1;
1643          }          }
1644    
# Line 1614  int get_section_index(SECTION_LIST *p_se Line 1651  int get_section_index(SECTION_LIST *p_se
1651                  index = (int)(p_section - p_section_list_pool->sections);                  index = (int)(p_section - p_section_list_pool->sections);
1652                  if (index < 0 || index >= BBS_max_section)                  if (index < 0 || index >= BBS_max_section)
1653                  {                  {
1654                          log_error("get_section_index(%d) error: index out of range\n", index);                          log_error("get_section_index(%d) error: index out of range", index);
1655                          return -2;                          return -2;
1656                  }                  }
1657          }          }
# Line 1626  int get_section_info(SECTION_LIST *p_sec Line 1663  int get_section_info(SECTION_LIST *p_sec
1663  {  {
1664          if (p_section == NULL)          if (p_section == NULL)
1665          {          {
1666                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
1667                  return -1;                  return -1;
1668          }          }
1669    
1670          if (section_list_rd_lock(p_section) < 0)          if (section_list_rd_lock(p_section) < 0)
1671          {          {
1672                  log_error("section_list_rd_lock(sid=%d) error\n", p_section->sid);                  log_error("section_list_rd_lock(sid=%d) error", p_section->sid);
1673                  return -2;                  return -2;
1674          }          }
1675    
# Line 1652  int get_section_info(SECTION_LIST *p_sec Line 1689  int get_section_info(SECTION_LIST *p_sec
1689          // release lock of section          // release lock of section
1690          if (section_list_rd_unlock(p_section) < 0)          if (section_list_rd_unlock(p_section) < 0)
1691          {          {
1692                  log_error("section_list_rd_unlock(sid=%d) error\n", p_section->sid);                  log_error("section_list_rd_unlock(sid=%d) error", p_section->sid);
1693                  return -2;                  return -2;
1694          }          }
1695    
# Line 1703  int section_list_try_rd_lock(SECTION_LIS Line 1740  int section_list_try_rd_lock(SECTION_LIS
1740          ret = semtimedop(p_section_list_pool->semid, sops, (index == BBS_max_section ? 2 : 4), &timeout);          ret = semtimedop(p_section_list_pool->semid, sops, (index == BBS_max_section ? 2 : 4), &timeout);
1741          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
1742          {          {
1743                  log_error("semop(index = %d, lock read) error %d\n", index, errno);                  log_error("semop(index = %d, lock read) error %d", index, errno);
1744          }          }
1745  #else  #else
1746          if (sem_timedwait(&(p_section_list_pool->sem[index]), &timeout) == -1)          if (sem_timedwait(&(p_section_list_pool->sem[index]), &timeout) == -1)
1747          {          {
1748                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1749                  {                  {
1750                          log_error("sem_timedwait(sem[%d]) error %d\n", index, errno);                          log_error("sem_timedwait(sem[%d]) error %d", index, errno);
1751                  }                  }
1752                  return -1;                  return -1;
1753          }          }
# Line 1721  int section_list_try_rd_lock(SECTION_LIS Line 1758  int section_list_try_rd_lock(SECTION_LIS
1758                  {                  {
1759                          if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                          if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1760                          {                          {
1761                                  log_error("sem_timedwait(sem[%d]) error %d\n", BBS_max_section, errno);                                  log_error("sem_timedwait(sem[%d]) error %d", BBS_max_section, errno);
1762                          }                          }
1763                          // release previously acquired lock                          // release previously acquired lock
1764                          if (sem_post(&(p_section_list_pool->sem[index])) == -1)                          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
1765                          {                          {
1766                                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                                  log_error("sem_post(sem[%d]) error %d", index, errno);
1767                          }                          }
1768                          return -1;                          return -1;
1769                  }                  }
# Line 1752  int section_list_try_rd_lock(SECTION_LIS Line 1789  int section_list_try_rd_lock(SECTION_LIS
1789                  // release lock on "all section"                  // release lock on "all section"
1790                  if (sem_post(&(p_section_list_pool->sem[BBS_max_section])) == -1)                  if (sem_post(&(p_section_list_pool->sem[BBS_max_section])) == -1)
1791                  {                  {
1792                          log_error("sem_post(sem[%d]) error %d\n", BBS_max_section, errno);                          log_error("sem_post(sem[%d]) error %d", BBS_max_section, errno);
1793                          ret = -1;                          ret = -1;
1794                  }                  }
1795          }          }
1796    
1797          if (sem_post(&(p_section_list_pool->sem[index])) == -1)          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
1798          {          {
1799                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                  log_error("sem_post(sem[%d]) error %d", index, errno);
1800                  return -1;                  return -1;
1801          }          }
1802  #endif  #endif
# Line 1801  int section_list_try_rw_lock(SECTION_LIS Line 1838  int section_list_try_rw_lock(SECTION_LIS
1838          ret = semtimedop(p_section_list_pool->semid, sops, 3, &timeout);          ret = semtimedop(p_section_list_pool->semid, sops, 3, &timeout);
1839          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
1840          {          {
1841                  log_error("semop(index = %d, lock write) error %d\n", index, errno);                  log_error("semop(index = %d, lock write) error %d", index, errno);
1842          }          }
1843  #else  #else
1844          if (sem_timedwait(&(p_section_list_pool->sem[index]), &timeout) == -1)          if (sem_timedwait(&(p_section_list_pool->sem[index]), &timeout) == -1)
1845          {          {
1846                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1847                  {                  {
1848                          log_error("sem_timedwait(sem[%d]) error %d\n", index, errno);                          log_error("sem_timedwait(sem[%d]) error %d", index, errno);
1849                  }                  }
1850                  return -1;                  return -1;
1851          }          }
# Line 1825  int section_list_try_rw_lock(SECTION_LIS Line 1862  int section_list_try_rw_lock(SECTION_LIS
1862    
1863          if (sem_post(&(p_section_list_pool->sem[index])) == -1)          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
1864          {          {
1865                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                  log_error("sem_post(sem[%d]) error %d", index, errno);
1866                  return -1;                  return -1;
1867          }          }
1868  #endif  #endif
# Line 1862  int section_list_rd_unlock(SECTION_LIST Line 1899  int section_list_rd_unlock(SECTION_LIST
1899          ret = semop(p_section_list_pool->semid, sops, (index == BBS_max_section ? 1 : 2));          ret = semop(p_section_list_pool->semid, sops, (index == BBS_max_section ? 1 : 2));
1900          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
1901          {          {
1902                  log_error("semop(index = %d, unlock read) error %d\n", index, errno);                  log_error("semop(index = %d, unlock read) error %d", index, errno);
1903          }          }
1904  #else  #else
1905          if (sem_wait(&(p_section_list_pool->sem[index])) == -1)          if (sem_wait(&(p_section_list_pool->sem[index])) == -1)
1906          {          {
1907                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1908                  {                  {
1909                          log_error("sem_wait(sem[%d]) error %d\n", index, errno);                          log_error("sem_wait(sem[%d]) error %d", index, errno);
1910                  }                  }
1911                  return -1;                  return -1;
1912          }          }
# Line 1880  int section_list_rd_unlock(SECTION_LIST Line 1917  int section_list_rd_unlock(SECTION_LIST
1917                  {                  {
1918                          if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                          if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1919                          {                          {
1920                                  log_error("sem_wait(sem[%d]) error %d\n", BBS_max_section, errno);                                  log_error("sem_wait(sem[%d]) error %d", BBS_max_section, errno);
1921                          }                          }
1922                          // release previously acquired lock                          // release previously acquired lock
1923                          if (sem_post(&(p_section_list_pool->sem[index])) == -1)                          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
1924                          {                          {
1925                                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                                  log_error("sem_post(sem[%d]) error %d", index, errno);
1926                          }                          }
1927                          return -1;                          return -1;
1928                  }                  }
# Line 1897  int section_list_rd_unlock(SECTION_LIST Line 1934  int section_list_rd_unlock(SECTION_LIST
1934          }          }
1935          else          else
1936          {          {
1937                  log_error("read_lock_count[%d] already 0\n", index);                  log_error("read_lock_count[%d] already 0", index);
1938          }          }
1939    
1940          if (index != BBS_max_section && p_section_list_pool->read_lock_count[BBS_max_section] > 0)          if (index != BBS_max_section && p_section_list_pool->read_lock_count[BBS_max_section] > 0)
# Line 1906  int section_list_rd_unlock(SECTION_LIST Line 1943  int section_list_rd_unlock(SECTION_LIST
1943          }          }
1944          else          else
1945          {          {
1946                  log_error("read_lock_count[%d] already 0\n", BBS_max_section);                  log_error("read_lock_count[%d] already 0", BBS_max_section);
1947          }          }
1948    
1949          if (index != BBS_max_section)          if (index != BBS_max_section)
# Line 1914  int section_list_rd_unlock(SECTION_LIST Line 1951  int section_list_rd_unlock(SECTION_LIST
1951                  // release lock on "all section"                  // release lock on "all section"
1952                  if (sem_post(&(p_section_list_pool->sem[BBS_max_section])) == -1)                  if (sem_post(&(p_section_list_pool->sem[BBS_max_section])) == -1)
1953                  {                  {
1954                          log_error("sem_post(sem[%d]) error %d\n", BBS_max_section, errno);                          log_error("sem_post(sem[%d]) error %d", BBS_max_section, errno);
1955                          ret = -1;                          ret = -1;
1956                  }                  }
1957          }          }
1958    
1959          if (sem_post(&(p_section_list_pool->sem[index])) == -1)          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
1960          {          {
1961                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                  log_error("sem_post(sem[%d]) error %d", index, errno);
1962                  return -1;                  return -1;
1963          }          }
1964  #endif  #endif
# Line 1951  int section_list_rw_unlock(SECTION_LIST Line 1988  int section_list_rw_unlock(SECTION_LIST
1988          ret = semop(p_section_list_pool->semid, sops, 1);          ret = semop(p_section_list_pool->semid, sops, 1);
1989          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
1990          {          {
1991                  log_error("semop(index = %d, unlock write) error %d\n", index, errno);                  log_error("semop(index = %d, unlock write) error %d", index, errno);
1992          }          }
1993  #else  #else
1994          if (sem_wait(&(p_section_list_pool->sem[index])) == -1)          if (sem_wait(&(p_section_list_pool->sem[index])) == -1)
1995          {          {
1996                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)                  if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
1997                  {                  {
1998                          log_error("sem_wait(sem[%d]) error %d\n", index, errno);                          log_error("sem_wait(sem[%d]) error %d", index, errno);
1999                  }                  }
2000                  return -1;                  return -1;
2001          }          }
# Line 1969  int section_list_rw_unlock(SECTION_LIST Line 2006  int section_list_rw_unlock(SECTION_LIST
2006          }          }
2007          else          else
2008          {          {
2009                  log_error("write_lock_count[%d] already 0\n", index);                  log_error("write_lock_count[%d] already 0", index);
2010          }          }
2011    
2012          if (sem_post(&(p_section_list_pool->sem[index])) == -1)          if (sem_post(&(p_section_list_pool->sem[index])) == -1)
2013          {          {
2014                  log_error("sem_post(sem[%d]) error %d\n", index, errno);                  log_error("sem_post(sem[%d]) error %d", index, errno);
2015                  return -1;                  return -1;
2016          }          }
2017  #endif  #endif
# Line 1987  int section_list_rd_lock(SECTION_LIST *p Line 2024  int section_list_rd_lock(SECTION_LIST *p
2024          int timer = 0;          int timer = 0;
2025          int sid = (p_section == NULL ? 0 : p_section->sid);          int sid = (p_section == NULL ? 0 : p_section->sid);
2026          int ret = -1;          int ret = -1;
2027            time_t tm_first_failure = 0;
2028    
2029          while (!SYS_server_exit)          while (!SYS_server_exit)
2030          {          {
# Line 1997  int section_list_rd_lock(SECTION_LIST *p Line 2035  int section_list_rd_lock(SECTION_LIST *p
2035                  }                  }
2036                  else if (errno == EAGAIN || errno == EINTR) // retry                  else if (errno == EAGAIN || errno == EINTR) // retry
2037                  {                  {
2038                            // Dead lock detection
2039                            if (tm_first_failure == 0)
2040                            {
2041                                    time(&tm_first_failure);
2042                            }
2043    
2044                          timer++;                          timer++;
2045                          if (timer % SECTION_TRY_LOCK_TIMES == 0)                          if (timer % SECTION_TRY_LOCK_TIMES == 0)
2046                          {                          {
2047                                  log_error("section_list_try_rd_lock() tried %d times on section %d\n", timer, sid);                                  log_error("section_list_try_rd_lock() tried %d times on section %d", timer, sid);
2048                                    if (time(NULL) - tm_first_failure >= SECTION_DEAD_LOCK_TIMEOUT)
2049                                    {
2050                                            log_error("Unable to acquire rd_lock for %d seconds", time(NULL) - tm_first_failure);
2051    #ifndef HAVE_SYSTEM_V
2052                                            section_list_reset_lock(p_section);
2053                                            log_error("Reset POSIX semaphore to resolve dead lock");
2054    #endif
2055                                            break;
2056                                    }
2057                          }                          }
2058                          usleep(100 * 1000); // 0.1 second                          usleep(100 * 1000); // 0.1 second
2059                  }                  }
2060                  else // failed                  else // failed
2061                  {                  {
2062                          log_error("section_list_try_rd_lock() failed on section %d\n", sid);                          log_error("section_list_try_rd_lock() failed on section %d", sid);
2063                          break;                          break;
2064                  }                  }
2065          }          }
# Line 2019  int section_list_rw_lock(SECTION_LIST *p Line 2072  int section_list_rw_lock(SECTION_LIST *p
2072          int timer = 0;          int timer = 0;
2073          int sid = (p_section == NULL ? 0 : p_section->sid);          int sid = (p_section == NULL ? 0 : p_section->sid);
2074          int ret = -1;          int ret = -1;
2075            time_t tm_first_failure = 0;
2076    
2077          while (!SYS_server_exit)          while (!SYS_server_exit)
2078          {          {
# Line 2029  int section_list_rw_lock(SECTION_LIST *p Line 2083  int section_list_rw_lock(SECTION_LIST *p
2083                  }                  }
2084                  else if (errno == EAGAIN || errno == EINTR) // retry                  else if (errno == EAGAIN || errno == EINTR) // retry
2085                  {                  {
2086                            // Dead lock detection
2087                            if (tm_first_failure == 0)
2088                            {
2089                                    time(&tm_first_failure);
2090                            }
2091    
2092                          timer++;                          timer++;
2093                          if (timer % SECTION_TRY_LOCK_TIMES == 0)                          if (timer % SECTION_TRY_LOCK_TIMES == 0)
2094                          {                          {
2095                                  log_error("section_list_try_rw_lock() tried %d times on section %d\n", timer, sid);                                  log_error("section_list_try_rw_lock() tried %d times on section %d", timer, sid);
2096                                    if (time(NULL) - tm_first_failure >= SECTION_DEAD_LOCK_TIMEOUT)
2097                                    {
2098                                            log_error("Unable to acquire rw_lock for %d seconds", time(NULL) - tm_first_failure);
2099    #ifndef HAVE_SYSTEM_V
2100                                            section_list_reset_lock(p_section);
2101                                            log_error("Reset POSIX semaphore to resolve dead lock");
2102    #endif
2103                                            break;
2104                                    }
2105                          }                          }
2106                          usleep(100 * 1000); // 0.1 second                          usleep(100 * 1000); // 0.1 second
2107                  }                  }
2108                  else // failed                  else // failed
2109                  {                  {
2110                          log_error("section_list_try_rw_lock() failed on section %d\n", sid);                          log_error("section_list_try_rw_lock() failed on section %d", sid);
2111                          break;                          break;
2112                  }                  }
2113          }          }
2114    
2115          return ret;          return ret;
2116  }  }
2117    
2118    #ifndef HAVE_SYSTEM_V
2119    int section_list_reset_lock(SECTION_LIST *p_section)
2120    {
2121            int index;
2122    
2123            if (p_section == NULL)
2124            {
2125                    log_error("NULL pointer error");
2126                    return -1;
2127            }
2128    
2129            index = get_section_index(p_section);
2130            if (index < 0)
2131            {
2132                    return -2;
2133            }
2134    
2135            if (sem_destroy(&(p_section_list_pool->sem[index])) == -1)
2136            {
2137                    log_error("sem_destroy(sem[%d]) error (%d)", index, errno);
2138            }
2139    
2140            p_section_list_pool->read_lock_count[index] = 0;
2141            p_section_list_pool->write_lock_count[index] = 0;
2142    
2143            if (sem_init(&(p_section_list_pool->sem[index]), 1, 1) == -1)
2144            {
2145                    log_error("sem_init(sem[%d]) error (%d)", index, errno);
2146            }
2147    
2148            if (index != BBS_max_section)
2149            {
2150                    if (sem_destroy(&(p_section_list_pool->sem[BBS_max_section])) == -1)
2151                    {
2152                            log_error("sem_destroy(sem[%d]) error (%d)", BBS_max_section, errno);
2153                    }
2154    
2155                    p_section_list_pool->read_lock_count[BBS_max_section] = 0;
2156                    p_section_list_pool->write_lock_count[BBS_max_section] = 0;
2157    
2158                    if (sem_init(&(p_section_list_pool->sem[BBS_max_section]), 1, 1) == -1)
2159                    {
2160                            log_error("sem_init(sem[%d]) error (%d)", BBS_max_section, errno);
2161                    }
2162            }
2163    
2164            return 0;
2165    }
2166    #endif


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

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