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

Diff of /lbbs/src/article_favor.c

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

Revision 1.2 by sysadm, Wed Oct 15 02:25:13 2025 UTC Revision 1.12 by sysadm, Fri Dec 19 06:16:26 2025 UTC
# Line 1  Line 1 
1  /***************************************************************************  /* SPDX-License-Identifier: GPL-3.0-or-later */
2                                           article_favor.c  -  description  /*
3                                                           -------------------   * article_favor
4          Copyright            : (C) 2004-2025 by Leaflet   *   - data model and basic operations of user favorite articles
5          Email                : leaflet@leafok.com   *
6   ***************************************************************************/   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>
7     */
8  /***************************************************************************  
9   *                                                                         *  #ifdef HAVE_CONFIG_H
10   *   This program is free software; you can redistribute it and/or modify  *  #include "config.h"
11   *   it under the terms of the GNU General Public License as published by  *  #endif
  *   the Free Software Foundation; either version 3 of the License, or     *  
  *   (at your option) any later version.                                   *  
  *                                                                         *  
  ***************************************************************************/  
12    
13  #include "article_favor.h"  #include "article_favor.h"
14  #include "common.h"  #include "common.h"
# Line 20  Line 16 
16  #include "log.h"  #include "log.h"
17  #include <stdlib.h>  #include <stdlib.h>
18  #include <string.h>  #include <string.h>
19    #include <sys/param.h>
20    
21  ARTICLE_FAVOR BBS_article_favor;  ARTICLE_FAVOR BBS_article_favor;
22    
# Line 32  int article_favor_load(int uid, ARTICLE_ Line 29  int article_favor_load(int uid, ARTICLE_
29    
30          if (p_favor == NULL)          if (p_favor == NULL)
31          {          {
32                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
33                  return -1;                  return -1;
34          }          }
35    
# Line 52  int article_favor_load(int uid, ARTICLE_ Line 49  int article_favor_load(int uid, ARTICLE_
49    
50          if ((db = db_open()) == NULL)          if ((db = db_open()) == NULL)
51          {          {
52                  log_error("article_favor_load() error: Unable to open DB\n");                  log_error("article_favor_load() error: Unable to open DB");
53                  return -2;                  return -2;
54          }          }
55    
# Line 62  int article_favor_load(int uid, ARTICLE_ Line 59  int article_favor_load(int uid, ARTICLE_
59                           uid);                           uid);
60          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
61          {          {
62                  log_error("Query article_favorite error: %s\n", mysql_error(db));                  log_error("Query article_favorite error: %s", mysql_error(db));
63                  return -3;                  return -3;
64          }          }
65          if ((rs = mysql_use_result(db)) == NULL)          if ((rs = mysql_use_result(db)) == NULL)
66          {          {
67                  log_error("Get article_favorite data failed\n");                  log_error("Get article_favorite data failed");
68                  return -3;                  return -3;
69          }          }
70    
# Line 79  int article_favor_load(int uid, ARTICLE_ Line 76  int article_favor_load(int uid, ARTICLE_
76                  (p_favor->aid_base_cnt)++;                  (p_favor->aid_base_cnt)++;
77                  if (p_favor->aid_base_cnt >= MAX_FAVOR_AID_BASE_CNT)                  if (p_favor->aid_base_cnt >= MAX_FAVOR_AID_BASE_CNT)
78                  {                  {
79                          log_error("Too many article_favorite records for uid=%d\n",                          log_error("Too many article_favorite records for uid=%d",
80                                            uid);                                            uid);
81                          break;                          break;
82                  }                  }
# Line 88  int article_favor_load(int uid, ARTICLE_ Line 85  int article_favor_load(int uid, ARTICLE_
85    
86          mysql_close(db);          mysql_close(db);
87    
88          log_common("Loaded %d article_favorite records for uid=%d\n", p_favor->aid_base_cnt, uid);          log_common("Loaded %d article_favorite records for uid=%d", p_favor->aid_base_cnt, uid);
89    
90          if (!keep_inc)          if (!keep_inc)
91          {          {
# Line 102  int article_favor_unload(ARTICLE_FAVOR * Line 99  int article_favor_unload(ARTICLE_FAVOR *
99  {  {
100          if (p_favor == NULL)          if (p_favor == NULL)
101          {          {
102                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
103                  return -1;                  return -1;
104          }          }
105    
# Line 126  int article_favor_save_inc(const ARTICLE Line 123  int article_favor_save_inc(const ARTICLE
123    
124          if (p_favor == NULL)          if (p_favor == NULL)
125          {          {
126                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
127                  return -1;                  return -1;
128          }          }
129    
# Line 137  int article_favor_save_inc(const ARTICLE Line 134  int article_favor_save_inc(const ARTICLE
134    
135          if ((db = db_open()) == NULL)          if ((db = db_open()) == NULL)
136          {          {
137                  log_error("article_favor_load() error: Unable to open DB\n");                  log_error("article_favor_load() error: Unable to open DB");
138                  return -2;                  return -2;
139          }          }
140    
# Line 147  int article_favor_save_inc(const ARTICLE Line 144  int article_favor_save_inc(const ARTICLE
144                           "DELETE FROM article_favorite WHERE UID = %d AND AID IN (",                           "DELETE FROM article_favorite WHERE UID = %d AND AID IN (",
145                           p_favor->uid);                           p_favor->uid);
146    
147          for (i = 0, j = 0; i < p_favor->aid_base_cnt && j < p_favor->aid_inc_cnt;)          for (i = 0, j = 0; j < p_favor->aid_inc_cnt;)
148          {          {
149                  if (p_favor->aid_base[i] == p_favor->aid_inc[j]) // XOR - delete record                  if (i < p_favor->aid_base_cnt && p_favor->aid_base[i] == p_favor->aid_inc[j]) // XOR - delete record
150                  {                  {
151                          snprintf(tuple_tmp, sizeof(tuple_tmp), "%d, ", p_favor->aid_inc[j]);                          snprintf(tuple_tmp, sizeof(tuple_tmp), "%d, ", p_favor->aid_inc[j]);
152                          strncat(sql_del, tuple_tmp, sizeof(sql_del) - 1 - strnlen(sql_del, sizeof(sql_del)));                          strncat(sql_del, tuple_tmp, sizeof(sql_del) - 1 - strnlen(sql_del, sizeof(sql_del)));
# Line 158  int article_favor_save_inc(const ARTICLE Line 155  int article_favor_save_inc(const ARTICLE
155                          i++;                          i++;
156                          j++;                          j++;
157                  }                  }
158                  else if (p_favor->aid_base[i] < p_favor->aid_inc[j]) // skip existing record                  else if (i < p_favor->aid_base_cnt && p_favor->aid_base[i] < p_favor->aid_inc[j]) // skip existing record
159                  {                  {
160                          i++;                          i++;
161                  }                  }
162                  else // if (p_favor->aid_base[i] > p_favor->aid_inc[j])                  else // if (i >= p_favor->aid_base_cnt || p_favor->aid_base[i] > p_favor->aid_inc[j])
163                  {                  {
164                          snprintf(tuple_tmp, sizeof(tuple_tmp),                          snprintf(tuple_tmp, sizeof(tuple_tmp),
165                                           "(%d, %d), ",                                           "(%d, %d), ",
# Line 180  int article_favor_save_inc(const ARTICLE Line 177  int article_favor_save_inc(const ARTICLE
177    
178                          if (mysql_query(db, sql_add) != 0)                          if (mysql_query(db, sql_add) != 0)
179                          {                          {
180                                  log_error("Add article_favorite error: %s\n", mysql_error(db));                                  log_error("Add article_favorite error: %s", mysql_error(db));
181                                  log_error("%s\n", sql_add);                                  log_error("%s", sql_add);
182                                  mysql_close(db);                                  mysql_close(db);
183                                  return -3;                                  return -3;
184                          }                          }
# Line 200  int article_favor_save_inc(const ARTICLE Line 197  int article_favor_save_inc(const ARTICLE
197    
198                          if (mysql_query(db, sql_del) != 0)                          if (mysql_query(db, sql_del) != 0)
199                          {                          {
200                                  log_error("Delete article_favorite error: %s\n", mysql_error(db));                                  log_error("Delete article_favorite error: %s", mysql_error(db));
201                                  log_error("%s\n", sql_del);                                  log_error("%s", sql_del);
202                                  mysql_close(db);                                  mysql_close(db);
203                                  return -3;                                  return -3;
204                          }                          }
# Line 215  int article_favor_save_inc(const ARTICLE Line 212  int article_favor_save_inc(const ARTICLE
212                  }                  }
213          }          }
214    
215          log_common("Saved %d and deleted %d article_favorite records for uid=%d\n",          log_common("Saved %d and deleted %d article_favorite records for uid=%d",
216                             cnt_total_add, cnt_total_del, p_favor->uid);                             cnt_total_add, cnt_total_del, p_favor->uid);
217    
218          mysql_close(db);          mysql_close(db);
# Line 227  int article_favor_merge_inc(ARTICLE_FAVO Line 224  int article_favor_merge_inc(ARTICLE_FAVO
224  {  {
225          int32_t aid_new[MAX_FAVOR_AID_BASE_CNT];          int32_t aid_new[MAX_FAVOR_AID_BASE_CNT];
226          int i, j, k;          int i, j, k;
227            int len;
228    
229          if (p_favor == NULL)          if (p_favor == NULL)
230          {          {
231                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
232                  return -1;                  return -1;
233          }          }
234    
# Line 256  int article_favor_merge_inc(ARTICLE_FAVO Line 254  int article_favor_merge_inc(ARTICLE_FAVO
254                  }                  }
255          }          }
256    
257          while (i < p_favor->aid_base_cnt && k < MAX_FAVOR_AID_BASE_CNT)          len = MIN(p_favor->aid_base_cnt - i, MAX_FAVOR_AID_BASE_CNT - k);
258            if (len > 0)
259          {          {
260                  aid_new[k++] = p_favor->aid_base[i++];                  memcpy(aid_new + k, p_favor->aid_base + i,
261                               sizeof(int32_t) * (size_t)len);
262                    i += len;
263                    k += len;
264          }          }
265          if (i < p_favor->aid_base_cnt)          if (i < p_favor->aid_base_cnt)
266          {          {
267                  log_error("Too many base aids, %d will be discarded\n", p_favor->aid_base_cnt - i);                  log_error("Too many base aids, %d will be discarded", p_favor->aid_base_cnt - i);
268          }          }
269    
270          while (j < p_favor->aid_inc_cnt && k < MAX_FAVOR_AID_BASE_CNT)          len = MIN(p_favor->aid_inc_cnt - j, MAX_FAVOR_AID_BASE_CNT - k);
271            if (len > 0)
272          {          {
273                  aid_new[k++] = p_favor->aid_inc[j++];                  memcpy(aid_new + k, p_favor->aid_inc + j,
274                               sizeof(int32_t) * (size_t)len);
275                    j += len;
276                    k += len;
277          }          }
278          if (j < p_favor->aid_inc_cnt)          if (j < p_favor->aid_inc_cnt)
279          {          {
280                  log_error("Too many inc aids, %d will be discarded\n", p_favor->aid_inc_cnt - j);                  log_error("Too many inc aids, %d will be discarded", p_favor->aid_inc_cnt - j);
281          }          }
282    
283          memcpy(p_favor->aid_base, aid_new, sizeof(int32_t) * (size_t)k);          memcpy(p_favor->aid_base, aid_new, sizeof(int32_t) * (size_t)k);
# Line 292  int article_favor_check(int32_t aid, con Line 298  int article_favor_check(int32_t aid, con
298    
299          if (p_favor == NULL)          if (p_favor == NULL)
300          {          {
301                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
302                  return -1;                  return -1;
303          }          }
304    
# Line 311  int article_favor_check(int32_t aid, con Line 317  int article_favor_check(int32_t aid, con
317                          mid = (left + right) / 2;                          mid = (left + right) / 2;
318                          if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))                          if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))
319                          {                          {
320                                  right = mid;                                  right = mid - 1;
321                          }                          }
322                          else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))                          else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))
323                          {                          {
# Line 343  int article_favor_set(int32_t aid, ARTIC Line 349  int article_favor_set(int32_t aid, ARTIC
349    
350          if (p_favor == NULL)          if (p_favor == NULL)
351          {          {
352                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
353                  return -1;                  return -1;
354          }          }
355    
# Line 362  int article_favor_set(int32_t aid, ARTIC Line 368  int article_favor_set(int32_t aid, ARTIC
368                          mid = (left + right) / 2;                          mid = (left + right) / 2;
369                          if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))                          if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))
370                          {                          {
371                                  right = mid;                                  right = mid - 1;
372                          }                          }
373                          else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))                          else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid]))
374                          {                          {
# Line 388  int article_favor_set(int32_t aid, ARTIC Line 394  int article_favor_set(int32_t aid, ARTIC
394    
395          if (aid == p_favor->aid_inc[left] && p_favor->aid_inc_cnt > 0) // Unset          if (aid == p_favor->aid_inc[left] && p_favor->aid_inc_cnt > 0) // Unset
396          {          {
397                  for (i = left; i < p_favor->aid_inc_cnt - 1; i++)                  if (p_favor->aid_inc_cnt > left + 1)
398                  {                  {
399                          p_favor->aid_inc[i] = p_favor->aid_inc[i + 1];                          memmove(p_favor->aid_inc + left,
400                                            p_favor->aid_inc + left + 1,
401                                            sizeof(int32_t) * (size_t)(p_favor->aid_inc_cnt - left - 1));
402                  }                  }
403    
404                  (p_favor->aid_inc_cnt)--;                  (p_favor->aid_inc_cnt)--;
# Line 404  int article_favor_set(int32_t aid, ARTIC Line 412  int article_favor_set(int32_t aid, ARTIC
412                  // Save incremental article favorite                  // Save incremental article favorite
413                  if (article_favor_save_inc(p_favor) < 0)                  if (article_favor_save_inc(p_favor) < 0)
414                  {                  {
415                          log_error("article_favor_save_inc() error\n");                          log_error("article_favor_save_inc() error");
416                          return -2;                          return -2;
417                  }                  }
418    
# Line 424  int article_favor_set(int32_t aid, ARTIC Line 432  int article_favor_set(int32_t aid, ARTIC
432                  right = left + 1;                  right = left + 1;
433          }          }
434    
435          for (i = p_favor->aid_inc_cnt - 1; i >= right; i--)          if (p_favor->aid_inc_cnt > right)
436          {          {
437                  p_favor->aid_inc[i + 1] = p_favor->aid_inc[i];                  memmove(p_favor->aid_inc + right + 1,
438                                    p_favor->aid_inc + right,
439                                    sizeof(int32_t) * (size_t)(p_favor->aid_inc_cnt - right));
440          }          }
441    
442          p_favor->aid_inc[right] = aid;          p_favor->aid_inc[right] = aid;
# Line 435  int article_favor_set(int32_t aid, ARTIC Line 445  int article_favor_set(int32_t aid, ARTIC
445          return 1; // Set complete          return 1; // Set complete
446  }  }
447    
448  int query_favor_articles(ARTICLE_FAVOR *p_favor, int page_id, ARTICLE **p_articles,  int query_favor_articles(ARTICLE_FAVOR *p_favor, int page_id, const ARTICLE **p_articles,
449                                                   char p_snames[][BBS_section_name_max_len + 1], int *p_article_count, int *p_page_count)                                                   char p_snames[][BBS_section_name_max_len + 1], int *p_article_count, int *p_page_count)
450  {  {
451          SECTION_LIST *p_section;          SECTION_LIST *p_section;
# Line 444  int query_favor_articles(ARTICLE_FAVOR * Line 454  int query_favor_articles(ARTICLE_FAVOR *
454    
455          if (p_favor == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL)          if (p_favor == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL)
456          {          {
457                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
458                  return -1;                  return -1;
459          }          }
460    
461          if (article_favor_save_inc(p_favor) < 0)          if (article_favor_save_inc(p_favor) < 0)
462          {          {
463                  log_error("article_favor_save_inc() error\n");                  log_error("article_favor_save_inc() error");
464                  return -2;                  return -2;
465          }          }
466          if (article_favor_merge_inc(p_favor) < 0)          if (article_favor_merge_inc(p_favor) < 0)
467          {          {
468                  log_error("article_favor_merge_inc() error\n");                  log_error("article_favor_merge_inc() error");
469                  return -2;                  return -2;
470          }          }
471    
472          *p_page_count = p_favor->aid_base_cnt / BBS_article_limit_per_page + (p_favor->aid_base_cnt % BBS_article_limit_per_page == 0 ? 0 : 1);          *p_page_count = (p_favor->aid_base_cnt + BBS_article_limit_per_page - 1) / BBS_article_limit_per_page;
473          *p_article_count = 0;          *p_article_count = 0;
474    
475          if (p_favor->aid_base_cnt == 0)          if (p_favor->aid_base_cnt == 0)
# Line 470  int query_favor_articles(ARTICLE_FAVOR * Line 480  int query_favor_articles(ARTICLE_FAVOR *
480    
481          if (page_id < 0 || page_id >= *p_page_count)          if (page_id < 0 || page_id >= *p_page_count)
482          {          {
483                  log_error("Invalid page_id = %d, not in range [0, %d)\n", page_id, *p_page_count);                  log_error("Invalid page_id = %d, not in range [0, %d)", page_id, *p_page_count);
484                  return -1;                  return -1;
485          }          }
486    
# Line 483  int query_favor_articles(ARTICLE_FAVOR * Line 493  int query_favor_articles(ARTICLE_FAVOR *
493                  p_articles[i] = article_block_find_by_aid(aid);                  p_articles[i] = article_block_find_by_aid(aid);
494                  if (p_articles[i] == NULL)                  if (p_articles[i] == NULL)
495                  {                  {
496                          log_error("article_block_find_by_aid(aid=%d) error: page_id=%d, i=%d\n", aid, page_id, i);                          log_error("article_block_find_by_aid(aid=%d) error: page_id=%d, i=%d", aid, page_id, i);
497                          return -3;                          return -3;
498                  }                  }
499    
500                  p_section = section_list_find_by_sid(p_articles[i]->sid);                  p_section = section_list_find_by_sid(p_articles[i]->sid);
501                  if (p_section == NULL)                  if (p_section == NULL)
502                  {                  {
503                          log_error("section_list_find_by_sid(%d) error\n", p_articles[i]->sid);                          log_error("section_list_find_by_sid(%d) error", p_articles[i]->sid);
504                          return -3;                          return -3;
505                  }                  }
506    
507                  // acquire lock of section                  if (get_section_info(p_section, p_snames[i], NULL, NULL) < 0)
                 if (section_list_rd_lock(p_section) < 0)  
                 {  
                         log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid);  
                         return -4;  
                 }  
   
                 memcpy(p_snames[i], p_section->sname, sizeof(p_snames[i]));  
   
                 // release lock of section  
                 if (section_list_rd_unlock(p_section) < 0)  
508                  {                  {
509                          log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid);                          log_error("get_section_info(sid=%d) error", p_section->sid);
510                          return -4;                          return -4;
511                  }                  }
512          }          }


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

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