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

Diff of /lbbs/src/section_list.c

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

Revision 1.10 by sysadm, Fri May 23 00:12:59 2025 UTC Revision 1.12 by sysadm, Fri May 23 10:45:54 2025 UTC
# Line 31  Line 31 
31  #define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id)  #define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id)
32  #define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT)  #define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT)
33    
34    #define CALCULATE_PAGE_THRESHOLD 100 // Adjust to tune performance of move topic
35    
36  struct article_block_t  struct article_block_t
37  {  {
38          ARTICLE articles[ARTICLE_PER_BLOCK];          ARTICLE articles[ARTICLE_PER_BLOCK];
# Line 309  ARTICLE *article_block_find_by_index(int Line 311  ARTICLE *article_block_find_by_index(int
311          return (p_block->articles + (index % ARTICLE_PER_BLOCK));          return (p_block->articles + (index % ARTICLE_PER_BLOCK));
312  }  }
313    
314  SECTION_LIST *section_list_create(const char *sname, const char *stitle, const char *master_name)  SECTION_LIST *section_list_create(int32_t sid, const char *sname, const char *stitle, const char *master_name)
315  {  {
316          SECTION_LIST *p_section;          SECTION_LIST *p_section;
317    
# Line 343  SECTION_LIST *section_list_create(const Line 345  SECTION_LIST *section_list_create(const
345    
346          p_section = p_section_list_pool + section_list_count;          p_section = p_section_list_pool + section_list_count;
347    
348            p_section->sid = sid;
349    
350          strncpy(p_section->sname, sname, sizeof(p_section->sname - 1));          strncpy(p_section->sname, sname, sizeof(p_section->sname - 1));
351          p_section->sname[sizeof(p_section->sname - 1)] = '\0';          p_section->sname[sizeof(p_section->sname - 1)] = '\0';
352    
# Line 530  int section_list_append_article(SECTION_ Line 534  int section_list_append_article(SECTION_
534          p_section->p_article_tail = p_article;          p_section->p_article_tail = p_article;
535    
536          // Update page          // Update page
537          if (p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0)          if ((p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0) ||
538                    p_section->article_count == 1)
539          {          {
540                  p_section->p_page_first_article[p_section->page_count] = p_article;                  p_section->p_page_first_article[p_section->page_count] = p_article;
541                  p_section->page_count++;                  p_section->page_count++;
# Line 610  int section_list_set_article_visible(SEC Line 615  int section_list_set_article_visible(SEC
615          return affected_count;          return affected_count;
616  }  }
617    
618  ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset)  ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset, ARTICLE **pp_next)
619  {  {
620          ARTICLE *p_article;          ARTICLE *p_article;
621          int left;          int left;
# Line 619  ARTICLE *section_list_find_article_with_ Line 624  ARTICLE *section_list_find_article_with_
624    
625          *p_page = -1;          *p_page = -1;
626          *p_offset = -1;          *p_offset = -1;
627            *pp_next = NULL;
628    
629          if (p_section == NULL)          if (p_section == NULL)
630          {          {
# Line 663  ARTICLE *section_list_find_article_with_ Line 669  ARTICLE *section_list_find_article_with_
669          p_article = p_section->p_page_first_article[*p_page];          p_article = p_section->p_page_first_article[*p_page];
670    
671          // p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid          // p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid
672          right = (*p_page == MAX(1, p_section->page_count) - 1 ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid);          right = (*p_page == MAX(0, p_section->page_count - 1) ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid);
673    
674          // left will be the offset of article found or offset to insert          // left will be the offset of article found or offset to insert
675          left = 0;          left = 0;
676    
677          while (aid > p_article->aid)          while (aid > p_article->aid)
678          {          {
                 // aid > p_article->aid  
679                  p_article = p_article->p_next;                  p_article = p_article->p_next;
680                  left++;                  left++;
681    
682                    if (aid == p_article->aid)
683                    {
684                            *pp_next = p_article->p_next;
685                            break;
686                    }
687    
688                  // over last article in the page                  // over last article in the page
689                  if (p_article == p_section->p_article_head || p_article->aid >= right)                  if (p_article == p_section->p_article_head || p_article->aid >= right)
690                  {                  {
691                          break;                          *pp_next = (p_article == p_section->p_article_head ? p_section->p_article_head : p_section->p_page_first_article[*p_page + 1]);
692                            *p_offset = left;
693                            return NULL; // not found
694                  }                  }
695          }          }
696    
697          if (aid != p_article->aid) // not exist          if (aid < p_article->aid)
698            {
699                    *pp_next = p_article;
700                    p_article = NULL; // not found
701            }
702            else // aid == p_article->aid
703          {          {
704                  p_article = NULL;                  *pp_next = p_article->p_next;
705          }          }
706    
707          *p_offset = left;          *p_offset = left;
# Line 694  ARTICLE *section_list_find_article_with_ Line 712  ARTICLE *section_list_find_article_with_
712  int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid)  int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid)
713  {  {
714          ARTICLE *p_article;          ARTICLE *p_article;
715            ARTICLE *p_next;
716          int32_t page;          int32_t page;
717          int32_t offset;          int32_t offset;
718          int visible_article_count;          int visible_article_count;
# Line 705  int section_list_calculate_page(SECTION_ Line 724  int section_list_calculate_page(SECTION_
724                  return -1;                  return -1;
725          }          }
726    
727          p_article = section_list_find_article_with_offset(p_section, start_aid, &page, &offset);          if (p_section->article_count == 0) // empty
728          if (p_article == NULL)          {
729                    p_section->page_count = 0;
730                    p_section->last_page_visible_article_count = 0;
731    
732                    return 0;
733            }
734    
735            if (start_aid > 0)
736          {          {
737                  if (page < 0)                  p_article = section_list_find_article_with_offset(p_section, start_aid, &page, &offset, &p_next);
738                    if (p_article == NULL)
739                  {                  {
740                          return 0;                          if (page < 0)
741                            {
742                                    return -1;
743                            }
744                            log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n",
745                                              start_aid, p_section->sid);
746                            return -2;
747                  }                  }
748    
749                  log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n", start_aid, p_section->sid);                  if (offset > 0)
750                    {
751                            p_article = p_section->p_page_first_article[page];
752                    }
753          }          }
754            else
         if (offset > 0)  
755          {          {
756                  p_article = p_section->p_page_first_article[page];                  p_article = p_section->p_article_head;
757                    page = 0;
758                    offset = 0;
759          }          }
760    
761          visible_article_count = 0;          visible_article_count = 0;
# Line 764  int section_list_calculate_page(SECTION_ Line 801  int section_list_calculate_page(SECTION_
801    
802          return 0;          return 0;
803  }  }
804    
805    int section_list_count_of_topic_articles(int32_t aid)
806    {
807            ARTICLE *p_article;
808            int article_count;
809    
810            p_article = article_block_find_by_aid(aid);
811            if (p_article == NULL)
812            {
813                    return 0; // Not found
814            }
815    
816            article_count = 0;
817    
818            do
819            {
820                    article_count++;
821                    p_article = p_article->p_topic_next;
822            } while (p_article->aid != aid);
823    
824            return article_count;
825    }
826    
827    int section_list_move_topic(SECTION_LIST *p_section_src, SECTION_LIST *p_section_dest, int32_t aid)
828    {
829            ARTICLE *p_article;
830            ARTICLE *p_next;
831            int32_t page;
832            int32_t offset;
833            int32_t move_article_count;
834            int32_t dest_article_count_old;
835            int32_t last_unaffected_aid_src;
836            int32_t first_inserted_aid_dest;
837            int move_counter;
838    
839            if (p_section_dest == NULL)
840            {
841                    log_error("section_list_move_topic() NULL pointer error\n");
842                    return -1;
843            }
844    
845            if ((p_article = section_list_find_article_with_offset(p_section_src, aid, &page, &offset, &p_next)) == NULL)
846            {
847                    log_error("section_list_move_topic() error: article %d not found in section %d\n", aid, p_section_src->sid);
848                    return -2;
849            }
850    
851            if (p_article->tid != 0)
852            {
853                    log_error("section_list_move_topic(aid = %d) error: article is not head of topic, tid = %d\n", aid, p_article->tid);
854                    return -2;
855            }
856    
857            last_unaffected_aid_src = (p_article == p_section_src->p_article_head ? 0 : p_article->p_prior->aid);
858    
859            move_article_count = section_list_count_of_topic_articles(aid);
860            if (move_article_count <= 0)
861            {
862                    log_error("section_list_count_of_topic_articles(aid = %d) <= 0\n", aid);
863                    return -2;
864            }
865    
866            if (p_section_dest->article_count + move_article_count > BBS_article_limit_per_section)
867            {
868                    log_error("section_list_move_topic() error: article_count %d reach limit in section %d\n",
869                                      p_section_dest->article_count + move_article_count, p_section_dest->sid);
870                    return -3;
871            }
872    
873            dest_article_count_old = p_section_dest->article_count;
874            move_counter = 0;
875            first_inserted_aid_dest = p_article->aid;
876    
877            do
878            {
879                    if (section_list_find_article_with_offset(p_section_dest, p_article->aid, &page, &offset, &p_next) != NULL)
880                    {
881                            log_error("section_list_move_topic() error: article %d already in section %d\n", p_article->aid, p_section_dest->sid);
882                            return -4;
883                    }
884    
885                    // Remove from bi-directional article list of src section
886                    if (p_section_src->p_article_head == p_article)
887                    {
888                            p_section_src->p_article_head = p_article->p_next;
889                    }
890                    if (p_section_src->p_article_tail == p_article)
891                    {
892                            p_section_src->p_article_tail = p_article->p_prior;
893                    }
894                    if (p_section_src->p_article_head == p_article) // || p_section_src->p_article_tail == p_article
895                    {
896                            p_section_src->p_article_head = NULL;
897                            p_section_src->p_article_tail = NULL;
898                    }
899    
900                    p_article->p_prior->p_next = p_article->p_next;
901                    p_article->p_next->p_prior = p_article->p_prior;
902    
903                    // Insert into bi-directional article list of dest section
904                    if (p_next == NULL) // empty section
905                    {
906                            p_section_dest->p_article_head = p_article;
907                            p_section_dest->p_article_tail = p_article;
908                            p_article->p_prior = p_article;
909                            p_article->p_next = p_article;
910                    }
911                    else
912                    {
913                            if (p_section_dest->p_article_head == p_next)
914                            {
915                                    if (p_article->aid < p_next->aid)
916                                    {
917                                            p_section_dest->p_article_head = p_article;
918                                    }
919                                    else // p_article->aid > p_next->aid
920                                    {
921                                            p_section_dest->p_article_tail = p_article;
922                                    }
923                            }
924    
925                            p_article->p_prior = p_next->p_prior;
926                            p_article->p_next = p_next;
927                            p_next->p_prior->p_next = p_article;
928                            p_next->p_prior = p_article;
929                    }
930    
931                    // Update article / topic counter of src / desc section
932                    p_section_src->article_count--;
933                    p_section_dest->article_count++;
934                    if (p_article->tid == 0)
935                    {
936                            p_section_src->topic_count--;
937                            p_section_dest->topic_count++;
938                    }
939    
940                    // Update visible article / topic counter of src / desc section
941                    if (p_article->visible)
942                    {
943                            p_section_src->visible_article_count--;
944                            p_section_dest->visible_article_count++;
945                            if (p_article->tid == 0)
946                            {
947                                    p_section_src->visible_topic_count--;
948                                    p_section_dest->visible_topic_count++;
949                            }
950                    }
951    
952                    // Update page for empty dest section
953                    if (p_section_dest->article_count == 1)
954                    {
955                            p_section_dest->p_page_first_article[0] = p_article;
956                            p_section_dest->page_count = 1;
957                            p_section_dest->last_page_visible_article_count = (p_article->visible ? 1 : 0);
958                    }
959    
960                    p_article = p_article->p_topic_next;
961    
962                    move_counter++;
963                    if (move_counter % CALCULATE_PAGE_THRESHOLD == 0)
964                    {
965                            // Re-calculate pages of desc section
966                            if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
967                            {
968                                    log_error("section_list_calculate_page(section = %d, aid = %d) error\n",
969                                                      p_section_dest->sid, first_inserted_aid_dest);
970                            }
971    
972                            first_inserted_aid_dest = p_article->aid;
973                    }
974            } while (p_article->aid != aid);
975    
976            if (p_section_dest->article_count - dest_article_count_old != move_article_count)
977            {
978                    log_error("section_list_move_topic() error: count of moved articles %d != %d\n",
979                                      p_section_dest->article_count - dest_article_count_old, move_article_count);
980            }
981    
982            // Re-calculate pages of src section
983            if (section_list_calculate_page(p_section_src, last_unaffected_aid_src) < 0)
984            {
985                    log_error("section_list_calculate_page(section = %d, aid = %d) error at aid = %d\n",
986                                      p_section_src->sid, last_unaffected_aid_src, aid);
987            }
988    
989            if (move_counter % CALCULATE_PAGE_THRESHOLD != 0)
990            {
991                    // Re-calculate pages of desc section
992                    if (section_list_calculate_page(p_section_dest, first_inserted_aid_dest) < 0)
993                    {
994                            log_error("section_list_calculate_page(section = %d, aid = %d) error\n",
995                                              p_section_dest->sid, first_inserted_aid_dest);
996                    }
997            }
998    
999            return move_article_count;
1000    }


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

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