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

Diff of /lbbs/src/section_list_loader.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.1 by sysadm, Mon May 26 03:42:45 2025 UTC Revision 1.4 by sysadm, Tue May 27 03:25:02 2025 UTC
# Line 17  Line 17 
17  #include "section_list_loader.h"  #include "section_list_loader.h"
18  #include "log.h"  #include "log.h"
19  #include "database.h"  #include "database.h"
20    #include "menu.h"
21  #include <stdio.h>  #include <stdio.h>
22  #include <string.h>  #include <string.h>
23  #include <errno.h>  #include <errno.h>
24    #include <signal.h>
25  #include <stdlib.h>  #include <stdlib.h>
26    #include <strings.h>
27    #include <unistd.h>
28    
29  int load_section_config_from_db(MYSQL *db)  #define SECTION_LIST_LOAD_INTERVAL 10 // second
30    
31    static int section_list_loader_pid;
32    
33    int load_section_config_from_db(void)
34  {  {
35            MYSQL *db;
36          MYSQL_RES *rs, *rs2;          MYSQL_RES *rs, *rs2;
37          MYSQL_ROW row, row2;          MYSQL_ROW row, row2;
38          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
# Line 32  int load_section_config_from_db(MYSQL *d Line 41  int load_section_config_from_db(MYSQL *d
41          SECTION_LIST *p_section;          SECTION_LIST *p_section;
42          int ret;          int ret;
43    
44            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          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
52                           "SELECT section_config.SID, sname, title, section_config.CID, read_user_level, write_user_level, "                           "SELECT section_config.SID, sname, section_config.title, section_config.CID, "
53                           "section_config.enable * section_class.enable AS enable "                           "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 "                           "FROM section_config INNER JOIN section_class ON section_config.CID = section_class.CID "
55                           "ORDER BY section_config.SID");                           "ORDER BY section_config.SID");
56    
57          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
58          {          {
59                  log_error("Query section_list error: %s\n", mysql_error(db));                  log_error("Query section_list error: %s\n", mysql_error(db));
60                  return -1;                  return -3;
61          }          }
62          if ((rs = mysql_store_result(db)) == NULL)          if ((rs = mysql_store_result(db)) == NULL)
63          {          {
64                  log_error("Get section_list data failed\n");                  log_error("Get section_list data failed\n");
65                  return -1;                  return -3;
66          }          }
67    
68            ret = 0;
69          while ((row = mysql_fetch_row(rs)))          while ((row = mysql_fetch_row(rs)))
70          {          {
71                  sid = atoi(row[0]);                  sid = atoi(row[0]);
# Line 63  int load_section_config_from_db(MYSQL *d Line 81  int load_section_config_from_db(MYSQL *d
81                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
82                  {                  {
83                          log_error("Query section_master error: %s\n", mysql_error(db));                          log_error("Query section_master error: %s\n", mysql_error(db));
84                          return -2;                          ret = -3;
85                            break;
86                  }                  }
87                  if ((rs2 = mysql_store_result(db)) == NULL)                  if ((rs2 = mysql_store_result(db)) == NULL)
88                  {                  {
89                          log_error("Get section_master data failed\n");                          log_error("Get section_master data failed\n");
90                          return -2;                          ret = -3;
91                            break;
92                  }                  }
93                  if ((row2 = mysql_fetch_row(rs2)))                  if ((row2 = mysql_fetch_row(rs2)))
94                  {                  {
# Line 88  int load_section_config_from_db(MYSQL *d Line 108  int load_section_config_from_db(MYSQL *d
108                          p_section = section_list_create(sid, row[1], row[2], "");                          p_section = section_list_create(sid, row[1], row[2], "");
109                          if (p_section == NULL)                          if (p_section == NULL)
110                          {                          {
111                                  log_error("load_section_config_from_db() error: load new section sid = %d sname = %s\n", sid, row[1]);                                  log_error("section_list_create() error: load new section sid = %d sname = %s\n", sid, row[1]);
112                                    ret = -4;
113                                  break;                                  break;
114                          }                          }
115    
# Line 130  int load_section_config_from_db(MYSQL *d Line 151  int load_section_config_from_db(MYSQL *d
151          }          }
152          mysql_free_result(rs);          mysql_free_result(rs);
153    
154            mysql_close(db);
155    
156            return ret;
157    }
158    
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                            ret = ERR_UNKNOWN_SECTION; // Unknown section found
245                            break;
246                    }
247    
248                    // acquire lock of current section if different from last one
249                    if (!global_lock && article.sid != last_sid)
250                    {
251                            if ((ret = section_list_rw_lock(p_section)) < 0)
252                            {
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    
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;          return 0;
413  }  }


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

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