ze-filter  (ze-filter-0.8.0-develop-180218)
zeDb.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 : janvier 2002
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 #include <ze-sys.h>
26 
27 #include <libze.h>
28 #include <zeDb.h>
29 
30 #if USE_BerkeleyDB
31 #define BDB_VERSION \
32  ((DB_VERSION_MAJOR << 16) | (DB_VERSION_MINOR << 8) | (DB_VERSION_PATCH))
33 #else
34 #define BDB_VERSION 0
35 #endif
36 
37 #define USE_DB_THREAD 1
38 
39 #define DT_DB_CHECKPOINT 3 MINUTES
40 #define DT_DB_COMPRESS 6 HOURS
41 
42 /* ****************************************************************************
43  * *
44  * *
45  ******************************************************************************/
46 static size_t db_db_cache_size = 16 * 1024 * 1024;
47 
48 static size_t db_env_cache_size = 16 * 1024 * 1024;
49 static int db_lk_max_locks = 0x8000;
50 static int db_lk_max_lockers = 1000;
51 static int db_lk_max_objects = 0x8000;
52 
53 size_t
55  size_t size;
56 {
57  size_t old = db_db_cache_size;
58 
59  db_db_cache_size = size;
60  return old;
61 }
62 
63 size_t
64 zeDb_SetDefaults(which, value)
65  int which;
66  size_t value;
67 {
68  size_t old = 0;
69 
70  switch (which) {
71  case DB_LK_MAX_LOCKS:
72  old = db_lk_max_locks;
73  db_lk_max_locks = value;
74  break;
75  case DB_LK_MAX_LOCKERS:
76  old = db_lk_max_lockers;
77  db_lk_max_lockers = value;
78  break;
79  case DB_LK_MAX_OBJECTS:
80  old = db_lk_max_objects;
81  db_lk_max_objects = value;
82  break;
83  case DB_ENV_CACHE_SIZE:
84  old = db_env_cache_size;
85  db_env_cache_size = value;
86  break;
87  case DB_DB_CACHE_SIZE:
88  old = db_db_cache_size;
89  db_db_cache_size = value;
90  break;
91  }
92  return old;
93 }
94 
95 static void
96 zeDb_DefaultsFromEnv()
97 {
98  char *env;
99  int err = 0;
100 
101  if ((env = getenv("DB_DB_CACHE_SIZE")) != NULL) {
102  unsigned long v;
103 
104  err = 0;
105  v = zeStr2ulong(env, &err, db_db_cache_size);
106  if (err == 0)
107  db_db_cache_size = v;
108  }
109  if ((env = getenv("DB_ENV_CACHE_SIZE")) != NULL) {
110  unsigned long v;
111 
112  err = 0;
113  v = zeStr2size(env, &err, db_env_cache_size);
114  if (err == 0)
115  db_env_cache_size = v;
116  }
117  if ((env = getenv("DB_LK_MAX_LOCKS")) != NULL) {
118  unsigned long v;
119 
120  err = 0;
121  v = zeStr2size(env, &err, db_lk_max_locks);
122  if (err == 0)
123  db_lk_max_locks = v;
124  }
125  if ((env = getenv("DB_LK_MAX_OBJECTS")) != NULL) {
126  unsigned long v;
127 
128  err = 0;
129  v = zeStr2ulong(env, &err, db_lk_max_objects);
130  if (err == 0)
131  db_lk_max_objects = v;
132  }
133  if ((env = getenv("DB_LK_MAX_LOCKERS")) != NULL) {
134  unsigned long v;
135 
136  err = 0;
137  v = zeStr2ulong(env, &err, db_lk_max_lockers);
138  if (err == 0)
139  db_lk_max_lockers = v;
140  }
141 }
142 
143 /* ****************************************************************************
144  * *
145  * *
146  ******************************************************************************/
147 bool
149 {
150 #if USE_BerkeleyDB
151  int major, minor, patch;
152  char *dbv = NULL;
153 
154  major = minor = patch = 0;
155  if ((dbv = db_version(&major, &minor, &patch)) == NULL) {
156  ZE_LogMsgError(0, "Error reading Berkeley DB version");
157  return FALSE;
158  }
159 
160  if ((major != DB_VERSION_MAJOR) ||
161  (minor != DB_VERSION_MINOR) || (patch != DB_VERSION_PATCH)) {
162  ZE_MessageError(8,
163  "Application compiled against Berkeley DB version %d.%d.%d "
164  "but runtime version is %d.%d.%d", DB_VERSION_MAJOR,
165  DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch);
166  return FALSE;
167  }
168 
169  return TRUE;
170 #else
171  return FALSE;
172 #endif
173 }
174 
175 /* ****************************************************************************
176  * *
177  * *
178  ******************************************************************************/
179 #define DIMDB 256
180 static ZEDB_T rwdb[DIMDB];
181 
182 static void *
183 zeDb_PeriodicTasks(arg)
184  void *arg;
185 {
186  DB_ENV *dbenv;
187  int nerra = 0, nerrb = 0;
188 
189  time_t ti_check, ti_compress;
190 
191  ZE_MessageInfo(9, "*** Starting Database Checkpoint thread");
192 
193  ASSERT(arg != NULL);
194 
195  dbenv = (DB_ENV *) arg;
196 
197  ti_check = ti_compress = time(NULL);
198  /*
199  * Checkpoint once a minute.
200  */
201  while (TRUE) {
202  int ret, i;
203  time_t now;
204 
205  sleep(1 MINUTES);
206  now = time(NULL);
207 
208  if (ti_check + DT_DB_CHECKPOINT <= now) {
209  ti_check = now;
210  ZE_MessageInfo(9, "Berkeley DB Database Checkpoint ");
211  if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
212  ZE_LogMsgError(0, "Database checkpoint error : %s", db_strerror(ret));
213  if (nerra++ > 10)
214  break;
215  } else
216  nerra = 0;
217  }
218 
219  if (ti_compress + DT_DB_COMPRESS <= now) {
220  ti_compress = now;
221  for (i = 0; i < DIMDB; i++) {
222  if (rwdb[i].OK) {
223  DB_COMPACT compact;
224 
225  memset(&compact, 0, sizeof (compact));
226  ZE_MessageInfo(9, "Compacting Database : %s", rwdb[i].database);
227  if ((ret = rwdb[i].dbh->compact(rwdb[i].dbh, NULL, NULL, NULL, NULL,
228  DB_FREE_SPACE, NULL)) != 0) {
229  ZE_LogMsgError(0, " Error compacting Database %s : %s",
230  rwdb[i].database, db_strerror(ret));
231  if (nerrb++ > 10)
232  break;
233  } else
234  nerrb = 0;
235  }
236  }
237  }
238  }
239  return NULL;
240 }
241 
242 ZEDB_ENV_T *
243 zeDb_EnvOpen(home, rdonly, dt_chkpoint)
244  char *home;
245  bool rdonly;
246  int dt_chkpoint;
247 {
248 #if USE_BerkeleyDB
249  int ret;
250  int flags = 0;
251  DB_ENV *dbenv = NULL;
252 
253  zeDb_DefaultsFromEnv();
254  /*
255  ** Create an environment and initialize it for additional error
256  ** reporting.
257  */
258  if ((ret = db_env_create(&dbenv, 0)) != 0) {
259  ZE_LogMsgError(0, "Error creating environment : %s", db_strerror(ret));
260  goto err;
261  }
262 
263  /*
264  ** Specify the shared memory buffer pool cachesize
265  ** Databases are in a subdirectory of the environment home.
266  */
267  {
268  size_t gbytes, bytes;
269 
270  bytes = db_env_cache_size % (1024 * 1024 * 1024);
271  gbytes = (db_env_cache_size - bytes) / (1024 * 1024 * 1024);
272 
273  if ((ret = dbenv->set_cachesize(dbenv, gbytes, bytes, 1)) != 0) {
274  ZE_LogMsgError(0, "Error setting environment cache size : %s",
275  db_strerror(ret));
276  goto err;
277  }
278  }
279 
280  /*
281  ** FLAGS
282  */
283  if (!rdonly) {
284 #if BDB_VERSION >= 0x40700
285  if ((ret = dbenv->log_set_config(dbenv, DB_LOG_AUTO_REMOVE, TRUE)) != 0)
286 #else
287  if ((ret = dbenv->set_flags(dbenv, DB_LOG_AUTOREMOVE, TRUE)) != 0)
288 #endif
289  {
290  ZE_LogMsgError(0, "Error setting environment flags : %s",
291  db_strerror(ret));
292  goto err;
293  }
294 #if _FFR_LOG_IN_MEMORY
295 #if BDB_VERSION >= 0x50000
296  if ((ret = dbenv->log_set_config(dbenv, DB_LOG_IN_MEMORY, TRUE)) != 0) {
297  ZE_LogMsgError(0, "Error setting environment flags : %s",
298  db_strerror(ret));
299  goto err;
300  }
301 #endif
302 #endif
303 
304  flags = DB_CREATE | /* Create the environment if it does
305  * not already exist. */
306  DB_INIT_TXN | /* Initialize transactions */
307  DB_INIT_LOCK | /* Initialize locking. */
308  DB_INIT_LOG | /* Initialize logging */
309  /*
310  * DB_INIT_REP |
311  *//*
312  * Initialize logging
313  */
314  DB_INIT_MPOOL; /* Initialize the in-memory cache. */
315 
316 #if USE_DB_THREAD
317  flags |= DB_THREAD;
318 #endif
319  flags |= DB_REGISTER | DB_RECOVER;
320 
321 #if 0
322  flags |= DB_FAILCHK;
323 #endif
324  }
325 
326  /*
327  * Open the environment with full transactional support.
328  */
329  if (rdonly) {
330  /*
331  * flags = DB_INIT_MPOOL
332  */ ;
333  }
334 
335  ret = dbenv->set_lk_max_locks(dbenv, db_lk_max_locks);
336  if (ret != 0)
337  ZE_LogMsgError(0, "Error setting max locks environment : %s %s",
338  home, db_strerror(ret));
339 
340  ret = dbenv->set_lk_max_objects(dbenv, db_lk_max_objects);
341  if (ret != 0)
342  ZE_LogMsgError(0, "Error setting max lock objects environment : %s %s",
343  home, db_strerror(ret));
344 
345  if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
346  ZE_LogMsgError(0, "Error opening environment : %s %s", home,
347  db_strerror(ret));
348  goto err;
349  }
350 
351  {
352  u_int32_t locks, objs, lockers, gbytes, bytes;
353  int partitions;
354 
355  locks = objs = lockers = 0;
356  (void) dbenv->get_lk_max_locks(dbenv, &locks);
357  (void) dbenv->get_lk_max_lockers(dbenv, &lockers);
358  (void) dbenv->get_lk_max_objects(dbenv, &objs);
359  ZE_MessageInfo(10, "DB Environment : max locks=%d objs=%d lockers=%d",
360  locks, objs, lockers);
361  (void) dbenv->get_cachesize(dbenv, &gbytes, &bytes, &partitions);
362  ZE_MessageInfo(10, "DB Environment : cache size=%ld partitions=%ld",
363  gbytes GBYTES + bytes, partitions);
364  }
365 
366  /*
367  * Start a checkpoint thread.
368  */
369  if (dt_chkpoint > 0 || TRUE) {
370  pthread_t ptid;
371  int res;
372 
373  if ((res =
374  pthread_create(&ptid, NULL, zeDb_PeriodicTasks, (void *) dbenv)) != 0)
375  {
376  errno = res;
377  ZE_LogSysError("Failed spawning zeDb_PeriodicTasks thread: %s\n",
378  strerror(errno));
379  exit(1);
380  }
381  }
382 
383  if (getenv("LOG_DB_ERRORS") != NULL) {
384  static FILE *ferr;
385  char *fname = "db_errors.txt";
386  char *env = NULL;
387 
388  env = getenv("LOG_DB_ERRORS");
389  if (STRCASEEQUAL(env, "yes")) {
390  if ((ferr = fopen(fname, "a")) != NULL) {
391  char *home = NULL;
392  static char pfx[256];
393 
394  (void) dbenv->get_home(dbenv, (const char **) &home);
395  snprintf(pfx, sizeof (pfx), "ze-filter (%s) ", STRNULL(home, "???"));
396  (void) dbenv->set_errpfx(dbenv, pfx);
397  (void) dbenv->set_errfile(dbenv, ferr);
398  }
399  }
400  }
401 
402  return dbenv;
403 err:
404  (void) dbenv->close(dbenv, 0);
405  return NULL;
406 #else
407  return NULL;
408 #endif
409 }
410 
411 /* ****************************************************************************
412  * *
413  * *
414  ******************************************************************************/
415 bool
417  ZEDB_ENV_T *dbenv;
418 {
419 #if USE_BerkeleyDB
420  int ret;
421 
422  ASSERT(dbenv != NULL);
423  if ((ret = dbenv->close(dbenv, 0)) != 0) {
424  ZE_LogMsgError(0, "Error closing environment : %s", db_strerror(ret));
425  return FALSE;
426  }
427  return TRUE;
428 #else
429  return NULL;
430 #endif
431 }
432 
433 /* ****************************************************************************
434  * *
435  * *
436  ******************************************************************************/
437 
439 
440 #if USE_BerkeleyDB
441 
442 static int
443 bt_compare_fcn(h, a, b)
444  DB *h;
445  const DBT *a;
446  const DBT *b;
447 {
448  if ((a == NULL) || (a->data == NULL) || (b == NULL) || (b->data == NULL))
449  return 0;
450 
451  return strcasecmp(a->data, b->data);
452 }
453 
454 #endif
455 
456 /* ****************************************************************************
457  * *
458  * *
459  ******************************************************************************/
460 
461 bool
462 zeDb_Open(h, dbenv, database, mode, rdonly, dbtype, dbcache)
463  ZEDB_T *h;
464  ZEDB_ENV_T *dbenv;
465  char *database;
466  int mode;
467  bool rdonly;
468  bool dbtype;
469  size_t dbcache;
470 {
471 #if USE_BerkeleyDB
472  DB *dbp;
473  int ret = TRUE;
474  int flags = 0;
475  char *lname = NULL;
476 
477  if (h == NULL)
478  return FALSE;
479 
480  /*
481  ** CHECK IF ALREADY OPEN...
482  */
483  if (h->OK) {
484  ZE_LogMsgError(0, "database already open : %s", STRNULL(h->database, ""));
485  return TRUE;
486  }
487 
488  if (h->signature == 0) {
489  FREE(h->database);
490  h->OK = FALSE;
492  }
493 
494  ret = h->err = db_create(&dbp, dbenv, 0);
495  if (ret != 0) {
496  ZE_LogMsgError(0, "db_create: %s", db_strerror(ret));
497  return FALSE;
498  }
499  h->dbenv = dbenv;
500 
501  /*
502  * setting cache size
503  */
504  if (dbenv == NULL) {
505  int res;
506  u_int32_t gbytes, bytes;
507  int ncache;
508  int32_t sz_cache = 0;
509 
510  gbytes = bytes = ncache = 0;
511 #if (BDB_VERSION >= 0x40200)
512  h->err = res = dbp->get_cachesize(dbp, &gbytes, &bytes, &ncache);
513  if (res != 0) {
514  ZE_LogMsgError(0, "Error getting %s database cache : %s", database,
515  db_strerror(ret));
516  return FALSE;
517  }
518  ZE_MessageInfo(12, "CACHE OLD : %ld %ld %ld", gbytes, bytes, ncache);
519 #endif
520 
521  sz_cache = db_db_cache_size;
522 
523  if (dbcache > sz_cache)
524  sz_cache = dbcache;
525 
526  if (sz_cache > bytes) {
527  bytes = sz_cache;
528  ZE_MessageInfo(10, "DB Database %-12s : cache size=%ld partitions=%ld",
529  zeBasename(database), gbytes GBYTES + bytes, ncache);
530  h->err = res = dbp->set_cachesize(dbp, gbytes, bytes, ncache);
531  if (res != 0) {
532  ZE_LogMsgError(0, "Error setting %s database cache : %s", database,
533  db_strerror(ret));
534  return FALSE;
535  }
536  }
537  }
538 
539  dbp->set_bt_compare(dbp, bt_compare_fcn);
540 
541 #if 0
542 
543 #ifndef DB_HASH_NELEM
544 #define DB_HASH_NELEM (64*1024)
545 #endif
546 
547  /*
548  * HASH
549  */
550  if (!dbtype) {
551  ret = dbp->set_h_nelem(dbp, DB_HASH_NELEM);
552  if (ret != 0) {
553  ZE_LogMsgError(0,
554  "Error setting hash nelem estimate on database %s : %d %s",
555  database, ret, db_strerror(ret));
556  }
557  }
558 #endif
559 
560  if (rdonly)
561  flags = DB_RDONLY;
562  else
563  flags = DB_CREATE;
564 
565  if (dbenv != NULL) {
566  flags |= DB_AUTO_COMMIT;
567 #if USE_DB_THREAD
568  flags |= DB_THREAD;
569 #endif
570  }
571 
572  /*
573  * flags = (rdonly ? DB_RDONLY : DB_CREATE | DB_AUTO_COMMIT);
574  */
575 
576  if (dbenv != NULL) {
577  char *home = NULL;
578 
579  lname = strdup(database);
580  if (lname != NULL) {
581  char *p = NULL;
582 
583  p = strrchr(lname, '/');
584  if (p != NULL)
585  database = ++p;
586  }
587 #if 0
588  dbenv->get_home(dbenv, (const char **) &home);
589 
590  ZE_MessageInfo(9,
591  "Opening database %s inside environment %s - flags = %08x",
592  database, STRNULL(home, "(NULL)"), flags);
593 #endif
594  }
595 #if (DB_VERSION >= 0x040100)
596  h->err = ret =
597  dbp->open(dbp, NULL, database, NULL, (dbtype ? DB_BTREE : DB_HASH), flags,
598  mode);
599 #else
600  h->err = ret = dbp->open(dbp, database, NULL, (dbtype ? DB_BTREE : DB_HASH),
601  flags, mode);
602 #endif /* DB_VERSION */
603 
604  if (ret != 0) {
605  ZE_LogMsgError(0, "Error opening database %s : %d %s", database, ret,
606  db_strerror(ret));
607  return FALSE;
608  }
609 
610  if ((h->database = strdup(database)) == NULL)
611  ZE_LogSysError("strdup(%s)", database);
612 
613  h->dbh = dbp;
614  h->OK = TRUE;
615  h->dbtype = dbtype;
616  h->rdonly = rdonly;
617  h->mode = mode;
618 
619  if (!h->rdonly) {
620  int i;
621 
622  for (i = 0; i < DIMDB; i++) {
623  if (!rwdb[i].OK) {
624  rwdb[i] = *h;
625  break;
626  }
627  }
628  }
629 #if 0
630 error:
631  ;
632 fin:
633  ;
634 #endif
635 
636  FREE(lname);
637 
638  return TRUE;
639 #else /* USE_BerkeleyDB */
640  return FALSE;
641 #endif /* USE_BerkeleyDB */
642 }
643 
644 /* ****************************************************************************
645  * *
646  * *
647  ******************************************************************************/
648 bool
650  ZEDB_T *h;
651 {
652 #if USE_BerkeleyDB
653  if (h == NULL)
654  return FALSE;
655 
656  return h->OK;
657 #else /* USE_BerkeleyDB */
658  return FALSE;
659 #endif /* USE_BerkeleyDB */
660 }
661 
662 /* ****************************************************************************
663  * *
664  * *
665  ******************************************************************************/
666 bool
668  ZEDB_T *h;
669 {
670 #if USE_BerkeleyDB
671  if (h == NULL)
672  return FALSE;
673 
674  if ((h->dbc != NULL) && (h->dbc->c_close != NULL))
675  h->dbc->c_close(h->dbc);
676  h->dbc = NULL;
677  if ((h->dbh != NULL) && (h->dbh->close != NULL))
678  h->dbh->close(h->dbh, 0);
679  h->dbh = NULL;
680 
681  FREE(h->database);
682  h->OK = FALSE;
683  h->signature = 0;
684 
685  return TRUE;
686 #else /* USE_BerkeleyDB */
687  return FALSE;
688 #endif /* USE_BerkeleyDB */
689 }
690 
691 /* ****************************************************************************
692  * *
693  * *
694  ******************************************************************************/
695 bool
697  ZEDB_T *h;
698 {
699 #if USE_BerkeleyDB
700  u_int32_t count = 0;
701  int ret;
702 
703  if (h == NULL)
704  return FALSE;
705 
706  if ((h->err = ret = h->dbh->truncate(h->dbh, NULL, &count, 0)) == 0) {
707  ZE_MessageInfo(13, "db emptied ");
708  } else {
709  ZE_LogMsgError(0, "Error emptyng %s DB : %s",
710  STRNULL(h->database, "???"), db_strerror(ret));
711  return FALSE;
712  }
713 
714  return TRUE;
715 #else /* USE_BerkeleyDB */
716  return FALSE;
717 #endif /* USE_BerkeleyDB */
718 }
719 
720 /* ****************************************************************************
721  * *
722  * *
723  ******************************************************************************/
724 bool
726  ZEDB_T *h;
727 {
728 #if USE_BerkeleyDB
729  int ret = 0;
730 
731  if ((h->err = ret = h->dbh->sync(h->dbh, 0)) == 0) {
732  ZE_MessageInfo(13, "db: %s synced", STRNULL(h->database, "???"));
733  } else {
734  ZE_LogMsgError(0, "Error syncing %s DB : %s",
735  STRNULL(h->database, "???"), db_strerror(ret));
736  return FALSE;
737  }
738 
739  return TRUE;
740 #else /* USE_BerkeleyDB */
741  return FALSE;
742 #endif /* USE_BerkeleyDB */
743 }
744 
745 /* ****************************************************************************
746  * *
747  * *
748  ******************************************************************************/
749 bool
750 zeDb_AddRec(h, k, d, sz)
751  ZEDB_T *h;
752  char *k;
753  void *d;
754  size_t sz;
755 {
756 #if USE_BerkeleyDB
757  DBT key, data;
758  int ret;
759 
760  memset(&key, 0, sizeof (key));
761  memset(&data, 0, sizeof (data));
762 
763  key.data = k;
764  key.size = strlen(k) + 1;
765  key.ulen = strlen(k) + 1;
766  key.flags = DB_DBT_USERMEM;
767  data.data = d;
768  data.size = sz;
769  data.ulen = sz;
770  data.flags = DB_DBT_USERMEM;
771 
772  if ((h->err = ret = h->dbh->put(h->dbh, NULL, &key, &data, 0)) == 0) {
773  ZE_MessageInfo(13, "db: %s: key stored", (char *) key.data);
774  } else {
775  ZE_LogMsgError(0, "Error adding record to %s DB : %s",
776  STRNULL(h->database, "???"), db_strerror(ret));
777  return FALSE;
778  }
779 
780  return TRUE;
781 #else /* USE_BerkeleyDB */
782  return FALSE;
783 #endif /* USE_BerkeleyDB */
784 }
785 
786 /* ****************************************************************************
787  * *
788  * *
789  ******************************************************************************/
790 bool
791 zeDb_GetRec(h, k, d, szd)
792  ZEDB_T *h;
793  char *k;
794  void *d;
795  size_t szd;
796 {
797 #if USE_BerkeleyDB
798  DBT key, data;
799  int ret;
800  bool result = TRUE;
801  char *buf = NULL;
802 
803  if (h == NULL) {
804  ZE_MessageError(9, "Database handle NULL");
805  return FALSE;
806  }
807  if (!h->OK) {
808  ZE_MessageError(9, "Database not opened (%s)",
809  STRNULL(h->database, "(NULL)"));
810  return FALSE;
811  }
812 
813  memset(&key, 0, sizeof (key));
814  memset(&data, 0, sizeof (data));
815  memset(d, 0, szd);
816  if ((buf = malloc(szd)) == NULL) {
817  ZE_LogSysError("malloc buffer");
818  result = FALSE;
819  goto fin;
820  }
821 
822  key.data = k;
823  key.size = strlen(k) + 1;
824  key.ulen = strlen(k) + 1;
825  key.flags = DB_DBT_USERMEM;
826  data.data = buf;
827  data.size = szd;
828  data.ulen = szd;
829  data.flags = DB_DBT_USERMEM;
830 
831  if ((h->err = ret = h->dbh->get(h->dbh, NULL, &key, &data, 0)) == 0) {
832  ZE_MessageInfo(13, "db: %s: get key", (char *) key.data);
833 
834  memset(d, 0, szd);
835 #if 1
836  memcpy(d, data.data, MIN(szd - 1, data.size));
837 #else
838  if (szd >= data.size)
839  szd = data.size;
840  memcpy(d, data.data, szd);
841 #endif
842  } else {
843  if (ret != DB_NOTFOUND)
844  ZE_LogMsgError(0, "Error getting record from DB %s : (%s) %s",
845  STRNULL(h->database, "???"), k, db_strerror(ret));
846  result = FALSE;
847  goto fin;
848  }
849 
850 fin:
851  FREE(buf);
852  return result;
853 #else /* USE_BerkeleyDB */
854  return FALSE;
855 #endif /* USE_BerkeleyDB */
856 }
857 
858 /* ****************************************************************************
859  * *
860  * *
861  ******************************************************************************/
862 bool
864  ZEDB_T *h;
865  char *k;
866 {
867 #if USE_BerkeleyDB
868  DBT key;
869  int ret;
870 
871  memset(&key, 0, sizeof (key));
872 
873  key.data = k;
874  key.size = strlen(k) + 1;
875 
876  if ((h->err = ret = h->dbh->del(h->dbh, NULL, &key, 0)) == 0) {
877  ZE_MessageInfo(13, "db: %s: key stored", (char *) key.data);
878  } else {
879  ZE_LogMsgError(0, "Error deleting record from %s DB : %s",
880  STRNULL(h->database, "???"), db_strerror(ret));
881  return FALSE;
882  }
883 
884  return TRUE;
885 #else /* USE_BerkeleyDB */
886  return FALSE;
887 #endif /* USE_BerkeleyDB */
888 }
889 
890 /* ****************************************************************************
891  * *
892  * *
893  ******************************************************************************/
894 
895 bool
897  ZEDB_T *h;
898 {
899 #if USE_BerkeleyDB
900  return (pthread_mutex_lock(&h->dbmutex) == 0);
901 #else /* USE_BerkeleyDB */
902  return FALSE;
903 #endif /* USE_BerkeleyDB */
904 }
905 
906 bool
908  ZEDB_T *h;
909 {
910 #if USE_BerkeleyDB
911  return (pthread_mutex_unlock(&h->dbmutex) == 0);
912 #else /* USE_BerkeleyDB */
913  return FALSE;
914 #endif /* USE_BerkeleyDB */
915 }
916 
917 /* ****************************************************************************
918  * *
919  * *
920  ******************************************************************************/
921 int
923  ZEDB_T *h;
924 {
925  if (h == NULL)
926  return 0;
927 
928  return h->err;
929 }
930 
931 /* ****************************************************************************
932  * *
933  * *
934  ******************************************************************************/
935 bool
936 zeDb_CursorOpen(h, rdonly)
937  ZEDB_T *h;
938  bool rdonly;
939 {
940 #if USE_BerkeleyDB
941  DB_ENV *dbenv = NULL;
942 
943  ASSERT(h != NULL);
944 
945  dbenv = h->dbenv;
946 
947  if (h->dbc == NULL) {
948  DBC *dbcp;
949  int ret;
950 
951  MUTEX_LOCK(&h->dbmutex);
952 
953  h->dbtxn = NULL;
954  if (!h->rdonly && !rdonly && dbenv != NULL) {
955  h->dbtxn = NULL;
956  /*
957  * Get the txn handle
958  */
959  ret = dbenv->txn_begin(dbenv, NULL, &h->dbtxn, 0);
960  if (ret != 0) {
961  ZE_LogMsgError(0, "Transaction begin failed on %s database : %s",
962  STRNULL(h->database, "???"), db_strerror(ret));
963  h->dbtxn = NULL;
964  }
965  }
966 
967  /*
968  * Acquire a cursor for the database.
969  */
970  if ((h->err = ret = h->dbh->cursor(h->dbh, h->dbtxn, &dbcp, 0)) != 0) {
971  ZE_LogMsgError(0, "Error creating cursor on %s database : %s",
972  STRNULL(h->database, "???"), db_strerror(ret));
973  }
974 
975  h->dbc = dbcp;
976 
977  MUTEX_UNLOCK(&h->dbmutex);
978  }
979 
980  return (h->dbc != NULL);
981 #else /* USE_BerkeleyDB */
982  return FALSE;
983 #endif /* USE_BerkeleyDB */
984 }
985 
986 /* ****************************************************************************
987  * *
988  * *
989  ******************************************************************************/
990 bool
992  ZEDB_T *h;
993 {
994 #if USE_BerkeleyDB
995  int ret = 0;
996 
997  ASSERT(h != NULL);
998  if (h->dbc == NULL)
999  return FALSE;
1000 
1001  MUTEX_LOCK(&h->dbmutex);
1002 
1003  if (h->dbc != NULL) {
1004  ret = h->dbc->c_close(h->dbc);
1005  if (ret != 0) {
1006  ZE_LogMsgError(0, "Error closing cursor on %s database : %s",
1007  STRNULL(h->database, "???"), db_strerror(ret));
1008  }
1009 
1010  if (h->dbtxn != NULL && h->dbenv != NULL) {
1011  if (ret == 0) {
1012  ret = h->dbtxn->commit(h->dbtxn, 0);
1013  if (ret != 0) {
1014  ZE_LogMsgError(0, "Error commiting transaction on %s database : %s",
1015  STRNULL(h->database, "???"), db_strerror(ret));
1016  }
1017  } else
1018  h->dbtxn->abort(h->dbtxn);
1019  }
1020  }
1021 
1022  h->dbtxn = NULL;
1023  h->dbc = NULL;
1024 
1025  if (!h->rdonly)
1026  zeDb_Flush(h);
1027 
1028  MUTEX_UNLOCK(&h->dbmutex);
1029 
1030  return TRUE;
1031 #else /* USE_BerkeleyDB */
1032  return FALSE;
1033 #endif /* USE_BerkeleyDB */
1034 }
1035 
1036 /* ****************************************************************************
1037  * *
1038  * *
1039  ******************************************************************************/
1040 bool
1041 zeDb_CursorGetFirst(h, k, szk, d, szd)
1042  ZEDB_T *h;
1043  char *k;
1044  size_t szk;
1045  void *d;
1046  size_t szd;
1047 {
1048 #if USE_BerkeleyDB
1049  DBT key, data;
1050  int ret;
1051  bool result = TRUE;
1052  char *buf = NULL;
1053  u_int32_t flags;
1054 
1055  if (h->dbc == NULL)
1056  return FALSE;
1057 
1058  memset(&key, 0, sizeof (key));
1059  memset(&data, 0, sizeof (data));
1060 
1061  if ((buf = malloc(szd)) == NULL) {
1062  ZE_LogSysError("malloc buffer");
1063  result = FALSE;
1064  goto fin;
1065  }
1066  key.data = k;
1067  key.size = strlen(k) + 1;
1068  key.ulen = szk;
1069  key.flags = DB_DBT_USERMEM;
1070  data.data = buf;
1071  data.size = szd;
1072  data.ulen = szd;
1073  data.flags = DB_DBT_USERMEM;
1074 
1075  flags = (key.size > 0 ? DB_SET_RANGE : DB_FIRST);
1076 
1077  if ((h->err = ret = h->dbc->c_get(h->dbc, &key, &data, flags)) == 0) {
1078  ZE_MessageInfo(13, "db: got first rec : %s", key.data);
1079 
1080 #if !USE_DB_THREAD
1081  memset(k, 0, szk);
1082  if (szk >= key.size)
1083  szk = key.size;
1084  memcpy(k, key.data, szk);
1085 #endif
1086 
1087  memset(d, 0, szd);
1088 #if 1
1089  memcpy(d, data.data, MIN(szd - 1, data.size));
1090 #else
1091  if (szd >= data.size)
1092  szd = data.size;
1093  memcpy(d, data.data, szd);
1094 #endif
1095  } else {
1096  if (ret != DB_NOTFOUND)
1097  ZE_LogMsgError(0, "Error getting record from %s DB : %s",
1098  STRNULL(h->database, "???"), db_strerror(ret));
1099  result = FALSE;
1100  goto fin;
1101  }
1102 
1103 fin:
1104  FREE(buf);
1105  return result;
1106 #else /* USE_BerkeleyDB */
1107  return FALSE;
1108 #endif /* USE_BerkeleyDB */
1109 }
1110 
1111 /* ****************************************************************************
1112  * *
1113  * *
1114  ******************************************************************************/
1115 bool
1116 zeDb_CursorGetNext(h, k, szk, d, szd)
1117  ZEDB_T *h;
1118  char *k;
1119  size_t szk;
1120  void *d;
1121  size_t szd;
1122 {
1123 #if USE_BerkeleyDB
1124  DBT key, data;
1125  int ret;
1126  bool result = TRUE;
1127  char *buf = NULL;
1128  u_int32_t flags;
1129 
1130  if (h->dbc == NULL)
1131  return FALSE;
1132 
1133  memset(&key, 0, sizeof (key));
1134  memset(&data, 0, sizeof (data));
1135  if ((buf = malloc(szd)) == NULL) {
1136  ZE_LogSysError("malloc buffer");
1137  result = FALSE;
1138  goto fin;
1139  }
1140 
1141  key.data = k;
1142  key.size = strlen(k) + 1;
1143  key.ulen = szk;
1144  key.flags = DB_DBT_USERMEM;
1145  data.data = buf;
1146  data.size = szd;
1147  data.ulen = data.size;
1148  data.flags = DB_DBT_USERMEM;
1149 
1150  flags = DB_NEXT;
1151 
1152  if ((h->err = ret = h->dbc->c_get(h->dbc, &key, &data, flags)) == 0) {
1153  ZE_MessageInfo(13, "db: got next rec : %s", key.data);
1154 #if !USE_DB_THREAD
1155  memset(k, 0, szk);
1156  if (szk >= key.size)
1157  szk = key.size;
1158  memcpy(k, key.data, szk);
1159 #endif
1160  memset(d, 0, szd);
1161 #if 1
1162  memcpy(d, data.data, MIN(szd - 1, data.size));
1163 #else
1164  if (szd >= data.size)
1165  szd = data.size;
1166  memcpy(d, data.data, szd);
1167 #endif
1168  } else {
1169  if (ret != DB_NOTFOUND)
1170  ZE_LogMsgError(0, "Error getting next record (%s) from %s DB : %s",
1171  k, STRNULL(h->database, "???"), db_strerror(ret));
1172  result = FALSE;
1173  goto fin;
1174  }
1175 
1176 fin:
1177  FREE(buf);
1178  return result;
1179 #else /* USE_BerkeleyDB */
1180  return FALSE;
1181 #endif /* USE_BerkeleyDB */
1182 }
1183 
1184 /* ****************************************************************************
1185  * *
1186  * *
1187  ******************************************************************************/
1188 bool
1190  ZEDB_T *h;
1191 {
1192 #if USE_BerkeleyDB
1193  int ret;
1194 
1195  if (h->dbc == NULL)
1196  return FALSE;
1197 
1198  if ((h->err = ret = h->dbc->c_del(h->dbc, 0)) != 0) {
1199  if (ret != DB_NOTFOUND)
1200  ZE_LogMsgError(0, "Error deleting record from %s DB : %s",
1201  STRNULL(h->database, "???"), db_strerror(ret));
1202  return FALSE;
1203  }
1204 
1205  return TRUE;
1206 #else /* USE_BerkeleyDB */
1207  return FALSE;
1208 #endif /* USE_BerkeleyDB */
1209 }
1210 
1211 /* ****************************************************************************
1212  * *
1213  * *
1214  ******************************************************************************/
1215 bool
1216 zeDb_CursorSetRange(h, k, d, sz, where)
1217  ZEDB_T *h;
1218  char *k;
1219  void *d;
1220  size_t sz;
1221  u_int32_t where;
1222 {
1223 #if USE_BerkeleyDB
1224  return FALSE;
1225 #else /* USE_BerkeleyDB */
1226  return FALSE;
1227 #endif /* USE_BerkeleyDB */
1228 }
1229 
1230 /* ****************************************************************************
1231  * *
1232  * *
1233  ******************************************************************************/
1234 bool
1235 zeDb_cursor_get(h, k, d, sz, where)
1236  ZEDB_T *h;
1237  char *k;
1238  void *d;
1239  size_t sz;
1240  u_int32_t where;
1241 {
1242 #if USE_BerkeleyDB
1243 #if 0
1244  if ((h->dbc == NULL) && !zeDb_CursorOpen(h))
1245  return FALSE;
1246 #endif
1247  /*
1248  **
1249  */
1250 
1251  return TRUE;
1252 #else /* USE_BerkeleyDB */
1253  return FALSE;
1254 #endif /* USE_BerkeleyDB */
1255 }
1256 
1257 
1258 /* ****************************************************************************
1259  * *
1260  * *
1261  ******************************************************************************/
1262 bool
1264  ZEDB_T *h;
1265  ZEDB_STAT_T **st;
1266 {
1267 #if USE_BerkeleyDB
1268  if (h == FALSE || st == FALSE)
1269  return FALSE;
1270 
1271  if (0) {
1272  if (h->dbh->stat_print(h->dbh, 0) == 0)
1273  return TRUE;
1274  } else {
1275  if (h->dbh->stat(h->dbh, NULL, (void *) st, 0) == 0)
1276  return TRUE;
1277  }
1278  /*
1279  * if (h->dbh->stat(h->dbh, NULL, (void *) st, DB_FAST_STAT) == 0)
1280  * return TRUE;
1281  */
1282 
1283  return FALSE;
1284 #else /* USE_BerkeleyDB */
1285  return FALSE;
1286 #endif /* USE_BerkeleyDB */
1287 }
1288 
1289 /* ****************************************************************************
1290  * *
1291  * *
1292  ******************************************************************************/
1293 bool
1295  ZEDB_T *h;
1296 {
1297 #if USE_BerkeleyDB
1298  if (h == NULL)
1299  return FALSE;
1300 
1301  if (!h->chkmtime)
1302  return TRUE;
1303 
1304 #if 0
1305  {
1306  time_t now;
1307  struct stat st;
1308 
1309  now = time(NULL);
1310 
1311  if (fstat(h->dbfd, &st) == 0) {
1312  if (h->mtime != 0) {
1313  /*
1314  * if database has changed
1315  */
1316  if (st.st_mtime > h->mtime) {
1317  DB *dbp = h->dbh;
1318 
1319  /*
1320  * close
1321  */
1322  if ((dbp != NULL) && (dbp->close != NULL))
1323  dbp->close(dbp, 0);
1324  if ((h->dbc != NULL) && (h->dbc->c_close != NULL))
1325  h->dbc->c_close(h->dbc);
1326 
1327 #if (DB_VERSION >= 0x040100)
1328  if ((h->err = ret = dbp->open(dbp, NULL, h->database, NULL,
1329  (h->dbtype ? DB_BTREE : DB_HASH),
1330  h->rdonly ? DB_RDONLY : DB_CREATE,
1331  h->mode)) != 0)
1332 #else
1333  if ((h->err = ret = dbp->open(dbp, h->database, NULL,
1334  (h->dbtype ? DB_BTREE : DB_HASH),
1335  h->rdonly ? DB_RDONLY : DB_CREATE,
1336  h->mode)) != 0)
1337 #endif /* DB_VERSION */
1338  {
1339  ZE_LogMsgError(0, "Error opening database %s : %s", h->database,
1340  db_strerror(ret));
1341  return FALSE;
1342  }
1343 
1344  dbp->set_bt_compare(dbp, bt_compare_fcn);
1345 
1346 
1347  h->mtime = st.st_mtime;
1348  }
1349  } else
1350  h->mtime = st.st_mtime;
1351  } else {
1352  ZE_LogSysError("lstat error");
1353  return FALSE;
1354  }
1355  }
1356 #endif
1357 
1358  return TRUE;
1359 #else /* USE_BerkeleyDB */
1360  return FALSE;
1361 #endif /* USE_BerkeleyDB */
1362 }
bool zeDb_Unlock(ZEDB_T *h)
Database unlock.
Definition: zeDb.c:907
int err
Definition: zeDb.h:66
void ZEDB_STAT_T
Definition: zeDb.h:100
#define DT_DB_CHECKPOINT
Definition: zeDb.c:39
bool zeDb_Stat(ZEDB_T *h, ZEDB_STAT_T **st)
Definition: zeDb.c:1263
bool zeDb_AddRec(ZEDB_T *h, char *k, void *d, size_t sz)
Definition: zeDb.c:750
#define ASSERT(a)
Definition: macros.h:27
unsigned long signature
Definition: zeDb.h:49
#define strrchr
Definition: ze-sys.h:219
#define DB_LK_MAX_LOCKS
Definition: zeDb.h:124
bool zeDb_OK(ZEDB_T *h)
Definition: zeDb.c:649
#define FREE(x)
Definition: macros.h:37
#define ZEDBSIGNATURE
Definition: zeDb.h:103
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
#define GBYTES
Definition: macros.h:153
bool zeDb_Empty(ZEDB_T *h)
Definition: zeDb.c:696
#define STRNULL(x, r)
Definition: macros.h:81
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
Definition: zeDb.h:47
#define FALSE
Definition: macros.h:160
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
bool zeDb_CursorGetFirst(ZEDB_T *h, char *k, size_t szk, void *d, size_t szd)
Definition: zeDb.c:1041
bool zeDb_DelRec(ZEDB_T *h, char *k)
Definition: zeDb.c:863
#define DB_ENV_CACHE_SIZE
Definition: zeDb.h:123
#define MIN(a, b)
Definition: macros.h:140
#define DT_DB_COMPRESS
Definition: zeDb.c:40
bool zeDb_Open(ZEDB_T *h, ZEDB_ENV_T *dbenv, char *database, int mode, bool rdonly, bool dbtype, size_t dbcache)
Definition: zeDb.c:462
size_t zeStr2size(char *s, int *error, size_t dval)
Definition: zeStrConvert.c:237
bool zeDb_Close(ZEDB_T *h)
Definition: zeDb.c:667
size_t zeDb_SetDefaultCacheSize(size_t size)
Definition: zeDb.c:54
uint32_t u_int32_t
Definition: zeDb.h:42
ZEDB_ENV_T * zeDb_EnvOpen(char *home, bool rdonly, int dt_chkpoint)
Definition: zeDb.c:243
#define DB_DB_CACHE_SIZE
Definition: zeDb.h:121
bool zeDb_EnvClose(ZEDB_ENV_T *dbenv)
Definition: zeDb.c:416
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
char * database
Definition: zeDb.h:50
bool zeDb_GetRec(ZEDB_T *h, char *k, void *d, size_t szd)
Definition: zeDb.c:791
#define TRUE
Definition: macros.h:157
#define memcpy(d, s, n)
Definition: ze-sys.h:224
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define DB_LK_MAX_LOCKERS
Definition: zeDb.h:125
pthread_mutex_t dbmutex
Definition: zeDb.h:51
#define ZE_MessageError(level,...)
Definition: zeSyslog.h:93
size_t zeDb_SetDefaults(int which, size_t value)
Definition: zeDb.c:64
bool zeDb_CursorOpen(ZEDB_T *h, bool rdonly)
Definition: zeDb.c:936
int zeDb_errno(ZEDB_T *h)
Definition: zeDb.c:922
void ZEDB_ENV_T
Definition: zeDb.h:85
bool zeDb_cursor_get(ZEDB_T *h, char *k, void *d, size_t sz, u_int32_t where)
Definition: zeDb.c:1235
bool zeDb_CheckLastMTime(ZEDB_T *)
Definition: zeDb.c:1294
bool zeDb_CursorDel(ZEDB_T *h)
Definition: zeDb.c:1189
#define DIMDB
Definition: zeDb.c:179
#define MINUTES
Definition: macros.h:143
#define OK
Definition: zeKStats.c:143
bool zeDb_CursorClose(ZEDB_T *h)
Definition: zeDb.c:991
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
unsigned long zeStr2ulong(char *s, int *error, unsigned long dval)
Definition: zeStrConvert.c:100
#define DB_LK_MAX_OBJECTS
Definition: zeDb.h:126
bool OK
Definition: zeDb.h:65
bool zeDb_CursorSetRange(ZEDB_T *h, char *k, void *d, size_t sz, u_int32_t where)
Definition: zeDb.c:1216
char * zeBasename(char *)
Definition: zeFileTools.c:63
bool zeDb_CursorGetNext(ZEDB_T *h, char *k, size_t szk, void *d, size_t szd)
Definition: zeDb.c:1116
bool zeDb_CheckVersion()
Definition: zeDb.c:148
bool zeDb_Flush(ZEDB_T *h)
Definition: zeDb.c:725
bool zeDb_Lock(ZEDB_T *h)
Database lock.
Definition: zeDb.c:896