bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr-util / dbm / apr_dbm_gdbm.c
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_strings.h"
18
19 #if APR_HAVE_STDLIB_H
20 #include <stdlib.h>     /* for free() */
21 #endif
22
23 #include "apu.h"
24
25 #if APU_HAVE_GDBM 
26 #include "apr_dbm_private.h"
27
28 #include <gdbm.h>
29
30 /* this is used in a few places to define a noop "function". it is needed
31    to stop "no effect" warnings from GCC. */
32 #define NOOP_FUNCTION if (0) ; else
33
34 /* ### define defaults for now; these will go away in a while */
35 #define REGISTER_CLEANUP(dbm, pdatum) NOOP_FUNCTION
36 #define SET_FILE(pdb, f) ((pdb)->file = (f))
37
38 typedef GDBM_FILE real_file_t;
39
40 typedef datum *cvt_datum_t;
41 #define CONVERT_DATUM(cvt, pinput) ((cvt) = (datum *)(pinput))
42
43 typedef datum result_datum_t;
44 #define RETURN_DATUM(poutput, rd) (*(poutput) = *(apr_datum_t *)&(rd))
45
46 #define APR_DBM_CLOSE(f)        gdbm_close(f)
47 #define APR_DBM_FETCH(f, k, v)  ((v) = gdbm_fetch(f, *(k)), APR_SUCCESS)
48 #define APR_DBM_STORE(f, k, v)  g2s(gdbm_store(f, *(k), *(v), GDBM_REPLACE))
49 #define APR_DBM_DELETE(f, k)    g2s(gdbm_delete(f, *(k)))
50 #define APR_DBM_FIRSTKEY(f, k)  ((k) = gdbm_firstkey(f), APR_SUCCESS)
51 #define APR_DBM_NEXTKEY(f, k, nk) ((nk) = gdbm_nextkey(f, *(k)), APR_SUCCESS)
52 #define APR_DBM_FREEDPTR(dptr)  ((dptr) ? free(dptr) : 0)
53
54 #undef REGISTER_CLEANUP
55 #define REGISTER_CLEANUP(dbm, pdatum) \
56     if ((pdatum)->dptr) \
57         apr_pool_cleanup_register((dbm)->pool, (pdatum)->dptr, \
58                              datum_cleanup, apr_pool_cleanup_null); \
59     else
60
61 #define APR_DBM_DBMODE_RO       GDBM_READER
62 #define APR_DBM_DBMODE_RW       GDBM_WRITER
63 #define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
64 #define APR_DBM_DBMODE_RWTRUNC  GDBM_NEWDB
65
66 /* map a GDBM error to an apr_status_t */
67 static apr_status_t g2s(int gerr)
68 {
69     if (gerr == -1) {
70         /* ### need to fix this */
71         return APR_EGENERAL;
72     }
73
74     return APR_SUCCESS;
75 }
76
77 static apr_status_t datum_cleanup(void *dptr)
78 {
79     if (dptr)
80         free(dptr);
81
82     return APR_SUCCESS;
83 }
84
85 static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
86 {
87     apr_status_t rv = APR_SUCCESS;
88
89     /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
90
91     if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
92         dbm->errmsg = NULL;
93     }
94     else {
95         dbm->errmsg = gdbm_strerror(gdbm_errno);
96         rv = APR_EGENERAL;        /* ### need something better */
97     }
98
99     /* captured it. clear it now. */
100     gdbm_errno = GDBM_NO_ERROR;
101
102     return rv;
103 }
104
105 /* --------------------------------------------------------------------------
106 **
107 ** DEFINE THE VTABLE FUNCTIONS FOR GDBM
108 */
109
110 static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
111                                  apr_int32_t mode, apr_fileperms_t perm,
112                                  apr_pool_t *pool)
113 {
114     real_file_t file;
115     int dbmode;
116
117     *pdb = NULL;
118
119     switch (mode) {
120     case APR_DBM_READONLY:
121         dbmode = APR_DBM_DBMODE_RO;
122         break;
123     case APR_DBM_READWRITE:
124         dbmode = APR_DBM_DBMODE_RW;
125         break;
126     case APR_DBM_RWCREATE:
127         dbmode = APR_DBM_DBMODE_RWCREATE;
128         break;
129     case APR_DBM_RWTRUNC:
130         dbmode = APR_DBM_DBMODE_RWTRUNC;
131         break;
132     default:
133         return APR_EINVAL;
134     }
135
136     {
137         /* Note: stupid cast to get rid of "const" on the pathname */
138         file = gdbm_open((char *) pathname, 0, dbmode,
139                          apr_posix_perms2mode(perm), NULL);
140         if (file == NULL)
141             return APR_EGENERAL;      /* ### need a better error */
142     }
143
144     /* we have an open database... return it */
145     *pdb = apr_pcalloc(pool, sizeof(**pdb));
146     (*pdb)->pool = pool;
147     (*pdb)->type = &apr_dbm_type_gdbm;
148     SET_FILE(*pdb, file);
149
150     /* ### register a cleanup to close the DBM? */
151
152     return APR_SUCCESS;
153 }
154
155 static void vt_gdbm_close(apr_dbm_t *dbm)
156 {
157     APR_DBM_CLOSE(dbm->file);
158 }
159
160 static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
161                                   apr_datum_t * pvalue)
162 {
163     apr_status_t rv;
164     cvt_datum_t ckey;
165     result_datum_t rd;
166
167     CONVERT_DATUM(ckey, &key);
168     rv = APR_DBM_FETCH(dbm->file, ckey, rd);
169     RETURN_DATUM(pvalue, rd);
170
171     REGISTER_CLEANUP(dbm, pvalue);
172
173     /* store the error info into DBM, and return a status code. Also, note
174        that *pvalue should have been cleared on error. */
175     return set_error(dbm, rv);
176 }
177
178 static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
179                                   apr_datum_t value)
180 {
181     apr_status_t rv;
182     cvt_datum_t ckey;
183     cvt_datum_t cvalue;
184
185     CONVERT_DATUM(ckey, &key);
186     CONVERT_DATUM(cvalue, &value);
187     rv = APR_DBM_STORE(dbm->file, ckey, cvalue);
188
189     /* store any error info into DBM, and return a status code. */
190     return set_error(dbm, rv);
191 }
192
193 static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
194 {
195     apr_status_t rv;
196     cvt_datum_t ckey;
197
198     CONVERT_DATUM(ckey, &key);
199     rv = APR_DBM_DELETE(dbm->file, ckey);
200
201     /* store any error info into DBM, and return a status code. */
202     return set_error(dbm, rv);
203 }
204
205 static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
206 {
207     datum *ckey = (datum *)&key;
208
209     return gdbm_exists(dbm->file, *ckey) != 0;
210 }
211
212 static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
213 {
214     apr_status_t rv;
215     result_datum_t rd;
216
217     rv = APR_DBM_FIRSTKEY(dbm->file, rd);
218     RETURN_DATUM(pkey, rd);
219
220     REGISTER_CLEANUP(dbm, pkey);
221
222     /* store any error info into DBM, and return a status code. */
223     return set_error(dbm, rv);
224 }
225
226 static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
227 {
228     apr_status_t rv;
229     cvt_datum_t ckey;
230     result_datum_t rd;
231
232     CONVERT_DATUM(ckey, pkey);
233     rv = APR_DBM_NEXTKEY(dbm->file, ckey, rd);
234     RETURN_DATUM(pkey, rd);
235
236     REGISTER_CLEANUP(dbm, pkey);
237
238     /* store any error info into DBM, and return a status code. */
239     return set_error(dbm, APR_SUCCESS);
240 }
241
242 static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
243 {
244     (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
245 }
246
247 static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
248                               const char **used1, const char **used2)
249 {
250     *used1 = apr_pstrdup(pool, pathname);
251     *used2 = NULL;
252 }
253
254
255 APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
256     "gdbm",
257
258     vt_gdbm_open,
259     vt_gdbm_close,
260     vt_gdbm_fetch,
261     vt_gdbm_store,
262     vt_gdbm_del,
263     vt_gdbm_exists,
264     vt_gdbm_firstkey,
265     vt_gdbm_nextkey,
266     vt_gdbm_freedatum,
267     vt_gdbm_usednames
268 };
269
270 #endif /* APU_HAVE_GDBM */