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

Contents of /lbbs/src/user_list.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations)
Wed Oct 22 04:48:53 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.5: +675 -456 lines
Content type: text/x-csrc
Add user_online_list

1 /***************************************************************************
2 user_list.c - description
3 -------------------
4 Copyright : (C) 2004-2025 by Leaflet
5 Email : leaflet@leafok.com
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "common.h"
18 #include "database.h"
19 #include "log.h"
20 #include "trie_dict.h"
21 #include "user_list.h"
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <sys/ipc.h>
27 #include <sys/mman.h>
28 #include <sys/param.h>
29 #include <sys/sem.h>
30 #include <sys/shm.h>
31
32 #ifdef _SEM_SEMUN_UNDEFINED
33 union semun
34 {
35 int val; /* Value for SETVAL */
36 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
37 unsigned short *array; /* Array for GETALL, SETALL */
38 struct seminfo *__buf; /* Buffer for IPC_INFO
39 (Linux-specific) */
40 };
41 #endif // #ifdef _SEM_SEMUN_UNDEFINED
42
43 #define USER_LIST_TRY_LOCK_WAIT_TIME 1 // second
44 #define USER_LIST_TRY_LOCK_TIMES 10
45
46 struct user_list_pool_t
47 {
48 int shmid;
49 int semid;
50 USER_LIST user_list[2];
51 USER_LIST *p_current;
52 USER_LIST *p_new;
53 USER_ONLINE_LIST user_online_list[2];
54 USER_ONLINE_LIST *p_online_current;
55 USER_ONLINE_LIST *p_online_new;
56 };
57 typedef struct user_list_pool_t USER_LIST_POOL;
58
59 static USER_LIST_POOL *p_user_list_pool = NULL;
60 static TRIE_NODE *p_trie_action_dict = NULL;
61
62 typedef struct user_action_map_t
63 {
64 char name[BBS_current_action_max_len + 1];
65 char title[BBS_current_action_max_len + 1];
66 } USER_ACTION_MAP;
67
68 const USER_ACTION_MAP user_action_map[] =
69 {
70 {"ARTICLE_FAVOR", "浏览收藏"},
71 {"BBS_NET", "站点穿梭"},
72 {"CHICKEN", "电子小鸡"},
73 {"EDIT_ARTICLE", "修改文章"},
74 {"MENU", "菜单选择"},
75 {"POST_ARTICLE", "撰写文章"},
76 {"REPLY_ARTICLE", "回复文章"},
77 {"USER_LIST", "查花名册"},
78 {"USER_ONLINE", "环顾四周"},
79 {"VIEW_ARTICLE", "阅读文章"},
80 {"VIEW_FILE", "查看文档"}};
81
82 const int user_action_map_size = 11;
83
84 static int user_list_try_rd_lock(int semid, int wait_sec);
85 static int user_list_try_rw_lock(int semid, int wait_sec);
86 static int user_list_rd_unlock(int semid);
87 static int user_list_rw_unlock(int semid);
88 static int user_list_rd_lock(int semid);
89 static int user_list_rw_lock(int semid);
90
91 static int user_list_load(MYSQL *db, USER_LIST *p_list);
92 static int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_list);
93
94 int user_list_load(MYSQL *db, USER_LIST *p_list)
95 {
96 MYSQL_RES *rs = NULL;
97 MYSQL_ROW row;
98 char sql[SQL_BUFFER_LEN];
99 int ret = 0;
100 int i;
101
102 if (db == NULL || p_list == NULL)
103 {
104 log_error("NULL pointer error\n");
105 return -1;
106 }
107
108 snprintf(sql, sizeof(sql),
109 "SELECT user_list.UID AS UID, username, nickname, gender, gender_pub, life, exp, "
110 "UNIX_TIMESTAMP(signup_dt), UNIX_TIMESTAMP(last_login_dt), UNIX_TIMESTAMP(birthday) "
111 "FROM user_list INNER JOIN user_pubinfo ON user_list.UID = user_pubinfo.UID "
112 "INNER JOIN user_reginfo ON user_list.UID = user_reginfo.UID "
113 "WHERE enable ORDER BY UID");
114
115 if (mysql_query(db, sql) != 0)
116 {
117 log_error("Query user info error: %s\n", mysql_error(db));
118 ret = -1;
119 goto cleanup;
120 }
121
122 if ((rs = mysql_use_result(db)) == NULL)
123 {
124 log_error("Get user info data failed\n");
125 ret = -1;
126 goto cleanup;
127 }
128
129 i = 0;
130 while ((row = mysql_fetch_row(rs)))
131 {
132 p_list->users[i].uid = atoi(row[0]);
133 strncpy(p_list->users[i].username, row[1], sizeof(p_list->users[i].username) - 1);
134 p_list->users[i].username[sizeof(p_list->users[i].username) - 1] = '\0';
135 strncpy(p_list->users[i].nickname, row[2], sizeof(p_list->users[i].nickname) - 1);
136 p_list->users[i].nickname[sizeof(p_list->users[i].nickname) - 1] = '\0';
137 p_list->users[i].gender = row[3][0];
138 p_list->users[i].gender_pub = (int8_t)(row[4] == NULL ? 0 : atoi(row[4]));
139 p_list->users[i].life = (row[5] == NULL ? 0 : atoi(row[5]));
140 p_list->users[i].exp = (row[6] == NULL ? 0 : atoi(row[6]));
141 p_list->users[i].signup_dt = (row[7] == NULL ? 0 : atol(row[7]));
142 p_list->users[i].last_login_dt = (row[8] == NULL ? 0 : atol(row[8]));
143 p_list->users[i].birthday = (row[9] == NULL ? 0 : atol(row[9]));
144
145 i++;
146 if (i >= BBS_max_user_count)
147 {
148 log_error("Too many users, exceed limit %d\n", BBS_max_user_count);
149 break;
150 }
151 }
152 mysql_free_result(rs);
153 rs = NULL;
154
155 p_list->user_count = i;
156
157 #ifdef _DEBUG
158 log_error("Loaded %d users\n", p_list->user_count);
159 #endif
160
161 cleanup:
162 mysql_free_result(rs);
163
164 return ret;
165 }
166
167 int user_online_list_load(MYSQL *db, USER_ONLINE_LIST *p_list)
168 {
169 MYSQL_RES *rs = NULL;
170 MYSQL_ROW row;
171 char sql[SQL_BUFFER_LEN];
172 int ret = 0;
173 int i;
174
175 if (db == NULL || p_list == NULL)
176 {
177 log_error("NULL pointer error\n");
178 return -1;
179 }
180
181 snprintf(sql, sizeof(sql),
182 "SELECT SID, UID, ip, current_action, UNIX_TIMESTAMP(login_tm), "
183 "UNIX_TIMESTAMP(last_tm) FROM user_online "
184 "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND) "
185 "ORDER BY last_tm DESC",
186 BBS_user_off_line);
187
188 if (mysql_query(db, sql) != 0)
189 {
190 log_error("Query user online error: %s\n", mysql_error(db));
191 ret = -1;
192 goto cleanup;
193 }
194
195 if ((rs = mysql_use_result(db)) == NULL)
196 {
197 log_error("Get user online data failed\n");
198 ret = -1;
199 goto cleanup;
200 }
201
202 i = 0;
203 while ((row = mysql_fetch_row(rs)))
204 {
205 strncpy(p_list->users[i].session_id, row[0], sizeof(p_list->users[i].session_id) - 1);
206
207 p_list->users[i].session_id[sizeof(p_list->users[i].session_id) - 1] = '\0';
208 if (query_user_info(atoi(row[1]), &(p_list->users[i].user_info)) <= 0)
209 {
210 log_error("query_user_info(%d) error\n", atoi(row[1]));
211 continue;
212 }
213
214 strncpy(p_list->users[i].ip, row[2], sizeof(p_list->users[i].ip) - 1);
215 p_list->users[i].ip[sizeof(p_list->users[i].ip) - 1] = '\0';
216
217 strncpy(p_list->users[i].current_action, row[3], sizeof(p_list->users[i].current_action) - 1);
218 p_list->users[i].current_action[sizeof(p_list->users[i].current_action) - 1] = '\0';
219 p_list->users[i].current_action_title = NULL;
220 if (p_list->users[i].current_action[0] == '\0')
221 {
222 p_list->users[i].current_action_title = "Web浏览";
223 }
224 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)
225 {
226 log_error("trie_dict_get(p_trie_action_dict, %s) error on session_id=%s\n",
227 p_list->users[i].current_action, p_list->users[i].session_id);
228 continue;
229 }
230
231 p_list->users[i].login_tm = (row[4] == NULL ? 0 : atol(row[4]));
232 p_list->users[i].last_tm = (row[5] == NULL ? 0 : atol(row[5]));
233
234 i++;
235 if (i >= BBS_max_user_online_count)
236 {
237 log_error("Too many online users, exceed limit %d\n", BBS_max_user_online_count);
238 break;
239 }
240 }
241 mysql_free_result(rs);
242 rs = NULL;
243
244 p_list->user_count = i;
245
246 #ifdef _DEBUG
247 log_error("Loaded %d users\n", p_list->user_count);
248 #endif
249
250 cleanup:
251 mysql_free_result(rs);
252
253 return ret;
254 }
255
256 int user_list_pool_init(void)
257 {
258 int shmid;
259 int semid;
260 int proj_id;
261 key_t key;
262 size_t size;
263 void *p_shm;
264 union semun arg;
265 int i;
266
267 if (p_user_list_pool != NULL || p_trie_action_dict != NULL)
268 {
269 log_error("p_user_list_pool already initialized\n");
270 return -1;
271 }
272
273 p_trie_action_dict = trie_dict_create();
274 if (p_trie_action_dict == NULL)
275 {
276 log_error("trie_dict_create() error\n");
277 return -1;
278 }
279
280 for (i = 0; i < user_action_map_size; i++)
281 {
282 if (trie_dict_set(p_trie_action_dict, user_action_map[i].name, (int64_t)(user_action_map[i].title)) < 0)
283 {
284 log_error("trie_dict_set(p_trie_action_dict, %s) error\n", user_action_map[i].name);
285 }
286 }
287
288 // Allocate shared memory
289 proj_id = (int)(time(NULL) % getpid());
290 key = ftok(VAR_USER_LIST_SHM, proj_id);
291 if (key == -1)
292 {
293 log_error("ftok(%s %d) error (%d)\n", VAR_USER_LIST_SHM, proj_id, errno);
294 return -2;
295 }
296
297 size = sizeof(USER_LIST_POOL);
298 shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
299 if (shmid == -1)
300 {
301 log_error("shmget(size = %d) error (%d)\n", size, errno);
302 return -3;
303 }
304 p_shm = shmat(shmid, NULL, 0);
305 if (p_shm == (void *)-1)
306 {
307 log_error("shmat(shmid=%d) error (%d)\n", shmid, errno);
308 return -3;
309 }
310
311 p_user_list_pool = p_shm;
312 p_user_list_pool->shmid = shmid;
313
314 // Allocate semaphore as user list pool lock
315 size = 2; // r_sem and w_sem
316 semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600);
317 if (semid == -1)
318 {
319 log_error("semget(user_list_pool_sem, size = %d) error (%d)\n", size, errno);
320 return -3;
321 }
322
323 // Initialize sem value to 0
324 arg.val = 0;
325 for (i = 0; i < size; i++)
326 {
327 if (semctl(semid, i, SETVAL, arg) == -1)
328 {
329 log_error("semctl(user_list_pool_sem, SETVAL) error (%d)\n", errno);
330 return -3;
331 }
332 }
333
334 p_user_list_pool->semid = semid;
335
336 // Set user counts to 0
337 p_user_list_pool->user_list[0].user_count = 0;
338 p_user_list_pool->user_list[1].user_count = 0;
339
340 p_user_list_pool->p_current = &(p_user_list_pool->user_list[0]);
341 p_user_list_pool->p_new = &(p_user_list_pool->user_list[1]);
342
343 p_user_list_pool->p_online_current = &(p_user_list_pool->user_online_list[0]);
344 p_user_list_pool->p_online_new = &(p_user_list_pool->user_online_list[1]);
345
346 return 0;
347 }
348
349 void user_list_pool_cleanup(void)
350 {
351 int shmid;
352
353 if (p_user_list_pool == NULL)
354 {
355 return;
356 }
357
358 shmid = p_user_list_pool->shmid;
359
360 if (semctl(p_user_list_pool->semid, 0, IPC_RMID) == -1)
361 {
362 log_error("semctl(semid = %d, IPC_RMID) error (%d)\n", p_user_list_pool->semid, errno);
363 }
364
365 if (shmdt(p_user_list_pool) == -1)
366 {
367 log_error("shmdt(shmid = %d) error (%d)\n", shmid, errno);
368 }
369
370 if (shmctl(shmid, IPC_RMID, NULL) == -1)
371 {
372 log_error("shmctl(shmid = %d, IPC_RMID) error (%d)\n", shmid, errno);
373 }
374
375 p_user_list_pool = NULL;
376
377 if (p_trie_action_dict != NULL)
378 {
379 trie_dict_destroy(p_trie_action_dict);
380
381 p_trie_action_dict = NULL;
382 }
383 }
384
385 int set_user_list_pool_shm_readonly(void)
386 {
387 int shmid;
388 void *p_shm;
389
390 if (p_user_list_pool == NULL)
391 {
392 log_error("p_user_list_pool not initialized\n");
393 return -1;
394 }
395
396 shmid = p_user_list_pool->shmid;
397
398 // Remap shared memory in read-only mode
399 p_shm = shmat(shmid, p_user_list_pool, SHM_RDONLY | SHM_REMAP);
400 if (p_shm == (void *)-1)
401 {
402 log_error("shmat(user_list_pool shmid = %d) error (%d)\n", shmid, errno);
403 return -3;
404 }
405
406 p_user_list_pool = p_shm;
407
408 return 0;
409 }
410
411 int detach_user_list_pool_shm(void)
412 {
413 if (p_user_list_pool != NULL && shmdt(p_user_list_pool) == -1)
414 {
415 log_error("shmdt(user_list_pool) error (%d)\n", errno);
416 return -1;
417 }
418
419 p_user_list_pool = NULL;
420
421 return 0;
422 }
423
424 int user_list_pool_reload(int online_user)
425 {
426 MYSQL *db = NULL;
427 USER_LIST *p_tmp;
428 USER_ONLINE_LIST *p_online_tmp;
429
430 if (p_user_list_pool == NULL)
431 {
432 log_error("p_user_list_pool not initialized\n");
433 return -1;
434 }
435
436 db = db_open();
437 if (db == NULL)
438 {
439 log_error("db_open() error: %s\n", mysql_error(db));
440 return -1;
441 }
442
443 if (online_user)
444 {
445 if (user_online_list_load(db, p_user_list_pool->p_online_new) < 0)
446 {
447 log_error("user_online_list_load() error\n");
448 return -2;
449 }
450 }
451 else
452 {
453 if (user_list_load(db, p_user_list_pool->p_new) < 0)
454 {
455 log_error("user_list_load() error\n");
456 return -2;
457 }
458 }
459
460 mysql_close(db);
461
462 if (user_list_rw_lock(p_user_list_pool->semid) < 0)
463 {
464 log_error("user_list_rw_lock() error\n");
465 return -3;
466 }
467
468 if (online_user)
469 {
470 // Swap p_online_current and p_online_new
471 p_online_tmp = p_user_list_pool->p_online_current;
472 p_user_list_pool->p_online_current = p_user_list_pool->p_online_new;
473 p_user_list_pool->p_online_new = p_online_tmp;
474 }
475 else
476 {
477 // Swap p_current and p_new
478 p_tmp = p_user_list_pool->p_current;
479 p_user_list_pool->p_current = p_user_list_pool->p_new;
480 p_user_list_pool->p_new = p_tmp;
481 }
482
483 if (user_list_rw_unlock(p_user_list_pool->semid) < 0)
484 {
485 log_error("user_list_rw_unlock() error\n");
486 return -3;
487 }
488
489 return 0;
490 }
491
492 int user_list_try_rd_lock(int semid, int wait_sec)
493 {
494 struct sembuf sops[2];
495 struct timespec timeout;
496 int ret;
497
498 sops[0].sem_num = 1; // w_sem
499 sops[0].sem_op = 0; // wait until unlocked
500 sops[0].sem_flg = 0;
501
502 sops[1].sem_num = 0; // r_sem
503 sops[1].sem_op = 1; // lock
504 sops[1].sem_flg = SEM_UNDO; // undo on terminate
505
506 timeout.tv_sec = wait_sec;
507 timeout.tv_nsec = 0;
508
509 ret = semtimedop(semid, sops, 2, &timeout);
510 if (ret == -1 && errno != EAGAIN && errno != EINTR)
511 {
512 log_error("semtimedop(lock read) error %d\n", errno);
513 }
514
515 return ret;
516 }
517
518 int user_list_try_rw_lock(int semid, int wait_sec)
519 {
520 struct sembuf sops[3];
521 struct timespec timeout;
522 int ret;
523
524 sops[0].sem_num = 1; // w_sem
525 sops[0].sem_op = 0; // wait until unlocked
526 sops[0].sem_flg = 0;
527
528 sops[1].sem_num = 1; // w_sem
529 sops[1].sem_op = 1; // lock
530 sops[1].sem_flg = SEM_UNDO; // undo on terminate
531
532 sops[2].sem_num = 0; // r_sem
533 sops[2].sem_op = 0; // wait until unlocked
534 sops[2].sem_flg = 0;
535
536 timeout.tv_sec = wait_sec;
537 timeout.tv_nsec = 0;
538
539 ret = semtimedop(semid, sops, 3, &timeout);
540 if (ret == -1 && errno != EAGAIN && errno != EINTR)
541 {
542 log_error("semtimedop(lock write) error %d\n", errno);
543 }
544
545 return ret;
546 }
547
548 int user_list_rd_unlock(int semid)
549 {
550 struct sembuf sops[2];
551 int ret;
552
553 sops[0].sem_num = 0; // r_sem
554 sops[0].sem_op = -1; // unlock
555 sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait
556
557 ret = semop(semid, sops, 1);
558 if (ret == -1 && errno != EAGAIN && errno != EINTR)
559 {
560 log_error("semop(unlock read) error %d\n", errno);
561 }
562
563 return ret;
564 }
565
566 int user_list_rw_unlock(int semid)
567 {
568 struct sembuf sops[1];
569 int ret;
570
571 sops[0].sem_num = 1; // w_sem
572 sops[0].sem_op = -1; // unlock
573 sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait
574
575 ret = semop(semid, sops, 1);
576 if (ret == -1 && errno != EAGAIN && errno != EINTR)
577 {
578 log_error("semop(unlock write) error %d\n", errno);
579 }
580
581 return ret;
582 }
583
584 int user_list_rd_lock(int semid)
585 {
586 int timer = 0;
587 int ret = -1;
588
589 while (!SYS_server_exit)
590 {
591 ret = user_list_try_rd_lock(semid, USER_LIST_TRY_LOCK_WAIT_TIME);
592 if (ret == 0) // success
593 {
594 break;
595 }
596 else if (errno == EAGAIN || errno == EINTR) // retry
597 {
598 timer++;
599 if (timer % USER_LIST_TRY_LOCK_TIMES == 0)
600 {
601 log_error("user_list_try_rd_lock() tried %d times\n", timer);
602 }
603 }
604 else // failed
605 {
606 log_error("user_list_try_rd_lock() failed\n");
607 break;
608 }
609 }
610
611 return ret;
612 }
613
614 int user_list_rw_lock(int semid)
615 {
616 int timer = 0;
617 int ret = -1;
618
619 while (!SYS_server_exit)
620 {
621 ret = user_list_try_rw_lock(semid, USER_LIST_TRY_LOCK_WAIT_TIME);
622 if (ret == 0) // success
623 {
624 break;
625 }
626 else if (errno == EAGAIN || errno == EINTR) // retry
627 {
628 timer++;
629 if (timer % USER_LIST_TRY_LOCK_TIMES == 0)
630 {
631 log_error("user_list_try_rw_lock() tried %d times\n", timer);
632 }
633 }
634 else // failed
635 {
636 log_error("user_list_try_rw_lock() failed\n");
637 break;
638 }
639 }
640
641 return ret;
642 }
643
644 int query_user_list(int page_id, USER_INFO *p_users, int *p_user_count, int *p_page_count)
645 {
646 int ret = 0;
647
648 if (p_users == NULL || p_user_count == NULL || p_page_count == NULL)
649 {
650 log_error("NULL pointer error\n");
651 return -1;
652 }
653
654 // acquire lock of user list
655 if (user_list_rd_lock(p_user_list_pool->semid) < 0)
656 {
657 log_error("user_list_rd_lock() error\n");
658 return -2;
659 }
660
661 if (p_user_list_pool->p_current->user_count == 0)
662 {
663 // empty list
664 ret = 0;
665 goto cleanup;
666 }
667
668 *p_page_count = p_user_list_pool->p_current->user_count / BBS_user_limit_per_page +
669 (p_user_list_pool->p_current->user_count % BBS_user_limit_per_page == 0 ? 0 : 1);
670
671 if (page_id < 0 || page_id >= *p_page_count)
672 {
673 log_error("Invalid page_id = %d, not in range [0, %d)\n", page_id, *p_page_count);
674 ret = -3;
675 goto cleanup;
676 }
677
678 *p_user_count = MIN(BBS_user_limit_per_page,
679 p_user_list_pool->p_current->user_count -
680 page_id * BBS_user_limit_per_page);
681
682 memcpy(p_users,
683 p_user_list_pool->p_current->users + page_id * BBS_user_limit_per_page,
684 sizeof(USER_INFO) * (size_t)(*p_user_count));
685
686 cleanup:
687 // release lock of user list
688 if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
689 {
690 log_error("user_list_rd_unlock() error\n");
691 ret = -1;
692 }
693
694 return ret;
695 }
696
697 int query_user_online_list(int page_id, USER_ONLINE_INFO *p_online_users, int *p_user_count, int *p_page_count)
698 {
699 int ret = 0;
700
701 if (p_online_users == NULL || p_user_count == NULL || p_page_count == NULL)
702 {
703 log_error("NULL pointer error\n");
704 return -1;
705 }
706
707 // acquire lock of user list
708 if (user_list_rd_lock(p_user_list_pool->semid) < 0)
709 {
710 log_error("user_list_rd_lock() error\n");
711 return -2;
712 }
713
714 if (p_user_list_pool->p_online_current->user_count == 0)
715 {
716 // empty list
717 ret = 0;
718 goto cleanup;
719 }
720
721 *p_page_count = p_user_list_pool->p_online_current->user_count / BBS_user_limit_per_page +
722 (p_user_list_pool->p_online_current->user_count % BBS_user_limit_per_page == 0 ? 0 : 1);
723
724 if (page_id < 0 || page_id >= *p_page_count)
725 {
726 log_error("Invalid page_id = %d, not in range [0, %d)\n", page_id, *p_page_count);
727 ret = -3;
728 goto cleanup;
729 }
730
731 *p_user_count = MIN(BBS_user_limit_per_page,
732 p_user_list_pool->p_online_current->user_count -
733 page_id * BBS_user_limit_per_page);
734
735 memcpy(p_online_users,
736 p_user_list_pool->p_online_current->users + page_id * BBS_user_limit_per_page,
737 sizeof(USER_ONLINE_INFO) * (size_t)(*p_user_count));
738
739 cleanup:
740 // release lock of user list
741 if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
742 {
743 log_error("user_list_rd_unlock() error\n");
744 ret = -1;
745 }
746
747 return ret;
748 }
749
750 int query_user_info(int32_t uid, USER_INFO *p_user)
751 {
752 int left;
753 int right;
754 int mid;
755 int ret = 0;
756
757 if (p_user == NULL)
758 {
759 log_error("NULL pointer error\n");
760 return -1;
761 }
762
763 // acquire lock of user list
764 if (user_list_rd_lock(p_user_list_pool->semid) < 0)
765 {
766 log_error("user_list_rd_lock() error\n");
767 return -2;
768 }
769
770 left = 0;
771 right = p_user_list_pool->p_current->user_count - 1;
772
773 while (left < right)
774 {
775 mid = (left + right) / 2;
776 if (uid < p_user_list_pool->p_current->users[mid].uid)
777 {
778 right = mid;
779 }
780 else if (uid > p_user_list_pool->p_current->users[mid].uid)
781 {
782 left = mid + 1;
783 }
784 else // if (uid == p_user_list_pool->p_current->users[mid].uid)
785 {
786 left = mid;
787 break;
788 }
789 }
790
791 if (uid == p_user_list_pool->p_current->users[left].uid) // Found
792 {
793 *p_user = p_user_list_pool->p_current->users[left];
794 ret = 1;
795 }
796
797 // release lock of user list
798 if (user_list_rd_unlock(p_user_list_pool->semid) < 0)
799 {
800 log_error("user_list_rd_unlock() error\n");
801 ret = -1;
802 }
803
804 return ret;
805 }

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