/[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.3 by sysadm, Tue May 27 00:54:59 2025 UTC Revision 1.16 by sysadm, Sat May 31 12:00:00 2025 UTC
# Line 15  Line 15 
15   ***************************************************************************/   ***************************************************************************/
16    
17  #include "section_list_loader.h"  #include "section_list_loader.h"
18    #include "article_cache.h"
19  #include "log.h"  #include "log.h"
20  #include "database.h"  #include "database.h"
21    #include "menu.h"
22  #include <stdio.h>  #include <stdio.h>
23  #include <string.h>  #include <string.h>
24  #include <errno.h>  #include <errno.h>
25    #include <signal.h>
26  #include <stdlib.h>  #include <stdlib.h>
27  #include <strings.h>  #include <strings.h>
28    #include <unistd.h>
29    
30    #define _POSIX_C_SOURCE 200809L
31    #include <string.h>
32    
33    #define SECTION_LIST_LOAD_INTERVAL 10 // second
34    
35    int section_list_loader_pid;
36    int last_article_op_log_mid;
37    
38  int load_section_config_from_db(void)  int load_section_config_from_db(void)
39  {  {
# Line 30  int load_section_config_from_db(void) Line 42  int load_section_config_from_db(void)
42          MYSQL_ROW row, row2;          MYSQL_ROW row, row2;
43          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
44          int32_t sid;          int32_t sid;
45          char master_name[BBS_username_max_len + 1];          char master_list[(BBS_username_max_len + 1) * 3 + 1];
46          SECTION_LIST *p_section;          SECTION_LIST *p_section;
47          int ret;          int ret;
48    
# Line 68  int load_section_config_from_db(void) Line 80  int load_section_config_from_db(void)
80                                   "SELECT username FROM section_master "                                   "SELECT username FROM section_master "
81                                   "INNER JOIN user_list ON section_master.UID = user_list.UID "                                   "INNER JOIN user_list ON section_master.UID = user_list.UID "
82                                   "WHERE SID = %d AND section_master.enable AND (NOW() BETWEEN begin_dt AND end_dt) "                                   "WHERE SID = %d AND section_master.enable AND (NOW() BETWEEN begin_dt AND end_dt) "
83                                   "ORDER BY major DESC LIMIT 1",                                   "ORDER BY major DESC, begin_dt ASC LIMIT 3",
84                                   sid);                                   sid);
85    
86                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
# Line 83  int load_section_config_from_db(void) Line 95  int load_section_config_from_db(void)
95                          ret = -3;                          ret = -3;
96                          break;                          break;
97                  }                  }
98                  if ((row2 = mysql_fetch_row(rs2)))  
99                  {                  master_list[0] = '\0';
100                          strncpy(master_name, row2[0], sizeof(master_name) - 1);                  while ((row2 = mysql_fetch_row(rs2)))
                         master_name[sizeof(master_name) - 1] = '\0';  
                 }  
                 else  
101                  {                  {
102                          master_name[0] = '\0';                          strncat(master_list, row2[0], sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
103                            strncat(master_list, " ", sizeof(master_list) - 1 - strnlen(master_list, sizeof(master_list)));
104                  }                  }
105                  mysql_free_result(rs2);                  mysql_free_result(rs2);
106    
# Line 98  int load_section_config_from_db(void) Line 108  int load_section_config_from_db(void)
108    
109                  if (p_section == NULL)                  if (p_section == NULL)
110                  {                  {
111                          p_section = section_list_create(sid, row[1], row[2], "");                          p_section = section_list_create(sid, row[1], row[2], master_list);
112                          if (p_section == NULL)                          if (p_section == NULL)
113                          {                          {
114                                  log_error("section_list_create() 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]);
# Line 126  int load_section_config_from_db(void) Line 136  int load_section_config_from_db(void)
136                          p_section->sname[sizeof(p_section->sname) - 1] = '\0';                          p_section->sname[sizeof(p_section->sname) - 1] = '\0';
137                          strncpy(p_section->stitle, row[1], sizeof(p_section->stitle) - 1);                          strncpy(p_section->stitle, row[1], sizeof(p_section->stitle) - 1);
138                          p_section->stitle[sizeof(p_section->stitle) - 1] = '\0';                          p_section->stitle[sizeof(p_section->stitle) - 1] = '\0';
139                          strncpy(p_section->master_name, master_name, sizeof(p_section->master_name) - 1);                          strncpy(p_section->master_list, master_list, sizeof(p_section->master_list) - 1);
140                          p_section->master_name[sizeof(p_section->master_name) - 1] = '\0';                          p_section->master_list[sizeof(p_section->master_list) - 1] = '\0';
141                  }                  }
142    
143                  p_section->class_id = atoi(row[3]);                  p_section->class_id = atoi(row[3]);
# Line 149  int load_section_config_from_db(void) Line 159  int load_section_config_from_db(void)
159          return ret;          return ret;
160  }  }
161    
162  int append_articles_from_db(int32_t start_aid, int global_lock)  int append_articles_from_db(int32_t start_aid, int global_lock, int article_count_limit)
163  {  {
164          MYSQL *db;          MYSQL *db;
165          MYSQL_RES *rs;          MYSQL_RES *rs;
166          MYSQL_ROW row;          MYSQL_ROW row;
167          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
168          ARTICLE article;          ARTICLE article;
169            ARTICLE *p_topic;
170          SECTION_LIST *p_section = NULL;          SECTION_LIST *p_section = NULL;
171          int32_t last_sid = 0;          int32_t last_sid = 0;
172            char sub_ip[IP_ADDR_LEN];
173            int article_count = 0;
174          int ret = 0;          int ret = 0;
175          int i;          int i;
176    
# Line 169  int append_articles_from_db(int32_t star Line 182  int append_articles_from_db(int32_t star
182          }          }
183    
184          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
185                           "SELECT AID, TID, SID, CID, UID, visible, excerption, "                           "SELECT bbs.AID, TID, SID, bbs.CID, UID, visible, excerption, ontop, `lock`, "
186                           "ontop, `lock`, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt "                           "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt, "
187                           "FROM bbs WHERE AID >= %d ORDER BY AID",                           "sub_ip, bbs_content.content "
188                           start_aid);                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
189                             "WHERE bbs.AID >= %d ORDER BY bbs.AID LIMIT %d",
190                             start_aid, article_count_limit);
191    
192          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
193          {          {
# Line 211  int append_articles_from_db(int32_t star Line 226  int append_articles_from_db(int32_t star
226                  article.excerption = (int8_t)atoi(row[i++]);                  article.excerption = (int8_t)atoi(row[i++]);
227                  article.ontop = (int8_t)atoi(row[i++]);                  article.ontop = (int8_t)atoi(row[i++]);
228                  article.lock = (int8_t)atoi(row[i++]);                  article.lock = (int8_t)atoi(row[i++]);
229                    article.transship = (int8_t)atoi(row[i++]);
230    
231                  strncpy(article.username, row[i++], sizeof(article.username) - 1);                  strncpy(article.username, row[i++], sizeof(article.username) - 1);
232                  article.username[sizeof(article.username) - 1] = '\0';                  article.username[sizeof(article.username) - 1] = '\0';
# Line 221  int append_articles_from_db(int32_t star Line 237  int append_articles_from_db(int32_t star
237    
238                  article.sub_dt = atol(row[i++]);                  article.sub_dt = atol(row[i++]);
239    
240                    strncpy(sub_ip, row[i++], sizeof(sub_ip) - 1);
241                    sub_ip[sizeof(sub_ip) - 1] = '\0';
242                    ip_mask(sub_ip, 1, '*');
243    
244                  // release lock of last section if different from current one                  // release lock of last section if different from current one
245                  if (!global_lock && article.sid != last_sid && last_sid != 0)                  if (!global_lock && article.sid != last_sid && last_sid != 0)
246                  {                  {
247                          if ((ret = section_list_rw_unlock(p_section)) < 0)                          if ((ret = section_list_rw_unlock(p_section)) < 0)
248                          {                          {
249                                  log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);                                  log_error("section_list_rw_unlock(sid=%d) error\n", p_section->sid);
250                                  break;                                  break;
251                          }                          }
252                  }                  }
# Line 234  int append_articles_from_db(int32_t star Line 254  int append_articles_from_db(int32_t star
254                  if ((p_section = section_list_find_by_sid(article.sid)) == NULL)                  if ((p_section = section_list_find_by_sid(article.sid)) == NULL)
255                  {                  {
256                          log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);                          log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", article.sid);
257                          ret = -4; // known section found                          ret = ERR_UNKNOWN_SECTION; // Unknown section found
258                          break;                          break;
259                  }                  }
260    
261                    if (article.visible != 0 && article.tid != 0)
262                    {
263                            // Check if topic article is visible
264                            p_topic = article_block_find_by_aid(article.tid);
265                            if (p_topic == NULL || p_topic->visible == 0)
266                            {
267                                    // log_error("Set article (aid = %d) as invisible due to invisible or non-existing topic head\n", article.aid);
268                                    article.tid = 0;
269                                    article.visible = 0;
270                            }
271                    }
272    
273                  // acquire lock of current section if different from last one                  // acquire lock of current section if different from last one
274                  if (!global_lock && article.sid != last_sid)                  if (!global_lock && article.sid != last_sid)
275                  {                  {
276                          if ((ret = section_list_rw_lock(NULL)) < 0)                          if ((ret = section_list_rw_lock(p_section)) < 0)
277                          {                          {
278                                  log_error("section_list_rw_lock(sid = 0) error\n");                                  log_error("section_list_rw_lock(sid=0) error\n");
279                                  break;                                  break;
280                          }                          }
281                  }                  }
# Line 253  int append_articles_from_db(int32_t star Line 285  int append_articles_from_db(int32_t star
285    
286                  if (section_list_append_article(p_section, &article) < 0)                  if (section_list_append_article(p_section, &article) < 0)
287                  {                  {
288                          log_error("section_list_append_article(sid = %d, aid = %d) error\n",                          log_error("section_list_append_article(sid=%d, aid=%d) error\n",
289                                            p_section->sid, article.aid);                                            p_section->sid, article.aid);
290                          ret = -3;                          ret = -3;
291                          break;                          break;
292                  }                  }
293    
294                    article_count++;
295    
296                    if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, &article, p_section, row[i++], sub_ip, 0) < 0)
297                    {
298                            log_error("article_cache_generate(aid=%d, cid=%d) error\n", article.aid, article.cid);
299                            ret = -4;
300                            break;
301                    }
302          }          }
303    
304          // release lock of last section          // release lock of last section
# Line 265  int append_articles_from_db(int32_t star Line 306  int append_articles_from_db(int32_t star
306          {          {
307                  if ((ret = section_list_rw_unlock(p_section)) < 0)                  if ((ret = section_list_rw_unlock(p_section)) < 0)
308                  {                  {
309                          log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);                          log_error("section_list_rw_unlock(sid=%d) error\n", p_section->sid);
310                  }                  }
311          }          }
312    
# Line 274  int append_articles_from_db(int32_t star Line 315  int append_articles_from_db(int32_t star
315          {          {
316                  if ((ret = section_list_rw_unlock(NULL)) < 0)                  if ((ret = section_list_rw_unlock(NULL)) < 0)
317                  {                  {
318                          log_error("section_list_rw_unlock(sid = 0) error\n");                          log_error("section_list_rw_unlock(sid=0) error\n");
319                  }                  }
320          }          }
321    
# Line 283  cleanup: Line 324  cleanup:
324    
325          mysql_close(db);          mysql_close(db);
326    
327            return (ret < 0 ? ret : article_count);
328    }
329    
330    int set_last_article_op_log_from_db(void)
331    {
332            MYSQL *db;
333            MYSQL_RES *rs;
334            MYSQL_ROW row;
335            char sql[SQL_BUFFER_LEN];
336    
337            db = db_open();
338            if (db == NULL)
339            {
340                    log_error("db_open() error: %s\n", mysql_error(db));
341                    return -1;
342            }
343    
344            snprintf(sql, sizeof(sql),
345                             "SELECT MID FROM bbs_article_op ORDER BY MID DESC LIMIT 1");
346    
347            if (mysql_query(db, sql) != 0)
348            {
349                    log_error("Query article op error: %s\n", mysql_error(db));
350                    return -2;
351            }
352            if ((rs = mysql_store_result(db)) == NULL)
353            {
354                    log_error("Get article op data failed\n");
355                    return -2;
356            }
357    
358            if ((row = mysql_fetch_row(rs)))
359            {
360                    last_article_op_log_mid = atoi(row[0]);
361            }
362    
363            mysql_free_result(rs);
364    
365            mysql_close(db);
366    
367            return last_article_op_log_mid;
368    }
369    
370    int apply_article_op_log_from_db(int op_count_limit)
371    {
372            MYSQL *db;
373            MYSQL_RES *rs, *rs2;
374            MYSQL_ROW row, row2;
375            char sql[SQL_BUFFER_LEN];
376            ARTICLE *p_article;
377            SECTION_LIST *p_section = NULL;
378            SECTION_LIST *p_section_dest;
379            char sub_ip[IP_ADDR_LEN];
380            int32_t last_sid = 0;
381            int32_t sid_dest;
382            int op_count = 0;
383            int ret = 0;
384    
385            db = db_open();
386            if (db == NULL)
387            {
388                    log_error("db_open() error: %s\n", mysql_error(db));
389                    return -3;
390            }
391    
392            snprintf(sql, sizeof(sql),
393                             "SELECT MID, AID, type FROM bbs_article_op "
394                             "WHERE MID > %d AND type NOT IN ('A') "
395                             "ORDER BY MID LIMIT %d",
396                             last_article_op_log_mid, op_count_limit);
397    
398            if (mysql_query(db, sql) != 0)
399            {
400                    log_error("Query article log error: %s\n", mysql_error(db));
401                    return -3;
402            }
403            if ((rs = mysql_store_result(db)) == NULL)
404            {
405                    log_error("Get article log data failed\n");
406                    return -3;
407            }
408    
409            while ((row = mysql_fetch_row(rs)))
410            {
411                    p_article = article_block_find_by_aid(atoi(row[1]));
412                    if (p_article == NULL) // related article has not been appended yet
413                    {
414                            ret = -2;
415                            break;
416                    }
417    
418                    // release lock of last section if different from current one
419                    if (p_article->sid != last_sid && last_sid != 0)
420                    {
421                            if ((ret = section_list_rw_unlock(p_section)) < 0)
422                            {
423                                    log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
424                                    break;
425                            }
426                    }
427    
428                    if ((p_section = section_list_find_by_sid(p_article->sid)) == NULL)
429                    {
430                            log_error("section_list_find_by_sid(%d) error: unknown section, try reloading section config\n", p_article->sid);
431                            ret = ERR_UNKNOWN_SECTION; // Unknown section found
432                            break;
433                    }
434    
435                    // acquire lock of current section if different from last one
436                    if (p_article->sid != last_sid)
437                    {
438                            if ((ret = section_list_rw_lock(p_section)) < 0)
439                            {
440                                    log_error("section_list_rw_lock(sid = 0) error\n");
441                                    break;
442                            }
443                    }
444    
445                    last_sid = p_article->sid;
446    
447                    switch (row[2][0])
448                    {
449                    case 'A': // Add article
450                            log_error("Operation type=A should not be found\n");
451                            break;
452                    case 'D': // Delete article
453                    case 'X': // Delete article by Admin
454                            p_article->visible = 0;
455                            if (p_article->tid == 0)
456                            {
457                                    // Set articles in the topic to be invisible
458                                    do
459                                    {
460                                            p_article = p_article->p_topic_next;
461                                            p_article->visible = 0;
462                                    } while (p_article->tid != 0);
463                            }
464                            break;
465                    case 'S': // Restore article
466                            p_article->visible = 1;
467                            break;
468                    case 'L': // Lock article
469                            p_article->lock = 1;
470                            break;
471                    case 'U': // Unlock article
472                            p_article->lock = 0;
473                            break;
474                    case 'M': // Modify article
475                            snprintf(sql, sizeof(sql),
476                                             "SELECT bbs.CID, sub_ip, bbs_content.content "
477                                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
478                                             "WHERE bbs.AID = %d",
479                                             p_article->aid);
480    
481                            if (mysql_query(db, sql) != 0)
482                            {
483                                    log_error("Query article error: %s\n", mysql_error(db));
484                                    ret = -3;
485                                    break;
486                            }
487                            if ((rs2 = mysql_use_result(db)) == NULL)
488                            {
489                                    log_error("Get article data failed\n");
490                                    ret = -3;
491                                    break;
492                            }
493                            if ((row2 = mysql_fetch_row(rs2)))
494                            {
495                                    p_article->cid = atoi(row2[0]);
496    
497                                    strncpy(sub_ip, row2[1], sizeof(sub_ip) - 1);
498                                    sub_ip[sizeof(sub_ip) - 1] = '\0';
499                                    ip_mask(sub_ip, 1, '*');
500    
501                                    if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, p_article, p_section, row2[2], sub_ip, 0) < 0)
502                                    {
503                                            log_error("article_cache_generate(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);
504                                            ret = -4;
505                                    }
506                            }
507                            else
508                            {
509                                    p_article->cid = 0;
510                                    ret = -4;
511                            }
512                            mysql_free_result(rs2);
513                            break;
514                    case 'T': // Move article
515                            snprintf(sql, sizeof(sql),
516                                             "SELECT SID FROM bbs WHERE AID = %d",
517                                             p_article->aid);
518    
519                            if (mysql_query(db, sql) != 0)
520                            {
521                                    log_error("Query article error: %s\n", mysql_error(db));
522                                    ret = -3;
523                                    break;
524                            }
525                            if ((rs2 = mysql_store_result(db)) == NULL)
526                            {
527                                    log_error("Get article data failed\n");
528                                    ret = -3;
529                                    break;
530                            }
531                            if ((row2 = mysql_fetch_row(rs2)))
532                            {
533                                    sid_dest = atoi(row2[0]);
534                            }
535                            else
536                            {
537                                    sid_dest = 0;
538                                    ret = -4;
539                            }
540                            mysql_free_result(rs2);
541    
542                            if (sid_dest > 0 && sid_dest != p_article->sid)
543                            {
544                                    p_section_dest = section_list_find_by_sid(sid_dest);
545                                    if (p_section_dest == NULL)
546                                    {
547                                            ret = ERR_UNKNOWN_SECTION;
548                                            break;
549                                    }
550                                    // acquire lock of dest section
551                                    if ((ret = section_list_rw_lock(p_section_dest)) < 0)
552                                    {
553                                            log_error("section_list_rw_lock(sid = %d) error\n", p_section_dest);
554                                            break;
555                                    }
556                                    // Move topic
557                                    if ((ret = section_list_move_topic(p_section, p_section_dest, p_article->aid)) < 0)
558                                    {
559                                            log_error("section_list_move_topic(src_sid=%d, dest_sid=%d, aid=%d) error (%d), retry in the next loop\n",
560                                                              p_section->sid, p_section_dest->sid, p_article->aid, ret);
561                                    }
562                                    // release lock of dest section
563                                    if (section_list_rw_unlock(p_section_dest) < 0)
564                                    {
565                                            log_error("section_list_rw_unlock(sid = %d) error\n", p_section_dest);
566                                            ret = -1;
567                                    }
568                            }
569                            break;
570                    case 'E': // Set article as excerption
571                            p_article->excerption = 1;
572                            break;
573                    case 'O': // Unset article as excerption
574                            p_article->excerption = 0;
575                            break;
576                    case 'F': // Set article on top
577                            p_article->ontop = 1;
578                            break;
579                    case 'V': // Unset article on top
580                            p_article->ontop = 0;
581                            break;
582                    case 'Z': // Set article as trnasship
583                            p_article->transship = 1;
584                            break;
585                    default:
586                            // log_error("Operation type=%s unknown, mid=%s\n", row[2], row[0]);
587                            break;
588                    }
589    
590                    if (ret < 0)
591                    {
592                            break;
593                    }
594    
595                    // Update MID with last successfully proceeded article_op_log
596                    last_article_op_log_mid = atoi(row[0]);
597    
598                    op_count++;
599            }
600    
601            // release lock of last section
602            if (last_sid != 0)
603            {
604                    if ((ret = section_list_rw_unlock(p_section)) < 0)
605                    {
606                            log_error("section_list_rw_unlock(sid = %d) error\n", p_section->sid);
607                    }
608            }
609    
610            mysql_free_result(rs);
611    
612            mysql_close(db);
613    
614            return (ret < 0 ? ret : op_count);
615    }
616    
617    int section_list_loader_launch(void)
618    {
619            int pid;
620            int ret;
621            int32_t last_aid;
622            int article_count;
623            int load_count;
624            int last_mid;
625            int i;
626    
627            if (section_list_loader_pid != 0)
628            {
629                    log_error("section_list_loader already running, pid = %d\n", section_list_loader_pid);
630                    return -2;
631            }
632    
633            pid = fork();
634    
635            if (pid > 0) // Parent process
636            {
637                    SYS_child_process_count++;
638                    section_list_loader_pid = pid;
639                    log_std("Section list loader process (%d) start\n", pid);
640                    return 0;
641            }
642            else if (pid < 0) // Error
643            {
644                    log_error("fork() error (%d)\n", errno);
645                    return -1;
646            }
647    
648            // Child process
649            SYS_child_process_count = 0;
650    
651            // Detach menu in shared memory
652            detach_menu_shm(p_bbs_menu);
653            free(p_bbs_menu);
654            p_bbs_menu = NULL;
655    
656            // Do section data loader periodically
657            while (!SYS_server_exit)
658            {
659                    if (SYS_section_list_reload)
660                    {
661                            SYS_section_list_reload = 0;
662    
663                            // Load section config
664                            if (load_section_config_from_db() < 0)
665                            {
666                                    log_error("load_section_config_from_db() error\n");
667                            }
668                            else
669                            {
670                                    log_error("Reload section config successfully\n");
671                            }
672                    }
673    
674                    // Load section articles
675                    article_count = article_block_article_count();
676    
677                    do
678                    {
679                            last_aid = article_block_last_aid();
680    
681                            if ((ret = append_articles_from_db(last_aid + 1, 0, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
682                            {
683                                    log_error("append_articles_from_db(%d, 0, %d) error\n", last_aid + 1, LOAD_ARTICLE_COUNT_LIMIT);
684    
685                                    if (ret == ERR_UNKNOWN_SECTION)
686                                    {
687                                            SYS_section_list_reload = 1; // Force reload section_list
688                                    }
689                            }
690                    } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
691    
692                    load_count = article_block_article_count() - article_count;
693                    if (load_count > 0)
694                    {
695                            log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
696                    }
697    
698                    if (SYS_section_list_reload)
699                    {
700                            continue;
701                    }
702    
703                    // Load article_op log
704                    last_mid = last_article_op_log_mid;
705    
706                    do
707                    {
708                            if ((ret = apply_article_op_log_from_db(LOAD_ARTICLE_COUNT_LIMIT)) < 0)
709                            {
710                                    log_error("apply_article_op_log_from_db() error\n");
711    
712                                    if (ret == ERR_UNKNOWN_SECTION)
713                                    {
714                                            SYS_section_list_reload = 1; // Force reload section_list
715                                    }
716                            }
717                    } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
718    
719                    if (last_article_op_log_mid > last_mid)
720                    {
721                            log_std("Proceeded %d article logs, last_mid = %d\n", last_article_op_log_mid - last_mid, last_article_op_log_mid);
722                    }
723    
724                    if (SYS_section_list_reload)
725                    {
726                            continue;
727                    }
728    
729                    for (i = 0; i < SECTION_LIST_LOAD_INTERVAL && !SYS_server_exit && !SYS_section_list_reload; i++)
730                    {
731                            sleep(1);
732                    }
733            }
734    
735            // Child process exit
736    
737            // Detach data pools shm
738            detach_section_list_shm();
739            detach_article_block_shm();
740            detach_trie_dict_shm();
741    
742            log_std("Section list loader process exit normally\n");
743            log_end();
744    
745            section_list_loader_pid = 0;
746    
747            _exit(0);
748    
749            return 0;
750    }
751    
752    int section_list_loader_reload(void)
753    {
754            if (section_list_loader_pid == 0)
755            {
756                    log_error("section_list_loader not running\n");
757                    return -2;
758            }
759    
760            if (kill(section_list_loader_pid, SIGHUP) < 0)
761            {
762                    log_error("Send SIGTERM signal failed (%d)\n", errno);
763                    return -1;
764            }
765    
766            return 0;
767    }
768    
769    int query_section_articles(SECTION_LIST *p_section, int page_id, ARTICLE *p_articles[], int *p_article_count, int *p_page_count)
770    {
771            ARTICLE *p_article;
772            ARTICLE *p_next_page_first_article;
773            int ret = 0;
774    
775            if (p_section == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL)
776            {
777                    log_error("query_section_articles() NULL pointer error\n");
778                    return -1;
779            }
780    
781            // acquire lock of section
782            if ((ret = section_list_rd_lock(p_section)) < 0)
783            {
784                    log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
785                    return -2;
786            }
787    
788            *p_page_count = p_section->page_count;
789    
790            if (p_section->visible_article_count == 0)
791            {
792                    *p_article_count = 0;
793            }
794            else if (page_id < 0 || page_id >= p_section->page_count)
795            {
796                    log_error("Invalid page_id=%d, not in range [0, %d)\n", page_id, p_section->page_count);
797                    ret = -3;
798            }
799            else
800            {
801                    ret = page_id;
802                    p_article = p_section->p_page_first_article[page_id];
803                    p_next_page_first_article =
804                            (page_id == p_section->page_count - 1 ? p_section->p_article_head : p_section->p_page_first_article[page_id + 1]);
805                    *p_article_count = 0;
806    
807                    do
808                    {
809                            if (p_article->visible)
810                            {
811                                    p_articles[*p_article_count] = p_article;
812                                    (*p_article_count)++;
813                            }
814                            p_article = p_article->p_next;
815                    } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);
816    
817                    if (*p_article_count != (page_id < p_section->page_count - 1 ? BBS_article_limit_per_page : p_section->last_page_visible_article_count))
818                    {
819                            log_error("Inconsistent visible article count %d detected in section %d page %d\n", *p_article_count, p_section->sid, page_id);
820                    }
821            }
822    
823            // release lock of section
824            if (section_list_rd_unlock(p_section) < 0)
825            {
826                    log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
827                    ret = -2;
828            }
829    
830          return ret;          return ret;
831  }  }
832    
833    int locate_article_in_section(SECTION_LIST *p_section, const ARTICLE *p_article_cur, int direction,
834                                                              int *p_page_id, int *p_visible_offset, int *p_article_count)
835    {
836            const ARTICLE *p_article = NULL;
837            ARTICLE *p_tmp;
838            int32_t aid = 0;
839            int page_id;
840            int offset;
841            int ret = 0;
842            int i;
843    
844            if (p_section == NULL || p_article_cur == NULL || p_page_id == NULL || p_visible_offset == NULL || p_article_count == NULL)
845            {
846                    log_error("locate_article_in_section() NULL pointer error\n");
847                    return -1;
848            }
849    
850            // acquire lock of section
851            if ((ret = section_list_rd_lock(p_section)) < 0)
852            {
853                    log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
854                    return -2;
855            }
856    
857            if (direction == 0)
858            {
859                    aid = p_article_cur->aid;
860            }
861            else if (direction == 1)
862            {
863                    p_article = p_article_cur;
864                    do
865                    {
866                            p_article = p_article->p_topic_next;
867                    } while (p_article != p_article_cur && p_article->visible == 0);
868    
869                    aid = (p_article->aid > p_article_cur->aid ? p_article->aid : 0);
870            }
871            else if (direction == -1)
872            {
873                    p_article = p_article_cur;
874                    do
875                    {
876                            p_article = p_article->p_topic_prior;
877                    } while (p_article != p_article_cur && p_article->visible == 0);
878    
879                    aid = (p_article->aid < p_article_cur->aid ? p_article->aid : 0);
880            }
881    
882            p_article = NULL;
883    
884            if (aid > 0)
885            {
886                    p_article = section_list_find_article_with_offset(p_section, aid, &page_id, &offset, &p_tmp);
887                    if (p_article != NULL)
888                    {
889                            *p_article_count = (page_id == p_section->page_count - 1 ? p_section->last_page_visible_article_count : BBS_article_limit_per_page);
890    
891                            p_article = p_section->p_page_first_article[page_id];
892                            for (i = 0; i < *p_article_count;)
893                            {
894                                    if (p_article->visible)
895                                    {
896                                            if (p_article->aid == aid)
897                                            {
898                                                    *p_page_id = page_id;
899                                                    *p_visible_offset = i;
900                                                    break;
901                                            }
902                                            i++;
903                                            if (i >= *p_article_count)
904                                            {
905                                                    log_error("Visible article (aid=%d) not found in page %d\n", aid, page_id);
906                                                    p_article = NULL;
907                                            }
908                                    }
909                                    p_article = p_article->p_next;
910                            }
911                    }
912            }
913    
914            // release lock of section
915            if (section_list_rd_unlock(p_section) < 0)
916            {
917                    log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
918                    ret = -2;
919            }
920    
921            return (ret < 0 ? ret : (p_article == NULL ? 0 : 1));
922    }


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

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