ze-filter  (ze-filter-0.8.0-develop-180218)
ze-resolve-cache.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : Tue Dec 20 22:45:42 CET 2005
13  *
14  * This program is free software, but with restricted license
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 
26 #include <ze-sys.h>
27 #include <libze.h>
28 #include <ze-libjc.h>
29 #include <ze-resolve-cache.h>
30 
31 static void resolve_cache_close();
32 static void *resolve_cache_clean(void *);
33 
34 static ZEMAP_T map = ZEMAP_INITIALIZER;
35 
36 static char *mapname = ZE_WDBDIR "/ze-res-cache.db";
37 static size_t mapcachesize = 2 * 1024 * 1024;
38 
39 #define VALUE_LEN_MAX 256
40 
41 #define RESOLVE_DT_REFRESH (1 DAYS)
42 #define RESOLVE_DT_EXPIRE (3 DAYS)
43 #define RESOLVE_DT_CHECK (1 HOURS)
44 #define RESOLVE_DT_LOOP (1 MINUTES)
45 #define RESOLVE_DT_SYNC (2 MINUTES)
46 
47 static time_t dt_refresh = RESOLVE_DT_REFRESH;
48 static time_t dt_sync = RESOLVE_DT_SYNC;
49 static time_t dt_check = RESOLVE_DT_CHECK;
50 static time_t dt_expire = RESOLVE_DT_EXPIRE;
51 
52 /* TODO
53 **
54 ** What fields shall be there ???
55 ** - value (the real value)
56 ** - result
57 ** - timestamp
58 ** - ...
59 */
60 
61 static int resolve_cyclic_task(void *arg);
62 
63 /* ****************************************************************************
64  * *
65  * *
66  **************************************************************************** */
67 bool
68 resolve_cache_check(prefix, key, value, size)
69  char *prefix;
70  char *key;
71  char *value;
72  size_t size;
73 {
74  bool res = FALSE;
75  char *s = NULL;
76  size_t sz;
77  char buf[VALUE_LEN_MAX];
78 
79  ASSERT(key);
80  ASSERT(value);
81  ASSERT(size >= 0);
82 
83  zeMap_Lock(&map);
84 
85  if (!zeMap_OK(&map) && !resolve_cache_init(NULL, RESOLVE_CACHE_RD))
86  goto fin;
87 
88  sz = strlen(prefix) + strlen(key) + 4;
89  if ((s = malloc(sz)) != NULL) {
90  /*
91  * XXX Add record creation and update time stamps
92  */
93 
94  snprintf(s, sz, "%s:%s", prefix, key);
95  res = zeMap_Lookup(&map, s, buf, sizeof (buf));
96  if (res) {
97  char *argv[8];
98  int argc;
99 
100  memset(argv, 0, sizeof (argv));
101  argc = zeStr2Tokens(buf, 8, argv, ";");
102 
103  if (argv[2] != NULL)
104  strlcpy(value, argv[2], size);
105  else
106  res = FALSE;
107  }
108  } else
109  ZE_LogSysError("malloc error");
110  FREE(s);
111 
112 fin:
113  zeMap_Unlock(&map);
114 
115  return res;
116 }
117 
118 /* ****************************************************************************
119  * *
120  * *
121  **************************************************************************** */
122 bool
123 resolve_cache_add(prefix, key, value)
124  char *prefix;
125  char *key;
126  char *value;
127 {
128  bool res = FALSE;
129  char *s = NULL;
130  size_t sz;
131 
132  ASSERT(prefix);
133  ASSERT(key);
134  ASSERT(value);
135 
136  zeMap_Lock(&map);
137 
138  if (!zeMap_OK(&map) && !resolve_cache_init(NULL, RESOLVE_CACHE_WR))
139  goto fin;
140 
141  sz = strlen(prefix) + strlen(key) + 4;
142  if ((s = malloc(sz)) != NULL) {
143  char buf[VALUE_LEN_MAX];
144  time_t first, last, now;
145  char *hostname = value;
146 
147  first = now = time(NULL);
148  last = 0;
149 
150  /*
151  * XXX Add record creation and update time stamps
152  */
153 
154  memset(buf, 0, sizeof (buf));
155  snprintf(s, sz, "%s:%s", prefix, key);
156 
157  if (zeMap_Lookup(&map, s, buf, sizeof (buf))) {
158  char *argv[8];
159  int argc;
160  char *name = NULL;
161  unsigned long tl;
162 
163  memset(argv, 0, sizeof (argv));
164  argc = zeStr2Tokens(buf, 8, argv, ";");
165 
166  if (argv[0] != NULL)
167  first = zeStr2ulong(argv[0], NULL, 0);
168  if (argv[1] != NULL)
169  last = zeStr2ulong(argv[1], NULL, 0);
170  hostname = argv[2];
171  }
172 
173  if (last + dt_refresh < now || !STRCASEEQUAL(value, hostname)) {
174  last = now;
175  /*
176  * snprintf(s, sz, "%s:%s", prefix, key);
177  */
178  snprintf(buf, sizeof (buf), "%lu;%lu;%s", first, last, value);
179  res = zeMap_Add(&map, s, buf, strlen(buf) + 1);
180  }
181 
182  } else
183  ZE_LogSysError("malloc error");
184  FREE(s);
185 
186 fin:
187  zeMap_Unlock(&map);
188 
189  return res;
190 }
191 
192 /* ****************************************************************************
193  * *
194  * *
195  **************************************************************************** */
196 bool
197 resolve_cache_times(p_sync, p_check, p_expire)
198  time_t p_sync;
199  time_t p_check;
200  time_t p_expire;
201 {
202  if (p_expire > 6 HOURS)
203  dt_expire = p_expire;
204  if (p_sync > 30 SECONDS)
205  dt_sync = p_sync;
206  if (p_check > 10 MINUTES)
207  dt_check = p_check;
208 
209  return TRUE;
210 }
211 
212 /* ****************************************************************************
213  * *
214  * *
215  **************************************************************************** */
216 static char browsekey[256];
217 
218 bool
219 resolve_cache_init(dbdir, rwmode)
220  char *dbdir;
221  int rwmode;
222 {
223  bool res = TRUE;
224 
225  if (!zeMap_OK(&map)) {
226  bool rdonly;
227  char name[512];
228 
229  if (dbdir == NULL || strlen(dbdir) == 0)
230  dbdir = ZE_WDBDIR;
231  snprintf(name, sizeof (name), "%s/%s", dbdir, "ze-res-cache.db");
232 
233  rdonly = rwmode == RESOLVE_CACHE_RD;
234 
235  res = zeMap_Open(&map, work_db_env, name, rdonly, mapcachesize);
236 
237  if (!rdonly) {
238  (void) atexit(resolve_cache_close);
239 
240  memset(browsekey, 0, sizeof (browsekey));
241  ZE_MessageInfo(10, "*** Registering resolve cache cyclic task...");
242  CycTasks_Register(resolve_cyclic_task, NULL, RESOLVE_DT_LOOP);
243  }
244  }
245 
246  return res;
247 }
248 
249 /* ****************************************************************************
250  * *
251  * *
252  **************************************************************************** */
253 static void
254 resolve_cache_close()
255 {
256 
257  (void) zeMap_Close(&map);
258 }
259 
260 /* ****************************************************************************
261  * *
262  * *
263  **************************************************************************** */
264 static bool
265 resolve_cache_sync()
266 {
267  bool res = TRUE;
268 
269  if (!zeMap_OK(&map))
270  goto fin;
271 
272  res = zeMap_Flush(&map);
273 
274 fin:
275  return res;
276 }
277 
278 
279 /* ****************************************************************************
280  * *
281  * *
282  **************************************************************************** */
283 static int
284 clean_up_cache(key, val, arg)
285  char *key;
286  char *val;
287  void *arg;
288 {
289  int r = ZEMAP_BROWSE_CONTINUE;
290  time_t *now = (time_t *) arg;
291 
292  if (key == NULL || val == NULL)
293  return r;
294 
295  ZE_MessageInfo(11, "CALLBACK : key=%-20s val=%s", key, val);
296 
297  {
298  char *argv[8];
299  int argc;
300  unsigned long tl;
301  time_t first, last;
302 
303  first = last = (time_t) 0;
304  memset(argv, 0, sizeof (argv));
305  argc = zeStr2Tokens(val, 8, argv, ";");
306 
307  if (argv[0] != NULL)
308  first = zeStr2ulong(argv[0], NULL, 0);
309  if (argv[1] != NULL)
310  last = zeStr2ulong(argv[1], NULL, 0);
311 
312  if (last + dt_expire < *now) {
313  ZE_MessageInfo(11, "Resolve cache entry expired %s %lu %lu", key, last);
314  r |= ZEMAP_BROWSE_DELETE;
315  }
316  }
317 
318  return r;
319 }
320 
321 
322 /* ****************************************************************************
323  * *
324  * *
325  **************************************************************************** */
327 
328 static int
329 resolve_cyclic_task(arg)
330  void *arg;
331 {
332  static time_t last_check = 0, last_sync = 0;
333  time_t now;
334 
335  now = time(NULL);
336  if (last_check == 0)
337  last_check = now;
338  if (last_sync == 0)
339  last_sync = now;
340 
341  ZE_MessageInfo(11, "Cleaning up and syncing map cyclic task...");
342 
343  zeMap_Lock(&map);
344 
345  if (last_check + dt_check <= now) {
346  timems_T ti, tf;
347 
348  ti = zeTime_ms();
349 
350  zeMap_Browse(&map, clean_up_cache, &now, browsekey, sizeof (browsekey),
351  1000);
352  last_check = now;
353 
355  tf = zeTime_ms();
356  ZE_MessageInfo(10, "Cleaning up resolve cache map dt = %lu",
357  (long) (tf - ti));
358  }
359  }
360 #if 0
361  if (last_sync + dt_sync <= now) {
362  timems_T ti, tf;
363  static int i = 0;
364 
365  ti = zeTime_ms();
366 
367  resolve_cache_sync();
368  last_sync = now;
369 
370  if (resolve_cache_show_cyclic_task && (++i % 6) == 0) {
371  tf = zeTime_ms();
372  ZE_MessageInfo(10, "Syncing resolve cache map dt = %lu",
373  (long) (tf - ti));
374  }
375  }
376 #endif
377 
378  zeMap_Unlock(&map);
379 
380  return 0;
381 }
382 
383 /* ****************************************************************************
384  * *
385  * *
386  **************************************************************************** */
387 void
389  bool enable;
390 {
392 }
#define RESOLVE_DT_REFRESH
#define ZEMAP_INITIALIZER
Definition: zeMap.h:38
#define ZEMAP_BROWSE_CONTINUE
Definition: zeMap.h:53
bool zeMap_Flush(ZEMAP_T *map)
Definition: zeMap.c:378
#define ZE_WDBDIR
Definition: defs.h:35
#define ASSERT(a)
Definition: macros.h:27
#define FREE(x)
Definition: macros.h:37
#define RESOLVE_DT_LOOP
uint64_t zeTime_ms()
Definition: zeTime.c:34
bool zeMap_OK(ZEMAP_T *map)
Definition: zeMap.c:62
bool resolve_cache_show_cyclic_task
#define FALSE
Definition: macros.h:160
#define ZEMAP_BROWSE_DELETE
Definition: zeMap.h:55
bool zeMap_Lookup(ZEMAP_T *map, char *key, char *value, size_t size)
Definition: zeMap.c:183
#define strlcpy
Definition: zeString.h:32
ZEDB_ENV_T * work_db_env
Definition: ze-databases.c:30
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
Definition: zeMap.h:27
bool CycTasks_Register(CYCLIC_F task, void *arg, time_t period)
Definition: zeCycTasks.c:91
bool zeMap_Browse(ZEMAP_T *map, ZEMAP_BROWSE_F func, void *arg, char *key, size_t ksz, time_t tmax)
Definition: zeMap.c:269
#define RESOLVE_DT_CHECK
bool zeMap_Open(ZEMAP_T *map, ZEDB_ENV_T *env, char *name, int rdonly, size_t cache_size)
Definition: zeMap.c:80
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define RESOLVE_DT_EXPIRE
#define RESOLVE_DT_SYNC
void resolve_cache_log_enable(bool enable)
#define TRUE
Definition: macros.h:157
bool resolve_cache_init(char *dbdir, int rwmode)
#define VALUE_LEN_MAX
bool zeMap_Add(ZEMAP_T *map, char *key, char *value, size_t size)
Definition: zeMap.c:221
bool resolve_cache_check(char *prefix, char *key, char *value, size_t size)
#define RESOLVE_CACHE_RD
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
time_t last
Definition: ze-connopen.c:60
bool zeMap_Unlock(ZEMAP_T *map)
Definition: zeMap.c:360
bool resolve_cache_times(time_t p_sync, time_t p_check, time_t p_expire)
#define MINUTES
Definition: macros.h:143
#define HOURS
Definition: macros.h:144
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
unsigned long zeStr2ulong(char *s, int *error, unsigned long dval)
Definition: zeStrConvert.c:100
bool zeMap_Lock(ZEMAP_T *map)
Definition: zeMap.c:342
bool resolve_cache_add(char *prefix, char *key, char *value)
#define RESOLVE_CACHE_WR
bool zeMap_Close(ZEMAP_T *map)
Definition: zeMap.c:137
uint64_t timems_T
Definition: zeTime.h:32
#define SECONDS
Definition: macros.h:142