/[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.8 - (hide annotations)
Wed May 28 07:30:23 2025 UTC (9 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.7: +21 -19 lines
Content type: text/x-csrc
Add section_list_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     int append_articles_from_db(int32_t start_aid, int global_lock)
162     {
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     int ret = 0;
172     int i;
173    
174     db = db_open();
175     if (db == NULL)
176     {
177     log_error("db_open() error: %s\n", mysql_error(db));
178     return -2;
179     }
180    
181     snprintf(sql, sizeof(sql),
182 sysadm 1.5 "SELECT AID, TID, SID, CID, UID, visible, excerption, ontop, `lock`, "
183     "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt "
184 sysadm 1.3 "FROM bbs WHERE AID >= %d ORDER BY AID",
185     start_aid);
186    
187     if (mysql_query(db, sql) != 0)
188     {
189     log_error("Query article list error: %s\n", mysql_error(db));
190     return -3;
191     }
192     if ((rs = mysql_use_result(db)) == NULL)
193     {
194     log_error("Get article list data failed\n");
195     return -3;
196     }
197    
198     // acquire global lock
199     if (global_lock)
200     {
201     if ((ret = section_list_rw_lock(NULL)) < 0)
202     {
203     log_error("section_list_rw_lock(sid = 0) error\n");
204     goto cleanup;
205     }
206     }
207    
208     while ((row = mysql_fetch_row(rs)))
209     {
210     bzero(&article, sizeof(ARTICLE));
211    
212     // copy data of article
213     i = 0;
214    
215     article.aid = atoi(row[i++]);
216     article.tid = atoi(row[i++]);
217     article.sid = atoi(row[i++]);
218     article.cid = atoi(row[i++]);
219     article.uid = atoi(row[i++]);
220     article.visible = (int8_t)atoi(row[i++]);
221     article.excerption = (int8_t)atoi(row[i++]);
222     article.ontop = (int8_t)atoi(row[i++]);
223     article.lock = (int8_t)atoi(row[i++]);
224 sysadm 1.5 article.transship = (int8_t)atoi(row[i++]);
225 sysadm 1.3
226     strncpy(article.username, row[i++], sizeof(article.username) - 1);
227     article.username[sizeof(article.username) - 1] = '\0';
228     strncpy(article.nickname, row[i++], sizeof(article.nickname) - 1);
229     article.nickname[sizeof(article.nickname) - 1] = '\0';
230     strncpy(article.title, row[i++], sizeof(article.title) - 1);
231     article.title[sizeof(article.title) - 1] = '\0';
232    
233     article.sub_dt = atol(row[i++]);
234    
235     // release lock of last section if different from current one
236     if (!global_lock && article.sid != last_sid && last_sid != 0)
237     {
238     if ((ret = section_list_rw_unlock(p_section)) < 0)
239     {
240     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
241     break;
242     }
243     }
244    
245     if ((p_section = section_list_find_by_sid(article.sid)) == NULL)
246     {
247     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);
248 sysadm 1.4 ret = ERR_UNKNOWN_SECTION; // Unknown section found
249 sysadm 1.3 break;
250     }
251    
252 sysadm 1.5 if (article.visible != 0 && article.tid != 0)
253     {
254     // Check if topic article is visible
255     p_topic = article_block_find_by_aid(article.tid);
256     if (p_topic == NULL || p_topic->visible == 0)
257     {
258     // log_error("Set article (aid = %d) as invisible due to invisible or non-existing topic head\n", article.aid);
259     article.tid = 0;
260     article.visible = 0;
261     }
262     }
263    
264 sysadm 1.3 // acquire lock of current section if different from last one
265     if (!global_lock && article.sid != last_sid)
266     {
267 sysadm 1.4 if ((ret = section_list_rw_lock(p_section)) < 0)
268 sysadm 1.3 {
269     log_error("section_list_rw_lock(sid = 0) error\n");
270     break;
271     }
272     }
273    
274     // append article to section list
275     last_sid = article.sid;
276    
277     if (section_list_append_article(p_section, &article) < 0)
278     {
279     log_error("section_list_append_article(sid = %d, aid = %d) error\n",
280     p_section->sid, article.aid);
281     ret = -3;
282     break;
283     }
284     }
285    
286     // release lock of last section
287     if (!global_lock && last_sid != 0)
288     {
289     if ((ret = section_list_rw_unlock(p_section)) < 0)
290     {
291     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
292     }
293     }
294    
295     // release global lock
296     if (global_lock)
297     {
298     if ((ret = section_list_rw_unlock(NULL)) < 0)
299     {
300     log_error("section_list_rw_unlock(sid = 0) error\n");
301     }
302     }
303    
304     cleanup:
305     mysql_free_result(rs);
306    
307     mysql_close(db);
308    
309     return ret;
310     }
311 sysadm 1.4
312 sysadm 1.5 int set_last_article_op_log_from_db(void)
313     {
314     MYSQL *db;
315     MYSQL_RES *rs;
316     MYSQL_ROW row;
317     char sql[SQL_BUFFER_LEN];
318    
319     db = db_open();
320     if (db == NULL)
321     {
322     log_error("db_open() error: %s\n", mysql_error(db));
323     return -1;
324     }
325    
326     snprintf(sql, sizeof(sql),
327     "SELECT MID FROM bbs_article_op ORDER BY MID DESC LIMIT 1");
328    
329     if (mysql_query(db, sql) != 0)
330     {
331     log_error("Query article op error: %s\n", mysql_error(db));
332     return -2;
333     }
334     if ((rs = mysql_store_result(db)) == NULL)
335     {
336     log_error("Get article op data failed\n");
337     return -2;
338     }
339    
340     if ((row = mysql_fetch_row(rs)))
341     {
342     last_article_op_log_mid = atoi(row[0]);
343     }
344    
345     mysql_free_result(rs);
346    
347     mysql_close(db);
348    
349     return last_article_op_log_mid;
350     }
351    
352     int apply_article_op_log_from_db(void)
353     {
354     MYSQL *db;
355     MYSQL_RES *rs, *rs2;
356     MYSQL_ROW row, row2;
357     char sql[SQL_BUFFER_LEN];
358     ARTICLE *p_article;
359     SECTION_LIST *p_section = NULL;
360     SECTION_LIST *p_section_dest;
361     int32_t last_sid = 0;
362     int32_t sid_dest;
363     int ret = 0;
364    
365     db = db_open();
366     if (db == NULL)
367     {
368     log_error("db_open() error: %s\n", mysql_error(db));
369     return -3;
370     }
371    
372     snprintf(sql, sizeof(sql),
373     "SELECT MID, AID, type FROM bbs_article_op "
374     "WHERE MID > %d AND type NOT IN ('A', 'M') ORDER BY MID",
375     last_article_op_log_mid);
376    
377     if (mysql_query(db, sql) != 0)
378     {
379     log_error("Query article log error: %s\n", mysql_error(db));
380     return -3;
381     }
382     if ((rs = mysql_store_result(db)) == NULL)
383     {
384     log_error("Get article log data failed\n");
385     return -3;
386     }
387    
388     while ((row = mysql_fetch_row(rs)))
389     {
390     p_article = article_block_find_by_aid(atoi(row[1]));
391     if (p_article == NULL) // related article has not been appended yet
392     {
393     ret = -2;
394     break;
395     }
396    
397     // release lock of last section if different from current one
398     if (p_article->sid != last_sid && last_sid != 0)
399     {
400     if ((ret = section_list_rw_unlock(p_section)) < 0)
401     {
402     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
403     break;
404     }
405     }
406    
407     if ((p_section = section_list_find_by_sid(p_article->sid)) == NULL)
408     {
409     log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", p_article->sid);
410     ret = ERR_UNKNOWN_SECTION; // Unknown section found
411     break;
412     }
413    
414     // acquire lock of current section if different from last one
415     if (p_article->sid != last_sid)
416     {
417     if ((ret = section_list_rw_lock(p_section)) < 0)
418     {
419     log_error("section_list_rw_lock(sid = 0) error\n");
420     break;
421     }
422     }
423    
424     last_sid = p_article->sid;
425    
426     switch (row[2][0])
427     {
428     case 'A': // Add article
429     log_error("Operation type=A should not be found\n");
430     break;
431     case 'D': // Delete article
432     case 'X': // Delete article by Admin
433     p_article->visible = 0;
434     if (p_article->tid == 0)
435     {
436     // Set articles in the topic to be invisible
437     do
438     {
439     p_article = p_article->p_topic_next;
440     p_article->visible = 0;
441     } while (p_article->tid != 0);
442     }
443     break;
444     case 'S': // Restore article
445     p_article->visible = 1;
446     break;
447     case 'L': // Lock article
448     p_article->lock = 1;
449     break;
450     case 'U': // Unlock article
451     p_article->lock = 0;
452     break;
453     case 'M': // Modify article
454     log_error("Operation type=M should not be found\n");
455     break;
456     case 'T': // Move article
457     snprintf(sql, sizeof(sql),
458     "SELECT SID FROM bbs WHERE AID = %d",
459     p_article->aid);
460    
461     if (mysql_query(db, sql) != 0)
462     {
463     log_error("Query article error: %s\n", mysql_error(db));
464     ret = -3;
465     break;
466     }
467     if ((rs2 = mysql_store_result(db)) == NULL)
468     {
469     log_error("Get article data failed\n");
470     ret = -3;
471     break;
472     }
473     if ((row2 = mysql_fetch_row(rs2)))
474     {
475     sid_dest = atoi(row2[0]);
476     }
477     else
478     {
479     sid_dest = 0;
480     ret = -4;
481     }
482     mysql_free_result(rs2);
483    
484     if (sid_dest > 0 && sid_dest != p_article->sid)
485     {
486     p_section_dest = section_list_find_by_sid(sid_dest);
487     if (p_section_dest == NULL)
488     {
489     ret = ERR_UNKNOWN_SECTION;
490     break;
491     }
492 sysadm 1.6 // acquire lock of dest section
493     if ((ret = section_list_rw_lock(p_section_dest)) < 0)
494     {
495     log_error("section_list_rw_lock(sid = %d) error\n", p_section_dest);
496     break;
497     }
498 sysadm 1.5 // Move topic
499     if ((ret = section_list_move_topic(p_section, p_section_dest, p_article->aid)) < 0)
500     {
501 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",
502     p_section->sid, p_section_dest->sid, p_article->aid, ret);
503     }
504     // release lock of dest section
505     if (section_list_rw_unlock(p_section_dest) < 0)
506     {
507     log_error("section_list_rw_unlock(sid = %d) error\n", p_section_dest);
508     ret = -1;
509 sysadm 1.5 }
510     }
511     break;
512     case 'E': // Set article as excerption
513     p_article->excerption = 1;
514     break;
515     case 'O': // Unset article as excerption
516     p_article->excerption = 0;
517     break;
518     case 'F': // Set article on top
519     p_article->ontop = 1;
520     break;
521     case 'V': // Unset article on top
522     p_article->ontop = 0;
523     break;
524     case 'Z': // Set article as trnasship
525     p_article->transship = 1;
526     break;
527     default:
528     // log_error("Operation type=%s unknown, mid=%s\n", row[2], row[0]);
529     break;
530     }
531    
532     if (ret < 0)
533     {
534     break;
535     }
536    
537     // Update MID with last successfully proceeded article_op_log
538     last_article_op_log_mid = atoi(row[0]);
539     }
540    
541     // release lock of last section
542     if (last_sid != 0)
543     {
544     if ((ret = section_list_rw_unlock(p_section)) < 0)
545     {
546     log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
547     }
548     }
549    
550     mysql_free_result(rs);
551    
552     mysql_close(db);
553    
554     return ret;
555     }
556    
557 sysadm 1.4 int section_list_loader_launch(void)
558     {
559     int pid;
560     int ret;
561     int32_t last_aid;
562     int article_count;
563     int load_count;
564 sysadm 1.5 int last_mid;
565 sysadm 1.4 int i;
566    
567     if (section_list_loader_pid != 0)
568     {
569     log_error("section_list_loader already running, pid = %d\n", section_list_loader_pid);
570     return -2;
571     }
572    
573     pid = fork();
574    
575     if (pid > 0) // Parent process
576     {
577     SYS_child_process_count++;
578     section_list_loader_pid = pid;
579     log_std("Section list loader process (%d) start\n", pid);
580     return 0;
581     }
582     else if (pid < 0) // Error
583     {
584     log_error("fork() error (%d)\n", errno);
585     return -1;
586     }
587    
588     // Child process
589     SYS_child_process_count = 0;
590    
591     // Detach menu in shared memory
592     detach_menu_shm(p_bbs_menu);
593     free(p_bbs_menu);
594     p_bbs_menu = NULL;
595    
596     // Do section data loader periodically
597     while (!SYS_server_exit)
598     {
599     if (SYS_section_list_reload)
600     {
601     SYS_section_list_reload = 0;
602    
603     // Load section config
604     if (load_section_config_from_db() < 0)
605     {
606     log_error("load_section_config_from_db() error\n");
607     }
608     else
609     {
610     log_error("Reload section config successfully\n");
611     }
612     }
613    
614     // Load section articles
615     last_aid = article_block_last_aid();
616     article_count = article_block_article_count();
617    
618     if ((ret = append_articles_from_db(last_aid + 1, 0)) < 0)
619     {
620     log_error("append_articles_from_db(%d, 0) error\n", last_aid + 1);
621    
622     if (ret == ERR_UNKNOWN_SECTION)
623     {
624     SYS_section_list_reload = 1; // Force reload section_list
625     }
626     }
627 sysadm 1.5
628     load_count = article_block_article_count() - article_count;
629    
630     if (load_count > 0)
631     {
632     log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
633     }
634    
635     if (SYS_section_list_reload)
636     {
637     continue;
638     }
639    
640     // Load article_op log
641     last_mid = last_article_op_log_mid;
642    
643     if ((ret = apply_article_op_log_from_db()) < 0)
644 sysadm 1.4 {
645 sysadm 1.5 log_error("apply_article_op_log_from_db() error\n");
646 sysadm 1.4
647 sysadm 1.5 if (ret == ERR_UNKNOWN_SECTION)
648 sysadm 1.4 {
649 sysadm 1.5 SYS_section_list_reload = 1; // Force reload section_list
650 sysadm 1.4 }
651 sysadm 1.5 }
652 sysadm 1.4
653 sysadm 1.5 if (last_article_op_log_mid > last_mid)
654     {
655     log_std("Proceeded %d article logs, last_mid = %d\n", last_article_op_log_mid - last_mid, last_article_op_log_mid);
656     }
657    
658     if (SYS_section_list_reload)
659     {
660     continue;
661     }
662    
663     for (i = 0; i < SECTION_LIST_LOAD_INTERVAL && !SYS_server_exit && !SYS_section_list_reload; i++)
664     {
665     sleep(1);
666 sysadm 1.4 }
667     }
668    
669     // Child process exit
670    
671     // Detach data pools shm
672     detach_section_list_shm();
673     detach_article_block_shm();
674     detach_trie_dict_shm();
675    
676     log_std("Section list loader process exit normally\n");
677     log_end();
678    
679     section_list_loader_pid = 0;
680    
681     _exit(0);
682    
683     return 0;
684     }
685    
686     int section_list_loader_reload(void)
687     {
688     if (section_list_loader_pid == 0)
689     {
690     log_error("section_list_loader not running\n");
691     return -2;
692     }
693    
694     if (kill(section_list_loader_pid, SIGHUP) < 0)
695     {
696     log_error("Send SIGTERM signal failed (%d)\n", errno);
697     return -1;
698     }
699    
700     return 0;
701     }
702 sysadm 1.7
703     int query_section_articles(SECTION_LIST *p_section, int32_t page_id, ARTICLE *p_articles[], int32_t *p_article_count)
704     {
705     ARTICLE *p_article;
706     ARTICLE *p_next_page_first_article;
707     int ret = 0;
708    
709     if (p_section == NULL || p_articles == NULL || p_article_count == NULL)
710     {
711     log_error("query_section_articles() NULL pointer error\n");
712     return -1;
713     }
714    
715     // acquire lock of section
716     if ((ret = section_list_rd_lock(p_section)) < 0)
717     {
718     log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
719     return -2;
720     }
721    
722 sysadm 1.8 if (page_id < 0 || page_id >= p_section->page_count)
723 sysadm 1.7 {
724 sysadm 1.8 log_error("Invalid page_id=%d, not in range [0, %d)\n", page_id, p_section->page_count);
725 sysadm 1.7 ret = -3;
726     }
727     else
728     {
729     ret = page_id;
730     p_article = p_section->p_page_first_article[page_id];
731     p_next_page_first_article =
732     (page_id == p_section->page_count - 1 ? p_section->p_article_head : p_section->p_page_first_article[page_id + 1]);
733     *p_article_count = 0;
734    
735     do
736     {
737     if (p_article->visible)
738     {
739     p_articles[*p_article_count] = p_article;
740     (*p_article_count)++;
741     }
742     p_article = p_article->p_next;
743     } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);
744 sysadm 1.8
745     if (*p_article_count != (page_id < p_section->page_count - 1 ? BBS_article_limit_per_page : p_section->last_page_visible_article_count))
746     {
747     log_error("Inconsistent visible article count %d detected in section %d page %d\n", *p_article_count, p_section->sid, page_id);
748     }
749 sysadm 1.7 }
750    
751     // release lock of section
752 sysadm 1.8 if (section_list_rd_unlock(p_section) < 0)
753 sysadm 1.7 {
754     log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
755     ret = -2;
756     }
757    
758     return ret;
759     }

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