/[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.66 - (hide annotations)
Sun Nov 16 02:06:56 2025 UTC (4 months ago) by sysadm
Branch: MAIN
Changes since 1.65: +14 -0 lines
Content type: text/x-csrc
log_restart on SIGHUP

1 sysadm 1.63 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * section_list_loader
4     * - load and query operations of section articles
5     *
6 sysadm 1.64 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 sysadm 1.63 */
8 sysadm 1.1
9 sysadm 1.65 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.11 #include "article_cache.h"
14 sysadm 1.44 #include "article_view_log.h"
15 sysadm 1.19 #include "bbs.h"
16 sysadm 1.30 #include "database.h"
17 sysadm 1.39 #include "ip_mask.h"
18 sysadm 1.1 #include "log.h"
19 sysadm 1.4 #include "menu.h"
20 sysadm 1.30 #include "section_list_loader.h"
21 sysadm 1.52 #include "user_list.h"
22 sysadm 1.45 #include "user_priv.h"
23 sysadm 1.1 #include <errno.h>
24 sysadm 1.4 #include <signal.h>
25 sysadm 1.29 #include <stdio.h>
26 sysadm 1.1 #include <stdlib.h>
27 sysadm 1.22 #include <string.h>
28 sysadm 1.4 #include <unistd.h>
29    
30 sysadm 1.5 int section_list_loader_pid;
31     int last_article_op_log_mid;
32 sysadm 1.1
33 sysadm 1.66 static void loader_proc_sig_usr1_handler(int i)
34     {
35     // Restart log
36     if (log_restart() < 0)
37     {
38     log_error("Restart logging failed\n");
39     }
40     }
41    
42 sysadm 1.38 int load_section_config_from_db(int update_gen_ex)
43 sysadm 1.1 {
44 sysadm 1.23 MYSQL *db = NULL;
45     MYSQL_RES *rs = NULL, *rs2 = NULL;
46 sysadm 1.1 MYSQL_ROW row, row2;
47     char sql[SQL_BUFFER_LEN];
48     int32_t sid;
49 sysadm 1.8 char master_list[(BBS_username_max_len + 1) * 3 + 1];
50 sysadm 1.1 SECTION_LIST *p_section;
51 sysadm 1.34 char ex_menu_conf[FILE_PATH_LEN];
52     MENU_SET ex_menu_set_new;
53 sysadm 1.23 int ret = 0;
54 sysadm 1.1
55 sysadm 1.2 db = db_open();
56     if (db == NULL)
57     {
58     log_error("db_open() error: %s\n", mysql_error(db));
59 sysadm 1.23 ret = -1;
60     goto cleanup;
61 sysadm 1.2 }
62    
63 sysadm 1.1 snprintf(sql, sizeof(sql),
64 sysadm 1.2 "SELECT section_config.SID, sname, section_config.title, section_config.CID, "
65 sysadm 1.34 "read_user_level, write_user_level, section_config.enable * section_class.enable AS enable, "
66     "UNIX_TIMESTAMP(ex_menu_tm) AS ex_menu_tm "
67 sysadm 1.2 "FROM section_config INNER JOIN section_class ON section_config.CID = section_class.CID "
68 sysadm 1.1 "ORDER BY section_config.SID");
69    
70     if (mysql_query(db, sql) != 0)
71     {
72     log_error("Query section_list error: %s\n", mysql_error(db));
73 sysadm 1.23 ret = -2;
74     goto cleanup;
75 sysadm 1.1 }
76     if ((rs = mysql_store_result(db)) == NULL)
77     {
78     log_error("Get section_list data failed\n");
79 sysadm 1.23 ret = -2;
80     goto cleanup;
81 sysadm 1.1 }
82 sysadm 1.2
83     ret = 0;
84 sysadm 1.1 while ((row = mysql_fetch_row(rs)))
85     {
86     sid = atoi(row[0]);
87    
88     // Query section master
89     snprintf(sql, sizeof(sql),
90     "SELECT username FROM section_master "
91     "INNER JOIN user_list ON section_master.UID = user_list.UID "
92     "WHERE SID = %d AND section_master.enable AND (NOW() BETWEEN begin_dt AND end_dt) "
93 sysadm 1.8 "ORDER BY major DESC, begin_dt ASC LIMIT 3",
94 sysadm 1.1 sid);
95    
96     if (mysql_query(db, sql) != 0)
97     {
98     log_error("Query section_master error: %s\n", mysql_error(db));
99 sysadm 1.2 ret = -3;
100     break;
101 sysadm 1.1 }
102     if ((rs2 = mysql_store_result(db)) == NULL)
103     {
104     log_error("Get section_master data failed\n");
105 sysadm 1.2 ret = -3;
106     break;
107 sysadm 1.1 }
108 sysadm 1.8
109     master_list[0] = '\0';
110     while ((row2 = mysql_fetch_row(rs2)))
111 sysadm 1.1 {
112 sysadm 1.8 strncat(master_list, row2[0], sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
113     strncat(master_list, " ", sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
114 sysadm 1.1 }
115     mysql_free_result(rs2);
116 sysadm 1.23 rs2 = NULL;
117 sysadm 1.1
118 sysadm 1.50 p_section = section_list_find_by_sid(sid);
119 sysadm 1.1
120     if (p_section == NULL)
121     {
122 sysadm 1.8 p_section = section_list_create(sid, row[1], row[2], master_list);
123 sysadm 1.1 if (p_section == NULL)
124     {
125 sysadm 1.2 log_error("section_list_create() error: load new section sid = %d sname = %s\n", sid, row[1]);
126     ret = -4;
127 sysadm 1.1 break;
128     }
129    
130     // acquire rw lock
131     ret = section_list_rw_lock(p_section);
132     if (ret < 0)
133     {
134     break;
135     }
136     }
137     else
138     {
139     // acquire rw lock
140     ret = section_list_rw_lock(p_section);
141     if (ret < 0)
142     {
143     break;
144     }
145    
146 sysadm 1.51 if (section_list_update(p_section, row[1], row[2], master_list) < 0)
147     {
148     log_error("section_list_update(sid=%d) error\n", p_section->sid);
149     ret = -4;
150     break;
151     }
152 sysadm 1.1 }
153    
154     p_section->class_id = atoi(row[3]);
155     p_section->read_user_level = atoi(row[4]);
156     p_section->write_user_level = atoi(row[5]);
157     p_section->enable = (int8_t)atoi(row[6]);
158    
159 sysadm 1.34 // Update gen_ex menu set
160 sysadm 1.46 if (update_gen_ex && p_section->enable && atol(row[7] == NULL ? "0" : row[7]) > p_section->ex_menu_tm)
161 sysadm 1.34 {
162     snprintf(ex_menu_conf, sizeof(ex_menu_conf), "%s/%d", VAR_GEN_EX_MENU_DIR, p_section->sid);
163    
164 sysadm 1.38 ret = load_menu(&ex_menu_set_new, ex_menu_conf);
165 sysadm 1.34 if (ret < 0)
166     {
167 sysadm 1.38 unload_menu(&ex_menu_set_new);
168     log_error("load_menu(%s) error: %d\n", ex_menu_conf, ret);
169 sysadm 1.34 }
170     else
171     {
172 sysadm 1.38 if (p_section->ex_menu_tm > 0)
173 sysadm 1.34 {
174 sysadm 1.38 unload_menu(&(p_section->ex_menu_set));
175 sysadm 1.34 }
176    
177 sysadm 1.38 ex_menu_set_new.allow_exit = 1; // Allow exit menu
178     memcpy(&(p_section->ex_menu_set), &ex_menu_set_new, sizeof(ex_menu_set_new));
179 sysadm 1.34
180 sysadm 1.38 p_section->ex_menu_tm = atol(row[7]);
181 sysadm 1.34 #ifdef _DEBUG
182 sysadm 1.38 log_common("Loaded gen_ex_menu of section %d [%s]\n", p_section->sid, p_section->sname);
183 sysadm 1.34 #endif
184     }
185     }
186    
187 sysadm 1.1 // release rw lock
188     ret = section_list_rw_unlock(p_section);
189     if (ret < 0)
190     {
191     break;
192     }
193     }
194 sysadm 1.23
195     cleanup:
196 sysadm 1.31 mysql_free_result(rs2);
197 sysadm 1.1 mysql_free_result(rs);
198 sysadm 1.2 mysql_close(db);
199    
200     return ret;
201 sysadm 1.1 }
202 sysadm 1.3
203 sysadm 1.9 int append_articles_from_db(int32_t start_aid, int global_lock, int article_count_limit)
204 sysadm 1.3 {
205 sysadm 1.23 MYSQL *db = NULL;
206     MYSQL_RES *rs = NULL;
207 sysadm 1.3 MYSQL_ROW row;
208     char sql[SQL_BUFFER_LEN];
209     ARTICLE article;
210 sysadm 1.5 ARTICLE *p_topic;
211 sysadm 1.3 SECTION_LIST *p_section = NULL;
212     int32_t last_sid = 0;
213 sysadm 1.16 char sub_ip[IP_ADDR_LEN];
214 sysadm 1.9 int article_count = 0;
215 sysadm 1.3 int ret = 0;
216     int i;
217    
218     db = db_open();
219     if (db == NULL)
220     {
221     log_error("db_open() error: %s\n", mysql_error(db));
222 sysadm 1.23 ret = -1;
223     goto cleanup;
224 sysadm 1.3 }
225    
226     snprintf(sql, sizeof(sql),
227 sysadm 1.11 "SELECT bbs.AID, TID, SID, bbs.CID, UID, visible, excerption, ontop, `lock`, "
228     "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt, "
229 sysadm 1.16 "sub_ip, bbs_content.content "
230 sysadm 1.11 "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
231     "WHERE bbs.AID >= %d ORDER BY bbs.AID LIMIT %d",
232 sysadm 1.9 start_aid, article_count_limit);
233 sysadm 1.3
234     if (mysql_query(db, sql) != 0)
235     {
236     log_error("Query article list error: %s\n", mysql_error(db));
237 sysadm 1.23 ret = -2;
238     goto cleanup;
239 sysadm 1.3 }
240 sysadm 1.11 if ((rs = mysql_use_result(db)) == NULL)
241 sysadm 1.3 {
242     log_error("Get article list data failed\n");
243 sysadm 1.23 ret = -2;
244     goto cleanup;
245 sysadm 1.3 }
246    
247     // acquire global lock
248 sysadm 1.23 if (global_lock && (ret = section_list_rw_lock(NULL)) < 0)
249 sysadm 1.3 {
250 sysadm 1.23 log_error("section_list_rw_lock(sid = 0) error\n");
251     goto cleanup;
252 sysadm 1.3 }
253    
254     while ((row = mysql_fetch_row(rs)))
255     {
256 sysadm 1.22 memset(&article, 0, sizeof(ARTICLE));
257 sysadm 1.3
258     // copy data of article
259     i = 0;
260    
261     article.aid = atoi(row[i++]);
262     article.tid = atoi(row[i++]);
263     article.sid = atoi(row[i++]);
264     article.cid = atoi(row[i++]);
265     article.uid = atoi(row[i++]);
266     article.visible = (int8_t)atoi(row[i++]);
267     article.excerption = (int8_t)atoi(row[i++]);
268     article.ontop = (int8_t)atoi(row[i++]);
269     article.lock = (int8_t)atoi(row[i++]);
270 sysadm 1.5 article.transship = (int8_t)atoi(row[i++]);
271 sysadm 1.3
272     strncpy(article.username, row[i++], sizeof(article.username) - 1);
273     article.username[sizeof(article.username) - 1] = '\0';
274     strncpy(article.nickname, row[i++], sizeof(article.nickname) - 1);
275     article.nickname[sizeof(article.nickname) - 1] = '\0';
276     strncpy(article.title, row[i++], sizeof(article.title) - 1);
277     article.title[sizeof(article.title) - 1] = '\0';
278    
279     article.sub_dt = atol(row[i++]);
280    
281 sysadm 1.16 strncpy(sub_ip, row[i++], sizeof(sub_ip) - 1);
282     sub_ip[sizeof(sub_ip) - 1] = '\0';
283     ip_mask(sub_ip, 1, '*');
284    
285 sysadm 1.3 // release lock of last section if different from current one
286     if (!global_lock && article.sid != last_sid && last_sid != 0)
287     {
288     if ((ret = section_list_rw_unlock(p_section)) < 0)
289     {
290 sysadm 1.11 log_error("section_list_rw_unlock(sid=%d) error\n", p_section->sid);
291 sysadm 1.3 break;
292     }
293     }
294    
295 sysadm 1.50 if ((p_section = section_list_find_by_sid(article.sid)) == NULL)
296 sysadm 1.3 {
297     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);
298 sysadm 1.4 ret = ERR_UNKNOWN_SECTION; // Unknown section found
299 sysadm 1.3 break;
300     }
301    
302 sysadm 1.5 if (article.visible != 0 && article.tid != 0)
303     {
304     // Check if topic article is visible
305     p_topic = article_block_find_by_aid(article.tid);
306     if (p_topic == NULL || p_topic->visible == 0)
307     {
308     // log_error("Set article (aid = %d) as invisible due to invisible or non-existing topic head\n", article.aid);
309     article.tid = 0;
310     article.visible = 0;
311     }
312     }
313    
314 sysadm 1.3 // acquire lock of current section if different from last one
315     if (!global_lock && article.sid != last_sid)
316     {
317 sysadm 1.4 if ((ret = section_list_rw_lock(p_section)) < 0)
318 sysadm 1.3 {
319 sysadm 1.11 log_error("section_list_rw_lock(sid=0) error\n");
320 sysadm 1.3 break;
321     }
322     }
323    
324     // append article to section list
325     last_sid = article.sid;
326    
327     if (section_list_append_article(p_section, &article) < 0)
328     {
329 sysadm 1.11 log_error("section_list_append_article(sid=%d, aid=%d) error\n",
330 sysadm 1.3 p_section->sid, article.aid);
331     ret = -3;
332     break;
333     }
334 sysadm 1.9
335     article_count++;
336    
337 sysadm 1.16 if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, &article, p_section, row[i++], sub_ip, 0) < 0)
338 sysadm 1.11 {
339     log_error("article_cache_generate(aid=%d, cid=%d) error\n", article.aid, article.cid);
340     ret = -4;
341     break;
342     }
343 sysadm 1.3 }
344    
345     // release lock of last section
346     if (!global_lock && last_sid != 0)
347     {
348     if ((ret = section_list_rw_unlock(p_section)) < 0)
349     {
350 sysadm 1.11 log_error("section_list_rw_unlock(sid=%d) error\n", p_section->sid);
351 sysadm 1.3 }
352     }
353    
354     // release global lock
355 sysadm 1.23 if (global_lock && (ret = section_list_rw_unlock(NULL)) < 0)
356 sysadm 1.3 {
357 sysadm 1.23 log_error("section_list_rw_unlock(sid=0) error\n");
358 sysadm 1.3 }
359    
360     cleanup:
361     mysql_free_result(rs);
362     mysql_close(db);
363    
364 sysadm 1.31 article_cache_cleanup();
365    
366 sysadm 1.9 return (ret < 0 ? ret : article_count);
367 sysadm 1.3 }
368 sysadm 1.4
369 sysadm 1.5 int set_last_article_op_log_from_db(void)
370     {
371 sysadm 1.23 MYSQL *db = NULL;
372     MYSQL_RES *rs = NULL;
373 sysadm 1.5 MYSQL_ROW row;
374     char sql[SQL_BUFFER_LEN];
375 sysadm 1.23 int ret = 0;
376 sysadm 1.5
377     db = db_open();
378     if (db == NULL)
379     {
380     log_error("db_open() error: %s\n", mysql_error(db));
381 sysadm 1.23 ret = -1;
382     goto cleanup;
383 sysadm 1.5 }
384    
385     snprintf(sql, sizeof(sql),
386     "SELECT MID FROM bbs_article_op ORDER BY MID DESC LIMIT 1");
387    
388     if (mysql_query(db, sql) != 0)
389     {
390     log_error("Query article op error: %s\n", mysql_error(db));
391 sysadm 1.23 ret = -2;
392     goto cleanup;
393 sysadm 1.5 }
394     if ((rs = mysql_store_result(db)) == NULL)
395     {
396     log_error("Get article op data failed\n");
397 sysadm 1.23 ret = -2;
398     goto cleanup;
399 sysadm 1.5 }
400    
401     if ((row = mysql_fetch_row(rs)))
402     {
403     last_article_op_log_mid = atoi(row[0]);
404     }
405    
406 sysadm 1.23 cleanup:
407 sysadm 1.5 mysql_free_result(rs);
408     mysql_close(db);
409    
410 sysadm 1.23 return (ret < 0 ? ret : last_article_op_log_mid);
411 sysadm 1.5 }
412    
413 sysadm 1.9 int apply_article_op_log_from_db(int op_count_limit)
414 sysadm 1.5 {
415 sysadm 1.23 MYSQL *db = NULL;
416     MYSQL_RES *rs = NULL, *rs2 = NULL;
417 sysadm 1.5 MYSQL_ROW row, row2;
418     char sql[SQL_BUFFER_LEN];
419     ARTICLE *p_article;
420     SECTION_LIST *p_section = NULL;
421     SECTION_LIST *p_section_dest;
422 sysadm 1.16 char sub_ip[IP_ADDR_LEN];
423 sysadm 1.5 int32_t last_sid = 0;
424     int32_t sid_dest;
425 sysadm 1.9 int op_count = 0;
426 sysadm 1.5 int ret = 0;
427    
428     db = db_open();
429     if (db == NULL)
430     {
431     log_error("db_open() error: %s\n", mysql_error(db));
432 sysadm 1.23 ret = -1;
433     goto cleanup;
434 sysadm 1.5 }
435    
436     snprintf(sql, sizeof(sql),
437     "SELECT MID, AID, type FROM bbs_article_op "
438 sysadm 1.9 "WHERE MID > %d AND type NOT IN ('A') "
439     "ORDER BY MID LIMIT %d",
440     last_article_op_log_mid, op_count_limit);
441 sysadm 1.5
442     if (mysql_query(db, sql) != 0)
443     {
444     log_error("Query article log error: %s\n", mysql_error(db));
445 sysadm 1.23 ret = -2;
446     goto cleanup;
447 sysadm 1.5 }
448     if ((rs = mysql_store_result(db)) == NULL)
449     {
450     log_error("Get article log data failed\n");
451 sysadm 1.23 ret = -2;
452     goto cleanup;
453 sysadm 1.5 }
454    
455     while ((row = mysql_fetch_row(rs)))
456     {
457     p_article = article_block_find_by_aid(atoi(row[1]));
458     if (p_article == NULL) // related article has not been appended yet
459     {
460     ret = -2;
461     break;
462     }
463    
464     // release lock of last section if different from current one
465     if (p_article->sid != last_sid && last_sid != 0)
466     {
467     if ((ret = section_list_rw_unlock(p_section)) < 0)
468     {
469     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
470     break;
471     }
472     }
473    
474 sysadm 1.50 if ((p_section = section_list_find_by_sid(p_article->sid)) == NULL)
475 sysadm 1.5 {
476     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", p_article->sid);
477     ret = ERR_UNKNOWN_SECTION; // Unknown section found
478     break;
479     }
480    
481     // acquire lock of current section if different from last one
482     if (p_article->sid != last_sid)
483     {
484     if ((ret = section_list_rw_lock(p_section)) < 0)
485     {
486     log_error("section_list_rw_lock(sid = 0) error\n");
487     break;
488     }
489     }
490    
491     last_sid = p_article->sid;
492    
493     switch (row[2][0])
494     {
495     case 'A': // Add article
496     log_error("Operation type=A should not be found\n");
497     break;
498     case 'D': // Delete article
499     case 'X': // Delete article by Admin
500 sysadm 1.20 if (section_list_set_article_visible(p_section, atoi(row[1]), 0) < 0)
501 sysadm 1.5 {
502 sysadm 1.20 log_error("section_list_set_article_visible(sid=%d, aid=%d, visible=0) error\n", p_section->sid, atoi(row[1]));
503     }
504     if (section_list_calculate_page(p_section, atoi(row[1])) < 0)
505     {
506     log_error("section_list_calculate_page(aid=%d) error\n", atoi(row[1]));
507 sysadm 1.5 }
508     break;
509     case 'S': // Restore article
510 sysadm 1.20 if (section_list_set_article_visible(p_section, atoi(row[1]), 1) < 0)
511     {
512     log_error("section_list_set_article_visible(sid=%d, aid=%d, visible=1) error\n", p_section->sid, atoi(row[1]));
513     }
514     if (section_list_calculate_page(p_section, atoi(row[1])) < 0)
515     {
516     log_error("section_list_calculate_page(aid=%d) error\n", atoi(row[1]));
517     }
518 sysadm 1.5 break;
519     case 'L': // Lock article
520     p_article->lock = 1;
521     break;
522     case 'U': // Unlock article
523     p_article->lock = 0;
524     break;
525     case 'M': // Modify article
526 sysadm 1.9 snprintf(sql, sizeof(sql),
527 sysadm 1.16 "SELECT bbs.CID, sub_ip, bbs_content.content "
528 sysadm 1.11 "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
529     "WHERE bbs.AID = %d",
530 sysadm 1.9 p_article->aid);
531    
532     if (mysql_query(db, sql) != 0)
533     {
534     log_error("Query article error: %s\n", mysql_error(db));
535     ret = -3;
536     break;
537     }
538 sysadm 1.12 if ((rs2 = mysql_use_result(db)) == NULL)
539 sysadm 1.9 {
540     log_error("Get article data failed\n");
541     ret = -3;
542     break;
543     }
544     if ((row2 = mysql_fetch_row(rs2)))
545     {
546     p_article->cid = atoi(row2[0]);
547 sysadm 1.11
548 sysadm 1.16 strncpy(sub_ip, row2[1], sizeof(sub_ip) - 1);
549     sub_ip[sizeof(sub_ip) - 1] = '\0';
550     ip_mask(sub_ip, 1, '*');
551    
552     if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, p_article, p_section, row2[2], sub_ip, 0) < 0)
553 sysadm 1.11 {
554     log_error("article_cache_generate(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);
555     ret = -4;
556     }
557 sysadm 1.9 }
558     else
559     {
560     p_article->cid = 0;
561     ret = -4;
562     }
563     mysql_free_result(rs2);
564 sysadm 1.23 rs2 = NULL;
565 sysadm 1.21
566     p_article->excerption = 0; // Set excerption = 0 implicitly in case of rare condition
567 sysadm 1.5 break;
568     case 'T': // Move article
569     snprintf(sql, sizeof(sql),
570     "SELECT SID FROM bbs WHERE AID = %d",
571     p_article->aid);
572    
573     if (mysql_query(db, sql) != 0)
574     {
575     log_error("Query article error: %s\n", mysql_error(db));
576     ret = -3;
577     break;
578     }
579     if ((rs2 = mysql_store_result(db)) == NULL)
580     {
581     log_error("Get article data failed\n");
582     ret = -3;
583     break;
584     }
585     if ((row2 = mysql_fetch_row(rs2)))
586     {
587     sid_dest = atoi(row2[0]);
588     }
589     else
590     {
591     sid_dest = 0;
592     ret = -4;
593     }
594     mysql_free_result(rs2);
595 sysadm 1.23 rs2 = NULL;
596 sysadm 1.5
597     if (sid_dest > 0 && sid_dest != p_article->sid)
598     {
599 sysadm 1.50 p_section_dest = section_list_find_by_sid(sid_dest);
600 sysadm 1.5 if (p_section_dest == NULL)
601     {
602     ret = ERR_UNKNOWN_SECTION;
603     break;
604     }
605 sysadm 1.6 // acquire lock of dest section
606     if ((ret = section_list_rw_lock(p_section_dest)) < 0)
607     {
608     log_error("section_list_rw_lock(sid = %d) error\n", p_section_dest);
609     break;
610     }
611 sysadm 1.5 // Move topic
612     if ((ret = section_list_move_topic(p_section, p_section_dest, p_article->aid)) < 0)
613     {
614 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",
615     p_section->sid, p_section_dest->sid, p_article->aid, ret);
616     }
617     // release lock of dest section
618     if (section_list_rw_unlock(p_section_dest) < 0)
619     {
620     log_error("section_list_rw_unlock(sid = %d) error\n", p_section_dest);
621     ret = -1;
622 sysadm 1.5 }
623     }
624     break;
625     case 'E': // Set article as excerption
626     p_article->excerption = 1;
627     break;
628     case 'O': // Unset article as excerption
629     p_article->excerption = 0;
630     break;
631     case 'F': // Set article on top
632     case 'V': // Unset article on top
633 sysadm 1.32 p_article->ontop = (row[2][0] == 'F' ? 1 : 0);
634     if (section_list_update_article_ontop(p_section, p_article) < 0)
635     {
636     log_error("section_list_update_article_ontop(sid=%d, aid=%d) error\n",
637     p_section->sid, p_article->aid);
638     }
639 sysadm 1.5 break;
640     case 'Z': // Set article as trnasship
641     p_article->transship = 1;
642     break;
643     default:
644     // log_error("Operation type=%s unknown, mid=%s\n", row[2], row[0]);
645     break;
646     }
647    
648     if (ret < 0)
649     {
650     break;
651     }
652    
653     // Update MID with last successfully proceeded article_op_log
654     last_article_op_log_mid = atoi(row[0]);
655 sysadm 1.9
656     op_count++;
657 sysadm 1.5 }
658    
659     // release lock of last section
660     if (last_sid != 0)
661     {
662     if ((ret = section_list_rw_unlock(p_section)) < 0)
663     {
664     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
665     }
666     }
667    
668 sysadm 1.23 cleanup:
669     mysql_free_result(rs2);
670 sysadm 1.5 mysql_free_result(rs);
671     mysql_close(db);
672    
673 sysadm 1.9 return (ret < 0 ? ret : op_count);
674 sysadm 1.5 }
675    
676 sysadm 1.39 static void section_list_ex_menu_set_cleanup(void)
677     {
678     int i;
679    
680     for (i = 0; i < p_section_list_pool->section_count; i++)
681     {
682     if (p_section_list_pool->sections[i].ex_menu_tm > 0)
683     {
684     unload_menu(&(p_section_list_pool->sections[i].ex_menu_set));
685     }
686     }
687     }
688    
689 sysadm 1.4 int section_list_loader_launch(void)
690     {
691 sysadm 1.34 struct sigaction act = {0};
692 sysadm 1.4 int pid;
693     int ret;
694     int32_t last_aid;
695     int article_count;
696     int load_count;
697 sysadm 1.5 int last_mid;
698 sysadm 1.52 time_t tm_section_list_reload = 0;
699 sysadm 1.54 time_t tm_user_list_reload = time(NULL);
700     time_t tm_user_online_list_reload = time(NULL);
701 sysadm 1.4
702     if (section_list_loader_pid != 0)
703     {
704     log_error("section_list_loader already running, pid = %d\n", section_list_loader_pid);
705     return -2;
706     }
707    
708     pid = fork();
709    
710     if (pid > 0) // Parent process
711     {
712     SYS_child_process_count++;
713     section_list_loader_pid = pid;
714 sysadm 1.18 log_common("Section list loader process (pid = %d) start\n", pid);
715 sysadm 1.4 return 0;
716     }
717     else if (pid < 0) // Error
718     {
719     log_error("fork() error (%d)\n", errno);
720     return -1;
721     }
722    
723     // Child process
724     SYS_child_process_count = 0;
725    
726     // Detach menu in shared memory
727 sysadm 1.36 detach_menu_shm(&bbs_menu);
728 sysadm 1.49 detach_menu_shm(&top10_menu);
729 sysadm 1.4
730 sysadm 1.34 // Set signal handler
731 sysadm 1.58 act.sa_handler = SIG_IGN;
732 sysadm 1.38 if (sigaction(SIGHUP, &act, NULL) == -1)
733     {
734     log_error("set signal action of SIGHUP error: %d\n", errno);
735     }
736     act.sa_handler = SIG_DFL;
737 sysadm 1.34 if (sigaction(SIGCHLD, &act, NULL) == -1)
738     {
739     log_error("set signal action of SIGCHLD error: %d\n", errno);
740     }
741 sysadm 1.66 act.sa_handler = loader_proc_sig_usr1_handler;
742     if (sigaction(SIGUSR1, &act, NULL) == -1)
743     {
744     log_error("set signal action of SIGUSR1 error: %d\n", errno);
745     }
746 sysadm 1.34
747 sysadm 1.4 // Do section data loader periodically
748     while (!SYS_server_exit)
749     {
750 sysadm 1.52 tm_section_list_reload = time(NULL);
751    
752 sysadm 1.38 if (SYS_conf_reload)
753 sysadm 1.4 {
754 sysadm 1.38 SYS_conf_reload = 0;
755 sysadm 1.4
756     // Load section config
757 sysadm 1.38 if (load_section_config_from_db(0) < 0)
758 sysadm 1.4 {
759 sysadm 1.38 log_error("load_section_config_from_db(0) error\n");
760 sysadm 1.4 }
761     else
762     {
763 sysadm 1.27 log_common("Reload section config successfully\n");
764 sysadm 1.4 }
765     }
766    
767     // Load section articles
768     article_count = article_block_article_count();
769    
770 sysadm 1.9 do
771 sysadm 1.4 {
772 sysadm 1.9 last_aid = article_block_last_aid();
773 sysadm 1.4
774 sysadm 1.9 if ((ret = append_articles_from_db(last_aid + 1, 0, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
775 sysadm 1.4 {
776 sysadm 1.9 log_error("append_articles_from_db(%d, 0, %d) error\n", last_aid + 1, LOAD_ARTICLE_COUNT_LIMIT);
777    
778     if (ret == ERR_UNKNOWN_SECTION)
779     {
780 sysadm 1.38 SYS_conf_reload = 1; // Force reload section_list
781 sysadm 1.9 }
782 sysadm 1.4 }
783 sysadm 1.9 } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
784 sysadm 1.5
785     load_count = article_block_article_count() - article_count;
786     if (load_count > 0)
787     {
788 sysadm 1.17 log_common("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
789 sysadm 1.5 }
790    
791 sysadm 1.38 if (SYS_conf_reload)
792 sysadm 1.5 {
793     continue;
794     }
795    
796     // Load article_op log
797     last_mid = last_article_op_log_mid;
798    
799 sysadm 1.9 do
800 sysadm 1.4 {
801 sysadm 1.9 if ((ret = apply_article_op_log_from_db(LOAD_ARTICLE_COUNT_LIMIT)) < 0)
802     {
803     log_error("apply_article_op_log_from_db() error\n");
804 sysadm 1.4
805 sysadm 1.9 if (ret == ERR_UNKNOWN_SECTION)
806     {
807 sysadm 1.38 SYS_conf_reload = 1; // Force reload section_list
808 sysadm 1.9 }
809 sysadm 1.4 }
810 sysadm 1.9 } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
811 sysadm 1.4
812 sysadm 1.5 if (last_article_op_log_mid > last_mid)
813     {
814 sysadm 1.17 log_common("Proceeded %d article logs, last_mid = %d\n", last_article_op_log_mid - last_mid, last_article_op_log_mid);
815 sysadm 1.5 }
816    
817 sysadm 1.52 // Reload user list
818     if (time(NULL) - tm_user_list_reload >= BBS_user_list_load_interval)
819 sysadm 1.5 {
820 sysadm 1.53 if (user_list_pool_reload(0) < 0)
821 sysadm 1.52 {
822 sysadm 1.53 log_error("user_list_pool_reload(all_user) error\n");
823 sysadm 1.52 }
824 sysadm 1.55
825     if (user_stat_update() < 0)
826     {
827     log_error("user_stat_update() error\n");
828     }
829    
830 sysadm 1.52 tm_user_list_reload = time(NULL);
831 sysadm 1.5 }
832    
833 sysadm 1.53 // Reload user online list
834     if (time(NULL) - tm_user_online_list_reload >= BBS_user_online_list_load_interval)
835     {
836     if (user_list_pool_reload(1) < 0)
837     {
838     log_error("user_list_pool_reload(online_user) error\n");
839     }
840 sysadm 1.55
841 sysadm 1.53 tm_user_online_list_reload = time(NULL);
842     }
843    
844 sysadm 1.52 // Wait for BBS_section_list_load_interval seconds
845     while (!SYS_server_exit && time(NULL) - tm_section_list_reload < BBS_section_list_load_interval)
846 sysadm 1.5 {
847     sleep(1);
848 sysadm 1.4 }
849     }
850    
851     // Child process exit
852    
853 sysadm 1.31 article_cache_cleanup();
854    
855 sysadm 1.34 // gen_ex_menu cleanup
856     section_list_ex_menu_set_cleanup();
857 sysadm 1.37
858 sysadm 1.4 // Detach data pools shm
859     detach_section_list_shm();
860     detach_article_block_shm();
861     detach_trie_dict_shm();
862 sysadm 1.52 detach_user_list_pool_shm();
863 sysadm 1.4
864 sysadm 1.17 log_common("Section list loader process exit normally\n");
865 sysadm 1.4 log_end();
866    
867     section_list_loader_pid = 0;
868    
869     _exit(0);
870    
871     return 0;
872     }
873    
874 sysadm 1.33 int query_section_articles(SECTION_LIST *p_section, int page_id, ARTICLE *p_articles[],
875     int *p_article_count, int *p_page_count, int *p_ontop_start_offset)
876 sysadm 1.7 {
877     ARTICLE *p_article;
878     ARTICLE *p_next_page_first_article;
879     int ret = 0;
880 sysadm 1.32 int i;
881 sysadm 1.7
882 sysadm 1.33 if (p_section == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL || p_ontop_start_offset == NULL)
883 sysadm 1.7 {
884 sysadm 1.34 log_error("NULL pointer error\n");
885 sysadm 1.7 return -1;
886     }
887    
888     // acquire lock of section
889     if ((ret = section_list_rd_lock(p_section)) < 0)
890     {
891     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
892     return -2;
893     }
894    
895 sysadm 1.32 *p_page_count = section_list_page_count_with_ontop(p_section);
896     *p_article_count = 0;
897 sysadm 1.33 *p_ontop_start_offset = BBS_article_limit_per_page;
898 sysadm 1.10
899 sysadm 1.9 if (p_section->visible_article_count == 0)
900     {
901 sysadm 1.32 // empty section
902 sysadm 1.9 }
903 sysadm 1.32 else if (page_id < 0 || page_id >= *p_page_count)
904 sysadm 1.7 {
905 sysadm 1.60 #ifdef _DEBUG
906 sysadm 1.32 log_error("Invalid page_id=%d, not in range [0, %d)\n", page_id, *p_page_count);
907 sysadm 1.60 #endif
908 sysadm 1.7 ret = -3;
909     }
910     else
911     {
912     ret = page_id;
913    
914 sysadm 1.32 if (page_id <= p_section->page_count - 1)
915 sysadm 1.7 {
916 sysadm 1.32 p_article = p_section->p_page_first_article[page_id];
917     p_next_page_first_article =
918     (page_id == p_section->page_count - 1 ? p_section->p_article_head : p_section->p_page_first_article[page_id + 1]);
919    
920     do
921     {
922     if (p_article->visible)
923     {
924     p_articles[*p_article_count] = p_article;
925     (*p_article_count)++;
926     }
927     p_article = p_article->p_next;
928     } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);
929    
930     if (*p_article_count != (page_id < p_section->page_count - 1 ? BBS_article_limit_per_page : p_section->last_page_visible_article_count))
931 sysadm 1.7 {
932 sysadm 1.32 log_error("Inconsistent visible article count %d detected in section %d page %d\n", *p_article_count, p_section->sid, page_id);
933 sysadm 1.7 }
934 sysadm 1.32 }
935 sysadm 1.8
936 sysadm 1.33 *p_ontop_start_offset = *p_article_count;
937    
938 sysadm 1.32 // Append ontop articles
939     if (page_id >= p_section->page_count - 1)
940 sysadm 1.8 {
941 sysadm 1.32 i = (page_id == p_section->page_count - 1
942     ? 0
943     : (page_id - p_section->page_count + 1) * BBS_article_limit_per_page - p_section->last_page_visible_article_count);
944     while (*p_article_count < BBS_article_limit_per_page && i < p_section->ontop_article_count)
945     {
946 sysadm 1.59 p_articles[*p_article_count] = p_section->p_ontop_articles[i++];
947     (*p_article_count)++;
948 sysadm 1.32 }
949 sysadm 1.8 }
950 sysadm 1.7 }
951    
952     // release lock of section
953 sysadm 1.8 if (section_list_rd_unlock(p_section) < 0)
954 sysadm 1.7 {
955     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
956     ret = -2;
957     }
958    
959     return ret;
960     }
961 sysadm 1.14
962 sysadm 1.24 int locate_article_in_section(SECTION_LIST *p_section, const ARTICLE *p_article_cur, int direction, int step,
963 sysadm 1.15 int *p_page_id, int *p_visible_offset, int *p_article_count)
964 sysadm 1.14 {
965 sysadm 1.15 const ARTICLE *p_article = NULL;
966 sysadm 1.40 const ARTICLE *p_article_last = NULL;
967 sysadm 1.15 ARTICLE *p_tmp;
968 sysadm 1.14 int32_t aid = 0;
969 sysadm 1.24 int page_id = 0;
970     int offset = 0;
971 sysadm 1.14 int ret = 0;
972 sysadm 1.15 int i;
973 sysadm 1.14
974 sysadm 1.15 if (p_section == NULL || p_article_cur == NULL || p_page_id == NULL || p_visible_offset == NULL || p_article_count == NULL)
975 sysadm 1.14 {
976 sysadm 1.34 log_error("NULL pointer error\n");
977 sysadm 1.14 return -1;
978     }
979    
980     // acquire lock of section
981     if ((ret = section_list_rd_lock(p_section)) < 0)
982     {
983     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
984     return -2;
985     }
986    
987     if (direction == 0)
988     {
989     aid = p_article_cur->aid;
990     }
991     else if (direction == 1)
992     {
993 sysadm 1.43 for (p_article_last = p_article_cur, p_article = p_article_cur->p_topic_next;
994     step > 0 && p_article->aid > p_article_cur->aid;
995 sysadm 1.40 p_article = p_article->p_topic_next)
996 sysadm 1.14 {
997 sysadm 1.24 if (p_article->visible)
998     {
999     step--;
1000 sysadm 1.40 p_article_last = p_article;
1001 sysadm 1.24 }
1002     }
1003 sysadm 1.43 p_article = p_article_last;
1004 sysadm 1.15
1005 sysadm 1.25 aid = (p_article->aid > p_article_cur->aid && p_article->visible ? p_article->aid : 0);
1006 sysadm 1.14 }
1007     else if (direction == -1)
1008     {
1009 sysadm 1.43 for (p_article_last = p_article_cur, p_article = p_article_cur->p_topic_prior;
1010     step > 0 && p_article->aid < p_article_cur->aid;
1011 sysadm 1.40 p_article = p_article->p_topic_prior)
1012 sysadm 1.14 {
1013 sysadm 1.24 if (p_article->visible)
1014     {
1015     step--;
1016 sysadm 1.40 p_article_last = p_article;
1017 sysadm 1.24 }
1018     }
1019 sysadm 1.43 p_article = p_article_last;
1020 sysadm 1.15
1021 sysadm 1.25 aid = (p_article->aid < p_article_cur->aid && p_article->visible ? p_article->aid : 0);
1022 sysadm 1.14 }
1023    
1024 sysadm 1.15 p_article = NULL;
1025    
1026 sysadm 1.14 if (aid > 0)
1027     {
1028 sysadm 1.15 p_article = section_list_find_article_with_offset(p_section, aid, &page_id, &offset, &p_tmp);
1029 sysadm 1.14 if (p_article != NULL)
1030     {
1031 sysadm 1.60 *p_article_count = (page_id >= p_section->page_count - 1 ? p_section->last_page_visible_article_count : BBS_article_limit_per_page);
1032 sysadm 1.15
1033     p_article = p_section->p_page_first_article[page_id];
1034 sysadm 1.25 for (i = 0; i < *p_article_count && p_article != NULL;)
1035 sysadm 1.15 {
1036     if (p_article->visible)
1037     {
1038     if (p_article->aid == aid)
1039     {
1040     *p_page_id = page_id;
1041     *p_visible_offset = i;
1042     break;
1043     }
1044     i++;
1045     if (i >= *p_article_count)
1046     {
1047     log_error("Visible article (aid=%d) not found in page %d\n", aid, page_id);
1048     p_article = NULL;
1049 sysadm 1.25 break;
1050 sysadm 1.15 }
1051     }
1052 sysadm 1.61
1053 sysadm 1.15 p_article = p_article->p_next;
1054 sysadm 1.61 if (p_article == p_section->p_page_first_article[page_id])
1055     {
1056     log_error("Dead loop detected at page=%d, article_count=%d\n", page_id, *p_article_count);
1057     break;
1058     }
1059 sysadm 1.15 }
1060 sysadm 1.32
1061     // Include ontop articles
1062     *p_article_count = section_list_page_article_count_with_ontop(p_section, page_id);
1063 sysadm 1.14 }
1064     }
1065    
1066     // release lock of section
1067     if (section_list_rd_unlock(p_section) < 0)
1068     {
1069     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1070     ret = -2;
1071     }
1072    
1073     return (ret < 0 ? ret : (p_article == NULL ? 0 : 1));
1074     }
1075 sysadm 1.34
1076 sysadm 1.62 int last_article_in_section(SECTION_LIST *p_section, const ARTICLE **pp_article)
1077     {
1078     int ret = 0;
1079    
1080     const ARTICLE *p_article;
1081    
1082     if (p_section == NULL || pp_article == NULL)
1083     {
1084     log_error("NULL pointer error\n");
1085     return -1;
1086     }
1087    
1088     *pp_article = NULL;
1089    
1090     // acquire lock of section
1091     if ((ret = section_list_rd_lock(p_section)) < 0)
1092     {
1093     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1094     return -2;
1095     }
1096    
1097     for (p_article = p_section->p_article_tail;
1098     p_article && p_article != p_section->p_article_head && !p_article->visible;
1099     p_article = p_article->p_prior)
1100     ;
1101    
1102     if (p_article && p_article->visible)
1103     {
1104     *pp_article = p_article;
1105     ret = 1;
1106     }
1107    
1108     // release lock of section
1109     if (section_list_rd_unlock(p_section) < 0)
1110     {
1111     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1112     ret = -2;
1113     }
1114    
1115     return ret;
1116     }
1117    
1118 sysadm 1.44 int scan_unread_article_in_section(SECTION_LIST *p_section, const ARTICLE *p_article_cur, const ARTICLE **pp_article_unread)
1119     {
1120     ARTICLE *p_article;
1121     int ret = 0;
1122    
1123     if (p_section == NULL || p_article_cur == NULL || pp_article_unread == NULL)
1124     {
1125     log_error("NULL pointer error\n");
1126     return -1;
1127     }
1128    
1129     if (p_article_cur->sid != p_section->sid)
1130     {
1131     log_error("Inconsistent SID\n");
1132     return -1;
1133     }
1134    
1135     // acquire lock of section
1136     if ((ret = section_list_rd_lock(p_section)) < 0)
1137     {
1138     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1139     return -2;
1140     }
1141    
1142     *pp_article_unread = NULL;
1143    
1144     for (p_article = p_article_cur->p_next; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_next)
1145     {
1146 sysadm 1.45 if (p_article->visible && p_article->uid != BBS_priv.uid && !article_view_log_is_viewed(p_article->aid, &BBS_article_view_log))
1147 sysadm 1.44 {
1148     *pp_article_unread = p_article;
1149     break;
1150     }
1151     }
1152    
1153     // release lock of section
1154     if (section_list_rd_unlock(p_section) < 0)
1155     {
1156     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1157     return -2;
1158     }
1159    
1160     return (p_article != NULL && p_article != p_article_cur ? 1 : 0);
1161     }
1162    
1163 sysadm 1.56 int scan_article_in_section_by_uid(SECTION_LIST *p_section, const ARTICLE *p_article_cur,
1164     int direction, int32_t uid, const ARTICLE **pp_article)
1165     {
1166     ARTICLE *p_article;
1167     int ret = 0;
1168    
1169     if (p_section == NULL || p_article_cur == NULL || pp_article == NULL)
1170     {
1171     log_error("NULL pointer error\n");
1172     return -1;
1173     }
1174    
1175     if (p_article_cur->sid != p_section->sid)
1176     {
1177     log_error("Inconsistent SID\n");
1178     return -1;
1179     }
1180    
1181     // acquire lock of section
1182     if ((ret = section_list_rd_lock(p_section)) < 0)
1183     {
1184     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1185     return -2;
1186     }
1187    
1188     *pp_article = NULL;
1189    
1190     if (direction >= 0)
1191     {
1192     for (p_article = p_article_cur->p_next; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_next)
1193     {
1194     if (p_article->visible && p_article->uid == uid)
1195     {
1196     *pp_article = p_article;
1197     break;
1198     }
1199     }
1200     }
1201     else // direction < 0
1202     {
1203     for (p_article = p_article_cur->p_prior; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_prior)
1204     {
1205     if (p_article->visible && p_article->uid == uid)
1206     {
1207     *pp_article = p_article;
1208     break;
1209     }
1210     }
1211     }
1212    
1213     // release lock of section
1214     if (section_list_rd_unlock(p_section) < 0)
1215     {
1216     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1217     return -2;
1218     }
1219    
1220     return (p_article != NULL && p_article != p_article_cur ? 1 : 0);
1221     }
1222    
1223     int scan_article_in_section_by_username(SECTION_LIST *p_section, const ARTICLE *p_article_cur,
1224     int direction, const char *username, const ARTICLE **pp_article)
1225     {
1226     ARTICLE *p_article;
1227     int ret = 0;
1228    
1229     if (p_section == NULL || p_article_cur == NULL || username == NULL || pp_article == NULL)
1230     {
1231     log_error("NULL pointer error\n");
1232     return -1;
1233     }
1234    
1235     if (p_article_cur->sid != p_section->sid)
1236     {
1237     log_error("Inconsistent SID\n");
1238     return -1;
1239     }
1240    
1241     // acquire lock of section
1242     if ((ret = section_list_rd_lock(p_section)) < 0)
1243     {
1244     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1245     return -2;
1246     }
1247    
1248     *pp_article = NULL;
1249    
1250     if (direction >= 0)
1251     {
1252     for (p_article = p_article_cur->p_next; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_next)
1253     {
1254     if (p_article->visible && strcasecmp(p_article->username, username) == 0)
1255     {
1256     *pp_article = p_article;
1257     break;
1258     }
1259     }
1260     }
1261     else // direction < 0
1262     {
1263     for (p_article = p_article_cur->p_prior; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_prior)
1264     {
1265     if (p_article->visible && strcasecmp(p_article->username, username) == 0)
1266     {
1267     *pp_article = p_article;
1268     break;
1269     }
1270     }
1271     }
1272    
1273     // release lock of section
1274     if (section_list_rd_unlock(p_section) < 0)
1275     {
1276     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1277     return -2;
1278     }
1279    
1280     return (p_article != NULL && p_article != p_article_cur ? 1 : 0);
1281     }
1282    
1283 sysadm 1.57 int scan_article_in_section_by_title(SECTION_LIST *p_section, const ARTICLE *p_article_cur,
1284 sysadm 1.61 int direction, const char *title, const ARTICLE **pp_article)
1285 sysadm 1.57 {
1286     ARTICLE *p_article;
1287     int ret = 0;
1288    
1289     if (p_section == NULL || p_article_cur == NULL || title == NULL || pp_article == NULL)
1290     {
1291     log_error("NULL pointer error\n");
1292     return -1;
1293     }
1294    
1295     if (p_article_cur->sid != p_section->sid)
1296     {
1297     log_error("Inconsistent SID\n");
1298     return -1;
1299     }
1300    
1301     // acquire lock of section
1302     if ((ret = section_list_rd_lock(p_section)) < 0)
1303     {
1304     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1305     return -2;
1306     }
1307    
1308     *pp_article = NULL;
1309    
1310     if (direction >= 0)
1311     {
1312     for (p_article = p_article_cur->p_next; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_next)
1313     {
1314     if (p_article->visible && strcasestr(p_article->title, title) != NULL)
1315     {
1316     *pp_article = p_article;
1317     break;
1318     }
1319     }
1320     }
1321     else // direction < 0
1322     {
1323     for (p_article = p_article_cur->p_prior; p_article != NULL && p_article != p_article_cur; p_article = p_article->p_prior)
1324     {
1325     if (p_article->visible && strcasestr(p_article->title, title) != NULL)
1326     {
1327     *pp_article = p_article;
1328     break;
1329     }
1330     }
1331     }
1332    
1333     // release lock of section
1334     if (section_list_rd_unlock(p_section) < 0)
1335     {
1336     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1337     return -2;
1338     }
1339    
1340     return (p_article != NULL && p_article != p_article_cur ? 1 : 0);
1341     }
1342    
1343 sysadm 1.34 int get_section_ex_menu_set(SECTION_LIST *p_section, MENU_SET *p_ex_menu_set)
1344     {
1345     int ret = 0;
1346    
1347     if (p_section == NULL || p_ex_menu_set == NULL)
1348     {
1349     log_error("NULL pointer error\n");
1350     return -1;
1351     }
1352    
1353     // acquire lock of section
1354     if ((ret = section_list_rd_lock(p_section)) < 0)
1355     {
1356     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
1357     return -2;
1358     }
1359    
1360     memcpy(p_ex_menu_set, &(p_section->ex_menu_set), sizeof(p_section->ex_menu_set));
1361    
1362     // release lock of section
1363     if (section_list_rd_unlock(p_section) < 0)
1364     {
1365     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
1366     ret = -2;
1367     }
1368    
1369     return ret;
1370     }

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