/[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.4 - (hide annotations)
Tue May 27 03:25:02 2025 UTC (9 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.3: +128 -2 lines
Content type: text/x-csrc
Add section_list_loader_launch() and section_list_loader_reload()

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     #define SECTION_LIST_LOAD_INTERVAL 10 // second
30    
31     static int section_list_loader_pid;
32 sysadm 1.1
33 sysadm 1.2 int load_section_config_from_db(void)
34 sysadm 1.1 {
35 sysadm 1.2 MYSQL *db;
36 sysadm 1.1 MYSQL_RES *rs, *rs2;
37     MYSQL_ROW row, row2;
38     char sql[SQL_BUFFER_LEN];
39     int32_t sid;
40     char master_name[BBS_username_max_len + 1];
41     SECTION_LIST *p_section;
42     int ret;
43    
44 sysadm 1.2 db = db_open();
45     if (db == NULL)
46     {
47     log_error("db_open() error: %s\n", mysql_error(db));
48     return -2;
49     }
50    
51 sysadm 1.1 snprintf(sql, sizeof(sql),
52 sysadm 1.2 "SELECT section_config.SID, sname, section_config.title, section_config.CID, "
53     "read_user_level, write_user_level, section_config.enable * section_class.enable AS enable "
54     "FROM section_config INNER JOIN section_class ON section_config.CID = section_class.CID "
55 sysadm 1.1 "ORDER BY section_config.SID");
56    
57     if (mysql_query(db, sql) != 0)
58     {
59     log_error("Query section_list error: %s\n", mysql_error(db));
60 sysadm 1.2 return -3;
61 sysadm 1.1 }
62     if ((rs = mysql_store_result(db)) == NULL)
63     {
64     log_error("Get section_list data failed\n");
65 sysadm 1.2 return -3;
66 sysadm 1.1 }
67 sysadm 1.2
68     ret = 0;
69 sysadm 1.1 while ((row = mysql_fetch_row(rs)))
70     {
71     sid = atoi(row[0]);
72    
73     // Query section master
74     snprintf(sql, sizeof(sql),
75     "SELECT username FROM section_master "
76     "INNER JOIN user_list ON section_master.UID = user_list.UID "
77     "WHERE SID = %d AND section_master.enable AND (NOW() BETWEEN begin_dt AND end_dt) "
78     "ORDER BY major DESC LIMIT 1",
79     sid);
80    
81     if (mysql_query(db, sql) != 0)
82     {
83     log_error("Query section_master error: %s\n", mysql_error(db));
84 sysadm 1.2 ret = -3;
85     break;
86 sysadm 1.1 }
87     if ((rs2 = mysql_store_result(db)) == NULL)
88     {
89     log_error("Get section_master data failed\n");
90 sysadm 1.2 ret = -3;
91     break;
92 sysadm 1.1 }
93     if ((row2 = mysql_fetch_row(rs2)))
94     {
95     strncpy(master_name, row2[0], sizeof(master_name) - 1);
96     master_name[sizeof(master_name) - 1] = '\0';
97     }
98     else
99     {
100     master_name[0] = '\0';
101     }
102     mysql_free_result(rs2);
103    
104     p_section = section_list_find_by_sid(sid);
105    
106     if (p_section == NULL)
107     {
108     p_section = section_list_create(sid, row[1], row[2], "");
109     if (p_section == NULL)
110     {
111 sysadm 1.2 log_error("section_list_create() error: load new section sid = %d sname = %s\n", sid, row[1]);
112     ret = -4;
113 sysadm 1.1 break;
114     }
115    
116     // acquire rw lock
117     ret = section_list_rw_lock(p_section);
118     if (ret < 0)
119     {
120     break;
121     }
122     }
123     else
124     {
125     // acquire rw lock
126     ret = section_list_rw_lock(p_section);
127     if (ret < 0)
128     {
129     break;
130     }
131    
132     strncpy(p_section->sname, row[1], sizeof(p_section->sname) - 1);
133     p_section->sname[sizeof(p_section->sname) - 1] = '\0';
134     strncpy(p_section->stitle, row[1], sizeof(p_section->stitle) - 1);
135     p_section->stitle[sizeof(p_section->stitle) - 1] = '\0';
136     strncpy(p_section->master_name, master_name, sizeof(p_section->master_name) - 1);
137     p_section->master_name[sizeof(p_section->master_name) - 1] = '\0';
138     }
139    
140     p_section->class_id = atoi(row[3]);
141     p_section->read_user_level = atoi(row[4]);
142     p_section->write_user_level = atoi(row[5]);
143     p_section->enable = (int8_t)atoi(row[6]);
144    
145     // release rw lock
146     ret = section_list_rw_unlock(p_section);
147     if (ret < 0)
148     {
149     break;
150     }
151     }
152     mysql_free_result(rs);
153    
154 sysadm 1.2 mysql_close(db);
155    
156     return ret;
157 sysadm 1.1 }
158 sysadm 1.3
159     int append_articles_from_db(int32_t start_aid, int global_lock)
160     {
161     MYSQL *db;
162     MYSQL_RES *rs;
163     MYSQL_ROW row;
164     char sql[SQL_BUFFER_LEN];
165     ARTICLE article;
166     SECTION_LIST *p_section = NULL;
167     int32_t last_sid = 0;
168     int ret = 0;
169     int i;
170    
171     db = db_open();
172     if (db == NULL)
173     {
174     log_error("db_open() error: %s\n", mysql_error(db));
175     return -2;
176     }
177    
178     snprintf(sql, sizeof(sql),
179     "SELECT AID, TID, SID, CID, UID, visible, excerption, "
180     "ontop, `lock`, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt "
181     "FROM bbs WHERE AID >= %d ORDER BY AID",
182     start_aid);
183    
184     if (mysql_query(db, sql) != 0)
185     {
186     log_error("Query article list error: %s\n", mysql_error(db));
187     return -3;
188     }
189     if ((rs = mysql_use_result(db)) == NULL)
190     {
191     log_error("Get article list data failed\n");
192     return -3;
193     }
194    
195     // acquire global lock
196     if (global_lock)
197     {
198     if ((ret = section_list_rw_lock(NULL)) < 0)
199     {
200     log_error("section_list_rw_lock(sid = 0) error\n");
201     goto cleanup;
202     }
203     }
204    
205     while ((row = mysql_fetch_row(rs)))
206     {
207     bzero(&article, sizeof(ARTICLE));
208    
209     // copy data of article
210     i = 0;
211    
212     article.aid = atoi(row[i++]);
213     article.tid = atoi(row[i++]);
214     article.sid = atoi(row[i++]);
215     article.cid = atoi(row[i++]);
216     article.uid = atoi(row[i++]);
217     article.visible = (int8_t)atoi(row[i++]);
218     article.excerption = (int8_t)atoi(row[i++]);
219     article.ontop = (int8_t)atoi(row[i++]);
220     article.lock = (int8_t)atoi(row[i++]);
221    
222     strncpy(article.username, row[i++], sizeof(article.username) - 1);
223     article.username[sizeof(article.username) - 1] = '\0';
224     strncpy(article.nickname, row[i++], sizeof(article.nickname) - 1);
225     article.nickname[sizeof(article.nickname) - 1] = '\0';
226     strncpy(article.title, row[i++], sizeof(article.title) - 1);
227     article.title[sizeof(article.title) - 1] = '\0';
228    
229     article.sub_dt = atol(row[i++]);
230    
231     // release lock of last section if different from current one
232     if (!global_lock && article.sid != last_sid && last_sid != 0)
233     {
234     if ((ret = section_list_rw_unlock(p_section)) < 0)
235     {
236     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
237     break;
238     }
239     }
240    
241     if ((p_section = section_list_find_by_sid(article.sid)) == NULL)
242     {
243     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);
244 sysadm 1.4 ret = ERR_UNKNOWN_SECTION; // Unknown section found
245 sysadm 1.3 break;
246     }
247    
248     // acquire lock of current section if different from last one
249     if (!global_lock && article.sid != last_sid)
250     {
251 sysadm 1.4 if ((ret = section_list_rw_lock(p_section)) < 0)
252 sysadm 1.3 {
253     log_error("section_list_rw_lock(sid = 0) error\n");
254     break;
255     }
256     }
257    
258     // append article to section list
259     last_sid = article.sid;
260    
261     if (section_list_append_article(p_section, &article) < 0)
262     {
263     log_error("section_list_append_article(sid = %d, aid = %d) error\n",
264     p_section->sid, article.aid);
265     ret = -3;
266     break;
267     }
268     }
269    
270     // release lock of last section
271     if (!global_lock && last_sid != 0)
272     {
273     if ((ret = section_list_rw_unlock(p_section)) < 0)
274     {
275     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
276     }
277     }
278    
279     // release global lock
280     if (global_lock)
281     {
282     if ((ret = section_list_rw_unlock(NULL)) < 0)
283     {
284     log_error("section_list_rw_unlock(sid = 0) error\n");
285     }
286     }
287    
288     cleanup:
289     mysql_free_result(rs);
290    
291     mysql_close(db);
292    
293     return ret;
294     }
295 sysadm 1.4
296     int section_list_loader_launch(void)
297     {
298     int pid;
299     int ret;
300     int32_t last_aid;
301     int article_count;
302     int load_count;
303     int i;
304    
305     if (section_list_loader_pid != 0)
306     {
307     log_error("section_list_loader already running, pid = %d\n", section_list_loader_pid);
308     return -2;
309     }
310    
311     pid = fork();
312    
313     if (pid > 0) // Parent process
314     {
315     SYS_child_process_count++;
316     section_list_loader_pid = pid;
317     log_std("Section list loader process (%d) start\n", pid);
318     return 0;
319     }
320     else if (pid < 0) // Error
321     {
322     log_error("fork() error (%d)\n", errno);
323     return -1;
324     }
325    
326     // Child process
327     SYS_child_process_count = 0;
328    
329     // Detach menu in shared memory
330     detach_menu_shm(p_bbs_menu);
331     free(p_bbs_menu);
332     p_bbs_menu = NULL;
333    
334     // Do section data loader periodically
335     while (!SYS_server_exit)
336     {
337     if (SYS_section_list_reload)
338     {
339     SYS_section_list_reload = 0;
340    
341     // Load section config
342     if (load_section_config_from_db() < 0)
343     {
344     log_error("load_section_config_from_db() error\n");
345     }
346     else
347     {
348     log_error("Reload section config successfully\n");
349     }
350     }
351    
352     // Load section articles
353     last_aid = article_block_last_aid();
354     article_count = article_block_article_count();
355    
356     if ((ret = append_articles_from_db(last_aid + 1, 0)) < 0)
357     {
358     log_error("append_articles_from_db(%d, 0) error\n", last_aid + 1);
359    
360     if (ret == ERR_UNKNOWN_SECTION)
361     {
362     SYS_section_list_reload = 1; // Force reload section_list
363     }
364     }
365     else
366     {
367     load_count = article_block_article_count() - article_count;
368    
369     if (load_count > 0)
370     {
371     log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
372     }
373    
374     for (i = 0; i < SECTION_LIST_LOAD_INTERVAL && !SYS_server_exit && !SYS_section_list_reload; i++)
375     {
376     sleep(1);
377     }
378     }
379     }
380    
381     // Child process exit
382    
383     // Detach data pools shm
384     detach_section_list_shm();
385     detach_article_block_shm();
386     detach_trie_dict_shm();
387    
388     log_std("Section list loader process exit normally\n");
389     log_end();
390    
391     section_list_loader_pid = 0;
392    
393     _exit(0);
394    
395     return 0;
396     }
397    
398     int section_list_loader_reload(void)
399     {
400     if (section_list_loader_pid == 0)
401     {
402     log_error("section_list_loader not running\n");
403     return -2;
404     }
405    
406     if (kill(section_list_loader_pid, SIGHUP) < 0)
407     {
408     log_error("Send SIGTERM signal failed (%d)\n", errno);
409     return -1;
410     }
411    
412     return 0;
413     }

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