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

Contents of /lbbs/src/article_view_log.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Tue Oct 14 03:24:27 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.9: +1 -1 lines
Content type: text/x-csrc
Skip save view_log if there is no incremental data

1 /***************************************************************************
2 article_view_log.c - description
3 -------------------
4 Copyright : (C) 2004-2025 by Leaflet
5 Email : leaflet@leafok.com
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "article_view_log.h"
18 #include "common.h"
19 #include "database.h"
20 #include "log.h"
21 #include <stdlib.h>
22 #include <string.h>
23
24 ARTICLE_VIEW_LOG BBS_article_view_log;
25
26 int article_view_log_load(int uid, ARTICLE_VIEW_LOG *p_view_log, int keep_inc)
27 {
28 MYSQL *db;
29 MYSQL_RES *rs;
30 MYSQL_ROW row;
31 char sql[SQL_BUFFER_LEN];
32
33 if (p_view_log == NULL)
34 {
35 log_error("NULL pointer error\n");
36 return -1;
37 }
38
39 p_view_log->uid = uid;
40
41 if (uid == 0)
42 {
43 p_view_log->aid_base_cnt = 0;
44 p_view_log->aid_base = NULL;
45
46 if (!keep_inc)
47 {
48 p_view_log->aid_inc_cnt = 0;
49 }
50
51 return 0;
52 }
53
54 if ((db = db_open()) == NULL)
55 {
56 log_error("article_view_log_load() error: Unable to open DB\n");
57 return -2;
58 }
59
60 snprintf(sql, sizeof(sql),
61 "SELECT AID FROM view_article_log WHERE UID = %d "
62 "ORDER BY AID",
63 uid);
64 if (mysql_query(db, sql) != 0)
65 {
66 log_error("Query view_article_log error: %s\n", mysql_error(db));
67 return -3;
68 }
69 if ((rs = mysql_store_result(db)) == NULL)
70 {
71 log_error("Get view_article_log data failed\n");
72 return -3;
73 }
74
75 p_view_log->aid_base_cnt = 0;
76 p_view_log->aid_base = malloc(sizeof(int32_t) * mysql_num_rows(rs));
77 if (p_view_log->aid_base == NULL)
78 {
79 log_error("malloc(INT32 * %d) error: OOM\n", mysql_num_rows(rs));
80 mysql_free_result(rs);
81 mysql_close(db);
82 return -4;
83 }
84
85 while ((row = mysql_fetch_row(rs)))
86 {
87 p_view_log->aid_base[(p_view_log->aid_base_cnt)++] = atoi(row[0]);
88 }
89 mysql_free_result(rs);
90
91 mysql_close(db);
92
93 log_common("Loaded %d view_article_log records for uid=%d\n", p_view_log->aid_base_cnt, uid);
94
95 if (!keep_inc)
96 {
97 p_view_log->aid_inc_cnt = 0;
98 }
99
100 return 0;
101 }
102
103 int article_view_log_unload(ARTICLE_VIEW_LOG *p_view_log)
104 {
105 if (p_view_log == NULL)
106 {
107 log_error("NULL pointer error\n");
108 return -1;
109 }
110
111 if (p_view_log->aid_base != NULL)
112 {
113 free(p_view_log->aid_base);
114 p_view_log->aid_base = NULL;
115 p_view_log->aid_base_cnt = 0;
116 }
117
118 return 0;
119 }
120
121 int article_view_log_save_inc(const ARTICLE_VIEW_LOG *p_view_log)
122 {
123 MYSQL *db = NULL;
124 char sql[SQL_BUFFER_LEN];
125 char tuple_tmp[LINE_BUFFER_LEN];
126 int i;
127 int affected_record = 0;
128
129 if (p_view_log == NULL)
130 {
131 log_error("NULL pointer error\n");
132 return -1;
133 }
134
135 if (p_view_log->uid <= 0 || p_view_log->aid_inc_cnt == 0)
136 {
137 return 0;
138 }
139
140 if ((db = db_open()) == NULL)
141 {
142 log_error("article_view_log_load() error: Unable to open DB\n");
143 return -2;
144 }
145
146 snprintf(sql, sizeof(sql),
147 "INSERT IGNORE INTO view_article_log(AID, UID, dt) VALUES ");
148
149 for (i = 0; i < p_view_log->aid_inc_cnt; i++)
150 {
151 snprintf(tuple_tmp, sizeof(tuple_tmp),
152 "(%d, %d, NOW())",
153 p_view_log->aid_inc[i], p_view_log->uid);
154 strncat(sql, tuple_tmp, sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));
155
156 if ((i + 1) % 100 == 0 || (i + 1) == p_view_log->aid_inc_cnt) // Insert 100 records per query
157 {
158 if (mysql_query(db, sql) != 0)
159 {
160 log_error("Add view_article_log error: %s\n", mysql_error(db));
161 mysql_close(db);
162 return -3;
163 }
164
165 affected_record += (int)mysql_affected_rows(db);
166
167 snprintf(sql, sizeof(sql),
168 "INSERT IGNORE INTO view_article_log(AID, UID, dt) VALUES ");
169 }
170 else
171 {
172 strncat(sql, ", ", sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));
173 }
174 }
175
176 log_common("Saved %d view_article_log records for uid=%d\n", affected_record, p_view_log->uid);
177
178 mysql_close(db);
179
180 return 0;
181 }
182
183 int article_view_log_merge_inc(ARTICLE_VIEW_LOG *p_view_log)
184 {
185 int32_t *aid_new;
186 int aid_new_cnt;
187 int i, j, k;
188
189 if (p_view_log == NULL)
190 {
191 log_error("NULL pointer error\n");
192 return -1;
193 }
194
195 if (p_view_log->aid_inc_cnt == 0) // Nothing to be merged
196 {
197 return 0;
198 }
199
200 aid_new_cnt = p_view_log->aid_base_cnt + p_view_log->aid_inc_cnt;
201
202 aid_new = malloc(sizeof(int32_t) * (size_t)aid_new_cnt);
203 if (aid_new == NULL)
204 {
205 log_error("malloc(INT32 * %d) error: OOM\n", aid_new_cnt);
206 return -2;
207 }
208
209 for (i = 0, j = 0, k = 0; i < p_view_log->aid_base_cnt && j < p_view_log->aid_inc_cnt;)
210 {
211 if (p_view_log->aid_base[i] <= p_view_log->aid_inc[j])
212 {
213 if (p_view_log->aid_base[i] == p_view_log->aid_inc[j])
214 {
215 log_error("Duplicate aid = %d found in both Base (offset = %d) and Inc (offset = %d)\n",
216 p_view_log->aid_base[i], i, j);
217 j++; // Skip duplicate one in Inc
218 }
219
220 aid_new[k++] = p_view_log->aid_base[i++];
221 }
222 else if (p_view_log->aid_base[i] > p_view_log->aid_inc[j])
223 {
224 aid_new[k++] = p_view_log->aid_inc[j++];
225 }
226 }
227
228 memcpy(aid_new + k, p_view_log->aid_base + i, sizeof(int32_t) * (size_t)(p_view_log->aid_base_cnt - i));
229 k += (p_view_log->aid_base_cnt - i);
230 memcpy(aid_new + k, p_view_log->aid_inc + j, sizeof(int32_t) * (size_t)(p_view_log->aid_inc_cnt - j));
231 k += (p_view_log->aid_inc_cnt - j);
232
233 free(p_view_log->aid_base);
234 p_view_log->aid_base = aid_new;
235 p_view_log->aid_base_cnt = k;
236
237 p_view_log->aid_inc_cnt = 0;
238
239 return 0;
240 }
241
242 int article_view_log_is_viewed(int32_t aid, const ARTICLE_VIEW_LOG *p_view_log)
243 {
244 int left;
245 int right;
246 int mid;
247 int i;
248
249 if (p_view_log == NULL)
250 {
251 log_error("NULL pointer error\n");
252 return -1;
253 }
254
255 for (i = 0; i < 2; i++)
256 {
257 left = 0;
258 right = (i == 0 ? p_view_log->aid_base_cnt : p_view_log->aid_inc_cnt) - 1;
259
260 if (right < 0)
261 {
262 continue;
263 }
264
265 while (left < right)
266 {
267 mid = (left + right) / 2;
268 if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
269 {
270 right = mid;
271 }
272 else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
273 {
274 left = mid + 1;
275 }
276 else // if (aid == p_view_log->aid_base[mid])
277 {
278 return 1;
279 }
280 }
281
282 if (aid == (i == 0 ? p_view_log->aid_base[left] : p_view_log->aid_inc[left])) // Found
283 {
284 return 1;
285 }
286 }
287
288 return 0;
289 }
290
291 int article_view_log_set_viewed(int32_t aid, ARTICLE_VIEW_LOG *p_view_log)
292 {
293 int left;
294 int right;
295 int mid;
296 int i;
297
298 if (p_view_log == NULL)
299 {
300 log_error("NULL pointer error\n");
301 return -1;
302 }
303
304 for (i = 0; i < 2; i++)
305 {
306 left = 0;
307 right = (i == 0 ? p_view_log->aid_base_cnt : p_view_log->aid_inc_cnt) - 1;
308
309 if (right < 0)
310 {
311 continue;
312 }
313
314 while (left < right)
315 {
316 mid = (left + right) / 2;
317 if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
318 {
319 right = mid;
320 }
321 else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
322 {
323 left = mid + 1;
324 }
325 else // if (aid == p_view_log->aid_base[mid])
326 {
327 return 0; // Already set
328 }
329 }
330
331 if (aid == (i == 0 ? p_view_log->aid_base[left] : p_view_log->aid_inc[left])) // Found
332 {
333 return 0; // Already set
334 }
335 }
336
337 // Merge if Inc is full
338 if (p_view_log->aid_inc_cnt >= MAX_VIEWED_AID_INC_CNT)
339 {
340 // Save incremental article view log
341 if (article_view_log_save_inc(p_view_log) < 0)
342 {
343 log_error("article_view_log_save_inc() error\n");
344 return -2;
345 }
346
347 article_view_log_merge_inc(p_view_log);
348
349 p_view_log->aid_inc[(p_view_log->aid_inc_cnt)++] = aid;
350
351 return 1; // Set complete
352 }
353
354 if (right < 0)
355 {
356 right = 0;
357 }
358 else if (aid > p_view_log->aid_inc[left])
359 {
360 right = left + 1;
361 }
362
363 for (i = p_view_log->aid_inc_cnt - 1; i >= right; i--)
364 {
365 p_view_log->aid_inc[i + 1] = p_view_log->aid_inc[i];
366 }
367
368 p_view_log->aid_inc[right] = aid;
369 (p_view_log->aid_inc_cnt)++;
370
371 return 1; // Set complete
372 }

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