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

Diff of /lbbs/src/user_list.c

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

Revision 1.30 by sysadm, Thu Nov 6 10:58:03 2025 UTC Revision 1.46 by sysadm, Thu Dec 18 02:56:01 2025 UTC
# Line 6  Line 6 
6   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>
7   */   */
8    
9    #ifdef HAVE_CONFIG_H
10    #include "config.h"
11    #endif
12    
13  #include "common.h"  #include "common.h"
14  #include "database.h"  #include "database.h"
15  #include "log.h"  #include "log.h"
# Line 13  Line 17 
17  #include "user_list.h"  #include "user_list.h"
18  #include "user_stat.h"  #include "user_stat.h"
19  #include <errno.h>  #include <errno.h>
20    #include <fcntl.h>
21  #include <stdlib.h>  #include <stdlib.h>
22  #include <string.h>  #include <string.h>
23  #include <time.h>  #include <time.h>
 #include <sys/ipc.h>  
24  #include <sys/mman.h>  #include <sys/mman.h>
25  #include <sys/param.h>  #include <sys/param.h>
26    #include <sys/stat.h>
27    
28    #ifdef HAVE_SYSTEM_V
29  #include <sys/sem.h>  #include <sys/sem.h>
 #include <sys/shm.h>  
30    
31  #ifdef _SEM_SEMUN_UNDEFINED  #ifdef _SEM_SEMUN_UNDEFINED
32  union semun  union semun
# Line 29  union semun Line 35  union semun
35          struct semid_ds *buf;  /* Buffer for IPC_STAT, IPC_SET */          struct semid_ds *buf;  /* Buffer for IPC_STAT, IPC_SET */
36          unsigned short *array; /* Array for GETALL, SETALL */          unsigned short *array; /* Array for GETALL, SETALL */
37          struct seminfo *__buf; /* Buffer for IPC_INFO          struct seminfo *__buf; /* Buffer for IPC_INFO
38                                                            (Linux-specific) */                                                          (Linux-specific) */
39  };  };
40  #endif // #ifdef _SEM_SEMUN_UNDEFINED  #endif // #ifdef _SEM_SEMUN_UNDEFINED
41    
42    #else
43    #include <semaphore.h>
44    #endif
45    
46  enum _user_list_constant_t  enum _user_list_constant_t
47  {  {
48          USER_LIST_TRY_LOCK_WAIT_TIME = 1, // second          USER_LIST_TRY_LOCK_WAIT_TIME = 1, // second
49          USER_LIST_TRY_LOCK_TIMES = 10,          USER_LIST_TRY_LOCK_TIMES = 10,
50            USER_LIST_DEAD_LOCK_TIMEOUT = 15, // second
51  };  };
52    
53  struct user_list_pool_t  struct user_list_pool_t
54  {  {
55          int shmid;          size_t shm_size;
56    #ifndef HAVE_SYSTEM_V
57            sem_t sem;
58            uint16_t read_lock_count;
59            uint16_t write_lock_count;
60    #else
61          int semid;          int semid;
62    #endif
63          USER_LIST user_list[2];          USER_LIST user_list[2];
64          USER_LIST *p_current;          int user_list_index_current;
65          USER_LIST *p_new;          int user_list_index_new;
66          USER_ONLINE_LIST user_online_list[2];          USER_ONLINE_LIST user_online_list[2];
67          USER_ONLINE_LIST *p_online_current;          int user_online_list_index_current;
68          USER_ONLINE_LIST *p_online_new;          int user_online_list_index_new;
69          USER_STAT_MAP user_stat_map;          USER_STAT_MAP user_stat_map;
70          int user_login_count;          int user_login_count;
71  };  };
72  typedef struct user_list_pool_t USER_LIST_POOL;  typedef struct user_list_pool_t USER_LIST_POOL;
73    
74    static char user_list_shm_name[FILE_NAME_LEN];
75  static USER_LIST_POOL *p_user_list_pool = NULL;  static USER_LIST_POOL *p_user_list_pool = NULL;
76  static TRIE_NODE *p_trie_action_dict = NULL;  static TRIE_NODE *p_trie_action_dict = NULL;
77    
# Line 73  const USER_ACTION_MAP user_action_map[] Line 91  const USER_ACTION_MAP user_action_map[]
91                  {"MENU", "菜单选择"},                  {"MENU", "菜单选择"},
92                  {"POST_ARTICLE", "撰写文章"},                  {"POST_ARTICLE", "撰写文章"},
93                  {"REPLY_ARTICLE", "回复文章"},                  {"REPLY_ARTICLE", "回复文章"},
94                    {"TOP10_MENU", "十大热门"},
95                  {"USER_LIST", "查花名册"},                  {"USER_LIST", "查花名册"},
96                  {"USER_ONLINE", "环顾四周"},                  {"USER_ONLINE", "环顾四周"},
97                  {"VIEW_ARTICLE", "阅读文章"},                  {"VIEW_ARTICLE", "阅读文章"},
# Line 81  const USER_ACTION_MAP user_action_map[] Line 100  const USER_ACTION_MAP user_action_map[]
100    
101  const int user_action_map_size = sizeof(user_action_map) / sizeof(USER_ACTION_MAP);  const int user_action_map_size = sizeof(user_action_map) / sizeof(USER_ACTION_MAP);
102    
103  static int user_list_try_rd_lock(int semid, int wait_sec);  static int user_list_try_rd_lock(int wait_sec);
104  static int user_list_try_rw_lock(int semid, int wait_sec);  static int user_list_try_rw_lock(int wait_sec);
105  static int user_list_rd_unlock(int semid);  static int user_list_rd_unlock(void);
106  static int user_list_rw_unlock(int semid);  static int user_list_rw_unlock(void);
107  static int user_list_rd_lock(int semid);  static int user_list_rd_lock(void);
108  static int user_list_rw_lock(int semid);  static int user_list_rw_lock(void);
109    #ifndef HAVE_SYSTEM_V
110    static int user_list_reset_lock(void);
111    #endif
112    
113  static int user_list_load(MYSQL *db, USER_LIST *p_list);  static int user_list_load(MYSQL *db, USER_LIST *p_list);
114  static int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_online_list);  static int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_online_list);
# Line 184  int user_list_load(MYSQL *db, USER_LIST Line 206  int user_list_load(MYSQL *db, USER_LIST
206                  p_list->users[i].signup_dt = (row[8] == NULL ? 0 : atol(row[8]));                  p_list->users[i].signup_dt = (row[8] == NULL ? 0 : atol(row[8]));
207                  p_list->users[i].last_login_dt = (row[9] == NULL ? 0 : atol(row[9]));                  p_list->users[i].last_login_dt = (row[9] == NULL ? 0 : atol(row[9]));
208                  p_list->users[i].last_logout_dt = (row[10] == NULL ? 0 : atol(row[10]));                  p_list->users[i].last_logout_dt = (row[10] == NULL ? 0 : atol(row[10]));
209                  p_list->users[i].birthday = (row[10] == NULL ? 0 : atol(row[11]));                  p_list->users[i].birthday = (row[11] == NULL ? 0 : atol(row[11]));
210                  intro_len = strlen((row[12] == NULL ? "" : row[12]));                  intro_len = strlen((row[12] == NULL ? "" : row[12]));
211                  if (intro_len >= sizeof(p_list->user_intro_buf) - 1 - intro_buf_offset)                  if (intro_len >= sizeof(p_list->user_intro_buf) - 1 - intro_buf_offset)
212                  {                  {
# Line 218  int user_list_load(MYSQL *db, USER_LIST Line 240  int user_list_load(MYSQL *db, USER_LIST
240    
241                  qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);                  qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);
242    
243  #ifdef _DEBUG                  log_debug("Rebuild index of %d users, last_uid=%d\n", i, p_list->users[i - 1].uid);
                 log_error("Rebuild index of %d users, last_uid=%d\n", i, p_list->users[i - 1].uid);  
 #endif  
244          }          }
245    
246          p_list->user_count = i;          p_list->user_count = i;
247    
248  #ifdef _DEBUG          log_debug("Loaded %d users\n", p_list->user_count);
         log_error("Loaded %d users\n", p_list->user_count);  
 #endif  
249    
250  cleanup:  cleanup:
251          mysql_free_result(rs);          mysql_free_result(rs);
# Line 384  int user_login_count_load(MYSQL *db) Line 402  int user_login_count_load(MYSQL *db)
402    
403  int user_list_pool_init(const char *filename)  int user_list_pool_init(const char *filename)
404  {  {
405          int shmid;          char filepath[FILE_PATH_LEN];
406          int semid;          int fd;
         int proj_id;  
         key_t key;  
407          size_t size;          size_t size;
408          void *p_shm;          void *p_shm;
409    #ifdef HAVE_SYSTEM_V
410            int proj_id;
411            key_t key;
412            int semid;
413          union semun arg;          union semun arg;
414    #endif
415          int i;          int i;
416    
417          if (p_user_list_pool != NULL || p_trie_action_dict != NULL)          if (p_user_list_pool != NULL || p_trie_action_dict != NULL)
# Line 415  int user_list_pool_init(const char *file Line 436  int user_list_pool_init(const char *file
436          }          }
437    
438          // Allocate shared memory          // Allocate shared memory
439          proj_id = (int)(time(NULL) % getpid());          size = sizeof(USER_LIST_POOL);
440          key = ftok(filename, proj_id);  
441          if (key == -1)          strncpy(filepath, filename, sizeof(filepath) - 1);
442            filepath[sizeof(filepath) - 1] = '\0';
443            snprintf(user_list_shm_name, sizeof(user_list_shm_name), "/USER_LIST_SHM_%s", basename(filepath));
444    
445            if (shm_unlink(user_list_shm_name) == -1 && errno != ENOENT)
446          {          {
447                  log_error("ftok(%s %d) error (%d)\n", filename, proj_id, errno);                  log_error("shm_unlink(%s) error (%d)\n", user_list_shm_name, errno);
448                  return -2;                  return -2;
449          }          }
450    
451          size = sizeof(USER_LIST_POOL);          if ((fd = shm_open(user_list_shm_name, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
         shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);  
         if (shmid == -1)  
452          {          {
453                  log_error("shmget(size = %d) error (%d)\n", size, errno);                  log_error("shm_open(%s) error (%d)\n", user_list_shm_name, errno);
454                  return -3;                  return -2;
455          }          }
456          p_shm = shmat(shmid, NULL, 0);          if (ftruncate(fd, (off_t)size) == -1)
         if (p_shm == (void *)-1)  
457          {          {
458                  log_error("shmat(shmid=%d) error (%d)\n", shmid, errno);                  log_error("ftruncate(size=%d) error (%d)\n", size, errno);
459                  return -3;                  close(fd);
460                    return -2;
461            }
462    
463            p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
464            if (p_shm == MAP_FAILED)
465            {
466                    log_error("mmap() error (%d)\n", errno);
467                    close(fd);
468                    return -2;
469            }
470    
471            if (close(fd) < 0)
472            {
473                    log_error("close(fd) error (%d)\n", errno);
474                    return -1;
475          }          }
476    
477          p_user_list_pool = p_shm;          p_user_list_pool = p_shm;
478          p_user_list_pool->shmid = shmid;          p_user_list_pool->shm_size = size;
479    
480          // Allocate semaphore as user list pool lock          // Allocate semaphore as user list pool lock
481    #ifndef HAVE_SYSTEM_V
482            if (sem_init(&(p_user_list_pool->sem), 1, 1) == -1)
483            {
484                    log_error("sem_init() error (%d)\n", errno);
485                    return -3;
486            }
487    
488            p_user_list_pool->read_lock_count = 0;
489            p_user_list_pool->write_lock_count = 0;
490    #else
491            proj_id = (int)(time(NULL) % getpid());
492            key = ftok(filename, proj_id);
493            if (key == -1)
494            {
495                    log_error("ftok(%s %d) error (%d)\n", filename, proj_id, errno);
496                    return -2;
497            }
498    
499          size = 2; // r_sem and w_sem          size = 2; // r_sem and w_sem
500          semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600);          semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600);
501          if (semid == -1)          if (semid == -1)
# Line 461  int user_list_pool_init(const char *file Line 516  int user_list_pool_init(const char *file
516          }          }
517    
518          p_user_list_pool->semid = semid;          p_user_list_pool->semid = semid;
519    #endif
520    
521          // Set user counts to 0          // Set user counts to 0
522          p_user_list_pool->user_list[0].user_count = 0;          p_user_list_pool->user_list[0].user_count = 0;
523          p_user_list_pool->user_list[1].user_count = 0;          p_user_list_pool->user_list[1].user_count = 0;
524    
525          p_user_list_pool->p_current = &(p_user_list_pool->user_list[0]);          p_user_list_pool->user_list_index_current = 0;
526          p_user_list_pool->p_new = &(p_user_list_pool->user_list[1]);          p_user_list_pool->user_list_index_new = 1;
527    
528          p_user_list_pool->p_online_current = &(p_user_list_pool->user_online_list[0]);          p_user_list_pool->user_online_list_index_current = 0;
529          p_user_list_pool->p_online_new = &(p_user_list_pool->user_online_list[1]);          p_user_list_pool->user_online_list_index_new = 1;
530    
531          user_stat_map_init(&(p_user_list_pool->user_stat_map));          user_stat_map_init(&(p_user_list_pool->user_stat_map));
532    
# Line 479  int user_list_pool_init(const char *file Line 535  int user_list_pool_init(const char *file
535    
536  void user_list_pool_cleanup(void)  void user_list_pool_cleanup(void)
537  {  {
         int shmid;  
   
538          if (p_user_list_pool == NULL)          if (p_user_list_pool == NULL)
539          {          {
540                  return;                  return;
541          }          }
542    
543          shmid = p_user_list_pool->shmid;  #ifdef HAVE_SYSTEM_V
   
544          if (semctl(p_user_list_pool->semid, 0, IPC_RMID) == -1)          if (semctl(p_user_list_pool->semid, 0, IPC_RMID) == -1)
545          {          {
546                  log_error("semctl(semid = %d, IPC_RMID) error (%d)\n", p_user_list_pool->semid, errno);                  log_error("semctl(semid = %d, IPC_RMID) error (%d)\n", p_user_list_pool->semid, errno);
547          }          }
548    #else
549          if (shmdt(p_user_list_pool) == -1)          if (sem_destroy(&(p_user_list_pool->sem)) == -1)
550          {          {
551                  log_error("shmdt(shmid = %d) error (%d)\n", shmid, errno);                  log_error("sem_destroy() error (%d)\n", errno);
552          }          }
553    #endif
554    
555            detach_user_list_pool_shm();
556    
557          if (shmid != 0 && shmctl(shmid, IPC_RMID, NULL) == -1)          if (shm_unlink(user_list_shm_name) == -1 && errno != ENOENT)
558          {          {
559                  log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", shmid, errno);                  log_error("shm_unlink(%s) error (%d)\n", user_list_shm_name, errno);
560          }          }
561    
562          p_user_list_pool = NULL;          user_list_shm_name[0] = '\0';
563    
564          if (p_trie_action_dict != NULL)          if (p_trie_action_dict != NULL)
565          {          {
# Line 515  void user_list_pool_cleanup(void) Line 571  void user_list_pool_cleanup(void)
571    
572  int set_user_list_pool_shm_readonly(void)  int set_user_list_pool_shm_readonly(void)
573  {  {
574          int shmid;          if (p_user_list_pool != NULL && mprotect(p_user_list_pool, p_user_list_pool->shm_size, PROT_READ) < 0)
         void *p_shm;  
   
         if (p_user_list_pool == NULL)  
575          {          {
576                  log_error("p_user_list_pool not initialized\n");                  log_error("mprotect() error (%d)\n", errno);
577                  return -1;                  return -1;
578          }          }
579    
         shmid = p_user_list_pool->shmid;  
   
         // Remap shared memory in read-only mode  
         p_shm = shmat(shmid, p_user_list_pool, SHM_RDONLY | SHM_REMAP);  
         if (p_shm == (void *)-1)  
         {  
                 log_error("shmat(user_list_pool shmid = %d) error (%d)\n", shmid, errno);  
                 return -3;  
         }  
   
         p_user_list_pool = p_shm;  
   
580          return 0;          return 0;
581  }  }
582    
583  int detach_user_list_pool_shm(void)  int detach_user_list_pool_shm(void)
584  {  {
585          if (p_user_list_pool != NULL && shmdt(p_user_list_pool) == -1)          if (p_user_list_pool != NULL && munmap(p_user_list_pool, p_user_list_pool->shm_size) < 0)
586          {          {
587                  log_error("shmdt(user_list_pool) error (%d)\n", errno);                  log_error("munmap() error (%d)\n", errno);
588                  return -1;                  return -1;
589          }          }
590    
# Line 555  int detach_user_list_pool_shm(void) Line 596  int detach_user_list_pool_shm(void)
596  int user_list_pool_reload(int online_user)  int user_list_pool_reload(int online_user)
597  {  {
598          MYSQL *db = NULL;          MYSQL *db = NULL;
599          USER_LIST *p_tmp;          int tmp;
         USER_ONLINE_LIST *p_online_tmp;  
600          int ret = 0;          int ret = 0;
601    
602          if (p_user_list_pool == NULL)          if (p_user_list_pool == NULL)
# Line 574  int user_list_pool_reload(int online_use Line 614  int user_list_pool_reload(int online_use
614    
615          if (online_user)          if (online_user)
616          {          {
617                  if (user_online_list_load(db, p_user_list_pool->p_online_new) < 0)                  if (user_online_list_load(db, &(p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_new])) < 0)
618                  {                  {
619                          log_error("user_online_list_load() error\n");                          log_error("user_online_list_load() error\n");
620                          ret = -2;                          ret = -2;
# Line 590  int user_list_pool_reload(int online_use Line 630  int user_list_pool_reload(int online_use
630          }          }
631          else          else
632          {          {
633                  if (user_list_load(db, p_user_list_pool->p_new) < 0)                  if (user_list_load(db, &(p_user_list_pool->user_list[p_user_list_pool->user_list_index_new])) < 0)
634                  {                  {
635                          log_error("user_list_load() error\n");                          log_error("user_list_load() error\n");
636                          ret = -2;                          ret = -2;
# Line 601  int user_list_pool_reload(int online_use Line 641  int user_list_pool_reload(int online_use
641          mysql_close(db);          mysql_close(db);
642          db = NULL;          db = NULL;
643    
644          if (user_list_rw_lock(p_user_list_pool->semid) < 0)          if (user_list_rw_lock() < 0)
645          {          {
646                  log_error("user_list_rw_lock() error\n");                  log_error("user_list_rw_lock() error\n");
647                  ret = -3;                  ret = -3;
# Line 611  int user_list_pool_reload(int online_use Line 651  int user_list_pool_reload(int online_use
651          if (online_user)          if (online_user)
652          {          {
653                  // Swap p_online_current and p_online_new                  // Swap p_online_current and p_online_new
654                  p_online_tmp = p_user_list_pool->p_online_current;                  tmp = p_user_list_pool->user_online_list_index_current;
655                  p_user_list_pool->p_online_current = p_user_list_pool->p_online_new;                  p_user_list_pool->user_online_list_index_current = p_user_list_pool->user_online_list_index_new;
656                  p_user_list_pool->p_online_new = p_online_tmp;                  p_user_list_pool->user_online_list_index_new = tmp;
657          }          }
658          else          else
659          {          {
660                  // Swap p_current and p_new                  // Swap index_current and index_new
661                  p_tmp = p_user_list_pool->p_current;                  tmp = p_user_list_pool->user_list_index_current;
662                  p_user_list_pool->p_current = p_user_list_pool->p_new;                  p_user_list_pool->user_list_index_current = p_user_list_pool->user_list_index_new;
663                  p_user_list_pool->p_new = p_tmp;                  p_user_list_pool->user_list_index_new = tmp;
664          }          }
665    
666          if (user_list_rw_unlock(p_user_list_pool->semid) < 0)          if (user_list_rw_unlock() < 0)
667          {          {
668                  log_error("user_list_rw_unlock() error\n");                  log_error("user_list_rw_unlock() error\n");
669                  ret = -3;                  ret = -3;
# Line 636  cleanup: Line 676  cleanup:
676          return ret;          return ret;
677  }  }
678    
679  int user_list_try_rd_lock(int semid, int wait_sec)  int user_list_try_rd_lock(int wait_sec)
680  {  {
681    #ifdef HAVE_SYSTEM_V
682          struct sembuf sops[2];          struct sembuf sops[2];
683    #endif
684          struct timespec timeout;          struct timespec timeout;
685          int ret;          int ret = 0;
686    
687            if (p_user_list_pool == NULL)
688            {
689                    log_error("p_user_list_pool not initialized\n");
690                    return -1;
691            }
692    
693            timeout.tv_sec = wait_sec;
694            timeout.tv_nsec = 0;
695    
696    #ifdef HAVE_SYSTEM_V
697          sops[0].sem_num = 1; // w_sem          sops[0].sem_num = 1; // w_sem
698          sops[0].sem_op = 0;      // wait until unlocked          sops[0].sem_op = 0;      // wait until unlocked
699          sops[0].sem_flg = 0;          sops[0].sem_flg = 0;
# Line 650  int user_list_try_rd_lock(int semid, int Line 702  int user_list_try_rd_lock(int semid, int
702          sops[1].sem_op = 1;                     // lock          sops[1].sem_op = 1;                     // lock
703          sops[1].sem_flg = SEM_UNDO; // undo on terminate          sops[1].sem_flg = SEM_UNDO; // undo on terminate
704    
705          timeout.tv_sec = wait_sec;          ret = semtimedop(p_user_list_pool->semid, sops, 2, &timeout);
         timeout.tv_nsec = 0;  
   
         ret = semtimedop(semid, sops, 2, &timeout);  
706          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
707          {          {
708                  log_error("semtimedop(lock read) error %d\n", errno);                  log_error("semop(lock read) error %d\n", errno);
709          }          }
710    #else
711            if (sem_timedwait(&(p_user_list_pool->sem), &timeout) == -1)
712            {
713                    if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
714                    {
715                            log_error("sem_timedwait() error %d\n", errno);
716                    }
717                    return -1;
718            }
719    
720            if (p_user_list_pool->write_lock_count == 0)
721            {
722                    p_user_list_pool->read_lock_count++;
723            }
724            else
725            {
726                    errno = EAGAIN;
727                    ret = -1;
728            }
729    
730            if (sem_post(&(p_user_list_pool->sem)) == -1)
731            {
732                    log_error("sem_post() error %d\n", errno);
733                    return -1;
734            }
735    #endif
736    
737          return ret;          return ret;
738  }  }
739    
740  int user_list_try_rw_lock(int semid, int wait_sec)  int user_list_try_rw_lock(int wait_sec)
741  {  {
742    #ifdef HAVE_SYSTEM_V
743          struct sembuf sops[3];          struct sembuf sops[3];
744    #endif
745          struct timespec timeout;          struct timespec timeout;
746          int ret;          int ret = 0;
747    
748            if (p_user_list_pool == NULL)
749            {
750                    log_error("p_user_list_pool not initialized\n");
751                    return -1;
752            }
753    
754            timeout.tv_sec = wait_sec;
755            timeout.tv_nsec = 0;
756    
757    #ifdef HAVE_SYSTEM_V
758          sops[0].sem_num = 1; // w_sem          sops[0].sem_num = 1; // w_sem
759          sops[0].sem_op = 0;      // wait until unlocked          sops[0].sem_op = 0;      // wait until unlocked
760          sops[0].sem_flg = 0;          sops[0].sem_flg = 0;
# Line 680  int user_list_try_rw_lock(int semid, int Line 767  int user_list_try_rw_lock(int semid, int
767          sops[2].sem_op = 0;      // wait until unlocked          sops[2].sem_op = 0;      // wait until unlocked
768          sops[2].sem_flg = 0;          sops[2].sem_flg = 0;
769    
770          timeout.tv_sec = wait_sec;          ret = semtimedop(p_user_list_pool->semid, sops, 3, &timeout);
         timeout.tv_nsec = 0;  
   
         ret = semtimedop(semid, sops, 3, &timeout);  
771          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
772          {          {
773                  log_error("semtimedop(lock write) error %d\n", errno);                  log_error("semop(lock write) error %d\n", errno);
774            }
775    #else
776            if (sem_timedwait(&(p_user_list_pool->sem), &timeout) == -1)
777            {
778                    if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
779                    {
780                            log_error("sem_timedwait() error %d\n", errno);
781                    }
782                    return -1;
783          }          }
784    
785            if (p_user_list_pool->read_lock_count == 0 && p_user_list_pool->write_lock_count == 0)
786            {
787                    p_user_list_pool->write_lock_count++;
788            }
789            else
790            {
791                    errno = EAGAIN;
792                    ret = -1;
793            }
794    
795            if (sem_post(&(p_user_list_pool->sem)) == -1)
796            {
797                    log_error("sem_post() error %d\n", errno);
798                    return -1;
799            }
800    #endif
801    
802          return ret;          return ret;
803  }  }
804    
805  int user_list_rd_unlock(int semid)  int user_list_rd_unlock(void)
806  {  {
807    #ifdef HAVE_SYSTEM_V
808          struct sembuf sops[2];          struct sembuf sops[2];
809          int ret;  #endif
810            int ret = 0;
811    
812            if (p_user_list_pool == NULL)
813            {
814                    log_error("p_user_list_pool not initialized\n");
815                    return -1;
816            }
817    
818    #ifdef HAVE_SYSTEM_V
819          sops[0].sem_num = 0;                                     // r_sem          sops[0].sem_num = 0;                                     // r_sem
820          sops[0].sem_op = -1;                                     // unlock          sops[0].sem_op = -1;                                     // unlock
821          sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait          sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait
822    
823          ret = semop(semid, sops, 1);          ret = semop(p_user_list_pool->semid, sops, 1);
824          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
825          {          {
826                  log_error("semop(unlock read) error %d\n", errno);                  log_error("semop(unlock read) error %d\n", errno);
827          }          }
828    #else
829            if (sem_wait(&(p_user_list_pool->sem)) == -1)
830            {
831                    if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
832                    {
833                            log_error("sem_wait() error %d\n", errno);
834                    }
835                    return -1;
836            }
837    
838            if (p_user_list_pool->read_lock_count > 0)
839            {
840                    p_user_list_pool->read_lock_count--;
841            }
842            else
843            {
844                    log_error("read_lock_count already 0\n");
845            }
846    
847            if (sem_post(&(p_user_list_pool->sem)) == -1)
848            {
849                    log_error("sem_post() error %d\n", errno);
850                    return -1;
851            }
852    #endif
853    
854          return ret;          return ret;
855  }  }
856    
857  int user_list_rw_unlock(int semid)  int user_list_rw_unlock(void)
858  {  {
859    #ifdef HAVE_SYSTEM_V
860          struct sembuf sops[1];          struct sembuf sops[1];
861          int ret;  #endif
862            int ret = 0;
863    
864            if (p_user_list_pool == NULL)
865            {
866                    log_error("p_user_list_pool not initialized\n");
867                    return -1;
868            }
869    
870    #ifdef HAVE_SYSTEM_V
871          sops[0].sem_num = 1;                                     // w_sem          sops[0].sem_num = 1;                                     // w_sem
872          sops[0].sem_op = -1;                                     // unlock          sops[0].sem_op = -1;                                     // unlock
873          sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait          sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait
874    
875          ret = semop(semid, sops, 1);          ret = semop(p_user_list_pool->semid, sops, 1);
876          if (ret == -1 && errno != EAGAIN && errno != EINTR)          if (ret == -1 && errno != EAGAIN && errno != EINTR)
877          {          {
878                  log_error("semop(unlock write) error %d\n", errno);                  log_error("semop(unlock write) error %d\n", errno);
879          }          }
880    #else
881            if (sem_wait(&(p_user_list_pool->sem)) == -1)
882            {
883                    if (errno != ETIMEDOUT && errno != EAGAIN && errno != EINTR)
884                    {
885                            log_error("sem_wait() error %d\n", errno);
886                    }
887                    return -1;
888            }
889    
890            if (p_user_list_pool->write_lock_count > 0)
891            {
892                    p_user_list_pool->write_lock_count--;
893            }
894            else
895            {
896                    log_error("write_lock_count already 0\n");
897            }
898    
899            if (sem_post(&(p_user_list_pool->sem)) == -1)
900            {
901                    log_error("sem_post() error %d\n", errno);
902                    return -1;
903            }
904    #endif
905    
906          return ret;          return ret;
907  }  }
908    
909  int user_list_rd_lock(int semid)  int user_list_rd_lock(void)
910  {  {
911          int timer = 0;          int timer = 0;
912          int ret = -1;          int ret = -1;
913            time_t tm_first_failure = 0;
914    
915            if (p_user_list_pool == NULL)
916            {
917                    log_error("p_user_list_pool not initialized\n");
918                    return -1;
919            }
920    
921          while (!SYS_server_exit)          while (!SYS_server_exit)
922          {          {
923                  ret = user_list_try_rd_lock(semid, USER_LIST_TRY_LOCK_WAIT_TIME);                  ret = user_list_try_rd_lock(USER_LIST_TRY_LOCK_WAIT_TIME);
924                  if (ret == 0) // success                  if (ret == 0) // success
925                  {                  {
926                          break;                          break;
# Line 746  int user_list_rd_lock(int semid) Line 931  int user_list_rd_lock(int semid)
931                          if (timer % USER_LIST_TRY_LOCK_TIMES == 0)                          if (timer % USER_LIST_TRY_LOCK_TIMES == 0)
932                          {                          {
933                                  log_error("user_list_try_rd_lock() tried %d times\n", timer);                                  log_error("user_list_try_rd_lock() tried %d times\n", timer);
934    
935                                    if (time(NULL) - tm_first_failure >= USER_LIST_DEAD_LOCK_TIMEOUT)
936                                    {
937                                            log_error("Unable to acquire rw_lock for %d seconds\n", time(NULL) - tm_first_failure);
938    #ifndef HAVE_SYSTEM_V
939                                            user_list_reset_lock();
940                                            log_error("Reset POSIX semaphore to resolve dead lock\n");
941    #endif
942                                            break;
943                                    }
944                          }                          }
945                            usleep(100 * 1000); // 0.1 second
946                  }                  }
947                  else // failed                  else // failed
948                  {                  {
# Line 758  int user_list_rd_lock(int semid) Line 954  int user_list_rd_lock(int semid)
954          return ret;          return ret;
955  }  }
956    
957  int user_list_rw_lock(int semid)  int user_list_rw_lock(void)
958  {  {
959          int timer = 0;          int timer = 0;
960          int ret = -1;          int ret = -1;
961            time_t tm_first_failure = 0;
962    
963            if (p_user_list_pool == NULL)
964            {
965                    log_error("p_user_list_pool not initialized\n");
966                    return -1;
967            }
968    
969          while (!SYS_server_exit)          while (!SYS_server_exit)
970          {          {
971                  ret = user_list_try_rw_lock(semid, USER_LIST_TRY_LOCK_WAIT_TIME);                  ret = user_list_try_rw_lock(USER_LIST_TRY_LOCK_WAIT_TIME);
972                  if (ret == 0) // success                  if (ret == 0) // success
973                  {                  {
974                          break;                          break;
# Line 776  int user_list_rw_lock(int semid) Line 979  int user_list_rw_lock(int semid)
979                          if (timer % USER_LIST_TRY_LOCK_TIMES == 0)                          if (timer % USER_LIST_TRY_LOCK_TIMES == 0)
980                          {                          {
981                                  log_error("user_list_try_rw_lock() tried %d times\n", timer);                                  log_error("user_list_try_rw_lock() tried %d times\n", timer);
982    
983                                    if (time(NULL) - tm_first_failure >= USER_LIST_DEAD_LOCK_TIMEOUT)
984                                    {
985                                            log_error("Unable to acquire rw_lock for %d seconds\n", time(NULL) - tm_first_failure);
986    #ifndef HAVE_SYSTEM_V
987                                            user_list_reset_lock();
988                                            log_error("Reset POSIX semaphore to resolve dead lock\n");
989    #endif
990                                            break;
991                                    }
992                          }                          }
993                            usleep(100 * 1000); // 0.1 second
994                  }                  }
995                  else // failed                  else // failed
996                  {                  {
# Line 788  int user_list_rw_lock(int semid) Line 1002  int user_list_rw_lock(int semid)
1002          return ret;          return ret;
1003  }  }
1004    
1005    #ifndef HAVE_SYSTEM_V
1006    int user_list_reset_lock(void)
1007    {
1008            if (p_user_list_pool == NULL)
1009            {
1010                    log_error("p_user_list_pool not initialized\n");
1011                    return -1;
1012            }
1013    
1014            if (sem_destroy(&(p_user_list_pool->sem)) == -1)
1015            {
1016                    log_error("sem_destroy() error (%d)\n", errno);
1017            }
1018    
1019            p_user_list_pool->read_lock_count = 0;
1020            p_user_list_pool->write_lock_count = 0;
1021    
1022            if (sem_init(&(p_user_list_pool->sem), 1, 1) == -1)
1023            {
1024                    log_error("sem_init() error (%d)\n", errno);
1025            }
1026    
1027            return 0;
1028    }
1029    #endif
1030    
1031  int query_user_list(int page_id, USER_INFO *p_users, int *p_user_count, int *p_page_count)  int query_user_list(int page_id, USER_INFO *p_users, int *p_user_count, int *p_page_count)
1032  {  {
1033          int ret = 0;          int ret = 0;
# Line 802  int query_user_list(int page_id, USER_IN Line 1042  int query_user_list(int page_id, USER_IN
1042          *p_page_count = 0;          *p_page_count = 0;
1043    
1044          // acquire lock of user list          // acquire lock of user list
1045          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1046          {          {
1047                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1048                  return -2;                  return -2;
1049          }          }
1050    
1051          if (p_user_list_pool->p_current->user_count == 0)          if (p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count == 0)
1052          {          {
1053                  // empty list                  // empty list
1054                  ret = 0;                  ret = 0;
1055                  goto cleanup;                  goto cleanup;
1056          }          }
1057    
1058          *p_page_count = p_user_list_pool->p_current->user_count / BBS_user_limit_per_page +          *p_page_count = (p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count + BBS_user_limit_per_page - 1) /
1059                                          (p_user_list_pool->p_current->user_count % BBS_user_limit_per_page == 0 ? 0 : 1);                                          BBS_user_limit_per_page;
1060    
1061          if (page_id < 0 || page_id >= *p_page_count)          if (page_id < 0 || page_id >= *p_page_count)
1062          {          {
# Line 826  int query_user_list(int page_id, USER_IN Line 1066  int query_user_list(int page_id, USER_IN
1066          }          }
1067    
1068          *p_user_count = MIN(BBS_user_limit_per_page,          *p_user_count = MIN(BBS_user_limit_per_page,
1069                                                  p_user_list_pool->p_current->user_count -                                                  p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count -
1070                                                          page_id * BBS_user_limit_per_page);                                                          page_id * BBS_user_limit_per_page);
1071    
1072          memcpy(p_users,          memcpy(p_users,
1073                     p_user_list_pool->p_current->users + page_id * BBS_user_limit_per_page,                     p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users + page_id * BBS_user_limit_per_page,
1074                     sizeof(USER_INFO) * (size_t)(*p_user_count));                     sizeof(USER_INFO) * (size_t)(*p_user_count));
1075    
1076  cleanup:  cleanup:
1077          // release lock of user list          // release lock of user list
1078          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1079          {          {
1080                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1081                  ret = -1;                  ret = -1;
# Line 858  int query_user_online_list(int page_id, Line 1098  int query_user_online_list(int page_id,
1098          *p_page_count = 0;          *p_page_count = 0;
1099    
1100          // acquire lock of user list          // acquire lock of user list
1101          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1102          {          {
1103                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1104                  return -2;                  return -2;
1105          }          }
1106    
1107          if (p_user_list_pool->p_online_current->user_count == 0)          if (p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count == 0)
1108          {          {
1109                  // empty list                  // empty list
1110                  ret = 0;                  ret = 0;
1111                  goto cleanup;                  goto cleanup;
1112          }          }
1113    
1114          *p_page_count = p_user_list_pool->p_online_current->user_count / BBS_user_limit_per_page +          *p_page_count = (p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count + BBS_user_limit_per_page - 1) / BBS_user_limit_per_page;
                                         (p_user_list_pool->p_online_current->user_count % BBS_user_limit_per_page == 0 ? 0 : 1);  
1115    
1116          if (page_id < 0 || page_id >= *p_page_count)          if (page_id < 0 || page_id >= *p_page_count)
1117          {          {
# Line 882  int query_user_online_list(int page_id, Line 1121  int query_user_online_list(int page_id,
1121          }          }
1122    
1123          *p_user_count = MIN(BBS_user_limit_per_page,          *p_user_count = MIN(BBS_user_limit_per_page,
1124                                                  p_user_list_pool->p_online_current->user_count -                                                  p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count -
1125                                                          page_id * BBS_user_limit_per_page);                                                          page_id * BBS_user_limit_per_page);
1126    
1127          memcpy(p_online_users,          memcpy(p_online_users,
1128                     p_user_list_pool->p_online_current->users + page_id * BBS_user_limit_per_page,                     p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].users + page_id * BBS_user_limit_per_page,
1129                     sizeof(USER_ONLINE_INFO) * (size_t)(*p_user_count));                     sizeof(USER_ONLINE_INFO) * (size_t)(*p_user_count));
1130    
1131  cleanup:  cleanup:
1132          // release lock of user list          // release lock of user list
1133          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1134          {          {
1135                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1136                  ret = -1;                  ret = -1;
# Line 909  int get_user_list_count(int *p_user_cnt) Line 1148  int get_user_list_count(int *p_user_cnt)
1148          }          }
1149    
1150          // acquire lock of user list          // acquire lock of user list
1151          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1152          {          {
1153                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1154                  return -2;                  return -2;
1155          }          }
1156    
1157          *p_user_cnt = p_user_list_pool->p_current->user_count;          *p_user_cnt = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count;
1158    
1159          // release lock of user list          // release lock of user list
1160          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1161          {          {
1162                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1163                  return -2;                  return -2;
# Line 936  int get_user_online_list_count(int *p_us Line 1175  int get_user_online_list_count(int *p_us
1175          }          }
1176    
1177          // acquire lock of user list          // acquire lock of user list
1178          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1179          {          {
1180                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1181                  return -2;                  return -2;
1182          }          }
1183    
1184          *p_user_cnt = p_user_list_pool->p_online_current->user_count;          *p_user_cnt = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count;
1185          *p_guest_cnt = p_user_list_pool->p_online_current->guest_count;          *p_guest_cnt = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].guest_count;
1186    
1187          // release lock of user list          // release lock of user list
1188          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1189          {          {
1190                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1191                  return -2;                  return -2;
# Line 979  int query_user_info(int32_t id, USER_INF Line 1218  int query_user_info(int32_t id, USER_INF
1218          }          }
1219    
1220          // acquire lock of user list          // acquire lock of user list
1221          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1222          {          {
1223                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1224                  return -2;                  return -2;
1225          }          }
1226    
1227          if (id >= 0 && id < p_user_list_pool->p_current->user_count) // Found          if (id >= 0 && id < p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count) // Found
1228          {          {
1229                  *p_user = p_user_list_pool->p_current->users[id];                  *p_user = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[id];
1230                  ret = 1;                  ret = 1;
1231          }          }
1232    
1233          // release lock of user list          // release lock of user list
1234          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1235          {          {
1236                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1237                  ret = -1;                  ret = -1;
# Line 1016  int query_user_info_by_uid(int32_t uid, Line 1255  int query_user_info_by_uid(int32_t uid,
1255          }          }
1256    
1257          // acquire lock of user list          // acquire lock of user list
1258          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1259          {          {
1260                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1261                  return -2;                  return -2;
1262          }          }
1263    
1264          left = 0;          left = 0;
1265          right = p_user_list_pool->p_current->user_count - 1;          right = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count - 1;
1266    
1267          while (left < right)          while (left < right)
1268          {          {
1269                  mid = (left + right) / 2;                  mid = (left + right) / 2;
1270                  if (uid < p_user_list_pool->p_current->index_uid[mid].uid)                  if (uid < p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1271                  {                  {
1272                          right = mid - 1;                          right = mid - 1;
1273                  }                  }
1274                  else if (uid > p_user_list_pool->p_current->index_uid[mid].uid)                  else if (uid > p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1275                  {                  {
1276                          left = mid + 1;                          left = mid + 1;
1277                  }                  }
1278                  else // if (uid == p_user_list_pool->p_current->index_uid[mid].uid)                  else // if (uid == p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1279                  {                  {
1280                          left = mid;                          left = mid;
1281                          break;                          break;
1282                  }                  }
1283          }          }
1284    
1285          if (uid == p_user_list_pool->p_current->index_uid[left].uid) // Found          if (uid == p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[left].uid) // Found
1286          {          {
1287                  id = p_user_list_pool->p_current->index_uid[left].id;                  id = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[left].id;
1288                  *p_user = p_user_list_pool->p_current->users[id];                  *p_user = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[id];
1289                  ret = 1;                  ret = 1;
1290    
1291                  if (p_intro_buf != NULL)                  if (p_intro_buf != NULL)
1292                  {                  {
1293                          strncpy(p_intro_buf, p_user_list_pool->p_current->users[id].intro, intro_buf_len - 1);                          strncpy(p_intro_buf, p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[id].intro, intro_buf_len - 1);
1294                          p_intro_buf[intro_buf_len - 1] = '\0';                          p_intro_buf[intro_buf_len - 1] = '\0';
1295                          p_user->intro = p_intro_buf;                          p_user->intro = p_intro_buf;
1296                  }                  }
1297          }          }
1298    
1299          // release lock of user list          // release lock of user list
1300          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1301          {          {
1302                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1303                  ret = -1;                  ret = -1;
# Line 1088  int query_user_info_by_username(const ch Line 1327  int query_user_info_by_username(const ch
1327          prefix_len = strlen(username_prefix);          prefix_len = strlen(username_prefix);
1328    
1329          // acquire lock of user list          // acquire lock of user list
1330          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1331          {          {
1332                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1333                  return -2;                  return -2;
1334          }          }
1335    
1336          left = 0;          left = 0;
1337          right = p_user_list_pool->p_current->user_count - 1;          right = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count - 1;
1338    
1339          while (left < right)          while (left < right)
1340          {          {
1341                  mid = (left + right) / 2;                  mid = (left + right) / 2;
1342                  comp = strncasecmp(username_prefix, p_user_list_pool->p_current->users[mid].username, prefix_len);                  comp = strncasecmp(username_prefix, p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[mid].username, prefix_len);
1343                  if (comp < 0)                  if (comp < 0)
1344                  {                  {
1345                          right = mid - 1;                          right = mid - 1;
# Line 1116  int query_user_info_by_username(const ch Line 1355  int query_user_info_by_username(const ch
1355                  }                  }
1356          }          }
1357    
1358          if (strncasecmp(username_prefix, p_user_list_pool->p_current->users[left].username, prefix_len) == 0) // Found          if (strncasecmp(username_prefix, p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[left].username, prefix_len) == 0) // Found
1359          {          {
1360  #ifdef _DEBUG                  log_debug("Debug: match found, pos=%d\n", left);
                 log_error("Debug: match found, pos=%d\n", left);  
 #endif  
1361    
1362                  left_save = left;                  left_save = left;
1363                  right = left;                  right = left;
# Line 1129  int query_user_info_by_username(const ch Line 1366  int query_user_info_by_username(const ch
1366                  while (left < right)                  while (left < right)
1367                  {                  {
1368                          mid = (left + right) / 2;                          mid = (left + right) / 2;
1369                          comp = strncasecmp(username_prefix, p_user_list_pool->p_current->users[mid].username, prefix_len);                          comp = strncasecmp(username_prefix, p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[mid].username, prefix_len);
1370                          if (comp > 0)                          if (comp > 0)
1371                          {                          {
1372                                  left = mid + 1;                                  left = mid + 1;
# Line 1146  int query_user_info_by_username(const ch Line 1383  int query_user_info_by_username(const ch
1383                          }                          }
1384                  }                  }
1385    
1386  #ifdef _DEBUG                  log_debug("Debug: first match found, pos=%d\n", right);
                 log_error("Debug: first match found, pos=%d\n", right);  
 #endif  
1387    
1388                  left = left_save;                  left = left_save;
1389                  left_save = right;                  left_save = right;
1390                  right = p_user_list_pool->p_current->user_count - 1;                  right = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count - 1;
1391    
1392                  while (left < right)                  while (left < right)
1393                  {                  {
1394                          mid = (left + right) / 2 + (left + right) % 2;                          mid = (left + right) / 2 + (left + right) % 2;
1395                          comp = strncasecmp(username_prefix, p_user_list_pool->p_current->users[mid].username, prefix_len);                          comp = strncasecmp(username_prefix, p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[mid].username, prefix_len);
1396                          if (comp < 0)                          if (comp < 0)
1397                          {                          {
1398                                  right = mid - 1;                                  right = mid - 1;
# Line 1174  int query_user_info_by_username(const ch Line 1409  int query_user_info_by_username(const ch
1409                          }                          }
1410                  }                  }
1411    
1412  #ifdef _DEBUG                  log_debug("Debug: last match found, pos=%d\n", left);
                 log_error("Debug: last match found, pos=%d\n", left);  
 #endif  
1413    
1414                  right = left;                  right = left;
1415                  left = left_save;                  left = left_save;
1416    
1417                  for (i = 0; i < max_user_cnt && left + i <= right; i++)                  for (i = 0; i < max_user_cnt && left + i <= right; i++)
1418                  {                  {
1419                          uid_list[i] = p_user_list_pool->p_current->users[left + i].uid;                          uid_list[i] = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[left + i].uid;
1420                          strncpy(username_list[i], p_user_list_pool->p_current->users[left + i].username, sizeof(username_list[i]) - 1);                          strncpy(username_list[i], p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].users[left + i].username, sizeof(username_list[i]) - 1);
1421                          username_list[i][sizeof(username_list[i]) - 1] = '\0';                          username_list[i][sizeof(username_list[i]) - 1] = '\0';
1422                  }                  }
1423                  ret = i;                  ret = i;
# Line 1192  int query_user_info_by_username(const ch Line 1425  int query_user_info_by_username(const ch
1425    
1426  cleanup:  cleanup:
1427          // release lock of user list          // release lock of user list
1428          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1429          {          {
1430                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1431                  ret = -1;                  ret = -1;
# Line 1212  int query_user_online_info(int32_t id, U Line 1445  int query_user_online_info(int32_t id, U
1445          }          }
1446    
1447          // acquire lock of user list          // acquire lock of user list
1448          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1449          {          {
1450                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1451                  return -2;                  return -2;
1452          }          }
1453    
1454          if (id >= 0 && id < p_user_list_pool->p_online_current->user_count) // Found          if (id >= 0 && id < p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count) // Found
1455          {          {
1456                  *p_user = p_user_list_pool->p_online_current->users[id];                  *p_user = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].users[id];
1457                  ret = 1;                  ret = 1;
1458          }          }
1459    
1460          // release lock of user list          // release lock of user list
1461          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1462          {          {
1463                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1464                  ret = -1;                  ret = -1;
# Line 1254  int query_user_online_info_by_uid(int32_ Line 1487  int query_user_online_info_by_uid(int32_
1487          *p_user_cnt = 0;          *p_user_cnt = 0;
1488    
1489          // acquire lock of user list          // acquire lock of user list
1490          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1491          {          {
1492                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1493                  return -2;                  return -2;
1494          }          }
1495    
1496          left = start_id;          left = start_id;
1497          right = p_user_list_pool->p_online_current->user_count - 1;          right = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count - 1;
1498    
1499          while (left < right)          while (left < right)
1500          {          {
1501                  mid = (left + right) / 2;                  mid = (left + right) / 2;
1502                  if (uid < p_user_list_pool->p_online_current->index_uid[mid].uid)                  if (uid < p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[mid].uid)
1503                  {                  {
1504                          right = mid - 1;                          right = mid - 1;
1505                  }                  }
1506                  else if (uid > p_user_list_pool->p_online_current->index_uid[mid].uid)                  else if (uid > p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[mid].uid)
1507                  {                  {
1508                          left = mid + 1;                          left = mid + 1;
1509                  }                  }
1510                  else // if (uid == p_user_list_pool->p_online_current->index_uid[mid].uid)                  else // if (uid == p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[mid].uid)
1511                  {                  {
1512                          left = mid;                          left = mid;
1513                          break;                          break;
1514                  }                  }
1515          }          }
1516    
1517          if (uid == p_user_list_pool->p_online_current->index_uid[left].uid)          if (uid == p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[left].uid)
1518          {          {
1519                  right = left;                  right = left;
1520                  left = start_id;                  left = start_id;
# Line 1289  int query_user_online_info_by_uid(int32_ Line 1522  int query_user_online_info_by_uid(int32_
1522                  while (left < right)                  while (left < right)
1523                  {                  {
1524                          mid = (left + right) / 2;                          mid = (left + right) / 2;
1525                          if (uid - 1 < p_user_list_pool->p_online_current->index_uid[mid].uid)                          if (uid - 1 < p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[mid].uid)
1526                          {                          {
1527                                  right = mid;                                  right = mid;
1528                          }                          }
1529                          else // if (uid - 1 >= p_user_list_pool->p_online_current->index_uid[mid].uid)                          else // if (uid - 1 >= p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[mid].uid)
1530                          {                          {
1531                                  left = mid + 1;                                  left = mid + 1;
1532                          }                          }
1533                  }                  }
1534    
1535                  for (i = 0;                  for (i = 0;
1536                           left < p_user_list_pool->p_online_current->user_count && i < user_cnt &&                           left < p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].user_count && i < user_cnt &&
1537                           uid == p_user_list_pool->p_online_current->index_uid[left].uid;                           uid == p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[left].uid;
1538                           left++, i++)                           left++, i++)
1539                  {                  {
1540                          id = p_user_list_pool->p_online_current->index_uid[left].id;                          id = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].index_uid[left].id;
1541                          p_users[i] = p_user_list_pool->p_online_current->users[id];                          p_users[i] = p_user_list_pool->user_online_list[p_user_list_pool->user_online_list_index_current].users[id];
1542                  }                  }
1543    
1544                  if (i > 0)                  if (i > 0)
# Line 1316  int query_user_online_info_by_uid(int32_ Line 1549  int query_user_online_info_by_uid(int32_
1549          }          }
1550    
1551          // release lock of user list          // release lock of user list
1552          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1553          {          {
1554                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1555                  ret = -1;                  ret = -1;
# Line 1340  int get_user_id_list(int32_t *p_uid_list Line 1573  int get_user_id_list(int32_t *p_uid_list
1573          }          }
1574    
1575          // acquire lock of user list          // acquire lock of user list
1576          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock() < 0)
1577          {          {
1578                  log_error("user_list_rd_lock() error\n");                  log_error("user_list_rd_lock() error\n");
1579                  return -2;                  return -2;
1580          }          }
1581    
1582          left = 0;          left = 0;
1583          right = p_user_list_pool->p_current->user_count - 1;          right = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count - 1;
1584    
1585          while (left < right)          while (left < right)
1586          {          {
1587                  mid = (left + right) / 2;                  mid = (left + right) / 2;
1588                  if (start_uid < p_user_list_pool->p_current->index_uid[mid].uid)                  if (start_uid < p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1589                  {                  {
1590                          right = mid - 1;                          right = mid - 1;
1591                  }                  }
1592                  else if (start_uid > p_user_list_pool->p_current->index_uid[mid].uid)                  else if (start_uid > p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1593                  {                  {
1594                          left = mid + 1;                          left = mid + 1;
1595                  }                  }
1596                  else // if (start_uid == p_user_list_pool->p_current->index_uid[mid].uid)                  else // if (start_uid == p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[mid].uid)
1597                  {                  {
1598                          left = mid;                          left = mid;
1599                          break;                          break;
1600                  }                  }
1601          }          }
1602    
1603          for (i = 0; i < *p_user_cnt && left + i < p_user_list_pool->p_current->user_count; i++)          for (i = 0; i < *p_user_cnt && left + i < p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].user_count; i++)
1604          {          {
1605                  p_uid_list[i] = p_user_list_pool->p_current->index_uid[left + i].uid;                  p_uid_list[i] = p_user_list_pool->user_list[p_user_list_pool->user_list_index_current].index_uid[left + i].uid;
1606          }          }
1607          *p_user_cnt = i;          *p_user_cnt = i;
1608    
1609          // release lock of user list          // release lock of user list
1610          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock() < 0)
1611          {          {
1612                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");
1613                  ret = -1;                  ret = -1;


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

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