/[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.3 - (hide annotations)
Sat Jun 7 10:00:10 2025 UTC (9 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.2: +28 -7 lines
Content type: text/x-csrc
Appy article_view_log to section_list

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     MYSQL *db;
127     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     return -3;
165     }
166    
167 sysadm 1.3 affected_record += (int)mysql_affected_rows(db);
168    
169 sysadm 1.1 snprintf(sql, sizeof(sql),
170 sysadm 1.3 "INSERT IGNORE INTO view_article_log(AID, UID, dt) VALUES ");
171 sysadm 1.1 }
172     else
173     {
174     strncat(sql, ", ", sizeof(sql) - 1 - strnlen(sql, sizeof(sql)));
175     }
176     }
177    
178 sysadm 1.3 log_common("Saved %d view_article_log records for uid=%d\n", affected_record, p_view_log->uid);
179    
180 sysadm 1.1 mysql_close(db);
181    
182     return 0;
183     }
184    
185     int article_view_log_merge_inc(ARTICLE_VIEW_LOG *p_view_log)
186     {
187     int32_t *aid_new;
188     int aid_new_cnt;
189     int i, j, k;
190    
191     if (p_view_log == NULL)
192     {
193     log_error("article_view_log_merge_inc() error: NULL pointer\n");
194     return -1;
195     }
196    
197     if (p_view_log->aid_inc_cnt == 0) // Nothing to be merged
198     {
199     return 0;
200     }
201    
202     aid_new_cnt = p_view_log->aid_base_cnt + p_view_log->aid_inc_cnt;
203    
204     aid_new = malloc(sizeof(int32_t) * (size_t)aid_new_cnt);
205     if (aid_new == NULL)
206     {
207     log_error("malloc(INT32 * %d) error: OOM\n", aid_new_cnt);
208     return -2;
209     }
210    
211     for (i = 0, j = 0, k = 0; i < p_view_log->aid_base_cnt && j < p_view_log->aid_inc_cnt;)
212     {
213     if (p_view_log->aid_base[i] <= p_view_log->aid_inc[j])
214     {
215     if (p_view_log->aid_base[i] == p_view_log->aid_inc[j])
216     {
217     log_error("Duplicate aid = %d found in both Base (offset = %d) and Inc (offset = %d)\n",
218     p_view_log->aid_base[i], i, j);
219     j++; // Skip duplicate one in Inc
220     }
221    
222     aid_new[k++] = p_view_log->aid_base[i++];
223     }
224     else if (p_view_log->aid_base[i] > p_view_log->aid_inc[j])
225     {
226     aid_new[k++] = p_view_log->aid_inc[j++];
227     }
228     }
229    
230     memcpy(aid_new + k, p_view_log->aid_base + i, sizeof(int32_t) * (size_t)(p_view_log->aid_base_cnt - i));
231     k += (p_view_log->aid_base_cnt - i);
232     memcpy(aid_new + k, p_view_log->aid_inc + j, sizeof(int32_t) * (size_t)(p_view_log->aid_inc_cnt - j));
233     k += (p_view_log->aid_inc_cnt - j);
234    
235     free(p_view_log->aid_base);
236     p_view_log->aid_base = aid_new;
237     p_view_log->aid_base_cnt = k;
238    
239     p_view_log->aid_inc_cnt = 0;
240    
241     return 0;
242     }
243    
244     int article_view_log_is_viewed(int32_t aid, const ARTICLE_VIEW_LOG *p_view_log)
245     {
246     int left;
247     int right;
248     int mid;
249     int i;
250    
251     if (p_view_log == NULL)
252     {
253     log_error("article_view_log_is_viewed() error: NULL pointer\n");
254     return -1;
255     }
256    
257     for (i = 0; i < 2; i++)
258     {
259     left = 0;
260     right = (i == 0 ? p_view_log->aid_base_cnt : p_view_log->aid_inc_cnt) - 1;
261    
262     if (right < 0)
263     {
264     continue;
265     }
266    
267     while (left < right)
268     {
269     mid = (left + right) / 2;
270     if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
271     {
272     right = mid;
273     }
274     else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
275     {
276     left = mid + 1;
277     }
278     else // if (aid == p_view_log->aid_base[mid])
279     {
280     return 1;
281     }
282     }
283    
284     if (aid == (i == 0 ? p_view_log->aid_base[left] : p_view_log->aid_inc[left])) // Found
285     {
286     return 1;
287     }
288     }
289    
290     return 0;
291     }
292    
293     int article_view_log_set_viewed(int32_t aid, ARTICLE_VIEW_LOG *p_view_log)
294     {
295     int left;
296     int right;
297     int mid;
298     int i;
299    
300     if (p_view_log == NULL)
301     {
302     log_error("article_view_log_set_viewed() error: NULL pointer\n");
303     return -1;
304     }
305    
306     for (i = 0; i < 2; i++)
307     {
308     left = 0;
309     right = (i == 0 ? p_view_log->aid_base_cnt : p_view_log->aid_inc_cnt) - 1;
310    
311     if (right < 0)
312     {
313     continue;
314     }
315    
316     while (left < right)
317     {
318     mid = (left + right) / 2;
319     if (aid < (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
320     {
321     right = mid;
322     }
323     else if (aid > (i == 0 ? p_view_log->aid_base[mid] : p_view_log->aid_inc[mid]))
324     {
325     left = mid + 1;
326     }
327     else // if (aid == p_view_log->aid_base[mid])
328     {
329     return 0; // Already set
330     }
331     }
332    
333     if (aid == (i == 0 ? p_view_log->aid_base[left] : p_view_log->aid_inc[left])) // Found
334     {
335     return 0; // Already set
336     }
337     }
338    
339     // Merge if Inc is full
340     if (p_view_log->aid_inc_cnt >= MAX_AID_INC_CNT)
341     {
342 sysadm 1.3 // Save incremental article view log
343     if (article_view_log_save_inc(p_view_log) < 0)
344     {
345     log_error("article_view_log_save_inc() error\n");
346     return -2;
347     }
348    
349 sysadm 1.1 article_view_log_merge_inc(p_view_log);
350    
351     p_view_log->aid_inc[(p_view_log->aid_inc_cnt)++] = aid;
352    
353     return 1; // Set complete
354     }
355    
356     if (right < 0)
357     {
358     right = 0;
359     }
360     else if (aid > p_view_log->aid_inc[left])
361     {
362     right = left + 1;
363     }
364    
365     for (i = p_view_log->aid_inc_cnt - 1; i >= right; i--)
366     {
367     p_view_log->aid_inc[i + 1] = p_view_log->aid_inc[i];
368     }
369    
370     p_view_log->aid_inc[right] = aid;
371     (p_view_log->aid_inc_cnt)++;
372    
373     return 1; // Set complete
374     }

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