/[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.1 - (show annotations)
Sat Jun 7 07:59:38 2025 UTC (9 months, 1 week ago) by sysadm
Branch: MAIN
Content type: text/x-csrc
Add article_view_log

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

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