/[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.6 by sysadm, Wed Oct 22 04:48:53 2025 UTC Revision 1.17 by sysadm, Thu Oct 23 01:58:05 2025 UTC
# Line 71  const USER_ACTION_MAP user_action_map[] Line 71  const USER_ACTION_MAP user_action_map[]
71                  {"BBS_NET", "站点穿梭"},                  {"BBS_NET", "站点穿梭"},
72                  {"CHICKEN", "电子小鸡"},                  {"CHICKEN", "电子小鸡"},
73                  {"EDIT_ARTICLE", "修改文章"},                  {"EDIT_ARTICLE", "修改文章"},
74                    {"LOGIN", "进入大厅"},
75                  {"MENU", "菜单选择"},                  {"MENU", "菜单选择"},
76                  {"POST_ARTICLE", "撰写文章"},                  {"POST_ARTICLE", "撰写文章"},
77                  {"REPLY_ARTICLE", "回复文章"},                  {"REPLY_ARTICLE", "回复文章"},
78                  {"USER_LIST", "查花名册"},                  {"USER_LIST", "查花名册"},
79                  {"USER_ONLINE", "环顾四周"},                  {"USER_ONLINE", "环顾四周"},
80                  {"VIEW_ARTICLE", "阅读文章"},                  {"VIEW_ARTICLE", "阅读文章"},
81                  {"VIEW_FILE", "查看文档"}};                  {"VIEW_FILE", "查看文档"},
82                    {"WWW", "Web浏览"}};
83    
84  const int user_action_map_size = 11;  const int user_action_map_size = sizeof(user_action_map) / sizeof(USER_ACTION_MAP);
85    
86  static int user_list_try_rd_lock(int semid, int wait_sec);  static int user_list_try_rd_lock(int semid, int wait_sec);
87  static int user_list_try_rw_lock(int semid, int wait_sec);  static int user_list_try_rw_lock(int semid, int wait_sec);
# Line 91  static int user_list_rw_lock(int semid); Line 93  static int user_list_rw_lock(int semid);
93  static int user_list_load(MYSQL *db, USER_LIST *p_list);  static int user_list_load(MYSQL *db, USER_LIST *p_list);
94  static int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_list);  static int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_list);
95    
96    static int user_info_index_uid_comp(const void *ptr1, const void *ptr2)
97    {
98            const USER_INFO_INDEX_UID *p1 = ptr1;
99            const USER_INFO_INDEX_UID *p2 = ptr2;
100    
101            if (p1->uid < p2->uid)
102            {
103                    return -1;
104            }
105            else if (p1->uid > p2->uid)
106            {
107                    return 1;
108            }
109            else if (p1->id < p2->id)
110            {
111                    return -1;
112            }
113            else if (p1->id > p2->id)
114            {
115                    return 1;
116            }
117            return 0;
118    }
119    
120  int user_list_load(MYSQL *db, USER_LIST *p_list)  int user_list_load(MYSQL *db, USER_LIST *p_list)
121  {  {
122          MYSQL_RES *rs = NULL;          MYSQL_RES *rs = NULL;
# Line 98  int user_list_load(MYSQL *db, USER_LIST Line 124  int user_list_load(MYSQL *db, USER_LIST
124          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
125          int ret = 0;          int ret = 0;
126          int i;          int i;
127            int j;
128            int32_t last_uid;
129            size_t intro_buf_offset;
130            size_t intro_len;
131    
132          if (db == NULL || p_list == NULL)          if (db == NULL || p_list == NULL)
133          {          {
# Line 105  int user_list_load(MYSQL *db, USER_LIST Line 135  int user_list_load(MYSQL *db, USER_LIST
135                  return -1;                  return -1;
136          }          }
137    
138            if (p_list->user_count > 0)
139            {
140                    last_uid = p_list->users[p_list->user_count - 1].uid;
141            }
142            else
143            {
144                    last_uid = -1;
145            }
146    
147          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
148                           "SELECT user_list.UID AS UID, username, nickname, gender, gender_pub, life, exp, "                           "SELECT user_list.UID AS UID, username, nickname, gender, gender_pub, life, exp, visit_count, "
149                           "UNIX_TIMESTAMP(signup_dt), UNIX_TIMESTAMP(last_login_dt), UNIX_TIMESTAMP(birthday) "                           "UNIX_TIMESTAMP(signup_dt), UNIX_TIMESTAMP(last_login_dt), UNIX_TIMESTAMP(birthday), `introduction` "
150                           "FROM user_list INNER JOIN user_pubinfo ON user_list.UID = user_pubinfo.UID "                           "FROM user_list INNER JOIN user_pubinfo ON user_list.UID = user_pubinfo.UID "
151                           "INNER JOIN user_reginfo ON user_list.UID = user_reginfo.UID "                           "INNER JOIN user_reginfo ON user_list.UID = user_reginfo.UID "
152                           "WHERE enable ORDER BY UID");                           "WHERE enable ORDER BY username");
153    
154          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
155          {          {
# Line 126  int user_list_load(MYSQL *db, USER_LIST Line 165  int user_list_load(MYSQL *db, USER_LIST
165                  goto cleanup;                  goto cleanup;
166          }          }
167    
168            intro_buf_offset = 0;
169          i = 0;          i = 0;
170          while ((row = mysql_fetch_row(rs)))          while ((row = mysql_fetch_row(rs)))
171          {          {
172                    // record
173                    p_list->users[i].id = i;
174                  p_list->users[i].uid = atoi(row[0]);                  p_list->users[i].uid = atoi(row[0]);
175                  strncpy(p_list->users[i].username, row[1], sizeof(p_list->users[i].username) - 1);                  strncpy(p_list->users[i].username, row[1], sizeof(p_list->users[i].username) - 1);
176                  p_list->users[i].username[sizeof(p_list->users[i].username) - 1] = '\0';                  p_list->users[i].username[sizeof(p_list->users[i].username) - 1] = '\0';
# Line 138  int user_list_load(MYSQL *db, USER_LIST Line 180  int user_list_load(MYSQL *db, USER_LIST
180                  p_list->users[i].gender_pub = (int8_t)(row[4] == NULL ? 0 : atoi(row[4]));                  p_list->users[i].gender_pub = (int8_t)(row[4] == NULL ? 0 : atoi(row[4]));
181                  p_list->users[i].life = (row[5] == NULL ? 0 : atoi(row[5]));                  p_list->users[i].life = (row[5] == NULL ? 0 : atoi(row[5]));
182                  p_list->users[i].exp = (row[6] == NULL ? 0 : atoi(row[6]));                  p_list->users[i].exp = (row[6] == NULL ? 0 : atoi(row[6]));
183                  p_list->users[i].signup_dt = (row[7] == NULL ? 0 : atol(row[7]));                  p_list->users[i].visit_count = (row[7] == NULL ? 0 : atoi(row[7]));
184                  p_list->users[i].last_login_dt = (row[8] == NULL ? 0 : atol(row[8]));                  p_list->users[i].signup_dt = (row[8] == NULL ? 0 : atol(row[8]));
185                  p_list->users[i].birthday = (row[9] == NULL ? 0 : atol(row[9]));                  p_list->users[i].last_login_dt = (row[9] == NULL ? 0 : atol(row[9]));
186                    p_list->users[i].birthday = (row[10] == NULL ? 0 : atol(row[10]));
187                    intro_len = strlen((row[11] == NULL ? "" : row[11]));
188                    if (intro_len >= sizeof(p_list->user_intro_buf) - 1 - intro_buf_offset)
189                    {
190                            log_error("OOM for user introduction: len=%d, i=%d\n", intro_len, i);
191                            break;
192                    }
193                    memcpy(p_list->user_intro_buf + intro_buf_offset,
194                               (row[11] == NULL ? "" : row[11]),
195                               intro_len + 1);
196                    p_list->users[i].intro = p_list->user_intro_buf + intro_buf_offset;
197                    intro_buf_offset += (intro_len + 1);
198    
199                  i++;                  i++;
200                  if (i >= BBS_max_user_count)                  if (i >= BBS_max_user_count)
# Line 152  int user_list_load(MYSQL *db, USER_LIST Line 206  int user_list_load(MYSQL *db, USER_LIST
206          mysql_free_result(rs);          mysql_free_result(rs);
207          rs = NULL;          rs = NULL;
208    
209            if (i != p_list->user_count || p_list->users[i - 1].uid != last_uid) // Count of users changed
210            {
211                    // Rebuild index
212                    for (j = 0; j < i; j++)
213                    {
214                            p_list->index_uid[j].uid = p_list->users[j].uid;
215                            p_list->index_uid[j].id = j;
216                    }
217    
218                    qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);
219    
220    #ifdef _DEBUG
221                    log_error("Rebuild index of %d users, last_uid=%d\n", i, p_list->users[i - 1].uid);
222    #endif
223            }
224    
225          p_list->user_count = i;          p_list->user_count = i;
226    
227  #ifdef _DEBUG  #ifdef _DEBUG
# Line 171  int user_online_list_load(MYSQL *db, USE Line 241  int user_online_list_load(MYSQL *db, USE
241          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
242          int ret = 0;          int ret = 0;
243          int i;          int i;
244            int j;
245    
246          if (db == NULL || p_list == NULL)          if (db == NULL || p_list == NULL)
247          {          {
# Line 181  int user_online_list_load(MYSQL *db, USE Line 252  int user_online_list_load(MYSQL *db, USE
252          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
253                           "SELECT SID, UID, ip, current_action, UNIX_TIMESTAMP(login_tm), "                           "SELECT SID, UID, ip, current_action, UNIX_TIMESTAMP(login_tm), "
254                           "UNIX_TIMESTAMP(last_tm) FROM user_online "                           "UNIX_TIMESTAMP(last_tm) FROM user_online "
255                           "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND) "                           "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND) AND UID <> 0 "
256                           "ORDER BY last_tm DESC",                           "ORDER BY last_tm DESC",
257                           BBS_user_off_line);                           BBS_user_off_line);
258    
# Line 202  int user_online_list_load(MYSQL *db, USE Line 273  int user_online_list_load(MYSQL *db, USE
273          i = 0;          i = 0;
274          while ((row = mysql_fetch_row(rs)))          while ((row = mysql_fetch_row(rs)))
275          {          {
276                    p_list->users[i].id = i;
277                  strncpy(p_list->users[i].session_id, row[0], sizeof(p_list->users[i].session_id) - 1);                  strncpy(p_list->users[i].session_id, row[0], sizeof(p_list->users[i].session_id) - 1);
   
278                  p_list->users[i].session_id[sizeof(p_list->users[i].session_id) - 1] = '\0';                  p_list->users[i].session_id[sizeof(p_list->users[i].session_id) - 1] = '\0';
279                  if (query_user_info(atoi(row[1]), &(p_list->users[i].user_info)) <= 0)  
280                    if ((ret = query_user_info_by_uid(atoi(row[1]), &(p_list->users[i].user_info))) <= 0)
281                  {                  {
282                          log_error("query_user_info(%d) error\n", atoi(row[1]));                          log_error("query_user_info_by_uid(%d) error\n", atoi(row[1]));
283                          continue;                          continue;
284                  }                  }
285    
# Line 219  int user_online_list_load(MYSQL *db, USE Line 291  int user_online_list_load(MYSQL *db, USE
291                  p_list->users[i].current_action_title = NULL;                  p_list->users[i].current_action_title = NULL;
292                  if (p_list->users[i].current_action[0] == '\0')                  if (p_list->users[i].current_action[0] == '\0')
293                  {                  {
294                          p_list->users[i].current_action_title = "Web浏览";                          p_list->users[i].current_action_title = "";
295                  }                  }
296                  else if (trie_dict_get(p_trie_action_dict, p_list->users[i].current_action, (int64_t *)(&(p_list->users[i].current_action_title))) < 0)                  else if (trie_dict_get(p_trie_action_dict, p_list->users[i].current_action, (int64_t *)(&(p_list->users[i].current_action_title))) < 0)
297                  {                  {
# Line 241  int user_online_list_load(MYSQL *db, USE Line 313  int user_online_list_load(MYSQL *db, USE
313          mysql_free_result(rs);          mysql_free_result(rs);
314          rs = NULL;          rs = NULL;
315    
316            if (i > 0)
317            {
318                    // Rebuild index
319                    for (j = 0; j < i; j++)
320                    {
321                            p_list->index_uid[j].uid = p_list->users[j].user_info.uid;
322                            p_list->index_uid[j].id = j;
323                    }
324    
325                    qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);
326    
327    #ifdef _DEBUG
328                    log_error("Rebuild index of %d online users\n", i);
329    #endif
330            }
331    
332          p_list->user_count = i;          p_list->user_count = i;
333    
334  #ifdef _DEBUG  #ifdef _DEBUG
335          log_error("Loaded %d users\n", p_list->user_count);          log_error("Loaded %d online users\n", p_list->user_count);
336  #endif  #endif
337    
338  cleanup:  cleanup:
# Line 426  int user_list_pool_reload(int online_use Line 514  int user_list_pool_reload(int online_use
514          MYSQL *db = NULL;          MYSQL *db = NULL;
515          USER_LIST *p_tmp;          USER_LIST *p_tmp;
516          USER_ONLINE_LIST *p_online_tmp;          USER_ONLINE_LIST *p_online_tmp;
517            int ret = 0;
518    
519          if (p_user_list_pool == NULL)          if (p_user_list_pool == NULL)
520          {          {
# Line 445  int user_list_pool_reload(int online_use Line 534  int user_list_pool_reload(int online_use
534                  if (user_online_list_load(db, p_user_list_pool->p_online_new) < 0)                  if (user_online_list_load(db, p_user_list_pool->p_online_new) < 0)
535                  {                  {
536                          log_error("user_online_list_load() error\n");                          log_error("user_online_list_load() error\n");
537                          return -2;                          ret = -2;
538                            goto cleanup;
539                  }                  }
540          }          }
541          else          else
# Line 453  int user_list_pool_reload(int online_use Line 543  int user_list_pool_reload(int online_use
543                  if (user_list_load(db, p_user_list_pool->p_new) < 0)                  if (user_list_load(db, p_user_list_pool->p_new) < 0)
544                  {                  {
545                          log_error("user_list_load() error\n");                          log_error("user_list_load() error\n");
546                          return -2;                          ret = -2;
547                            goto cleanup;
548                  }                  }
549          }          }
550    
551          mysql_close(db);          mysql_close(db);
552            db = NULL;
553    
554          if (user_list_rw_lock(p_user_list_pool->semid) < 0)          if (user_list_rw_lock(p_user_list_pool->semid) < 0)
555          {          {
556                  log_error("user_list_rw_lock() error\n");                  log_error("user_list_rw_lock() error\n");
557                  return -3;                  ret = -3;
558                    goto cleanup;
559          }          }
560    
561          if (online_user)          if (online_user)
# Line 483  int user_list_pool_reload(int online_use Line 576  int user_list_pool_reload(int online_use
576          if (user_list_rw_unlock(p_user_list_pool->semid) < 0)          if (user_list_rw_unlock(p_user_list_pool->semid) < 0)
577          {          {
578                  log_error("user_list_rw_unlock() error\n");                  log_error("user_list_rw_unlock() error\n");
579                  return -3;                  ret = -3;
580                    goto cleanup;
581          }          }
582    
583          return 0;  cleanup:
584            mysql_close(db);
585    
586            return ret;
587  }  }
588    
589  int user_list_try_rd_lock(int semid, int wait_sec)  int user_list_try_rd_lock(int semid, int wait_sec)
# Line 651  int query_user_list(int page_id, USER_IN Line 748  int query_user_list(int page_id, USER_IN
748                  return -1;                  return -1;
749          }          }
750    
751            *p_user_count = 0;
752            *p_page_count = 0;
753    
754          // acquire lock of user list          // acquire lock of user list
755          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock(p_user_list_pool->semid) < 0)
756          {          {
# Line 704  int query_user_online_list(int page_id, Line 804  int query_user_online_list(int page_id,
804                  return -1;                  return -1;
805          }          }
806    
807            *p_user_count = 0;
808            *p_page_count = 0;
809    
810          // acquire lock of user list          // acquire lock of user list
811          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock(p_user_list_pool->semid) < 0)
812          {          {
# Line 747  cleanup: Line 850  cleanup:
850          return ret;          return ret;
851  }  }
852    
853  int query_user_info(int32_t uid, USER_INFO *p_user)  int query_user_info(int32_t id, USER_INFO *p_user)
854    {
855            int ret = 0;
856    
857            if (p_user == NULL)
858            {
859                    log_error("NULL pointer error\n");
860                    return -1;
861            }
862    
863            // acquire lock of user list
864            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
865            {
866                    log_error("user_list_rd_lock() error\n");
867                    return -2;
868            }
869    
870            if (id >= 0 && id < p_user_list_pool->p_current->user_count) // Found
871            {
872                    *p_user = p_user_list_pool->p_current->users[id];
873                    ret = 1;
874            }
875    
876            // release lock of user list
877            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
878            {
879                    log_error("user_list_rd_unlock() error\n");
880                    ret = -1;
881            }
882    
883            return ret;
884    }
885    
886    int query_user_info_by_uid(int32_t uid, USER_INFO *p_user)
887  {  {
888          int left;          int left;
889          int right;          int right;
890          int mid;          int mid;
891            int32_t id;
892          int ret = 0;          int ret = 0;
893    
894          if (p_user == NULL)          if (p_user == NULL)
# Line 773  int query_user_info(int32_t uid, USER_IN Line 910  int query_user_info(int32_t uid, USER_IN
910          while (left < right)          while (left < right)
911          {          {
912                  mid = (left + right) / 2;                  mid = (left + right) / 2;
913                  if (uid < p_user_list_pool->p_current->users[mid].uid)                  if (uid < p_user_list_pool->p_current->index_uid[mid].uid)
914                  {                  {
915                          right = mid;                          right = mid;
916                  }                  }
917                  else if (uid > p_user_list_pool->p_current->users[mid].uid)                  else if (uid > p_user_list_pool->p_current->index_uid[mid].uid)
918                  {                  {
919                          left = mid + 1;                          left = mid + 1;
920                  }                  }
921                  else // if (uid == p_user_list_pool->p_current->users[mid].uid)                  else // if (uid == p_user_list_pool->p_current->index_uid[mid].uid)
922                  {                  {
923                          left = mid;                          left = mid;
924                          break;                          break;
925                  }                  }
926          }          }
927    
928          if (uid == p_user_list_pool->p_current->users[left].uid) // Found          if (uid == p_user_list_pool->p_current->index_uid[left].uid) // Found
929            {
930                    id = p_user_list_pool->p_current->index_uid[left].id;
931                    *p_user = p_user_list_pool->p_current->users[id];
932                    ret = 1;
933            }
934    
935            // release lock of user list
936            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
937          {          {
938                  *p_user = p_user_list_pool->p_current->users[left];                  log_error("user_list_rd_unlock() error\n");
939                    ret = -1;
940            }
941    
942            return ret;
943    }
944    
945    int query_user_online_info(int32_t id, USER_ONLINE_INFO *p_user)
946    {
947            int ret = 0;
948    
949            if (p_user == NULL)
950            {
951                    log_error("NULL pointer error\n");
952                    return -1;
953            }
954    
955            // acquire lock of user list
956            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
957            {
958                    log_error("user_list_rd_lock() error\n");
959                    return -2;
960            }
961    
962            if (id >= 0 && id < p_user_list_pool->p_online_current->user_count) // Found
963            {
964                    *p_user = p_user_list_pool->p_online_current->users[id];
965                  ret = 1;                  ret = 1;
966          }          }
967    
968          // release lock of user list          // release lock of user list
969            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
970            {
971                    log_error("user_list_rd_unlock() error\n");
972                    ret = -1;
973            }
974    
975            return ret;
976    }
977    
978    int query_user_online_info_by_uid(int32_t uid, USER_ONLINE_INFO *p_users, int *p_user_cnt, int start_id)
979    {
980            int left;
981            int right;
982            int mid;
983            int32_t id;
984            int ret = 0;
985            int i;
986    
987            if (p_users == NULL || p_user_cnt == NULL)
988            {
989                    log_error("NULL pointer error\n");
990                    return -1;
991            }
992    
993            // acquire lock of user list
994            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
995            {
996                    log_error("user_list_rd_lock() error\n");
997                    return -2;
998            }
999    
1000            left = start_id;
1001            right = p_user_list_pool->p_online_current->user_count - 1;
1002    
1003            while (left < right)
1004            {
1005                    mid = (left + right) / 2;
1006                    if (uid < p_user_list_pool->p_online_current->index_uid[mid].uid)
1007                    {
1008                            right = mid;
1009                    }
1010                    else if (uid > p_user_list_pool->p_online_current->index_uid[mid].uid)
1011                    {
1012                            left = mid + 1;
1013                    }
1014                    else // if (uid == p_user_list_pool->p_online_current->index_uid[mid].uid)
1015                    {
1016                            left = mid;
1017                            break;
1018                    }
1019            }
1020    
1021            if (uid == p_user_list_pool->p_online_current->index_uid[left].uid)
1022            {
1023                    right = left;
1024                    left = start_id;
1025    
1026                    while (left < right)
1027                    {
1028                            mid = (left + right) / 2;
1029                            if (uid - 1 < p_user_list_pool->p_online_current->index_uid[mid].uid)
1030                            {
1031                                    right = mid;
1032                            }
1033                            else // if (uid - 1 >= p_user_list_pool->p_online_current->index_uid[mid].uid)
1034                            {
1035                                    left = mid + 1;
1036                            }
1037                    }
1038    
1039                    for (i = 0;
1040                             left < p_user_list_pool->p_online_current->user_count && i < *p_user_cnt &&
1041                             uid == p_user_list_pool->p_online_current->index_uid[left].uid;
1042                             left++, i++)
1043                    {
1044                            id = p_user_list_pool->p_online_current->index_uid[left].id;
1045                            p_users[i] = p_user_list_pool->p_online_current->users[id];
1046                    }
1047    
1048                    if (i > 0)
1049                    {
1050                            *p_user_cnt = i;
1051                            ret = 1;
1052                    }
1053            }
1054    
1055            // release lock of user list
1056          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)          if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
1057          {          {
1058                  log_error("user_list_rd_unlock() error\n");                  log_error("user_list_rd_unlock() error\n");


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

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