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

Diff of /lbbs/src/article_view_log.c

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

Revision 1.2 by sysadm, Sat Jun 7 08:07:07 2025 UTC Revision 1.19 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_view_log.c  -  description  /*
3                                                           -------------------   * article_view_log
4          Copyright            : (C) 2004-2025 by Leaflet   *   - data persistence and query of article view log
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_view_log.h"  #include "article_view_log.h"
 #include "log.h"  
14  #include "common.h"  #include "common.h"
15  #include "database.h"  #include "database.h"
16    #include "log.h"
17  #include <stdlib.h>  #include <stdlib.h>
   
 #define _XOPEN_SOURCE 500  
 #define _POSIX_C_SOURCE 200809L  
18  #include <string.h>  #include <string.h>
19    
20    ARTICLE_VIEW_LOG BBS_article_view_log;
21    
22  int article_view_log_load(int uid, ARTICLE_VIEW_LOG *p_view_log, int keep_inc)  int article_view_log_load(int uid, ARTICLE_VIEW_LOG *p_view_log, int keep_inc)
23  {  {
24          MYSQL *db;          MYSQL *db;
# Line 33  int article_view_log_load(int uid, ARTIC Line 28  int article_view_log_load(int uid, ARTIC
28    
29          if (p_view_log == NULL)          if (p_view_log == NULL)
30          {          {
31                  log_error("article_view_log_load() error: NULL pointer\n");                  log_error("NULL pointer error");
32                  return -1;                  return -1;
33          }          }
34    
35            p_view_log->uid = uid;
36    
37          if (uid == 0)          if (uid == 0)
38          {          {
39                  p_view_log->aid_base_cnt = 0;                  p_view_log->aid_base_cnt = 0;
# Line 52  int article_view_log_load(int uid, ARTIC Line 49  int article_view_log_load(int uid, ARTIC
49    
50          if ((db = db_open()) == NULL)          if ((db = db_open()) == NULL)
51          {          {
52                  log_error("article_view_log_load() error: Unable to open DB\n");                  log_error("article_view_log_load() error: Unable to open DB");
53                  return -2;                  return -2;
54          }          }
55    
# Line 62  int article_view_log_load(int uid, ARTIC Line 59  int article_view_log_load(int uid, ARTIC
59                           uid);                           uid);
60          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
61          {          {
62                  log_error("Query view_article_log error: %s\n", mysql_error(db));                  log_error("Query view_article_log error: %s", mysql_error(db));
63                  return -3;                  return -3;
64          }          }
65          if ((rs = mysql_store_result(db)) == NULL)          if ((rs = mysql_store_result(db)) == NULL)
66          {          {
67                  log_error("Get view_article_log data failed\n");                  log_error("Get view_article_log data failed");
68                  return -3;                  return -3;
69          }          }
70    
# Line 75  int article_view_log_load(int uid, ARTIC Line 72  int article_view_log_load(int uid, ARTIC
72          p_view_log->aid_base = malloc(sizeof(int32_t) * mysql_num_rows(rs));          p_view_log->aid_base = malloc(sizeof(int32_t) * mysql_num_rows(rs));
73          if (p_view_log->aid_base == NULL)          if (p_view_log->aid_base == NULL)
74          {          {
75                  log_error("malloc(INT32 * %d) error: OOM\n", mysql_num_rows(rs));                  log_error("malloc(INT32 * %d) error: OOM", mysql_num_rows(rs));
76                  mysql_free_result(rs);                  mysql_free_result(rs);
77                  mysql_close(db);                  mysql_close(db);
78                  return -4;                  return -4;
# Line 89  int article_view_log_load(int uid, ARTIC Line 86  int article_view_log_load(int uid, ARTIC
86    
87          mysql_close(db);          mysql_close(db);
88    
89            log_common("Loaded %d view_article_log records for uid=%d", p_view_log->aid_base_cnt, uid);
90    
91          if (!keep_inc)          if (!keep_inc)
92          {          {
93                  p_view_log->aid_inc_cnt = 0;                  p_view_log->aid_inc_cnt = 0;
# Line 101  int article_view_log_unload(ARTICLE_VIEW Line 100  int article_view_log_unload(ARTICLE_VIEW
100  {  {
101          if (p_view_log == NULL)          if (p_view_log == NULL)
102          {          {
103                  log_error("article_view_log_unload() error: NULL pointer\n");                  log_error("NULL pointer error");
104                  return -1;                  return -1;
105          }          }
106    
# Line 115  int article_view_log_unload(ARTICLE_VIEW Line 114  int article_view_log_unload(ARTICLE_VIEW
114          return 0;          return 0;
115  }  }
116    
117  int article_view_log_save_inc(int uid, const ARTICLE_VIEW_LOG *p_view_log)  int article_view_log_save_inc(const ARTICLE_VIEW_LOG *p_view_log)
118  {  {
119          MYSQL *db;          MYSQL *db = NULL;
120          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
121          char tuple_tmp[LINE_BUFFER_LEN];          char tuple_tmp[LINE_BUFFER_LEN];
122          int i;          int i;
123            int affected_record = 0;
124    
125          if (p_view_log == NULL)          if (p_view_log == NULL)
126          {          {
127                  log_error("article_view_log_save_inc() error: NULL pointer\n");                  log_error("NULL pointer error");
128                  return -1;                  return -1;
129          }          }
130    
131            if (p_view_log->uid <= 0 || p_view_log->aid_inc_cnt == 0)
132            {
133                    return 0;
134            }
135    
136          if ((db = db_open()) == NULL)          if ((db = db_open()) == NULL)
137          {          {
138                  log_error("article_view_log_load() error: Unable to open DB\n");                  log_error("article_view_log_load() error: Unable to open DB");
139                  return -2;                  return -2;
140          }          }
141    
142          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
143                           "INSERT INTO view_article_log(AID, UID, dt) ");                           "INSERT IGNORE INTO view_article_log(AID, UID, dt) VALUES ");
144    
145          for (i = 0; i < p_view_log->aid_inc_cnt; i++)          for (i = 0; i < p_view_log->aid_inc_cnt; i++)
146          {          {
147                  snprintf(tuple_tmp, sizeof(tuple_tmp),                  snprintf(tuple_tmp, sizeof(tuple_tmp),
148                                   "(%d, %d, NOW())",                                   "(%d, %d, NOW())",
149                                   p_view_log->aid_inc[i], uid);                                   p_view_log->aid_inc[i], p_view_log->uid);
150                  strncat(sql, tuple_tmp, sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));                  strncat(sql, tuple_tmp, sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));
151    
152                  if (i % 100 == 0) // Insert 100 records per query                  if ((i + 1) % 100 == 0 || (i + 1) == p_view_log->aid_inc_cnt) // Insert 100 records per query
153                  {                  {
                         strncat(sql, " ON DUPLICATE KEY UPDATE 0 + 0", sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));  
   
154                          if (mysql_query(db, sql) != 0)                          if (mysql_query(db, sql) != 0)
155                          {                          {
156                                  log_error("Add view_article_log error: %s\n", mysql_error(db));                                  log_error("Add view_article_log error: %s", mysql_error(db));
157                                    mysql_close(db);
158                                  return -3;                                  return -3;
159                          }                          }
160    
161                            affected_record += (int)mysql_affected_rows(db);
162    
163                          snprintf(sql, sizeof(sql),                          snprintf(sql, sizeof(sql),
164                                           "INSERT INTO view_article_log(AID, UID, dt) ");                                           "INSERT IGNORE INTO view_article_log(AID, UID, dt) VALUES ");
165                  }                  }
166                  else                  else
167                  {                  {
# Line 163  int article_view_log_save_inc(int uid, c Line 169  int article_view_log_save_inc(int uid, c
169                  }                  }
170          }          }
171    
172            log_common("Saved %d view_article_log records for uid=%d", affected_record, p_view_log->uid);
173    
174          mysql_close(db);          mysql_close(db);
175    
176          return 0;          return 0;
# Line 173  int article_view_log_merge_inc(ARTICLE_V Line 181  int article_view_log_merge_inc(ARTICLE_V
181          int32_t *aid_new;          int32_t *aid_new;
182          int aid_new_cnt;          int aid_new_cnt;
183          int i, j, k;          int i, j, k;
184            int len;
185    
186          if (p_view_log == NULL)          if (p_view_log == NULL)
187          {          {
188                  log_error("article_view_log_merge_inc() error: NULL pointer\n");                  log_error("NULL pointer error");
189                  return -1;                  return -1;
190          }          }
191    
# Line 190  int article_view_log_merge_inc(ARTICLE_V Line 199  int article_view_log_merge_inc(ARTICLE_V
199          aid_new = malloc(sizeof(int32_t) * (size_t)aid_new_cnt);          aid_new = malloc(sizeof(int32_t) * (size_t)aid_new_cnt);
200          if (aid_new == NULL)          if (aid_new == NULL)
201          {          {
202                  log_error("malloc(INT32 * %d) error: OOM\n", aid_new_cnt);                  log_error("malloc(INT32 * %d) error: OOM", aid_new_cnt);
203                  return -2;                  return -2;
204          }          }
205    
# Line 200  int article_view_log_merge_inc(ARTICLE_V Line 209  int article_view_log_merge_inc(ARTICLE_V
209                  {                  {
210                          if (p_view_log->aid_base[i] == p_view_log->aid_inc[j])                          if (p_view_log->aid_base[i] == p_view_log->aid_inc[j])
211                          {                          {
212                                  log_error("Duplicate aid = %d found in both Base (offset = %d) and Inc (offset = %d)\n",                                  log_error("Duplicate aid = %d found in both Base (offset = %d) and Inc (offset = %d)",
213                                                    p_view_log->aid_base[i], i, j);                                                    p_view_log->aid_base[i], i, j);
214                                  j++; // Skip duplicate one in Inc                                  j++; // Skip duplicate one in Inc
215                          }                          }
# Line 213  int article_view_log_merge_inc(ARTICLE_V Line 222  int article_view_log_merge_inc(ARTICLE_V
222                  }                  }
223          }          }
224    
225          memcpy(aid_new + k, p_view_log->aid_base + i, sizeof(int32_t) * (size_t)(p_view_log->aid_base_cnt - i));          len = p_view_log->aid_base_cnt - i;
226          k += (p_view_log->aid_base_cnt - i);          if (len > 0)
227          memcpy(aid_new + k, p_view_log->aid_inc + j, sizeof(int32_t) * (size_t)(p_view_log->aid_inc_cnt - j));          {
228          k += (p_view_log->aid_inc_cnt - j);                  memcpy(aid_new + k, p_view_log->aid_base + i,
229                               sizeof(int32_t) * (size_t)len);
230                    k += len;
231            }
232            len = p_view_log->aid_inc_cnt - j;
233            if (len > 0)
234            {
235                    memcpy(aid_new + k, p_view_log->aid_inc + j,
236                               sizeof(int32_t) * (size_t)len);
237                    k += len;
238            }
239    
240          free(p_view_log->aid_base);          free(p_view_log->aid_base);
241          p_view_log->aid_base = aid_new;          p_view_log->aid_base = aid_new;
# Line 236  int article_view_log_is_viewed(int32_t a Line 255  int article_view_log_is_viewed(int32_t a
255    
256          if (p_view_log == NULL)          if (p_view_log == NULL)
257          {          {
258                  log_error("article_view_log_is_viewed() error: NULL pointer\n");                  log_error("NULL pointer error");
259                  return -1;                  return -1;
260          }          }
261    
# Line 255  int article_view_log_is_viewed(int32_t a Line 274  int article_view_log_is_viewed(int32_t a
274                          mid = (left + right) / 2;                          mid = (left + right) / 2;
275                          if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))                          if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
276                          {                          {
277                                  right = mid;                                  right = mid - 1;
278                          }                          }
279                          else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))                          else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
280                          {                          {
# Line 285  int article_view_log_set_viewed(int32_t Line 304  int article_view_log_set_viewed(int32_t
304    
305          if (p_view_log == NULL)          if (p_view_log == NULL)
306          {          {
307                  log_error("article_view_log_set_viewed() error: NULL pointer\n");                  log_error("NULL pointer error");
308                  return -1;                  return -1;
309          }          }
310    
# Line 304  int article_view_log_set_viewed(int32_t Line 323  int article_view_log_set_viewed(int32_t
323                          mid = (left + right) / 2;                          mid = (left + right) / 2;
324                          if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))                          if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
325                          {                          {
326                                  right = mid;                                  right = mid - 1;
327                          }                          }
328                          else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))                          else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
329                          {                          {
# Line 323  int article_view_log_set_viewed(int32_t Line 342  int article_view_log_set_viewed(int32_t
342          }          }
343    
344          // Merge if Inc is full          // Merge if Inc is full
345          if (p_view_log->aid_inc_cnt >= MAX_AID_INC_CNT)          if (p_view_log->aid_inc_cnt >= MAX_VIEWED_AID_INC_CNT)
346          {          {
347                    // Save incremental article view log
348                    if (article_view_log_save_inc(p_view_log) < 0)
349                    {
350                            log_error("article_view_log_save_inc() error");
351                            return -2;
352                    }
353    
354                  article_view_log_merge_inc(p_view_log);                  article_view_log_merge_inc(p_view_log);
355    
356                  p_view_log->aid_inc[(p_view_log->aid_inc_cnt)++] = aid;                  p_view_log->aid_inc[(p_view_log->aid_inc_cnt)++] = aid;
# Line 341  int article_view_log_set_viewed(int32_t Line 367  int article_view_log_set_viewed(int32_t
367                  right = left + 1;                  right = left + 1;
368          }          }
369    
370          for (i = p_view_log->aid_inc_cnt - 1; i >= right; i--)          if (p_view_log->aid_inc_cnt > right)
371          {          {
372                  p_view_log->aid_inc[i + 1] = p_view_log->aid_inc[i];                  memmove(p_view_log->aid_inc + right + 1,
373                                    p_view_log->aid_inc + right,
374                                    sizeof(int32_t) * (size_t)(p_view_log->aid_inc_cnt - right));
375          }          }
376    
377          p_view_log->aid_inc[right] = aid;          p_view_log->aid_inc[right] = aid;


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

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