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

Annotation of /lbbs/src/article_view_log.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Mon Jun 16 11:21:03 2025 UTC (9 months ago) by sysadm
Branch: MAIN
Changes since 1.3: +2 -1 lines
Content type: text/x-csrc
Refine

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

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