Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / mkmap_db.c
blobcb00066d0fc80bf782b043836441851772cff925
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* mkmap_db 3
6 /* SUMMARY
7 /* create or open database, DB style
8 /* SYNOPSIS
9 /* #include <mkmap.h>
11 /* MKMAP *mkmap_hash_open(path)
12 /* const char *path;
14 /* MKMAP *mkmap_btree_open(path)
15 /* const char *path;
16 /* DESCRIPTION
17 /* This module implements support for creating DB databases.
19 /* mkmap_hash_open() and mkmap_btree_open() take a file name,
20 /* append the ".db" suffix, and do whatever initialization is
21 /* required before the Berkeley DB open routine is called.
23 /* All errors are fatal.
24 /* SEE ALSO
25 /* dict_db(3), DB dictionary interface.
26 /* LICENSE
27 /* .ad
28 /* .fi
29 /* The Secure Mailer license must be distributed with this software.
30 /* AUTHOR(S)
31 /* Wietse Venema
32 /* IBM T.J. Watson Research
33 /* P.O. Box 704
34 /* Yorktown Heights, NY 10598, USA
35 /*--*/
37 /* System library. */
39 #include <sys_defs.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <errno.h>
44 /* Utility library. */
46 #include <msg.h>
47 #include <mymalloc.h>
48 #include <stringops.h>
49 #include <dict.h>
50 #include <dict_db.h>
51 #include <myflock.h>
53 /* Global library. */
55 #include <mail_params.h>
57 /* Application-specific. */
59 #include "mkmap.h"
61 #ifdef HAS_DB
62 #ifdef PATH_DB_H
63 #include PATH_DB_H
64 #else
65 #include <db.h>
66 #endif
68 typedef struct MKMAP_DB {
69 MKMAP mkmap; /* parent class */
70 char *lock_file; /* path name */
71 int lock_fd; /* -1 or open locked file */
72 } MKMAP_DB;
74 /* mkmap_db_after_close - clean up after closing database */
76 static void mkmap_db_after_close(MKMAP *mp)
78 MKMAP_DB *mkmap = (MKMAP_DB *) mp;
80 if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0)
81 msg_warn("close %s: %m", mkmap->lock_file);
82 myfree(mkmap->lock_file);
85 /* mkmap_db_after_open - lock newly created database */
87 static void mkmap_db_after_open(MKMAP *mp)
89 MKMAP_DB *mkmap = (MKMAP_DB *) mp;
91 if (mkmap->lock_fd < 0) {
92 if ((mkmap->lock_fd = open(mkmap->lock_file, O_RDWR, 0644)) < 0)
93 msg_fatal("open lockfile %s: %m", mkmap->lock_file);
94 if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
95 msg_fatal("lock %s: %m", mkmap->lock_file);
99 /* mkmap_db_before_open - lock existing database */
101 static MKMAP *mkmap_db_before_open(const char *path,
102 DICT *(*db_open) (const char *, int, int))
104 MKMAP_DB *mkmap = (MKMAP_DB *) mymalloc(sizeof(*mkmap));
105 struct stat st;
108 * Override the default per-table cache size for map (re)builds.
110 * db_cache_size" is defined in util/dict_db.c and defaults to 128kB, which
111 * works well for the lookup code.
113 * We use a larger per-table cache when building ".db" files. For "hash"
114 * files performance degrades rapidly unless the memory pool is O(file
115 * size).
117 * For "btree" files peformance is good with sorted input even for small
118 * memory pools, but with random input degrades rapidly unless the memory
119 * pool is O(file size).
121 * XXX This should be specified via the DICT interface so that the buffer
122 * size becomes an object property, instead of being specified by poking
123 * a global variable so that it becomes a class property.
125 dict_db_cache_size = var_db_create_buf;
128 * Fill in the generic members.
130 mkmap->lock_file = concatenate(path, ".db", (char *) 0);
131 mkmap->mkmap.open = db_open;
132 mkmap->mkmap.after_open = mkmap_db_after_open;
133 mkmap->mkmap.after_close = mkmap_db_after_close;
136 * Unfortunately, not all systems that might support db databases do
137 * support locking on open(), so we open the file before updating it.
139 * XXX Berkeley DB 4.1 refuses to open a zero-length file. This means we can
140 * open and lock only an existing file, and that we must not truncate it.
142 if ((mkmap->lock_fd = open(mkmap->lock_file, O_RDWR, 0644)) < 0) {
143 if (errno != ENOENT)
144 msg_fatal("open %s: %m", mkmap->lock_file);
148 * Get an exclusive lock - we're going to change the database so we can't
149 * have any spectators.
151 * XXX Horror. Berkeley DB 4.1 refuses to open a zero-length file. This
152 * means that we must examine the size while the file is locked, and that
153 * we must unlink a zero-length file while it is locked. Avoid a race
154 * condition where two processes try to open the same zero-length file
155 * and where the second process ends up deleting the wrong file.
157 else {
158 if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
159 msg_fatal("lock %s: %m", mkmap->lock_file);
160 if (fstat(mkmap->lock_fd, &st) < 0)
161 msg_fatal("fstat %s: %m", mkmap->lock_file);
162 if (st.st_size == 0) {
163 if (st.st_nlink > 0) {
164 if (unlink(mkmap->lock_file) < 0)
165 msg_fatal("cannot remove zero-length database file %s: %m",
166 mkmap->lock_file);
167 msg_warn("removing zero-length database file: %s",
168 mkmap->lock_file);
170 close(mkmap->lock_fd);
171 mkmap->lock_fd = -1;
175 return (&mkmap->mkmap);
178 /* mkmap_hash_open - create or open hashed DB file */
180 MKMAP *mkmap_hash_open(const char *path)
182 return (mkmap_db_before_open(path, dict_hash_open));
185 /* mkmap_btree_open - create or open btree DB file */
187 MKMAP *mkmap_btree_open(const char *path)
189 return (mkmap_db_before_open(path, dict_btree_open));
192 #endif