/[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.7 by sysadm, Tue May 27 12:24:43 2025 UTC Revision 1.15 by sysadm, Sat May 31 10:23:23 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"  #include "menu.h"
# Line 26  Line 27 
27  #include <strings.h>  #include <strings.h>
28  #include <unistd.h>  #include <unistd.h>
29    
30    #define _POSIX_C_SOURCE 200809L
31    #include <string.h>
32    
33  #define SECTION_LIST_LOAD_INTERVAL 10 // second  #define SECTION_LIST_LOAD_INTERVAL 10 // second
34    
35  int section_list_loader_pid;  int section_list_loader_pid;
# Line 38  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 76  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 91  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 106  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 134  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 157  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;
# Line 167  int append_articles_from_db(int32_t star Line 169  int append_articles_from_db(int32_t star
169          ARTICLE *p_topic;          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            int article_count = 0;
173          int ret = 0;          int ret = 0;
174          int i;          int i;
175    
# Line 178  int append_articles_from_db(int32_t star Line 181  int append_articles_from_db(int32_t star
181          }          }
182    
183          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
184                           "SELECT AID, TID, SID, CID, UID, visible, excerption, ontop, `lock`, "                           "SELECT bbs.AID, TID, SID, bbs.CID, UID, visible, excerption, ontop, `lock`, "
185                           "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt "                           "transship, username, nickname, title, UNIX_TIMESTAMP(sub_dt) AS sub_dt, "
186                           "FROM bbs WHERE AID >= %d ORDER BY AID",                           "bbs_content.content "
187                           start_aid);                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
188                             "WHERE bbs.AID >= %d ORDER BY bbs.AID LIMIT %d",
189                             start_aid, article_count_limit);
190    
191          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
192          {          {
# Line 236  int append_articles_from_db(int32_t star Line 241  int append_articles_from_db(int32_t star
241                  {                  {
242                          if ((ret = section_list_rw_unlock(p_section)) < 0)                          if ((ret = section_list_rw_unlock(p_section)) < 0)
243                          {                          {
244                                  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);
245                                  break;                                  break;
246                          }                          }
247                  }                  }
# Line 265  int append_articles_from_db(int32_t star Line 270  int append_articles_from_db(int32_t star
270                  {                  {
271                          if ((ret = section_list_rw_lock(p_section)) < 0)                          if ((ret = section_list_rw_lock(p_section)) < 0)
272                          {                          {
273                                  log_error("section_list_rw_lock(sid = 0) error\n");                                  log_error("section_list_rw_lock(sid=0) error\n");
274                                  break;                                  break;
275                          }                          }
276                  }                  }
# Line 275  int append_articles_from_db(int32_t star Line 280  int append_articles_from_db(int32_t star
280    
281                  if (section_list_append_article(p_section, &article) < 0)                  if (section_list_append_article(p_section, &article) < 0)
282                  {                  {
283                          log_error("section_list_append_article(sid = %d, aid = %d) error\n",                          log_error("section_list_append_article(sid=%d, aid=%d) error\n",
284                                            p_section->sid, article.aid);                                            p_section->sid, article.aid);
285                          ret = -3;                          ret = -3;
286                          break;                          break;
287                  }                  }
288    
289                    article_count++;
290    
291                    if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, &article, p_section, row[i++], 0) < 0)
292                    {
293                            log_error("article_cache_generate(aid=%d, cid=%d) error\n", article.aid, article.cid);
294                            ret = -4;
295                            break;
296                    }
297          }          }
298    
299          // release lock of last section          // release lock of last section
# Line 287  int append_articles_from_db(int32_t star Line 301  int append_articles_from_db(int32_t star
301          {          {
302                  if ((ret = section_list_rw_unlock(p_section)) < 0)                  if ((ret = section_list_rw_unlock(p_section)) < 0)
303                  {                  {
304                          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);
305                  }                  }
306          }          }
307    
# Line 296  int append_articles_from_db(int32_t star Line 310  int append_articles_from_db(int32_t star
310          {          {
311                  if ((ret = section_list_rw_unlock(NULL)) < 0)                  if ((ret = section_list_rw_unlock(NULL)) < 0)
312                  {                  {
313                          log_error("section_list_rw_unlock(sid = 0) error\n");                          log_error("section_list_rw_unlock(sid=0) error\n");
314                  }                  }
315          }          }
316    
# Line 305  cleanup: Line 319  cleanup:
319    
320          mysql_close(db);          mysql_close(db);
321    
322          return ret;          return (ret < 0 ? ret : article_count);
323  }  }
324    
325  int set_last_article_op_log_from_db(void)  int set_last_article_op_log_from_db(void)
# Line 348  int set_last_article_op_log_from_db(void Line 362  int set_last_article_op_log_from_db(void
362          return last_article_op_log_mid;          return last_article_op_log_mid;
363  }  }
364    
365  int apply_article_op_log_from_db(void)  int apply_article_op_log_from_db(int op_count_limit)
366  {  {
367          MYSQL *db;          MYSQL *db;
368          MYSQL_RES *rs, *rs2;          MYSQL_RES *rs, *rs2;
# Line 359  int apply_article_op_log_from_db(void) Line 373  int apply_article_op_log_from_db(void)
373          SECTION_LIST *p_section_dest;          SECTION_LIST *p_section_dest;
374          int32_t last_sid = 0;          int32_t last_sid = 0;
375          int32_t sid_dest;          int32_t sid_dest;
376            int op_count = 0;
377          int ret = 0;          int ret = 0;
378    
379          db = db_open();          db = db_open();
# Line 370  int apply_article_op_log_from_db(void) Line 385  int apply_article_op_log_from_db(void)
385    
386          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
387                           "SELECT MID, AID, type FROM bbs_article_op "                           "SELECT MID, AID, type FROM bbs_article_op "
388                           "WHERE MID > %d AND type NOT IN ('A', 'M') ORDER BY MID",                           "WHERE MID > %d AND type NOT IN ('A') "
389                           last_article_op_log_mid);                           "ORDER BY MID LIMIT %d",
390                             last_article_op_log_mid, op_count_limit);
391    
392          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
393          {          {
# Line 450  int apply_article_op_log_from_db(void) Line 466  int apply_article_op_log_from_db(void)
466                          p_article->lock = 0;                          p_article->lock = 0;
467                          break;                          break;
468                  case 'M': // Modify article                  case 'M': // Modify article
469                          log_error("Operation type=M should not be found\n");                          snprintf(sql, sizeof(sql),
470                                             "SELECT bbs.CID, bbs_content.content "
471                                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
472                                             "WHERE bbs.AID = %d",
473                                             p_article->aid);
474    
475                            if (mysql_query(db, sql) != 0)
476                            {
477                                    log_error("Query article error: %s\n", mysql_error(db));
478                                    ret = -3;
479                                    break;
480                            }
481                            if ((rs2 = mysql_use_result(db)) == NULL)
482                            {
483                                    log_error("Get article data failed\n");
484                                    ret = -3;
485                                    break;
486                            }
487                            if ((row2 = mysql_fetch_row(rs2)))
488                            {
489                                    p_article->cid = atoi(row2[0]);
490    
491                                    if (article_cache_generate(VAR_ARTICLE_CACHE_DIR, p_article, p_section, row2[1], 0) < 0)
492                                    {
493                                            log_error("article_cache_generate(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);
494                                            ret = -4;
495                                    }
496                            }
497                            else
498                            {
499                                    p_article->cid = 0;
500                                    ret = -4;
501                            }
502                            mysql_free_result(rs2);
503                          break;                          break;
504                  case 'T': // Move article                  case 'T': // Move article
505                          snprintf(sql, sizeof(sql),                          snprintf(sql, sizeof(sql),
# Line 535  int apply_article_op_log_from_db(void) Line 584  int apply_article_op_log_from_db(void)
584    
585                  // Update MID with last successfully proceeded article_op_log                  // Update MID with last successfully proceeded article_op_log
586                  last_article_op_log_mid = atoi(row[0]);                  last_article_op_log_mid = atoi(row[0]);
587    
588                    op_count++;
589          }          }
590    
591          // release lock of last section          // release lock of last section
# Line 550  int apply_article_op_log_from_db(void) Line 601  int apply_article_op_log_from_db(void)
601    
602          mysql_close(db);          mysql_close(db);
603    
604          return ret;          return (ret < 0 ? ret : op_count);
605  }  }
606    
607  int section_list_loader_launch(void)  int section_list_loader_launch(void)
# Line 611  int section_list_loader_launch(void) Line 662  int section_list_loader_launch(void)
662                  }                  }
663    
664                  // Load section articles                  // Load section articles
                 last_aid = article_block_last_aid();  
665                  article_count = article_block_article_count();                  article_count = article_block_article_count();
666    
667                  if ((ret = append_articles_from_db(last_aid + 1, 0)) < 0)                  do
668                  {                  {
669                          log_error("append_articles_from_db(%d, 0) error\n", last_aid + 1);                          last_aid = article_block_last_aid();
670    
671                          if (ret == ERR_UNKNOWN_SECTION)                          if ((ret = append_articles_from_db(last_aid + 1, 0, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
672                          {                          {
673                                  SYS_section_list_reload = 1; // Force reload section_list                                  log_error("append_articles_from_db(%d, 0, %d) error\n", last_aid + 1, LOAD_ARTICLE_COUNT_LIMIT);
674    
675                                    if (ret == ERR_UNKNOWN_SECTION)
676                                    {
677                                            SYS_section_list_reload = 1; // Force reload section_list
678                                    }
679                          }                          }
680                  }                  } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
681    
682                  load_count = article_block_article_count() - article_count;                  load_count = article_block_article_count() - article_count;
   
683                  if (load_count > 0)                  if (load_count > 0)
684                  {                  {
685                          log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());                          log_std("Incrementally load %d articles, last_aid = %d\n", load_count, article_block_last_aid());
# Line 639  int section_list_loader_launch(void) Line 693  int section_list_loader_launch(void)
693                  // Load article_op log                  // Load article_op log
694                  last_mid = last_article_op_log_mid;                  last_mid = last_article_op_log_mid;
695    
696                  if ((ret = apply_article_op_log_from_db()) < 0)                  do
697                  {                  {
698                          log_error("apply_article_op_log_from_db() error\n");                          if ((ret = apply_article_op_log_from_db(LOAD_ARTICLE_COUNT_LIMIT)) < 0)
   
                         if (ret == ERR_UNKNOWN_SECTION)  
699                          {                          {
700                                  SYS_section_list_reload = 1; // Force reload section_list                                  log_error("apply_article_op_log_from_db() error\n");
701    
702                                    if (ret == ERR_UNKNOWN_SECTION)
703                                    {
704                                            SYS_section_list_reload = 1; // Force reload section_list
705                                    }
706                          }                          }
707                  }                  } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
708    
709                  if (last_article_op_log_mid > last_mid)                  if (last_article_op_log_mid > last_mid)
710                  {                  {
# Line 699  int section_list_loader_reload(void) Line 756  int section_list_loader_reload(void)
756          return 0;          return 0;
757  }  }
758    
759  int query_section_articles(SECTION_LIST *p_section, int32_t page_id, ARTICLE *p_articles[], int32_t *p_article_count)  int query_section_articles(SECTION_LIST *p_section, int page_id, ARTICLE *p_articles[], int *p_article_count, int *p_page_count)
760  {  {
761          ARTICLE *p_article;          ARTICLE *p_article;
762          ARTICLE *p_next_page_first_article;          ARTICLE *p_next_page_first_article;
763          int ret = 0;          int ret = 0;
764    
765          if (p_section == NULL || p_articles == NULL || p_article_count == NULL)          if (p_section == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL)
766          {          {
767                  log_error("query_section_articles() NULL pointer error\n");                  log_error("query_section_articles() NULL pointer error\n");
768                  return -1;                  return -1;
# Line 718  int query_section_articles(SECTION_LIST Line 775  int query_section_articles(SECTION_LIST
775                  return -2;                  return -2;
776          }          }
777    
778          if (page_id >= p_section->page_count)          *p_page_count = p_section->page_count;
779    
780            if (p_section->visible_article_count == 0)
781          {          {
782                  page_id = p_section->page_count - 1;                  *p_article_count = 0;
783          }          }
784            else if (page_id < 0 || page_id >= p_section->page_count)
         if (page_id < 0)  
785          {          {
786                    log_error("Invalid page_id=%d, not in range [0, %d)\n", page_id, p_section->page_count);
787                  ret = -3;                  ret = -3;
788          }          }
789          else          else
# Line 744  int query_section_articles(SECTION_LIST Line 803  int query_section_articles(SECTION_LIST
803                          }                          }
804                          p_article = p_article->p_next;                          p_article = p_article->p_next;
805                  } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);                  } while (p_article != p_next_page_first_article && (*p_article_count) <= BBS_article_limit_per_page);
806    
807                    if (*p_article_count != (page_id < p_section->page_count - 1 ? BBS_article_limit_per_page : p_section->last_page_visible_article_count))
808                    {
809                            log_error("Inconsistent visible article count %d detected in section %d page %d\n", *p_article_count, p_section->sid, page_id);
810                    }
811          }          }
812    
813          // release lock of section          // release lock of section
814          if ((ret = section_list_rd_unlock(p_section)) < 0)          if (section_list_rd_unlock(p_section) < 0)
815          {          {
816                  log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);                  log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
817                  ret = -2;                  ret = -2;
# Line 755  int query_section_articles(SECTION_LIST Line 819  int query_section_articles(SECTION_LIST
819    
820          return ret;          return ret;
821  }  }
822    
823    int locate_article_in_section(SECTION_LIST *p_section, const ARTICLE *p_article_cur, int direction,
824                                                              int *p_page_id, int *p_visible_offset, int *p_article_count)
825    {
826            const ARTICLE *p_article = NULL;
827            ARTICLE *p_tmp;
828            int32_t aid = 0;
829            int page_id;
830            int offset;
831            int ret = 0;
832            int i;
833    
834            if (p_section == NULL || p_article_cur == NULL || p_page_id == NULL || p_visible_offset == NULL || p_article_count == NULL)
835            {
836                    log_error("locate_article_in_section() NULL pointer error\n");
837                    return -1;
838            }
839    
840            // acquire lock of section
841            if ((ret = section_list_rd_lock(p_section)) < 0)
842            {
843                    log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);
844                    return -2;
845            }
846    
847            if (direction == 0)
848            {
849                    aid = p_article_cur->aid;
850            }
851            else if (direction == 1)
852            {
853                    p_article = p_article_cur;
854                    do
855                    {
856                            p_article = p_article->p_topic_next;
857                    } while (p_article != p_article_cur && p_article->visible == 0);
858    
859                    aid = (p_article->aid > p_article_cur->aid ? p_article->aid : 0);
860            }
861            else if (direction == -1)
862            {
863                    p_article = p_article_cur;
864                    do
865                    {
866                            p_article = p_article->p_topic_prior;
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    
872            p_article = NULL;
873    
874            if (aid > 0)
875            {
876                    p_article = section_list_find_article_with_offset(p_section, aid, &page_id, &offset, &p_tmp);
877                    if (p_article != NULL)
878                    {
879                            *p_article_count = (page_id == p_section->page_count - 1 ? p_section->last_page_visible_article_count : BBS_article_limit_per_page);
880    
881                            p_article = p_section->p_page_first_article[page_id];
882                            for (i = 0; i < *p_article_count;)
883                            {
884                                    if (p_article->visible)
885                                    {
886                                            if (p_article->aid == aid)
887                                            {
888                                                    *p_page_id = page_id;
889                                                    *p_visible_offset = i;
890                                                    break;
891                                            }
892                                            i++;
893                                            if (i >= *p_article_count)
894                                            {
895                                                    log_error("Visible article (aid=%d) not found in page %d\n", aid, page_id);
896                                                    p_article = NULL;
897                                            }
898                                    }
899                                    p_article = p_article->p_next;
900                            }
901                    }
902            }
903    
904            // release lock of section
905            if (section_list_rd_unlock(p_section) < 0)
906            {
907                    log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);
908                    ret = -2;
909            }
910    
911            return (ret < 0 ? ret : (p_article == NULL ? 0 : 1));
912    }


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

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