~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to db/db185/db185.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * See the file LICENSE for redistribution information.
 
3
 *
 
4
 * Copyright (c) 1996-2001
 
5
 *      Sleepycat Software.  All rights reserved.
 
6
 */
 
7
 
 
8
#include "db_config.h"
 
9
 
 
10
#ifndef lint
 
11
static const char copyright[] =
 
12
    "Copyright (c) 1996-2001\nSleepycat Software Inc.  All rights reserved.\n";
 
13
static const char revid[] =
 
14
    "$Id: db185.c,v 11.18 2001/04/10 20:43:53 bostic Exp $";
 
15
#endif
 
16
 
 
17
#ifndef NO_SYSTEM_INCLUDES
 
18
#include <sys/types.h>
 
19
 
 
20
#include <fcntl.h>
 
21
#include <string.h>
 
22
#include <unistd.h>
 
23
#endif
 
24
 
 
25
#include "db_int.h"
 
26
#include "db185_int.h"
 
27
 
 
28
static int      db185_close __P((DB185 *));
 
29
static int      db185_compare __P((DB *, const DBT *, const DBT *));
 
30
static int      db185_del __P((const DB185 *, const DBT185 *, u_int));
 
31
static int      db185_fd __P((const DB185 *));
 
32
static int      db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
 
33
static u_int32_t
 
34
                db185_hash __P((DB *, const void *, u_int32_t));
 
35
static void     db185_openstderr __P((DB_FH *));
 
36
static size_t   db185_prefix __P((DB *, const DBT *, const DBT *));
 
37
static int      db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
 
38
static int      db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
 
39
static int      db185_sync __P((const DB185 *, u_int));
 
40
 
 
41
/*
 
42
 * EXTERN: #define dbopen __db185_open
 
43
 * EXTERN: DB185 *__db185_open
 
44
 * EXTERN:     __P((const char *, int, int, DBTYPE, const void *));
 
45
 */
 
46
DB185 *
 
47
__db185_open(file, oflags, mode, type, openinfo)
 
48
        const char *file;
 
49
        int oflags, mode;
 
50
        DBTYPE type;
 
51
        const void *openinfo;
 
52
{
 
53
        const BTREEINFO *bi;
 
54
        const HASHINFO *hi;
 
55
        const RECNOINFO *ri;
 
56
        DB *dbp;
 
57
        DB185 *db185p;
 
58
        DB_FH fh;
 
59
        size_t nw;
 
60
        int ret;
 
61
 
 
62
        dbp = NULL;
 
63
        db185p = NULL;
 
64
 
 
65
        if ((ret = db_create(&dbp, NULL, 0)) != 0)
 
66
                goto err;
 
67
 
 
68
        if ((ret = __os_calloc(NULL, 1, sizeof(DB185), &db185p)) != 0)
 
69
                goto err;
 
70
 
 
71
        /*
 
72
         * !!!
 
73
         * The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one
 
74
         * from DB 2.0.
 
75
         */
 
76
        switch (type) {
 
77
        case 0:                                 /* DB_BTREE */
 
78
                type = DB_BTREE;
 
79
                if ((bi = openinfo) != NULL) {
 
80
                        if (bi->flags & ~R_DUP)
 
81
                                goto einval;
 
82
                        if (bi->flags & R_DUP)
 
83
                                (void)dbp->set_flags(dbp, DB_DUP);
 
84
                        if (bi->cachesize != 0)
 
85
                                (void)dbp->set_cachesize
 
86
                                    (dbp, 0, bi->cachesize, 0);
 
87
                        if (bi->minkeypage != 0)
 
88
                                (void)dbp->set_bt_minkey(dbp, bi->minkeypage);
 
89
                        if (bi->psize != 0)
 
90
                                (void)dbp->set_pagesize(dbp, bi->psize);
 
91
                        /*
 
92
                         * !!!
 
93
                         * Comparisons and prefix calls work because the DBT
 
94
                         * structures in 1.85 and 2.0 have the same initial
 
95
                         * fields.
 
96
                         */
 
97
                        if (bi->prefix != NULL) {
 
98
                                db185p->prefix = bi->prefix;
 
99
                                dbp->set_bt_prefix(dbp, db185_prefix);
 
100
                        }
 
101
                        if (bi->compare != NULL) {
 
102
                                db185p->compare = bi->compare;
 
103
                                dbp->set_bt_compare(dbp, db185_compare);
 
104
                        }
 
105
                        if (bi->lorder != 0)
 
106
                                dbp->set_lorder(dbp, bi->lorder);
 
107
                }
 
108
                break;
 
109
        case 1:                                 /* DB_HASH */
 
110
                type = DB_HASH;
 
111
                if ((hi = openinfo) != NULL) {
 
112
                        if (hi->bsize != 0)
 
113
                                (void)dbp->set_pagesize(dbp, hi->bsize);
 
114
                        if (hi->ffactor != 0)
 
115
                                (void)dbp->set_h_ffactor(dbp, hi->ffactor);
 
116
                        if (hi->nelem != 0)
 
117
                                (void)dbp->set_h_nelem(dbp, hi->nelem);
 
118
                        if (hi->cachesize != 0)
 
119
                                (void)dbp->set_cachesize
 
120
                                    (dbp, 0, hi->cachesize, 0);
 
121
                        if (hi->hash != NULL) {
 
122
                                db185p->hash = hi->hash;
 
123
                                (void)dbp->set_h_hash(dbp, db185_hash);
 
124
                        }
 
125
                        if (hi->lorder != 0)
 
126
                                dbp->set_lorder(dbp, hi->lorder);
 
127
                }
 
128
 
 
129
                break;
 
130
        case 2:                                 /* DB_RECNO */
 
131
                type = DB_RECNO;
 
132
 
 
133
                /* DB 1.85 did renumbering by default. */
 
134
                (void)dbp->set_flags(dbp, DB_RENUMBER);
 
135
 
 
136
                /*
 
137
                 * !!!
 
138
                 * The file name given to DB 1.85 recno is the name of the DB
 
139
                 * 2.0 backing file.  If the file doesn't exist, create it if
 
140
                 * the user has the O_CREAT flag set, DB 1.85 did it for you,
 
141
                 * and DB 2.0 doesn't.
 
142
                 *
 
143
                 * !!!
 
144
                 * Setting the file name to NULL specifies that we're creating
 
145
                 * a temporary backing file, in DB 2.X.  If we're opening the
 
146
                 * DB file read-only, change the flags to read-write, because
 
147
                 * temporary backing files cannot be opened read-only, and DB
 
148
                 * 2.X will return an error.  We are cheating here -- if the
 
149
                 * application does a put on the database, it will succeed --
 
150
                 * although that would be a stupid thing for the application
 
151
                 * to do.
 
152
                 *
 
153
                 * !!!
 
154
                 * Note, the file name in DB 1.85 was a const -- we don't do
 
155
                 * that in DB 2.0, so do that cast.
 
156
                 */
 
157
                if (file != NULL) {
 
158
                        if (oflags & O_CREAT && __os_exists(file, NULL) != 0)
 
159
                                if (__os_openhandle(NULL, file,
 
160
                                    oflags, mode, &fh) == 0)
 
161
                                        (void)__os_closehandle(&fh);
 
162
                        (void)dbp->set_re_source(dbp, file);
 
163
 
 
164
                        if (O_RDONLY)
 
165
                                oflags &= ~O_RDONLY;
 
166
                        oflags |= O_RDWR;
 
167
                        file = NULL;
 
168
                }
 
169
 
 
170
                if ((ri = openinfo) != NULL) {
 
171
                        /*
 
172
                         * !!!
 
173
                         * We can't support the bfname field.
 
174
                         */
 
175
#define BFMSG   "DB: DB 1.85's recno bfname field is not supported.\n"
 
176
                        if (ri->bfname != NULL) {
 
177
                                db185_openstderr(&fh);
 
178
                                (void)__os_write(NULL, &fh,
 
179
                                    BFMSG, sizeof(BFMSG) - 1, &nw);
 
180
                                goto einval;
 
181
                        }
 
182
 
 
183
                        if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
 
184
                                goto einval;
 
185
                        if (ri->flags & R_FIXEDLEN) {
 
186
                                if (ri->bval != 0)
 
187
                                        (void)dbp->set_re_pad(dbp, ri->bval);
 
188
                                if (ri->reclen != 0)
 
189
                                        (void)dbp->set_re_len(dbp, ri->reclen);
 
190
                        } else
 
191
                                if (ri->bval != 0)
 
192
                                        (void)dbp->set_re_delim(dbp, ri->bval);
 
193
 
 
194
                        /*
 
195
                         * !!!
 
196
                         * We ignore the R_NOKEY flag, but that's okay, it was
 
197
                         * only an optimization that was never implemented.
 
198
                         */
 
199
                        if (ri->flags & R_SNAPSHOT)
 
200
                                (void)dbp->set_flags(dbp, DB_SNAPSHOT);
 
201
 
 
202
                        if (ri->cachesize != 0)
 
203
                                (void)dbp->set_cachesize
 
204
                                    (dbp, 0, ri->cachesize, 0);
 
205
                        if (ri->psize != 0)
 
206
                                (void)dbp->set_pagesize(dbp, ri->psize);
 
207
                        if (ri->lorder != 0)
 
208
                                dbp->set_lorder(dbp, ri->lorder);
 
209
                }
 
210
                break;
 
211
        default:
 
212
                goto einval;
 
213
        }
 
214
 
 
215
        db185p->close = db185_close;
 
216
        db185p->del = db185_del;
 
217
        db185p->fd = db185_fd;
 
218
        db185p->get = db185_get;
 
219
        db185p->put = db185_put;
 
220
        db185p->seq = db185_seq;
 
221
        db185p->sync = db185_sync;
 
222
 
 
223
        /*
 
224
         * Store a reference so we can indirect from the DB 1.85 structure
 
225
         * to the underlying DB structure, and vice-versa.  This has to be
 
226
         * done BEFORE the DB::open method call because the hash callback
 
227
         * is exercised as part of hash database initialiation.
 
228
         *
 
229
         * XXX
 
230
         * Overload the cj_internal field for this purpose.
 
231
         */
 
232
        db185p->dbp = dbp;
 
233
        dbp->cj_internal = db185p;
 
234
 
 
235
        /* Open the database. */
 
236
        if ((ret = dbp->open(dbp,
 
237
            file, NULL, type, __db_oflags(oflags), mode)) != 0)
 
238
                goto err;
 
239
 
 
240
        /* Create the cursor used for sequential ops. */
 
241
        if ((ret = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc, 0)) != 0)
 
242
                goto err;
 
243
 
 
244
        return (db185p);
 
245
 
 
246
einval: ret = EINVAL;
 
247
 
 
248
err:    if (db185p != NULL)
 
249
                __os_free(NULL, db185p, sizeof(DB185));
 
250
        if (dbp != NULL)
 
251
                (void)dbp->close(dbp, 0);
 
252
 
 
253
        __os_set_errno(ret);
 
254
        return (NULL);
 
255
}
 
256
 
 
257
static int
 
258
db185_close(db185p)
 
259
        DB185 *db185p;
 
260
{
 
261
        DB *dbp;
 
262
        int ret;
 
263
 
 
264
        dbp = db185p->dbp;
 
265
 
 
266
        ret = dbp->close(dbp, 0);
 
267
 
 
268
        __os_free(NULL, db185p, sizeof(DB185));
 
269
 
 
270
        if (ret == 0)
 
271
                return (0);
 
272
 
 
273
        __os_set_errno(ret);
 
274
        return (-1);
 
275
}
 
276
 
 
277
static int
 
278
db185_del(db185p, key185, flags)
 
279
        const DB185 *db185p;
 
280
        const DBT185 *key185;
 
281
        u_int flags;
 
282
{
 
283
        DB *dbp;
 
284
        DBT key;
 
285
        int ret;
 
286
 
 
287
        dbp = db185p->dbp;
 
288
 
 
289
        memset(&key, 0, sizeof(key));
 
290
        key.data = key185->data;
 
291
        key.size = key185->size;
 
292
 
 
293
        if (flags & ~R_CURSOR)
 
294
                goto einval;
 
295
        if (flags & R_CURSOR)
 
296
                ret = db185p->dbc->c_del(db185p->dbc, 0);
 
297
        else
 
298
                ret = dbp->del(dbp, NULL, &key, 0);
 
299
 
 
300
        switch (ret) {
 
301
        case 0:
 
302
                return (0);
 
303
        case DB_NOTFOUND:
 
304
                return (1);
 
305
        }
 
306
 
 
307
        __os_set_errno(ret);
 
308
        return (-1);
 
309
 
 
310
einval: __os_set_errno(EINVAL);
 
311
        return (-1);
 
312
}
 
313
 
 
314
static int
 
315
db185_fd(db185p)
 
316
        const DB185 *db185p;
 
317
{
 
318
        DB *dbp;
 
319
        int fd, ret;
 
320
 
 
321
        dbp = db185p->dbp;
 
322
 
 
323
        if ((ret = dbp->fd(dbp, &fd)) == 0)
 
324
                return (fd);
 
325
 
 
326
        __os_set_errno(ret);
 
327
        return (-1);
 
328
}
 
329
 
 
330
static int
 
331
db185_get(db185p, key185, data185, flags)
 
332
        const DB185 *db185p;
 
333
        const DBT185 *key185;
 
334
        DBT185 *data185;
 
335
        u_int flags;
 
336
{
 
337
        DB *dbp;
 
338
        DBT key, data;
 
339
        int ret;
 
340
 
 
341
        dbp = db185p->dbp;
 
342
 
 
343
        memset(&key, 0, sizeof(key));
 
344
        key.data = key185->data;
 
345
        key.size = key185->size;
 
346
        memset(&data, 0, sizeof(data));
 
347
        data.data = data185->data;
 
348
        data.size = data185->size;
 
349
 
 
350
        if (flags)
 
351
                goto einval;
 
352
 
 
353
        switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
 
354
        case 0:
 
355
                data185->data = data.data;
 
356
                data185->size = data.size;
 
357
                return (0);
 
358
        case DB_NOTFOUND:
 
359
                return (1);
 
360
        }
 
361
 
 
362
        __os_set_errno(ret);
 
363
        return (-1);
 
364
 
 
365
einval: __os_set_errno(EINVAL);
 
366
        return (-1);
 
367
}
 
368
 
 
369
static int
 
370
db185_put(db185p, key185, data185, flags)
 
371
        const DB185 *db185p;
 
372
        DBT185 *key185;
 
373
        const DBT185 *data185;
 
374
        u_int flags;
 
375
{
 
376
        DB *dbp;
 
377
        DBC *dbcp_put;
 
378
        DBT key, data;
 
379
        int ret;
 
380
 
 
381
        dbp = db185p->dbp;
 
382
 
 
383
        memset(&key, 0, sizeof(key));
 
384
        key.data = key185->data;
 
385
        key.size = key185->size;
 
386
        memset(&data, 0, sizeof(data));
 
387
        data.data = data185->data;
 
388
        data.size = data185->size;
 
389
 
 
390
        switch (flags) {
 
391
        case 0:
 
392
                ret = dbp->put(dbp, NULL, &key, &data, 0);
 
393
                break;
 
394
        case R_CURSOR:
 
395
                ret = db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT);
 
396
                break;
 
397
        case R_IAFTER:
 
398
        case R_IBEFORE:
 
399
                if (dbp->type != DB_RECNO)
 
400
                        goto einval;
 
401
 
 
402
                if ((ret = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0) {
 
403
                        __os_set_errno(ret);
 
404
                        return (-1);
 
405
                }
 
406
                if ((ret =
 
407
                    dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) {
 
408
                        (void)dbcp_put->c_close(dbcp_put);
 
409
                        __os_set_errno(ret);
 
410
                        return (-1);
 
411
                }
 
412
                memset(&data, 0, sizeof(data));
 
413
                data.data = data185->data;
 
414
                data.size = data185->size;
 
415
                ret = dbcp_put->c_put(dbcp_put,
 
416
                    &key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
 
417
                (void)dbcp_put->c_close(dbcp_put);
 
418
                __os_set_errno(ret);
 
419
                break;
 
420
        case R_NOOVERWRITE:
 
421
                ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
 
422
                break;
 
423
        case R_SETCURSOR:
 
424
                if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
 
425
                        goto einval;
 
426
 
 
427
                if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
 
428
                        break;
 
429
                ret =
 
430
                    db185p->dbc->c_get(db185p->dbc, &key, &data, DB_SET_RANGE);
 
431
                break;
 
432
        default:
 
433
                goto einval;
 
434
        }
 
435
 
 
436
        switch (ret) {
 
437
        case 0:
 
438
                key185->data = key.data;
 
439
                key185->size = key.size;
 
440
                return (0);
 
441
        case DB_KEYEXIST:
 
442
                return (1);
 
443
        }
 
444
        __os_set_errno(ret);
 
445
        return (-1);
 
446
 
 
447
einval: __os_set_errno(EINVAL);
 
448
        return (-1);
 
449
}
 
450
 
 
451
static int
 
452
db185_seq(db185p, key185, data185, flags)
 
453
        const DB185 *db185p;
 
454
        DBT185 *key185, *data185;
 
455
        u_int flags;
 
456
{
 
457
        DB *dbp;
 
458
        DBT key, data;
 
459
        int ret;
 
460
 
 
461
        dbp = db185p->dbp;
 
462
 
 
463
        memset(&key, 0, sizeof(key));
 
464
        key.data = key185->data;
 
465
        key.size = key185->size;
 
466
        memset(&data, 0, sizeof(data));
 
467
        data.data = data185->data;
 
468
        data.size = data185->size;
 
469
 
 
470
        switch (flags) {
 
471
        case R_CURSOR:
 
472
                flags = DB_SET_RANGE;
 
473
                break;
 
474
        case R_FIRST:
 
475
                flags = DB_FIRST;
 
476
                break;
 
477
        case R_LAST:
 
478
                if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
 
479
                        goto einval;
 
480
                flags = DB_LAST;
 
481
                break;
 
482
        case R_NEXT:
 
483
                flags = DB_NEXT;
 
484
                break;
 
485
        case R_PREV:
 
486
                if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
 
487
                        goto einval;
 
488
                flags = DB_PREV;
 
489
                break;
 
490
        default:
 
491
                goto einval;
 
492
        }
 
493
        switch (ret = db185p->dbc->c_get(db185p->dbc, &key, &data, flags)) {
 
494
        case 0:
 
495
                key185->data = key.data;
 
496
                key185->size = key.size;
 
497
                data185->data = data.data;
 
498
                data185->size = data.size;
 
499
                return (0);
 
500
        case DB_NOTFOUND:
 
501
                return (1);
 
502
        }
 
503
 
 
504
        __os_set_errno(ret);
 
505
        return (-1);
 
506
 
 
507
einval: __os_set_errno(EINVAL);
 
508
        return (-1);
 
509
}
 
510
 
 
511
static int
 
512
db185_sync(db185p, flags)
 
513
        const DB185 *db185p;
 
514
        u_int flags;
 
515
{
 
516
        DB *dbp;
 
517
        DB_FH fh;
 
518
        size_t nw;
 
519
        int ret;
 
520
 
 
521
        dbp = db185p->dbp;
 
522
 
 
523
        switch (flags) {
 
524
        case 0:
 
525
                break;
 
526
        case R_RECNOSYNC:
 
527
                /*
 
528
                 * !!!
 
529
                 * We can't support the R_RECNOSYNC flag.
 
530
                 */
 
531
#define RSMSG   "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
 
532
                db185_openstderr(&fh);
 
533
                (void)__os_write(NULL, &fh, RSMSG, sizeof(RSMSG) - 1, &nw);
 
534
                goto einval;
 
535
        default:
 
536
                goto einval;
 
537
        }
 
538
 
 
539
        if ((ret = dbp->sync(dbp, 0)) == 0)
 
540
                return (0);
 
541
 
 
542
        __os_set_errno(ret);
 
543
        return (-1);
 
544
 
 
545
einval: __os_set_errno(EINVAL);
 
546
        return (-1);
 
547
}
 
548
 
 
549
static void
 
550
db185_openstderr(fhp)
 
551
        DB_FH *fhp;
 
552
{
 
553
        /* Dummy up the results of an __os_openhandle() on stderr. */
 
554
        memset(fhp, 0, sizeof(*fhp));
 
555
        F_SET(fhp, DB_FH_VALID);
 
556
 
 
557
#ifndef STDERR_FILENO
 
558
#define STDERR_FILENO   2
 
559
#endif
 
560
        fhp->fd = STDERR_FILENO;
 
561
}
 
562
 
 
563
/*
 
564
 * db185_compare --
 
565
 *      Cutout routine to call the user's Btree comparison function.
 
566
 */
 
567
static int
 
568
db185_compare(dbp, a, b)
 
569
        DB *dbp;
 
570
        const DBT *a, *b;
 
571
{
 
572
        return (((DB185 *)dbp->cj_internal)->compare(a, b));
 
573
}
 
574
 
 
575
/*
 
576
 * db185_prefix --
 
577
 *      Cutout routine to call the user's Btree prefix function.
 
578
 */
 
579
static size_t
 
580
db185_prefix(dbp, a, b)
 
581
        DB *dbp;
 
582
        const DBT *a, *b;
 
583
{
 
584
        return (((DB185 *)dbp->cj_internal)->prefix(a, b));
 
585
}
 
586
 
 
587
/*
 
588
 * db185_hash --
 
589
 *      Cutout routine to call the user's hash function.
 
590
 */
 
591
static u_int32_t
 
592
db185_hash(dbp, key, len)
 
593
        DB *dbp;
 
594
        const void *key;
 
595
        u_int32_t len;
 
596
{
 
597
        return (((DB185 *)dbp->cj_internal)->hash(key, (size_t)len));
 
598
}