/[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.9 by sysadm, Wed Oct 22 07:39:02 2025 UTC Revision 1.19 by sysadm, Thu Oct 23 05:54:16 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 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)
                 {  
                         log_error("query_user_info(%d) error\n", atoi(row[1]));  
                         continue;  
                 }  
                 else if (ret == 0) // skip Guest  
283                  {                  {
284                            log_error("query_user_info_by_uid(%d) error\n", atoi(row[1]));
285                          continue;                          continue;
286                  }                  }
287    
# Line 273  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 375  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 458  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 477  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 485  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 515  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 683  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 736  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 857  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 909  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    
991            if (p_users == NULL || p_user_cnt == NULL)
992            {
993                    log_error("NULL pointer error\n");
994                    return -1;
995            }
996    
997            // acquire lock of user list
998            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
999            {
1000                    log_error("user_list_rd_lock() error\n");
1001                    return -2;
1002            }
1003    
1004            left = start_id;
1005            right = p_user_list_pool->p_online_current->user_count - 1;
1006    
1007            while (left < right)
1008            {
1009                    mid = (left + right) / 2;
1010                    if (uid < p_user_list_pool->p_online_current->index_uid[mid].uid)
1011                    {
1012                            right = mid;
1013                    }
1014                    else if (uid > p_user_list_pool->p_online_current->index_uid[mid].uid)
1015                    {
1016                            left = mid + 1;
1017                    }
1018                    else // if (uid == p_user_list_pool->p_online_current->index_uid[mid].uid)
1019                    {
1020                            left = mid;
1021                            break;
1022                    }
1023            }
1024    
1025            if (uid == p_user_list_pool->p_online_current->index_uid[left].uid)
1026            {
1027                    right = left;
1028                    left = start_id;
1029    
1030                    while (left < right)
1031                    {
1032                            mid = (left + right) / 2;
1033                            if (uid - 1 < p_user_list_pool->p_online_current->index_uid[mid].uid)
1034                            {
1035                                    right = mid;
1036                            }
1037                            else // if (uid - 1 >= p_user_list_pool->p_online_current->index_uid[mid].uid)
1038                            {
1039                                    left = mid + 1;
1040                            }
1041                    }
1042    
1043                    for (i = 0;
1044                             left < p_user_list_pool->p_online_current->user_count && i < *p_user_cnt &&
1045                             uid == p_user_list_pool->p_online_current->index_uid[left].uid;
1046                             left++, i++)
1047                    {
1048                            id = p_user_list_pool->p_online_current->index_uid[left].id;
1049                            p_users[i] = p_user_list_pool->p_online_current->users[id];
1050                    }
1051    
1052                    if (i > 0)
1053                    {
1054                            *p_user_cnt = i;
1055                            ret = 1;
1056                    }
1057            }
1058    
1059            // release lock of user list
1060            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
1061            {
1062                    log_error("user_list_rd_unlock() error\n");
1063                    ret = -1;
1064            }
1065    
1066            return ret;
1067    }
1068    
1069    int get_user_id_list(int32_t *p_uid_list, int *p_user_cnt, int start_uid)
1070    {
1071            int left;
1072            int right;
1073            int mid;
1074            int ret = 0;
1075            int i;
1076    
1077            if (p_uid_list == NULL || p_user_cnt == NULL)
1078            {
1079                    log_error("NULL pointer error\n");
1080                    return -1;
1081            }
1082    
1083            // acquire lock of user list
1084            if (user_list_rd_lock(p_user_list_pool->semid) < 0)
1085            {
1086                    log_error("user_list_rd_lock() error\n");
1087                    return -2;
1088            }
1089    
1090            left = 0;
1091            right = p_user_list_pool->p_current->user_count - 1;
1092    
1093            while (left < right)
1094            {
1095                    mid = (left + right) / 2;
1096                    if (start_uid < p_user_list_pool->p_current->index_uid[mid].uid)
1097                    {
1098                            right = mid;
1099                    }
1100                    else if (start_uid > p_user_list_pool->p_current->index_uid[mid].uid)
1101                    {
1102                            left = mid + 1;
1103                    }
1104                    else // if (start_uid == p_user_list_pool->p_current->index_uid[mid].uid)
1105                    {
1106                            left = mid;
1107                            break;
1108                    }
1109            }
1110    
1111            for (i = 0; i < *p_user_cnt && left + i < p_user_list_pool->p_current->user_count; i++)
1112            {
1113                    p_uid_list[i] = p_user_list_pool->p_current->index_uid[left + i].uid;
1114            }
1115            *p_user_cnt = i;
1116    
1117            // release lock of user list
1118            if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
1119            {
1120                    log_error("user_list_rd_unlock() error\n");
1121                    ret = -1;
1122            }
1123    
1124            return ret;
1125    }
1126    
1127    int user_stat_update(void)
1128    {
1129            return user_stat_map_update(&(p_user_list_pool->user_stat_map));
1130    }
1131    
1132    int user_article_cnt_inc(int32_t uid, int n)
1133    {
1134            return user_stat_article_cnt_inc(&(p_user_list_pool->user_stat_map), uid, n);
1135    }
1136    
1137    int get_user_article_cnt(int32_t uid)
1138    {
1139            const USER_STAT *p_stat;
1140            int ret;
1141    
1142            ret = user_stat_get(&(p_user_list_pool->user_stat_map), uid, &p_stat);
1143            if (ret < 0)
1144            {
1145                    log_error("user_stat_get(uid=%d) error: %d\n", uid, ret);
1146                    return -1;
1147            }
1148            else if (ret == 0) // user not found
1149            {
1150                    return -1;
1151            }
1152    
1153            return p_stat->article_count;
1154    }


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

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