/[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.8 by sysadm, Wed Oct 22 07:16:48 2025 UTC Revision 1.20 by sysadm, Thu Oct 23 09:54:54 2025 UTC
# Line 19  Line 19 
19  #include "log.h"  #include "log.h"
20  #include "trie_dict.h"  #include "trie_dict.h"
21  #include "user_list.h"  #include "user_list.h"
22    #include "user_stat.h"
23  #include <errno.h>  #include <errno.h>
24  #include <stdlib.h>  #include <stdlib.h>
25  #include <string.h>  #include <string.h>
# Line 53  struct user_list_pool_t Line 54  struct user_list_pool_t
54          USER_ONLINE_LIST user_online_list[2];          USER_ONLINE_LIST user_online_list[2];
55          USER_ONLINE_LIST *p_online_current;          USER_ONLINE_LIST *p_online_current;
56          USER_ONLINE_LIST *p_online_new;          USER_ONLINE_LIST *p_online_new;
57            USER_STAT_MAP user_stat_map;
58  };  };
59  typedef struct user_list_pool_t USER_LIST_POOL;  typedef struct user_list_pool_t USER_LIST_POOL;
60    
# Line 106  static int user_info_index_uid_comp(cons Line 108  static int user_info_index_uid_comp(cons
108          {          {
109                  return 1;                  return 1;
110          }          }
111            else if (p1->id < p2->id)
112            {
113                    return -1;
114            }
115            else if (p1->id > p2->id)
116            {
117                    return 1;
118            }
119          return 0;          return 0;
120  }  }
121    
# Line 116  int user_list_load(MYSQL *db, USER_LIST Line 126  int user_list_load(MYSQL *db, USER_LIST
126          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
127          int ret = 0;          int ret = 0;
128          int i;          int i;
129            int j;
130            int32_t last_uid;
131            size_t intro_buf_offset;
132            size_t intro_len;
133    
134          if (db == NULL || p_list == NULL)          if (db == NULL || p_list == NULL)
135          {          {
# Line 123  int user_list_load(MYSQL *db, USER_LIST Line 137  int user_list_load(MYSQL *db, USER_LIST
137                  return -1;                  return -1;
138          }          }
139    
140            if (p_list->user_count > 0)
141            {
142                    last_uid = p_list->users[p_list->user_count - 1].uid;
143            }
144            else
145            {
146                    last_uid = -1;
147            }
148    
149          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
150                           "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, "
151                           "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` "
152                           "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 "
153                           "INNER JOIN user_reginfo ON user_list.UID = user_reginfo.UID "                           "INNER JOIN user_reginfo ON user_list.UID = user_reginfo.UID "
154                           "WHERE enable ORDER BY username");                           "WHERE enable ORDER BY username");
# Line 144  int user_list_load(MYSQL *db, USER_LIST Line 167  int user_list_load(MYSQL *db, USER_LIST
167                  goto cleanup;                  goto cleanup;
168          }          }
169    
170            intro_buf_offset = 0;
171          i = 0;          i = 0;
172          while ((row = mysql_fetch_row(rs)))          while ((row = mysql_fetch_row(rs)))
173          {          {
# Line 158  int user_list_load(MYSQL *db, USER_LIST Line 182  int user_list_load(MYSQL *db, USER_LIST
182                  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]));
183                  p_list->users[i].life = (row[5] == NULL ? 0 : atoi(row[5]));                  p_list->users[i].life = (row[5] == NULL ? 0 : atoi(row[5]));
184                  p_list->users[i].exp = (row[6] == NULL ? 0 : atoi(row[6]));                  p_list->users[i].exp = (row[6] == NULL ? 0 : atoi(row[6]));
185                  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]));
186                  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]));
187                  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]));
188                    p_list->users[i].birthday = (row[10] == NULL ? 0 : atol(row[10]));
189                  // index                  intro_len = strlen((row[11] == NULL ? "" : row[11]));
190                  p_list->index_uid[i].uid = p_list->users[i].uid;                  if (intro_len >= sizeof(p_list->user_intro_buf) - 1 - intro_buf_offset)
191                  p_list->index_uid[i].id = i;                  {
192                            log_error("OOM for user introduction: len=%d, i=%d\n", intro_len, i);
193                            break;
194                    }
195                    memcpy(p_list->user_intro_buf + intro_buf_offset,
196                               (row[11] == NULL ? "" : row[11]),
197                               intro_len + 1);
198                    p_list->users[i].intro = p_list->user_intro_buf + intro_buf_offset;
199                    intro_buf_offset += (intro_len + 1);
200    
201                  i++;                  i++;
202                  if (i >= BBS_max_user_count)                  if (i >= BBS_max_user_count)
# Line 176  int user_list_load(MYSQL *db, USER_LIST Line 208  int user_list_load(MYSQL *db, USER_LIST
208          mysql_free_result(rs);          mysql_free_result(rs);
209          rs = NULL;          rs = NULL;
210    
211          p_list->user_count = i;          if (i != p_list->user_count || p_list->users[i - 1].uid != last_uid) // Count of users changed
212            {
213                    // Rebuild index
214                    for (j = 0; j < i; j++)
215                    {
216                            p_list->index_uid[j].uid = p_list->users[j].uid;
217                            p_list->index_uid[j].id = j;
218                    }
219    
220                    qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);
221    
222    #ifdef _DEBUG
223                    log_error("Rebuild index of %d users, last_uid=%d\n", i, p_list->users[i - 1].uid);
224    #endif
225            }
226    
227          // Sort index          p_list->user_count = i;
         qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);  
228    
229  #ifdef _DEBUG  #ifdef _DEBUG
230          log_error("Loaded %d users\n", p_list->user_count);          log_error("Loaded %d users\n", p_list->user_count);
# Line 198  int user_online_list_load(MYSQL *db, USE Line 243  int user_online_list_load(MYSQL *db, USE
243          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
244          int ret = 0;          int ret = 0;
245          int i;          int i;
246            int j;
247    
248          if (db == NULL || p_list == NULL)          if (db == NULL || p_list == NULL)
249          {          {
# Line 208  int user_online_list_load(MYSQL *db, USE Line 254  int user_online_list_load(MYSQL *db, USE
254          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
255                           "SELECT SID, UID, ip, current_action, UNIX_TIMESTAMP(login_tm), "                           "SELECT SID, UID, ip, current_action, UNIX_TIMESTAMP(login_tm), "
256                           "UNIX_TIMESTAMP(last_tm) FROM user_online "                           "UNIX_TIMESTAMP(last_tm) FROM user_online "
257                           "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND) "                           "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND) AND UID <> 0 "
258                           "ORDER BY last_tm DESC",                           "ORDER BY last_tm DESC",
259                           BBS_user_off_line);                           BBS_user_off_line);
260    
# Line 233  int user_online_list_load(MYSQL *db, USE Line 279  int user_online_list_load(MYSQL *db, USE
279                  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);
280                  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';
281    
282                  if ((ret = query_user_info_by_uid(atoi(row[1]), &(p_list->users[i].user_info))) < 0)                  if ((ret = query_user_info_by_uid(atoi(row[1]), &(p_list->users[i].user_info))) <= 0)
283                  {                  {
284                          log_error("query_user_info(%d) error\n", atoi(row[1]));                          log_error("query_user_info_by_uid(%d) error\n", atoi(row[1]));
285                          continue;                          continue;
286                  }                  }
                 else if (ret == 0) // Guest  
                 {  
                         p_list->users[i].user_info.id = -1;  
                         p_list->users[i].user_info.uid = 0;  
                         strncpy(p_list->users[i].user_info.username, "guest", sizeof(p_list->users[i].user_info.username) - 1);  
                         p_list->users[i].user_info.username[sizeof(p_list->users[i].user_info.username) - 1] = '\0';  
                         strncpy(p_list->users[i].user_info.nickname, "Guest", sizeof(p_list->users[i].user_info.nickname) - 1);  
                         p_list->users[i].user_info.nickname[sizeof(p_list->users[i].user_info.nickname) - 1] = '\0';  
                         p_list->users[i].user_info.gender = 'M';  
                         p_list->users[i].user_info.gender_pub = 0;  
                         p_list->users[i].user_info.life = 150;  
                         p_list->users[i].user_info.exp = 0;  
                         p_list->users[i].user_info.signup_dt = 0;  
                         p_list->users[i].user_info.last_login_dt = 0;  
                         p_list->users[i].user_info.birthday = 0;  
                 }  
287    
288                  strncpy(p_list->users[i].ip, row[2], sizeof(p_list->users[i].ip) - 1);                  strncpy(p_list->users[i].ip, row[2], sizeof(p_list->users[i].ip) - 1);
289                  p_list->users[i].ip[sizeof(p_list->users[i].ip) - 1] = '\0';                  p_list->users[i].ip[sizeof(p_list->users[i].ip) - 1] = '\0';
# Line 285  int user_online_list_load(MYSQL *db, USE Line 315  int user_online_list_load(MYSQL *db, USE
315          mysql_free_result(rs);          mysql_free_result(rs);
316          rs = NULL;          rs = NULL;
317    
318            if (i > 0)
319            {
320                    // Rebuild index
321                    for (j = 0; j < i; j++)
322                    {
323                            p_list->index_uid[j].uid = p_list->users[j].user_info.uid;
324                            p_list->index_uid[j].id = j;
325                    }
326    
327                    qsort(p_list->index_uid, (size_t)i, sizeof(USER_INFO_INDEX_UID), user_info_index_uid_comp);
328    
329    #ifdef _DEBUG
330                    log_error("Rebuild index of %d online users\n", i);
331    #endif
332            }
333    
334          p_list->user_count = i;          p_list->user_count = i;
335    
336  #ifdef _DEBUG  #ifdef _DEBUG
337          log_error("Loaded %d users\n", p_list->user_count);          log_error("Loaded %d online users\n", p_list->user_count);
338  #endif  #endif
339    
340  cleanup:  cleanup:
# Line 387  int user_list_pool_init(void) Line 433  int user_list_pool_init(void)
433          p_user_list_pool->p_online_current = &(p_user_list_pool->user_online_list[0]);          p_user_list_pool->p_online_current = &(p_user_list_pool->user_online_list[0]);
434          p_user_list_pool->p_online_new = &(p_user_list_pool->user_online_list[1]);          p_user_list_pool->p_online_new = &(p_user_list_pool->user_online_list[1]);
435    
436            user_stat_map_init(&(p_user_list_pool->user_stat_map));
437    
438          return 0;          return 0;
439  }  }
440    
# Line 470  int user_list_pool_reload(int online_use Line 518  int user_list_pool_reload(int online_use
518          MYSQL *db = NULL;          MYSQL *db = NULL;
519          USER_LIST *p_tmp;          USER_LIST *p_tmp;
520          USER_ONLINE_LIST *p_online_tmp;          USER_ONLINE_LIST *p_online_tmp;
521            int ret = 0;
522    
523          if (p_user_list_pool == NULL)          if (p_user_list_pool == NULL)
524          {          {
# Line 489  int user_list_pool_reload(int online_use Line 538  int user_list_pool_reload(int online_use
538                  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)
539                  {                  {
540                          log_error("user_online_list_load() error\n");                          log_error("user_online_list_load() error\n");
541                          return -2;                          ret = -2;
542                            goto cleanup;
543                  }                  }
544          }          }
545          else          else
# Line 497  int user_list_pool_reload(int online_use Line 547  int user_list_pool_reload(int online_use
547                  if (user_list_load(db, p_user_list_pool->p_new) < 0)                  if (user_list_load(db, p_user_list_pool->p_new) < 0)
548                  {                  {
549                          log_error("user_list_load() error\n");                          log_error("user_list_load() error\n");
550                          return -2;                          ret = -2;
551                            goto cleanup;
552                  }                  }
553          }          }
554    
555          mysql_close(db);          mysql_close(db);
556            db = NULL;
557    
558          if (user_list_rw_lock(p_user_list_pool->semid) < 0)          if (user_list_rw_lock(p_user_list_pool->semid) < 0)
559          {          {
560                  log_error("user_list_rw_lock() error\n");                  log_error("user_list_rw_lock() error\n");
561                  return -3;                  ret = -3;
562                    goto cleanup;
563          }          }
564    
565          if (online_user)          if (online_user)
# Line 527  int user_list_pool_reload(int online_use Line 580  int user_list_pool_reload(int online_use
580          if (user_list_rw_unlock(p_user_list_pool->semid) < 0)          if (user_list_rw_unlock(p_user_list_pool->semid) < 0)
581          {          {
582                  log_error("user_list_rw_unlock() error\n");                  log_error("user_list_rw_unlock() error\n");
583                  return -3;                  ret = -3;
584                    goto cleanup;
585          }          }
586    
587          return 0;  cleanup:
588            mysql_close(db);
589    
590            return ret;
591  }  }
592    
593  int user_list_try_rd_lock(int semid, int wait_sec)  int user_list_try_rd_lock(int semid, int wait_sec)
# Line 695  int query_user_list(int page_id, USER_IN Line 752  int query_user_list(int page_id, USER_IN
752                  return -1;                  return -1;
753          }          }
754    
755            *p_user_count = 0;
756            *p_page_count = 0;
757    
758          // acquire lock of user list          // acquire lock of user list
759          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock(p_user_list_pool->semid) < 0)
760          {          {
# Line 748  int query_user_online_list(int page_id, Line 808  int query_user_online_list(int page_id,
808                  return -1;                  return -1;
809          }          }
810    
811            *p_user_count = 0;
812            *p_page_count = 0;
813    
814          // acquire lock of user list          // acquire lock of user list
815          if (user_list_rd_lock(p_user_list_pool->semid) < 0)          if (user_list_rd_lock(p_user_list_pool->semid) < 0)
816          {          {
# Line 869  int query_user_info_by_uid(int32_t uid, Line 932  int query_user_info_by_uid(int32_t uid,
932          if (uid == p_user_list_pool->p_current->index_uid[left].uid) // Found          if (uid == p_user_list_pool->p_current->index_uid[left].uid) // Found
933          {          {
934                  id = p_user_list_pool->p_current->index_uid[left].id;                  id = p_user_list_pool->p_current->index_uid[left].id;
935                  if ((ret = query_user_info(id, p_user)) <= 0)                  *p_user = p_user_list_pool->p_current->users[id];
936                  {                  ret = 1;
                         log_error("query_user_info(id=%d) error: %d\n", id, ret);  
                 }  
                 else  
                 {  
                         ret = 1;  
                 }  
937          }          }
938    
939          // release lock of user list          // release lock of user list
# Line 921  int query_user_online_info(int32_t id, U Line 978  int query_user_online_info(int32_t id, U
978    
979          return ret;          return ret;
980  }  }
981    
982    int query_user_online_info_by_uid(int32_t uid, USER_ONLINE_INFO *p_users, int *p_user_cnt, int start_id)
983    {
984            int left;
985            int right;
986            int mid;
987            int32_t id;
988            int ret = 0;
989            int i;
990            int user_cnt;
991    
992            if (p_users == NULL || p_user_cnt == NULL)
993            {
994                    log_error("NULL pointer error\n");
995                    return -1;
996            }
997    
998            user_cnt = *p_user_cnt;
999            *p_user_cnt = 0;
1000    
1001            // acquire lock of user list
1002            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
1003            {
1004                    log_error("user_list_rd_lock() error\n");
1005                    return -2;
1006            }
1007    
1008            left = start_id;
1009            right = p_user_list_pool->p_online_current->user_count - 1;
1010    
1011            while (left < right)
1012            {
1013                    mid = (left + right) / 2;
1014                    if (uid < p_user_list_pool->p_online_current->index_uid[mid].uid)
1015                    {
1016                            right = mid;
1017                    }
1018                    else if (uid > p_user_list_pool->p_online_current->index_uid[mid].uid)
1019                    {
1020                            left = mid + 1;
1021                    }
1022                    else // if (uid == p_user_list_pool->p_online_current->index_uid[mid].uid)
1023                    {
1024                            left = mid;
1025                            break;
1026                    }
1027            }
1028    
1029            if (uid == p_user_list_pool->p_online_current->index_uid[left].uid)
1030            {
1031                    right = left;
1032                    left = start_id;
1033    
1034                    while (left < right)
1035                    {
1036                            mid = (left + right) / 2;
1037                            if (uid - 1 < p_user_list_pool->p_online_current->index_uid[mid].uid)
1038                            {
1039                                    right = mid;
1040                            }
1041                            else // if (uid - 1 >= p_user_list_pool->p_online_current->index_uid[mid].uid)
1042                            {
1043                                    left = mid + 1;
1044                            }
1045                    }
1046    
1047                    for (i = 0;
1048                             left < p_user_list_pool->p_online_current->user_count && i < user_cnt &&
1049                             uid == p_user_list_pool->p_online_current->index_uid[left].uid;
1050                             left++, i++)
1051                    {
1052                            id = p_user_list_pool->p_online_current->index_uid[left].id;
1053                            p_users[i] = p_user_list_pool->p_online_current->users[id];
1054                    }
1055    
1056                    if (i > 0)
1057                    {
1058                            *p_user_cnt = i;
1059                            ret = 1;
1060                    }
1061            }
1062    
1063            // release lock of user list
1064            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
1065            {
1066                    log_error("user_list_rd_unlock() error\n");
1067                    ret = -1;
1068            }
1069    
1070            return ret;
1071    }
1072    
1073    int get_user_id_list(int32_t *p_uid_list, int *p_user_cnt, int start_uid)
1074    {
1075            int left;
1076            int right;
1077            int mid;
1078            int ret = 0;
1079            int i;
1080    
1081            if (p_uid_list == NULL || p_user_cnt == NULL)
1082            {
1083                    log_error("NULL pointer error\n");
1084                    return -1;
1085            }
1086    
1087            // acquire lock of user list
1088            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
1089            {
1090                    log_error("user_list_rd_lock() error\n");
1091                    return -2;
1092            }
1093    
1094            left = 0;
1095            right = p_user_list_pool->p_current->user_count - 1;
1096    
1097            while (left < right)
1098            {
1099                    mid = (left + right) / 2;
1100                    if (start_uid < p_user_list_pool->p_current->index_uid[mid].uid)
1101                    {
1102                            right = mid;
1103                    }
1104                    else if (start_uid > p_user_list_pool->p_current->index_uid[mid].uid)
1105                    {
1106                            left = mid + 1;
1107                    }
1108                    else // if (start_uid == p_user_list_pool->p_current->index_uid[mid].uid)
1109                    {
1110                            left = mid;
1111                            break;
1112                    }
1113            }
1114    
1115            for (i = 0; i < *p_user_cnt && left + i < p_user_list_pool->p_current->user_count; i++)
1116            {
1117                    p_uid_list[i] = p_user_list_pool->p_current->index_uid[left + i].uid;
1118            }
1119            *p_user_cnt = i;
1120    
1121            // release lock of user list
1122            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
1123            {
1124                    log_error("user_list_rd_unlock() error\n");
1125                    ret = -1;
1126            }
1127    
1128            return ret;
1129    }
1130    
1131    int user_stat_update(void)
1132    {
1133            return user_stat_map_update(&(p_user_list_pool->user_stat_map));
1134    }
1135    
1136    int user_article_cnt_inc(int32_t uid, int n)
1137    {
1138            return user_stat_article_cnt_inc(&(p_user_list_pool->user_stat_map), uid, n);
1139    }
1140    
1141    int get_user_article_cnt(int32_t uid)
1142    {
1143            const USER_STAT *p_stat;
1144            int ret;
1145    
1146            ret = user_stat_get(&(p_user_list_pool->user_stat_map), uid, &p_stat);
1147            if (ret < 0)
1148            {
1149                    log_error("user_stat_get(uid=%d) error: %d\n", uid, ret);
1150                    return -1;
1151            }
1152            else if (ret == 0) // user not found
1153            {
1154                    return -1;
1155            }
1156    
1157            return p_stat->article_count;
1158    }


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

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