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

Annotation of /lbbs/src/section_list_loader.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (hide annotations)
Thu May 29 02:21:31 2025 UTC (9 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.9: +4 -2 lines
Content type: text/x-csrc
Add section page number display

1 sysadm 1.1 /***************************************************************************
2     section_list_loader.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 "section_list_loader.h"
18     #include "log.h"
19     #include "database.h"
20 sysadm 1.4 #include "menu.h"
21 sysadm 1.1 #include <stdio.h>
22     #include <string.h>
23     #include <errno.h>
24 sysadm 1.4 #include <signal.h>
25 sysadm 1.1 #include <stdlib.h>
26 sysadm 1.3 #include <strings.h>
27 sysadm 1.4 #include <unistd.h>
28    
29 sysadm 1.8 #define _POSIX_C_SOURCE 200809L
30     #include <string.h>
31    
32 sysadm 1.4 #define SECTION_LIST_LOAD_INTERVAL 10 // second
33    
34 sysadm 1.5 int section_list_loader_pid;
35     int last_article_op_log_mid;
36 sysadm 1.1
37 sysadm 1.2 int load_section_config_from_db(void)
38 sysadm 1.1 {
39 sysadm 1.2 MYSQL *db;
40 sysadm 1.1 MYSQL_RES *rs, *rs2;
41     MYSQL_ROW row, row2;
42     char sql[SQL_BUFFER_LEN];
43     int32_t sid;
44 sysadm 1.8 char master_list[(BBS_username_max_len + 1) * 3 + 1];
45 sysadm 1.1 SECTION_LIST *p_section;
46     int ret;
47    
48 sysadm 1.2 db = db_open();
49     if (db == NULL)
50     {
51     log_error("db_open() error: %s\n", mysql_error(db));
52     return -2;
53     }
54    
55 sysadm 1.1 snprintf(sql, sizeof(sql),
56 sysadm 1.2 "SELECT section_config.SID, sname, section_config.title, section_config.CID, "
57     "read_user_level, write_user_level, section_config.enable * section_class.enable AS enable "
58     "FROM section_config INNER JOIN section_class ON section_config.CID = section_class.CID "
59 sysadm 1.1 "ORDER BY section_config.SID");
60    
61     if (mysql_query(db, sql) != 0)
62     {
63     log_error("Query section_list error: %s\n", mysql_error(db));
64 sysadm 1.2 return -3;
65 sysadm 1.1 }
66     if ((rs = mysql_store_result(db)) == NULL)
67     {
68     log_error("Get section_list data failed\n");
69 sysadm 1.2 return -3;
70 sysadm 1.1 }
71 sysadm 1.2
72     ret = 0;
73 sysadm 1.1 while ((row = mysql_fetch_row(rs)))
74     {
75     sid = atoi(row[0]);
76    
77     // Query section master
78     snprintf(sql, sizeof(sql),
79     "SELECT username FROM section_master "
80     "INNER JOIN user_list ON section_master.UID = user_list.UID "
81     "WHERE SID = %d AND section_master.enable AND (NOW() BETWEEN begin_dt AND end_dt) "
82 sysadm 1.8 "ORDER BY major DESC, begin_dt ASC LIMIT 3",
83 sysadm 1.1 sid);
84    
85     if (mysql_query(db, sql) != 0)
86     {
87     log_error("Query section_master error: %s\n", mysql_error(db));
88 sysadm 1.2 ret = -3;
89     break;
90 sysadm 1.1 }
91     if ((rs2 = mysql_store_result(db)) == NULL)
92     {
93     log_error("Get section_master data failed\n");
94 sysadm 1.2 ret = -3;
95     break;
96 sysadm 1.1 }
97 sysadm 1.8
98     master_list[0] = '\0';
99     while ((row2 = mysql_fetch_row(rs2)))
100 sysadm 1.1 {
101 sysadm 1.8 strncat(master_list, row2[0], sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
102     strncat(master_list, " ", sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
103 sysadm 1.1 }
104     mysql_free_result(rs2);
105    
106     p_section = section_list_find_by_sid(sid);
107    
108     if (p_section == NULL)
109     {
110 sysadm 1.8 p_section = section_list_create(sid, row[1], row[2], master_list);
111 sysadm 1.1 if (p_section == NULL)
112     {
113 sysadm 1.2 log_error("section_list_create() error: load new section sid = %d sname = %s\n", sid, row[1]);
114     ret = -4;
115 sysadm 1.1 break;
116     }
117    
118     // acquire rw lock
119     ret = section_list_rw_lock(p_section);
120     if (ret < 0)
121     {
122     break;
123     }
124     }
125     else
126     {
127     // acquire rw lock
128     ret = section_list_rw_lock(p_section);
129     if (ret < 0)
130     {
131     break;
132     }
133    
134     strncpy(p_section->sname, row[1], sizeof(p_section->sname) - 1);
135     p_section->sname[sizeof(p_section->sname) - 1] = '\0';
136     strncpy(p_section->stitle, row[1], sizeof(p_section->stitle) - 1);
137     p_section->stitle[sizeof(p_section->stitle) - 1] = '\0';
138 sysadm 1.8 strncpy(p_section->master_list, master_list, sizeof(p_section->master_list) - 1);
139     p_section->master_list[sizeof(p_section->master_list) - 1] = '\0';
140 sysadm 1.1 }
141    
142     p_section->class_id = atoi(row[3]);
143     p_section->read_user_level = atoi(row[4]);
144     p_section->write_user_level = atoi(row[5]);
145     p_section->enable = (int8_t)atoi(row[6]);
146    
147     // release rw lock
148     ret = section_list_rw_unlock(p_section);
149     if (ret < 0)
150     {
151     break;
152     }
153     }
154     mysql_free_result(rs);
155    
156 sysadm 1.2 mysql_close(db);
157    
158     return ret;
159 sysadm 1.1 }
160 sysadm 1.3
161 sysadm 1.9 int append_articles_from_db(int32_t start_aid, int global_lock, int article_count_limit)
162 sysadm 1.3 {
163     MYSQL *db;
164     MYSQL_RES *rs;
165     MYSQL_ROW row;
166     char sql[SQL_BUFFER_LEN];
167     ARTICLE article;
168 sysadm 1.5 ARTICLE *p_topic;
169 sysadm 1.3 SECTION_LIST *p_section = NULL;
170     int32_t last_sid = 0;
171 sysadm 1.9 int article_count = 0;
172 sysadm 1.3 int ret = 0;
173     int i;
174    
175     db = db_open();
176     if (db == NULL)
177     {
178     log_error("db_open() error: %s\n", mysql_error(db));
179     return -2;
180     }
181    
182     snprintf(sql, sizeof(sql),
183 sysadm 1.5 "SELECT AID, TID, SID, CID, UID, visible, excerption, ontop, `lock`, "
184     "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt "
185 sysadm 1.9 "FROM bbs WHERE AID >= %d ORDER BY AID LIMIT %d",
186     start_aid, article_count_limit);
187 sysadm 1.3
188     if (mysql_query(db, sql) != 0)
189     {
190     log_error("Query article list error: %s\n", mysql_error(db));
191     return -3;
192     }
193 sysadm 1.9 if ((rs = mysql_store_result(db)) == NULL)
194 sysadm 1.3 {
195     log_error("Get article list data failed\n");
196     return -3;
197     }
198    
199     // acquire global lock
200     if (global_lock)
201     {
202     if ((ret = section_list_rw_lock(NULL)) < 0)
203     {
204     log_error("section_list_rw_lock(sid = 0) error\n");
205     goto cleanup;
206     }
207     }
208    
209     while ((row = mysql_fetch_row(rs)))
210     {
211     bzero(&article, sizeof(ARTICLE));
212    
213     // copy data of article
214     i = 0;
215    
216     article.aid = atoi(row[i++]);
217     article.tid = atoi(row[i++]);
218     article.sid = atoi(row[i++]);
219     article.cid = atoi(row[i++]);
220     article.uid = atoi(row[i++]);
221     article.visible = (int8_t)atoi(row[i++]);
222     article.excerption = (int8_t)atoi(row[i++]);
223     article.ontop = (int8_t)atoi(row[i++]);
224     article.lock = (int8_t)atoi(row[i++]);
225 sysadm 1.5 article.transship = (int8_t)atoi(row[i++]);
226 sysadm 1.3
227     strncpy(article.username, row[i++], sizeof(article.username) - 1);
228     article.username[sizeof(article.username) - 1] = '\0';
229     strncpy(article.nickname, row[i++], sizeof(article.nickname) - 1);
230     article.nickname[sizeof(article.nickname) - 1] = '\0';
231     strncpy(article.title, row[i++], sizeof(article.title) - 1);
232     article.title[sizeof(article.title) - 1] = '\0';
233    
234     article.sub_dt = atol(row[i++]);
235    
236     // release lock of last section if different from current one
237     if (!global_lock && article.sid != last_sid && last_sid != 0)
238     {
239     if ((ret = section_list_rw_unlock(p_section)) < 0)
240     {
241     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
242     break;
243     }
244     }
245    
246     if ((p_section = section_list_find_by_sid(article.sid)) == NULL)
247     {
248     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);
249 sysadm 1.4 ret = ERR_UNKNOWN_SECTION; // Unknown section found
250 sysadm 1.3 break;
251     }
252    
253 sysadm 1.5 if (article.visible != 0 && article.tid != 0)
254     {
255     // Check if topic article is visible
256     p_topic = article_block_find_by_aid(article.tid);
257     if (p_topic == NULL || p_topic->visible == 0)
258     {
259     // log_error("Set article (aid = %d) as invisible due to invisible or non-existing topic head\n", article.aid);
260     article.tid = 0;
261     article.visible = 0;
262     }
263     }
264    
265 sysadm 1.3 // acquire lock of current section if different from last one
266     if (!global_lock && article.sid != last_sid)
267     {
268 sysadm 1.4 if ((ret = section_list_rw_lock(p_section)) < 0)
269 sysadm 1.3 {
270     log_error("section_list_rw_lock(sid = 0) error\n");
271     break;
272     }
273     }
274    
275     // append article to section list
276     last_sid = article.sid;
277    
278     if (section_list_append_article(p_section, &article) < 0)
279     {
280     log_error("section_list_append_article(sid = %d, aid = %d) error\n",
281     p_section->sid, article.aid);
282     ret = -3;
283     break;
284     }
285 sysadm 1.9
286     article_count++;
287    
288     // TODO: generate content cache
289 sysadm 1.3 }
290    
291     // release lock of last section
292     if (!global_lock && last_sid != 0)
293     {
294     if ((ret = section_list_rw_unlock(p_section)) < 0)
295     {
296     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
297     }
298     }
299    
300     // release global lock
301     if (global_lock)
302     {
303     if ((ret = section_list_rw_unlock(NULL)) < 0)
304     {
305     log_error("section_list_rw_unlock(sid = 0) error\n");
306     }
307     }
308    
309     cleanup:
310     mysql_free_result(rs);
311    
312     mysql_close(db);
313    
314 sysadm 1.9 return (ret < 0 ? ret : article_count);
315 sysadm 1.3 }
316 sysadm 1.4
317 sysadm 1.5 int set_last_article_op_log_from_db(void)
318     {
319     MYSQL *db;
320     MYSQL_RES *rs;
321     MYSQL_ROW row;
322     char sql[SQL_BUFFER_LEN];
323    
324     db = db_open();
325     if (db == NULL)
326     {
327     log_error("db_open() error: %s\n", mysql_error(db));
328     return -1;
329     }
330    
331     snprintf(sql, sizeof(sql),
332     "SELECT MID FROM bbs_article_op ORDER BY MID DESC LIMIT 1");
333    
334     if (mysql_query(db, sql) != 0)
335     {
336     log_error("Query article op error: %s\n", mysql_error(db));
337     return -2;
338     }
339     if ((rs = mysql_store_result(db)) == NULL)
340     {
341     log_error("Get article op data failed\n");
342     return -2;
343     }
344    
345     if ((row = mysql_fetch_row(rs)))
346     {
347     last_article_op_log_mid = atoi(row[0]);
348     }
349    
350     mysql_free_result(rs);
351    
352     mysql_close(db);
353    
354     return last_article_op_log_mid;
355     }
356    
357 sysadm 1.9 int apply_article_op_log_from_db(int op_count_limit)
358 sysadm 1.5 {
359     MYSQL *db;
360     MYSQL_RES *rs, *rs2;
361     MYSQL_ROW row, row2;
362     char sql[SQL_BUFFER_LEN];
363     ARTICLE *p_article;
364     SECTION_LIST *p_section = NULL;
365     SECTION_LIST *p_section_dest;
366     int32_t last_sid = 0;
367     int32_t sid_dest;
368 sysadm 1.9 int op_count = 0;
369 sysadm 1.5 int ret = 0;
370    
371     db = db_open();
372     if (db == NULL)
373     {
374     log_error("db_open() error: %s\n", mysql_error(db));
375     return -3;
376     }
377    
378     snprintf(sql, sizeof(sql),
379     "SELECT MID, AID, type FROM bbs_article_op "
380 sysadm 1.9 "WHERE MID > %d AND type NOT IN ('A') "
381     "ORDER BY MID LIMIT %d",
382     last_article_op_log_mid, op_count_limit);
383 sysadm 1.5
384     if (mysql_query(db, sql) != 0)
385     {
386     log_error("Query article log error: %s\n", mysql_error(db));
387     return -3;
388     }
389     if ((rs = mysql_store_result(db)) == NULL)
390     {
391     log_error("Get article log data failed\n");
392     return -3;
393     }
394    
395     while ((row = mysql_fetch_row(rs)))
396     {
397     p_article = article_block_find_by_aid(atoi(row[1]));
398     if (p_article == NULL) // related article has not been appended yet
399     {
400     ret = -2;
401     break;
402     }
403    
404     // release lock of last section if different from current one
405     if (p_article->sid != last_sid && last_sid != 0)
406     {
407     if ((ret = section_list_rw_unlock(p_section)) < 0)
408     {
409     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
410     break;
411     }
412     }
413    
414     if ((p_section = section_list_find_by_sid(p_article->sid)) == NULL)
415     {
416     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", p_article->sid);
417     ret = ERR_UNKNOWN_SECTION; // Unknown section found
418     break;
419     }
420    
421     // acquire lock of current section if different from last one
422     if (p_article->sid != last_sid)
423     {
424     if ((ret = section_list_rw_lock(p_section)) < 0)
425     {
426     log_error("section_list_rw_lock(sid = 0) error\n");
427     break;
428     }
429     }
430    
431     last_sid = p_article->sid;
432    
433     switch (row[2][0])
434     {
435     case 'A': // Add article
436     log_error("Operation type=A should not be found\n");
437     break;
438     case 'D': // Delete article
439     case 'X': // Delete article by Admin
440     p_article->visible = 0;
441     if (p_article->tid == 0)
442     {
443     // Set articles in the topic to be invisible
444     do
445     {
446     p_article = p_article->p_topic_next;
447     p_article->visible = 0;
448     } while (p_article->tid != 0);
449     }
450     break;
451     case 'S': // Restore article
452     p_article->visible = 1;
453     break;
454     case 'L': // Lock article
455     p_article->lock = 1;
456     break;
457     case 'U': // Unlock article
458     p_article->lock = 0;
459     break;
460     case 'M': // Modify article
461 sysadm 1.9 snprintf(sql, sizeof(sql),
462     "SELECT CID FROM bbs WHERE AID = %d",
463     p_article->aid);
464    
465     if (mysql_query(db, sql) != 0)
466     {
467     log_error("Query article error: %s\n", mysql_error(db));
468     ret = -3;
469     break;
470     }
471     if ((rs2 = mysql_store_result(db)) == NULL)
472     {
473     log_error("Get article data failed\n");
474     ret = -3;
475     break;
476     }
477     if ((row2 = mysql_fetch_row(rs2)))
478     {
479     p_article->cid = atoi(row2[0]);
480     }
481     else
482     {
483     p_article->cid = 0;
484     ret = -4;
485     }
486     mysql_free_result(rs2);
487    
488     if (p_article->cid > 0)
489     {
490     // TODO: generate content cache
491     }
492    
493 sysadm 1.5 break;
494     case 'T': // Move article
495     snprintf(sql, sizeof(sql),
496     "SELECT SID FROM bbs WHERE AID = %d",
497     p_article->aid);
498    
499     if (mysql_query(db, sql) != 0)
500     {
501     log_error("Query article error: %s\n", mysql_error(db));
502     ret = -3;
503     break;
504     }
505     if ((rs2 = mysql_store_result(db)) == NULL)
506     {
507     log_error("Get article data failed\n");
508     ret = -3;
509     break;
510     }
511     if ((row2 = mysql_fetch_row(rs2)))
512     {
513     sid_dest = atoi(row2[0]);
514     }
515     else
516     {
517     sid_dest = 0;
518     ret = -4;
519     }
520     mysql_free_result(rs2);
521    
522     if (sid_dest > 0 && sid_dest != p_article->sid)
523     {
524     p_section_dest = section_list_find_by_sid(sid_dest);
525     if (p_section_dest == NULL)
526     {
527     ret = ERR_UNKNOWN_SECTION;
528     break;
529     }
530 sysadm 1.6 // acquire lock of dest section
531     if ((ret = section_list_rw_lock(p_section_dest)) < 0)
532     {
533     log_error("section_list_rw_lock(sid = %d) error\n", p_section_dest);
534     break;
535     }
536 sysadm 1.5 // Move topic
537     if ((ret = section_list_move_topic(p_section, p_section_dest, p_article->aid)) < 0)
538     {
539 sysadm 1.6 log_error("section_list_move_topic(src_sid=%d, dest_sid=%d, aid=%d) error (%d), retry in the next loop\n",
540     p_section->sid, p_section_dest->sid, p_article->aid, ret);
541     }
542     // release lock of dest section
543     if (section_list_rw_unlock(p_section_dest) < 0)
544     {
545     log_error("section_list_rw_unlock(sid = %d) error\n", p_section_dest);
546     ret = -1;
547 sysadm 1.5 }
548     }
549     break;
550     case 'E': // Set article as excerption
551     p_article->excerption = 1;
552     break;
553     case 'O': // Unset article as excerption
554     p_article->excerption = 0;
555     break;
556     case 'F': // Set article on top
557     p_article->ontop = 1;
558     break;
559     case 'V': // Unset article on top
560     p_article->ontop = 0;
561     break;
562     case 'Z': // Set article as trnasship
563     p_article->transship = 1;
564     break;
565     default:
566     // log_error("Operation type=%s unknown, mid=%s\n", row[2], row[0]);
567     break;
568     }
569    
570     if (ret < 0)
571     {
572     break;
573     }
574    
575     // Update MID with last successfully proceeded article_op_log
576     last_article_op_log_mid = atoi(row[0]);
577 sysadm 1.9
578     op_count++;
579 sysadm 1.5 }
580    
581     // release lock of last section
582     if (last_sid != 0)
583     {
584     if ((ret = section_list_rw_unlock(p_section)) < 0)
585     {
586     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
587     }
588     }
589    
590     mysql_free_result(rs);
591    
592     mysql_close(db);
593    
594 sysadm 1.9 return (ret < 0 ? ret : op_count);
595 sysadm 1.5 }
596    
597 sysadm 1.4 int section_list_loader_launch(void)
598     {
599     int pid;
600     int ret;
601     int32_t last_aid;
602     int article_count;
603     int load_count;
604 sysadm 1.5 int last_mid;
605 sysadm 1.4 int i;
606    
607     if (section_list_loader_pid != 0)
608     {
609     log_error("section_list_loader already running, pid = %d\n", section_list_loader_pid);
610     return -2;
611     }
612    
613     pid = fork();
614    
615     if (pid > 0) // Parent process
616     {
617     SYS_child_process_count++;
618     section_list_loader_pid = pid;
619     log_std("Section list loader process (%d) start\n", pid);
620     return 0;
621     }
622     else if (pid < 0) // Error
623     {
624     log_error("fork() error (%d)\n", errno);
625     return -1;
626     }
627    
628     // Child process
629     SYS_child_process_count = 0;
630    
631     // Detach menu in shared memory
632     detach_menu_shm(p_bbs_menu);
633     free(p_bbs_menu);
634     p_bbs_menu = NULL;
635    
636     // Do section data loader periodically
637     while (!SYS_server_exit)
638     {
639     if (SYS_section_list_reload)
640     {
641     SYS_section_list_reload = 0;
642    
643     // Load section config
644     if (load_section_config_from_db() < 0)
645     {
646     log_error("load_section_config_from_db() error\n");
647     }
648     else
649     {
650     log_error("Reload section config successfully\n");
651     }
652     }
653    
654     // Load section articles
655     article_count = article_block_article_count();
656    
657 sysadm 1.9 do
658 sysadm 1.4 {
659 sysadm 1.9 last_aid = article_block_last_aid();
660 sysadm 1.4
661 sysadm 1.9 if ((ret = append_articles_from_db(last_aid + 1, 0, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
662 sysadm 1.4 {
663 sysadm 1.9 log_error("append_articles_from_db(%d, 0, %d) error\n", last_aid + 1, LOAD_ARTICLE_COUNT_LIMIT);
664    
665     if (ret == ERR_UNKNOWN_SECTION)
666     {
667     SYS_section_list_reload = 1; // Force reload section_list
668     }
669 sysadm 1.4 }
670 sysadm 1.9 } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
671 sysadm 1.5
672     load_count = article_block_article_count() - article_count;
673     if (load_count > 0)
674     {
675     log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
676     }
677    
678     if (SYS_section_list_reload)
679     {
680     continue;
681     }
682    
683     // Load article_op log
684     last_mid = last_article_op_log_mid;
685    
686 sysadm 1.9 do
687 sysadm 1.4 {
688 sysadm 1.9 if ((ret = apply_article_op_log_from_db(LOAD_ARTICLE_COUNT_LIMIT)) < 0)
689     {
690     log_error("apply_article_op_log_from_db() error\n");
691 sysadm 1.4
692 sysadm 1.9 if (ret == ERR_UNKNOWN_SECTION)
693     {
694     SYS_section_list_reload = 1; // Force reload section_list
695     }
696 sysadm 1.4 }
697 sysadm 1.9 } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
698 sysadm 1.4
699 sysadm 1.5 if (last_article_op_log_mid > last_mid)
700     {
701     log_std("Proceeded %d article logs, last_mid = %d\n", last_article_op_log_mid - last_mid, last_article_op_log_mid);
702     }
703    
704     if (SYS_section_list_reload)
705     {
706     continue;
707     }
708    
709     for (i = 0; i < SECTION_LIST_LOAD_INTERVAL && !SYS_server_exit && !SYS_section_list_reload; i++)
710     {
711     sleep(1);
712 sysadm 1.4 }
713     }
714    
715     // Child process exit
716    
717     // Detach data pools shm
718     detach_section_list_shm();
719     detach_article_block_shm();
720     detach_trie_dict_shm();
721    
722     log_std("Section list loader process exit normally\n");
723     log_end();
724    
725     section_list_loader_pid = 0;
726    
727     _exit(0);
728    
729     return 0;
730     }
731    
732     int section_list_loader_reload(void)
733     {
734     if (section_list_loader_pid == 0)
735     {
736     log_error("section_list_loader not running\n");
737     return -2;
738     }
739    
740     if (kill(section_list_loader_pid, SIGHUP) < 0)
741     {
742     log_error("Send SIGTERM signal failed (%d)\n", errno);
743     return -1;
744     }
745    
746     return 0;
747     }
748 sysadm 1.7
749 sysadm 1.10 int query_section_articles(SECTION_LIST *p_section, int page_id, ARTICLE *p_articles[], int *p_article_count, int *p_page_count)
750 sysadm 1.7 {
751     ARTICLE *p_article;
752     ARTICLE *p_next_page_first_article;
753     int ret = 0;
754    
755 sysadm 1.10 if (p_section == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL)
756 sysadm 1.7 {
757     log_error("query_section_articles() NULL pointer error\n");
758     return -1;
759     }
760    
761     // acquire lock of section
762     if ((ret = section_list_rd_lock(p_section)) < 0)
763     {
764     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
765     return -2;
766     }
767    
768 sysadm 1.10 *p_page_count = p_section->page_count;
769    
770 sysadm 1.9 if (p_section->visible_article_count == 0)
771     {
772     *p_article_count = 0;
773     }
774     else if (page_id < 0 || page_id >= p_section->page_count)
775 sysadm 1.7 {
776 sysadm 1.8 log_error("Invalid page_id=%d, not in range [0, %d)\n", page_id, p_section->page_count);
777 sysadm 1.7 ret = -3;
778     }
779     else
780     {
781     ret = page_id;
782     p_article = p_section->p_page_first_article[page_id];
783     p_next_page_first_article =
784     (page_id == p_section->page_count - 1 ? p_section->p_article_head : p_section->p_page_first_article[page_id + 1]);
785     *p_article_count = 0;
786    
787     do
788     {
789     if (p_article->visible)
790     {
791     p_articles[*p_article_count] = p_article;
792     (*p_article_count)++;
793     }
794     p_article = p_article->p_next;
795     } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);
796 sysadm 1.8
797     if (*p_article_count != (page_id < p_section->page_count - 1 ? BBS_article_limit_per_page : p_section->last_page_visible_article_count))
798     {
799     log_error("Inconsistent visible article count %d detected in section %d page %d\n", *p_article_count, p_section->sid, page_id);
800     }
801 sysadm 1.7 }
802    
803     // release lock of section
804 sysadm 1.8 if (section_list_rd_unlock(p_section) < 0)
805 sysadm 1.7 {
806     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
807     ret = -2;
808     }
809    
810     return ret;
811     }

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