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

« back to all changes in this revision

Viewing changes to db/cxx/cxx_table.cpp

  • 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) 1997-2001
 
5
 *      Sleepycat Software.  All rights reserved.
 
6
 */
 
7
 
 
8
#include "db_config.h"
 
9
 
 
10
#ifndef lint
 
11
static const char revid[] = "$Id: cxx_table.cpp,v 11.48 2001/06/19 18:59:02 dda Exp $";
 
12
#endif /* not lint */
 
13
 
 
14
#include <errno.h>
 
15
#include <string.h>
 
16
 
 
17
#include "db_cxx.h"
 
18
#include "cxx_int.h"
 
19
 
 
20
#include "db_int.h"
 
21
#include "db_page.h"
 
22
#include "db_auto.h"
 
23
#include "crdel_auto.h"
 
24
#include "db_ext.h"
 
25
#include "common_ext.h"
 
26
 
 
27
////////////////////////////////////////////////////////////////////////
 
28
//                                                                    //
 
29
//                            Db                                      //
 
30
//                                                                    //
 
31
////////////////////////////////////////////////////////////////////////
 
32
 
 
33
// A truism for the DbEnv object is that there is a valid
 
34
// DB_ENV handle from the constructor until close().
 
35
// After the close, the DB handle is invalid and
 
36
// no operations are permitted on the Db (other than
 
37
// destructor).  Leaving the Db handle open and not
 
38
// doing a close is generally considered an error.
 
39
//
 
40
// We used to allow Db objects to be closed and reopened.
 
41
// This implied always keeping a valid DB object, and
 
42
// coordinating the open objects between Db/DbEnv turned
 
43
// out to be overly complicated.  Now we do not allow this.
 
44
 
 
45
Db::Db(DbEnv *env, u_int32_t flags)
 
46
:       imp_(0)
 
47
,       env_(env)
 
48
,       construct_error_(0)
 
49
,       flags_(0)
 
50
,       construct_flags_(flags)
 
51
{
 
52
        if (env_ == 0)
 
53
                flags_ |= DB_CXX_PRIVATE_ENV;
 
54
        initialize();
 
55
}
 
56
 
 
57
// Note: if the user has not closed, we call _destroy_check
 
58
// to warn against this non-safe programming practice.
 
59
// We can't close, because the environment may already
 
60
// be closed/destroyed.
 
61
//
 
62
Db::~Db()
 
63
{
 
64
        DB *db;
 
65
 
 
66
        db = unwrap(this);
 
67
        if (db != NULL) {
 
68
                DbEnv::_destroy_check("Db", 0);
 
69
                cleanup();
 
70
        }
 
71
}
 
72
 
 
73
// private method to initialize during constructor.
 
74
// initialize must create a backing DB object,
 
75
// and if that creates a new DB_ENV, it must be tied to a new DbEnv.
 
76
// If there is an error, construct_error_ is set; this is examined
 
77
// during open.
 
78
//
 
79
int Db::initialize()
 
80
{
 
81
        u_int32_t cxx_flags;
 
82
        DB *db;
 
83
        int err;
 
84
        DB_ENV *cenv = unwrap(env_);
 
85
 
 
86
        cxx_flags = construct_flags_ & DB_CXX_NO_EXCEPTIONS;
 
87
 
 
88
        // Create a new underlying DB object.
 
89
        // We rely on the fact that if a NULL DB_ENV* is given,
 
90
        // one is allocated by DB.
 
91
        //
 
92
        if ((err = db_create(&db, cenv,
 
93
                             construct_flags_ & ~cxx_flags)) != 0) {
 
94
                construct_error_ = err;
 
95
                return (err);
 
96
        }
 
97
 
 
98
        // Associate the DB with this object
 
99
        imp_ = wrap(db);
 
100
        db->cj_internal = this;
 
101
 
 
102
        // Create a new DbEnv from a DB_ENV* if it was created locally.
 
103
        // It is deleted in Db::close().
 
104
        //
 
105
        if ((flags_ & DB_CXX_PRIVATE_ENV) != 0)
 
106
                env_ = new DbEnv(db->dbenv, cxx_flags);
 
107
 
 
108
        return (0);
 
109
}
 
110
 
 
111
// private method to cleanup after destructor or during close.
 
112
// If the environment was created by this Db object, we optionally
 
113
// delete it, or return it so the caller can delete it after
 
114
// last use.
 
115
//
 
116
void Db::cleanup()
 
117
{
 
118
        DB *db = unwrap(this);
 
119
 
 
120
        if (db != NULL) {
 
121
                // extra safety
 
122
                db->cj_internal = 0;
 
123
                imp_ = 0;
 
124
 
 
125
                // we must dispose of the DbEnv object if
 
126
                // we created it.  This will be the case
 
127
                // if a NULL DbEnv was passed into the constructor.
 
128
                // The underlying DB_ENV object will be inaccessible
 
129
                // after the close, so we must clean it up now.
 
130
                //
 
131
                if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) {
 
132
                        env_->cleanup();
 
133
                        delete env_;
 
134
                        env_ = 0;
 
135
                }
 
136
        }
 
137
        construct_error_ = 0;
 
138
}
 
139
 
 
140
// Return a tristate value corresponding to whether we should
 
141
// throw exceptions on errors:
 
142
//   ON_ERROR_RETURN
 
143
//   ON_ERROR_THROW
 
144
//   ON_ERROR_UNKNOWN
 
145
//
 
146
int Db::error_policy()
 
147
{
 
148
        if (env_ != NULL)
 
149
                return (env_->error_policy());
 
150
        else {
 
151
                // If the env_ is null, that means that the user
 
152
                // did not attach an environment, so the correct error
 
153
                // policy can be deduced from constructor flags
 
154
                // for this Db.
 
155
                //
 
156
                if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
 
157
                        return (ON_ERROR_RETURN);
 
158
                }
 
159
                else {
 
160
                        return (ON_ERROR_THROW);
 
161
                }
 
162
        }
 
163
}
 
164
 
 
165
int Db::close(u_int32_t flags)
 
166
{
 
167
        DB *db = unwrap(this);
 
168
        int err;
 
169
 
 
170
        // after a DB->close (no matter if success or failure),
 
171
        // the underlying DB object must not be accessed,
 
172
        // so we clean up in advance.
 
173
        //
 
174
        cleanup();
 
175
 
 
176
        // It's safe to throw an error after the close,
 
177
        // since our error mechanism does not peer into
 
178
        // the DB* structures.
 
179
        //
 
180
        if ((err = db->close(db, flags)) != 0 && err != DB_INCOMPLETE)
 
181
                DB_ERROR("Db::close", err, error_policy());
 
182
 
 
183
        return (err);
 
184
}
 
185
 
 
186
int Db::cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags)
 
187
{
 
188
        DB *db = unwrap(this);
 
189
        DBC *dbc = 0;
 
190
        int err;
 
191
 
 
192
        if ((err = db->cursor(db, unwrap(txnid), &dbc, flags)) != 0) {
 
193
                DB_ERROR("Db::cursor", err, error_policy());
 
194
                return (err);
 
195
        }
 
196
 
 
197
        // The following cast implies that Dbc can be no larger than DBC
 
198
        *cursorp = (Dbc*)dbc;
 
199
        return (0);
 
200
}
 
201
 
 
202
int Db::del(DbTxn *txnid, Dbt *key, u_int32_t flags)
 
203
{
 
204
        DB *db = unwrap(this);
 
205
        int err;
 
206
 
 
207
        if ((err = db->del(db, unwrap(txnid), key, flags)) != 0) {
 
208
                // DB_NOTFOUND is a "normal" return, so should not be
 
209
                // thrown as an error
 
210
                //
 
211
                if (err != DB_NOTFOUND) {
 
212
                        DB_ERROR("Db::del", err, error_policy());
 
213
                        return (err);
 
214
                }
 
215
        }
 
216
        return (err);
 
217
}
 
218
 
 
219
void Db::err(int error, const char *format, ...)
 
220
{
 
221
        va_list args;
 
222
        DB *db = unwrap(this);
 
223
 
 
224
        va_start(args, format);
 
225
        __db_real_err(db->dbenv, error, 1, 1, format, args);
 
226
        va_end(args);
 
227
}
 
228
 
 
229
void Db::errx(const char *format, ...)
 
230
{
 
231
        va_list args;
 
232
        DB *db = unwrap(this);
 
233
 
 
234
        va_start(args, format);
 
235
        __db_real_err(db->dbenv, 0, 0, 1, format, args);
 
236
        va_end(args);
 
237
}
 
238
 
 
239
int Db::fd(int *fdp)
 
240
{
 
241
        DB *db = unwrap(this);
 
242
        int err;
 
243
 
 
244
        if ((err = db->fd(db, fdp)) != 0) {
 
245
                DB_ERROR("Db::fd", err, error_policy());
 
246
                return (err);
 
247
        }
 
248
        return (0);
 
249
}
 
250
 
 
251
int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
 
252
{
 
253
        DB *db = unwrap(this);
 
254
        int err;
 
255
 
 
256
        if ((err = db->get(db, unwrap(txnid), key, value, flags)) != 0) {
 
257
                // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
 
258
                // so should not be thrown as an error
 
259
                //
 
260
                if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
 
261
                        const char *name = "Db::get";
 
262
                        if (err == ENOMEM && DB_OVERFLOWED_DBT(value))
 
263
                                DB_ERROR_DBT(name, value, error_policy());
 
264
                        else
 
265
                                DB_ERROR(name, err, error_policy());
 
266
                        return (err);
 
267
                }
 
268
        }
 
269
        return (err);
 
270
}
 
271
 
 
272
int Db::get_byteswapped(int *isswapped)
 
273
{
 
274
        DB *db = (DB *)unwrapConst(this);
 
275
        return (db->get_byteswapped(db, isswapped));
 
276
}
 
277
 
 
278
int Db::get_type(DBTYPE *dbtype)
 
279
{
 
280
        DB *db = (DB *)unwrapConst(this);
 
281
        return (db->get_type(db, dbtype));
 
282
}
 
283
 
 
284
int Db::join(Dbc **curslist, Dbc **cursorp, u_int32_t flags)
 
285
{
 
286
        // Dbc is a "compatible" subclass of DBC -
 
287
        // that is, no virtual functions or even extra data members,
 
288
        // so this cast, although technically non-portable,
 
289
        // "should" always be okay.
 
290
        //
 
291
        DBC **list = (DBC **)(curslist);
 
292
        DB *db = unwrap(this);
 
293
        DBC *dbc = 0;
 
294
        int err;
 
295
 
 
296
        if ((err = db->join(db, list, &dbc, flags)) != 0) {
 
297
                DB_ERROR("Db::join_cursor", err, error_policy());
 
298
                return (err);
 
299
        }
 
300
        *cursorp = (Dbc*)dbc;
 
301
        return (0);
 
302
}
 
303
 
 
304
int Db::key_range(DbTxn *txnid, Dbt *key,
 
305
                  DB_KEY_RANGE *results, u_int32_t flags)
 
306
{
 
307
        DB *db = unwrap(this);
 
308
        int err;
 
309
 
 
310
        if ((err = db->key_range(db, unwrap(txnid), key,
 
311
                                 results, flags)) != 0) {
 
312
                DB_ERROR("Db::key_range", err, error_policy());
 
313
                return (err);
 
314
        }
 
315
        return (0);
 
316
}
 
317
 
 
318
// If an error occurred during the constructor, report it now.
 
319
// Otherwise, call the underlying DB->open method.
 
320
//
 
321
int Db::open(const char *file, const char *database,
 
322
             DBTYPE type, u_int32_t flags, int mode)
 
323
{
 
324
        int err;
 
325
        DB *db = unwrap(this);
 
326
 
 
327
        if ((err = construct_error_) != 0)
 
328
                DB_ERROR("Db::open", construct_error_, error_policy());
 
329
        else if ((err = db->open(db, file, database, type, flags, mode)) != 0)
 
330
                DB_ERROR("Db::open", err, error_policy());
 
331
 
 
332
        return (err);
 
333
}
 
334
 
 
335
int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags)
 
336
{
 
337
        DB *db = unwrap(this);
 
338
        int err;
 
339
 
 
340
        if ((err = db->pget(db, unwrap(txnid), key, pkey,
 
341
                            value, flags)) != 0) {
 
342
                // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
 
343
                // so should not be thrown as an error
 
344
                //
 
345
                if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
 
346
                        const char *name = "Db::pget";
 
347
                        if (err == ENOMEM && DB_OVERFLOWED_DBT(value))
 
348
                                DB_ERROR_DBT(name, value, error_policy());
 
349
                        else
 
350
                                DB_ERROR(name, err, error_policy());
 
351
                        return (err);
 
352
                }
 
353
        }
 
354
        return (err);
 
355
}
 
356
 
 
357
int Db::put(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
 
358
{
 
359
        int err;
 
360
        DB *db = unwrap(this);
 
361
 
 
362
        if ((err = db->put(db, unwrap(txnid), key, value, flags)) != 0) {
 
363
 
 
364
                // DB_KEYEXIST is a "normal" return, so should not be
 
365
                // thrown as an error
 
366
                //
 
367
                if (err != DB_KEYEXIST) {
 
368
                        DB_ERROR("Db::put", err, error_policy());
 
369
                        return (err);
 
370
                }
 
371
        }
 
372
        return (err);
 
373
}
 
374
 
 
375
int Db::rename(const char *file, const char *database,
 
376
               const char *newname, u_int32_t flags)
 
377
{
 
378
        int err = 0;
 
379
        DB *db = unwrap(this);
 
380
 
 
381
        if (!db) {
 
382
                DB_ERROR("Db::rename", EINVAL, error_policy());
 
383
                return (EINVAL);
 
384
        }
 
385
 
 
386
        // after a DB->rename (no matter if success or failure),
 
387
        // the underlying DB object must not be accessed,
 
388
        // so we clean up in advance.
 
389
        //
 
390
        cleanup();
 
391
 
 
392
        if ((err = db->rename(db, file, database, newname, flags)) != 0) {
 
393
                DB_ERROR("Db::rename", err, error_policy());
 
394
                return (err);
 
395
        }
 
396
        return (0);
 
397
}
 
398
 
 
399
int Db::remove(const char *file, const char *database, u_int32_t flags)
 
400
{
 
401
        int err = 0;
 
402
        DB *db = unwrap(this);
 
403
 
 
404
        if (!db) {
 
405
                DB_ERROR("Db::remove", EINVAL, error_policy());
 
406
                return (EINVAL);
 
407
        }
 
408
 
 
409
        // after a DB->remove (no matter if success or failure),
 
410
        // the underlying DB object must not be accessed,
 
411
        // so we clean up in advance.
 
412
        //
 
413
        cleanup();
 
414
 
 
415
        if ((err = db->remove(db, file, database, flags)) != 0)
 
416
                DB_ERROR("Db::remove", err, error_policy());
 
417
 
 
418
        return (err);
 
419
}
 
420
 
 
421
int Db::truncate(DbTxn *txnid, u_int32_t *countp, u_int32_t flags)
 
422
{
 
423
        int err = 0;
 
424
        DB *db = unwrap(this);
 
425
 
 
426
        if (!db) {
 
427
                DB_ERROR("Db::truncate", EINVAL, error_policy());
 
428
                return (EINVAL);
 
429
        }
 
430
        if ((err = db->truncate(db, unwrap(txnid), countp, flags)) != 0) {
 
431
                DB_ERROR("Db::truncate", err, error_policy());
 
432
                return (err);
 
433
        }
 
434
        return (0);
 
435
}
 
436
 
 
437
int Db::stat(void *sp, u_int32_t flags)
 
438
{
 
439
        int err;
 
440
        DB *db = unwrap(this);
 
441
 
 
442
        if (!db) {
 
443
                DB_ERROR("Db::stat", EINVAL, error_policy());
 
444
                return (EINVAL);
 
445
        }
 
446
        if ((err = db->stat(db, sp, flags)) != 0) {
 
447
                DB_ERROR("Db::stat", err, error_policy());
 
448
                return (err);
 
449
        }
 
450
        return (0);
 
451
}
 
452
 
 
453
int Db::sync(u_int32_t flags)
 
454
{
 
455
        int err;
 
456
        DB *db = unwrap(this);
 
457
 
 
458
        if (!db) {
 
459
                DB_ERROR("Db::sync", EINVAL, error_policy());
 
460
                return (EINVAL);
 
461
        }
 
462
        if ((err = db->sync(db, flags)) != 0 && err != DB_INCOMPLETE) {
 
463
                DB_ERROR("Db::sync", err, error_policy());
 
464
                return (err);
 
465
        }
 
466
        return (err);
 
467
}
 
468
 
 
469
int Db::upgrade(const char *name, u_int32_t flags)
 
470
{
 
471
        int err;
 
472
        DB *db = unwrap(this);
 
473
 
 
474
        if (!db) {
 
475
                DB_ERROR("Db::upgrade", EINVAL, error_policy());
 
476
                return (EINVAL);
 
477
        }
 
478
        if ((err = db->upgrade(db, name, flags)) != 0) {
 
479
                DB_ERROR("Db::upgrade", err, error_policy());
 
480
                return (err);
 
481
        }
 
482
        return (0);
 
483
}
 
484
////////////////////////////////////////////////////////////////////////
 
485
//
 
486
// callbacks
 
487
//
 
488
// *_intercept_c are 'glue' functions that must be declared
 
489
// as extern "C" so to be typesafe.  Using a C++ method, even
 
490
// a static class method with 'correct' arguments, will not pass
 
491
// the test; some picky compilers do not allow mixing of function
 
492
// pointers to 'C' functions with function pointers to C++ functions.
 
493
//
 
494
// One wart with this scheme is that the *_callback_ method pointer
 
495
// must be declared public to be accessible by the C intercept.
 
496
// It's possible to accomplish the goal without this, and with
 
497
// another public transfer method, but it's just too much overhead.
 
498
// These callbacks are supposed to be *fast*.
 
499
//
 
500
// The DBTs we receive in these callbacks from the C layer may be
 
501
// manufactured there, but we want to treat them as a Dbts.
 
502
// Technically speaking, these DBTs were not constructed as a Dbts,
 
503
// but it should be safe to cast them as such given that Dbt is a
 
504
// *very* thin extension of the DBT.  That is, Dbt has no additional
 
505
// data elements, does not use virtual functions, virtual inheritance,
 
506
// multiple inheritance, RTI, or any other language feature that
 
507
// causes the structure to grow or be displaced.  Although this may
 
508
// sound risky, a design goal of C++ is complete structure
 
509
// compatibility with C, and has the philosophy 'if you don't use it,
 
510
// you shouldn't incur the overhead'.  If the C/C++ compilers you're
 
511
// using on a given machine do not have matching struct layouts, then
 
512
// a lot more things will be broken than just this.
 
513
//
 
514
// The alternative, creating a Dbt here in the callback, and populating
 
515
// it from the DBT, is just too slow and cumbersome to be very useful.
 
516
 
 
517
/* associate callback */
 
518
extern "C" int _db_associate_intercept_c(DB *secondary,
 
519
                                         const DBT *key,
 
520
                                         const DBT *data,
 
521
                                         DBT *retval)
 
522
{
 
523
        Db *cxxthis;
 
524
 
 
525
        DB_ASSERT(secondary != NULL);
 
526
        cxxthis = (Db *)secondary->cj_internal;
 
527
        DB_ASSERT(cxxthis != NULL);
 
528
        DB_ASSERT(cxxthis->associate_callback_ != 0);
 
529
 
 
530
        return (*cxxthis->associate_callback_)(cxxthis,
 
531
                                               Dbt::get_const_Dbt(key),
 
532
                                               Dbt::get_const_Dbt(data),
 
533
                                               Dbt::get_Dbt(retval));
 
534
}
 
535
 
 
536
int Db::associate(Db *secondary, int (*callback)(Db *, const Dbt *,
 
537
        const Dbt *, Dbt *), u_int32_t flags)
 
538
{
 
539
        DB *cthis = unwrap(this);
 
540
 
 
541
        /* Since the secondary Db is used as the first argument
 
542
         * to the callback, we store the C++ callback on it
 
543
         * rather than on 'this'.
 
544
         */
 
545
        secondary->associate_callback_ = callback;
 
546
        return ((*(cthis->associate))
 
547
                (cthis, unwrap(secondary), _db_associate_intercept_c, flags));
 
548
}
 
549
 
 
550
/* feedback callback */
 
551
extern "C" void _db_feedback_intercept_c(DB *cthis, int opcode, int pct)
 
552
{
 
553
        Db *cxxthis;
 
554
 
 
555
        DB_ASSERT(cthis != NULL);
 
556
        cxxthis = (Db *)cthis->cj_internal;
 
557
        DB_ASSERT(cxxthis != NULL);
 
558
        DB_ASSERT(cxxthis->feedback_callback_ != 0);
 
559
 
 
560
        (*cxxthis->feedback_callback_)(cxxthis, opcode, pct);
 
561
        return;
 
562
}
 
563
 
 
564
int Db::set_feedback(void (*arg)(Db *cxxthis, int opcode, int pct))
 
565
{
 
566
        DB *cthis = unwrap(this);
 
567
        feedback_callback_ = arg;
 
568
        return ((*(cthis->set_feedback))
 
569
                (cthis, _db_feedback_intercept_c));
 
570
}
 
571
 
 
572
/* append_recno callback */
 
573
extern "C" int _db_append_recno_intercept_c(DB *cthis, DBT *data,
 
574
                                            db_recno_t recno)
 
575
{
 
576
        Db *cxxthis;
 
577
 
 
578
        DB_ASSERT(cthis != NULL);
 
579
        cxxthis = (Db *)cthis->cj_internal;
 
580
        DB_ASSERT(cxxthis != NULL);
 
581
        DB_ASSERT(cxxthis->append_recno_callback_ != 0);
 
582
 
 
583
        return (*cxxthis->append_recno_callback_)(cxxthis,
 
584
                                                  Dbt::get_Dbt(data),
 
585
                                                  recno);
 
586
}
 
587
 
 
588
int Db::set_append_recno(int (*arg)(Db *cxxthis, Dbt *data, db_recno_t recno))
 
589
{
 
590
        DB *cthis = unwrap(this);
 
591
        append_recno_callback_ = arg;
 
592
        return ((*(cthis->set_append_recno))
 
593
                (cthis, _db_append_recno_intercept_c));
 
594
}
 
595
 
 
596
/* bt_compare callback */
 
597
extern "C" int _db_bt_compare_intercept_c(DB *cthis, const DBT *data1,
 
598
                                          const DBT *data2)
 
599
{
 
600
        Db *cxxthis;
 
601
 
 
602
        DB_ASSERT(cthis != NULL);
 
603
        cxxthis = (Db *)cthis->cj_internal;
 
604
        DB_ASSERT(cxxthis != NULL);
 
605
        DB_ASSERT(cxxthis->bt_compare_callback_ != 0);
 
606
 
 
607
        return (*cxxthis->bt_compare_callback_)(cxxthis,
 
608
                                                Dbt::get_const_Dbt(data1),
 
609
                                                Dbt::get_const_Dbt(data2));
 
610
}
 
611
 
 
612
int Db::set_bt_compare(int (*arg)(Db *cxxthis, const Dbt *data1,
 
613
                                  const Dbt *data2))
 
614
{
 
615
        DB *cthis = unwrap(this);
 
616
        bt_compare_callback_ = arg;
 
617
        return ((*(cthis->set_bt_compare))
 
618
                (cthis, _db_bt_compare_intercept_c));
 
619
}
 
620
 
 
621
/* bt_prefix callback */
 
622
extern "C" size_t _db_bt_prefix_intercept_c(DB *cthis, const DBT *data1,
 
623
                                            const DBT *data2)
 
624
{
 
625
        Db *cxxthis;
 
626
 
 
627
        DB_ASSERT(cthis != NULL);
 
628
        cxxthis = (Db *)cthis->cj_internal;
 
629
        DB_ASSERT(cxxthis != NULL);
 
630
        DB_ASSERT(cxxthis->bt_prefix_callback_ != 0);
 
631
 
 
632
        return (*cxxthis->bt_prefix_callback_)(cxxthis,
 
633
                                               Dbt::get_const_Dbt(data1),
 
634
                                               Dbt::get_const_Dbt(data2));
 
635
}
 
636
 
 
637
int Db::set_bt_prefix(size_t (*arg)(Db *cxxthis, const Dbt *data1,
 
638
                                    const Dbt *data2))
 
639
{
 
640
        DB *cthis = unwrap(this);
 
641
        bt_prefix_callback_ = arg;
 
642
        return ((*(cthis->set_bt_prefix))
 
643
                (cthis, _db_bt_prefix_intercept_c));
 
644
}
 
645
 
 
646
/* dup_compare callback */
 
647
extern "C" int _db_dup_compare_intercept_c(DB *cthis, const DBT *data1,
 
648
                                           const DBT *data2)
 
649
{
 
650
        Db *cxxthis;
 
651
 
 
652
        DB_ASSERT(cthis != NULL);
 
653
        cxxthis = (Db *)cthis->cj_internal;
 
654
        DB_ASSERT(cxxthis != NULL);
 
655
        DB_ASSERT(cxxthis->dup_compare_callback_ != 0);
 
656
 
 
657
        return (*cxxthis->dup_compare_callback_)(cxxthis,
 
658
                                                 Dbt::get_const_Dbt(data1),
 
659
                                                 Dbt::get_const_Dbt(data2));
 
660
}
 
661
 
 
662
int Db::set_dup_compare(int (*arg)(Db *cxxthis, const Dbt *data1,
 
663
                                   const Dbt *data2))
 
664
{
 
665
        DB *cthis = unwrap(this);
 
666
        dup_compare_callback_ = arg;
 
667
        return ((*(cthis->set_dup_compare))
 
668
                (cthis, _db_dup_compare_intercept_c));
 
669
}
 
670
 
 
671
/* h_hash callback */
 
672
extern "C" u_int32_t _db_h_hash_intercept_c(DB *cthis, const void *data,
 
673
                                            u_int32_t len)
 
674
{
 
675
        Db *cxxthis;
 
676
 
 
677
        DB_ASSERT(cthis != NULL);
 
678
        cxxthis = (Db *)cthis->cj_internal;
 
679
        DB_ASSERT(cxxthis != NULL);
 
680
        DB_ASSERT(cxxthis->h_hash_callback_ != 0);
 
681
 
 
682
        return (*cxxthis->h_hash_callback_)(cxxthis, data, len);
 
683
}
 
684
 
 
685
int Db::set_h_hash(u_int32_t (*arg)(Db *cxxthis, const void *data,
 
686
                                    u_int32_t len))
 
687
{
 
688
        DB *cthis = unwrap(this);
 
689
        h_hash_callback_ = arg;
 
690
        return ((*(cthis->set_h_hash))
 
691
                (cthis, _db_h_hash_intercept_c));
 
692
}
 
693
 
 
694
// This is a 'glue' function declared as extern "C" so it will
 
695
// be compatible with picky compilers that do not allow mixing
 
696
// of function pointers to 'C' functions with function pointers
 
697
// to C++ functions.
 
698
//
 
699
extern "C"
 
700
int _verify_callback_c(void *handle, const void *str_arg)
 
701
{
 
702
        char *str;
 
703
        ostream *out;
 
704
 
 
705
        str = (char *)str_arg;
 
706
        out = (ostream *)handle;
 
707
 
 
708
        (*out) << str;
 
709
        if (out->fail())
 
710
                return (EIO);
 
711
 
 
712
        return (0);
 
713
}
 
714
 
 
715
int Db::verify(const char *name, const char *subdb,
 
716
               ostream *ostr, u_int32_t flags)
 
717
{
 
718
        int err;
 
719
        DB *db = unwrap(this);
 
720
 
 
721
        if (!db) {
 
722
                DB_ERROR("Db::verify", EINVAL, error_policy());
 
723
                return (EINVAL);
 
724
        }
 
725
        if ((err = __db_verify_internal(db, name, subdb, ostr,
 
726
                                        _verify_callback_c, flags)) != 0) {
 
727
                DB_ERROR("Db::verify", err, error_policy());
 
728
                return (err);
 
729
        }
 
730
        return (0);
 
731
}
 
732
 
 
733
// This is a variant of the DB_WO_ACCESS macro to define a simple set_
 
734
// method calling the underlying C method, but unlike a simple
 
735
// set method, it may return an error or raise an exception.
 
736
// Note this macro expects that input _argspec is an argument
 
737
// list element (e.g. "char *arg") defined in terms of "arg".
 
738
//
 
739
#define DB_DB_ACCESS(_name, _argspec)                          \
 
740
\
 
741
int Db::set_##_name(_argspec)                                  \
 
742
{                                                              \
 
743
        int ret;                                               \
 
744
        DB *db = unwrap(this);                                 \
 
745
                                                               \
 
746
        if ((ret = (*(db->set_##_name))(db, arg)) != 0) {      \
 
747
                DB_ERROR("Db::set_" # _name, ret, error_policy()); \
 
748
        }                                                      \
 
749
        return (ret);                                          \
 
750
}
 
751
 
 
752
#define DB_DB_ACCESS_NORET(_name, _argspec)                    \
 
753
                                                               \
 
754
void Db::set_##_name(_argspec)                                 \
 
755
{                                                              \
 
756
        DB *db = unwrap(this);                                 \
 
757
                                                               \
 
758
        (*(db->set_##_name))(db, arg);                         \
 
759
        return;                                                \
 
760
}
 
761
 
 
762
DB_DB_ACCESS(bt_compare, bt_compare_fcn_type arg)
 
763
DB_DB_ACCESS(bt_maxkey, u_int32_t arg)
 
764
DB_DB_ACCESS(bt_minkey, u_int32_t arg)
 
765
DB_DB_ACCESS(bt_prefix, bt_prefix_fcn_type arg)
 
766
DB_DB_ACCESS(dup_compare, dup_compare_fcn_type arg)
 
767
DB_DB_ACCESS_NORET(errfile, FILE *arg)
 
768
DB_DB_ACCESS_NORET(errpfx, const char *arg)
 
769
DB_DB_ACCESS(flags, u_int32_t arg)
 
770
DB_DB_ACCESS(h_ffactor, u_int32_t arg)
 
771
DB_DB_ACCESS(h_hash, h_hash_fcn_type arg)
 
772
DB_DB_ACCESS(h_nelem, u_int32_t arg)
 
773
DB_DB_ACCESS(lorder, int arg)
 
774
DB_DB_ACCESS(pagesize, u_int32_t arg)
 
775
DB_DB_ACCESS(re_delim, int arg)
 
776
DB_DB_ACCESS(re_len, u_int32_t arg)
 
777
DB_DB_ACCESS(re_pad, int arg)
 
778
DB_DB_ACCESS(re_source, char *arg)
 
779
DB_DB_ACCESS(q_extentsize, u_int32_t arg)
 
780
 
 
781
// Here are the get/set methods that don't fit the above mold.
 
782
//
 
783
 
 
784
int Db::set_alloc(db_malloc_fcn_type malloc_fcn,
 
785
                     db_realloc_fcn_type realloc_fcn,
 
786
                     db_free_fcn_type free_fcn)
 
787
{
 
788
        DB *db;
 
789
 
 
790
        db = unwrap(this);
 
791
        return db->set_alloc(db, malloc_fcn, realloc_fcn, free_fcn);
 
792
}
 
793
 
 
794
void Db::set_errcall(void (*arg)(const char *, char *))
 
795
{
 
796
        env_->set_errcall(arg);
 
797
}
 
798
 
 
799
void *Db::get_app_private() const
 
800
{
 
801
        return unwrapConst(this)->app_private;
 
802
}
 
803
 
 
804
void Db::set_app_private(void *value)
 
805
{
 
806
        unwrap(this)->app_private = value;
 
807
}
 
808
 
 
809
int Db::set_cachesize(u_int32_t gbytes, u_int32_t bytes, int ncache)
 
810
{
 
811
        int ret;
 
812
        DB *db = unwrap(this);
 
813
 
 
814
        if ((ret = (*(db->set_cachesize))(db, gbytes, bytes, ncache)) != 0) {
 
815
                DB_ERROR("Db::set_cachesize", ret, error_policy());
 
816
        }
 
817
        return (ret);
 
818
}
 
819
 
 
820
int Db::set_paniccall(void (*callback)(DbEnv *, int))
 
821
{
 
822
        return (env_->set_paniccall(callback));
 
823
}
 
824
 
 
825
void Db::set_error_stream(ostream *error_stream)
 
826
{
 
827
        env_->set_error_stream(error_stream);
 
828
}
 
829
 
 
830
////////////////////////////////////////////////////////////////////////
 
831
//                                                                    //
 
832
//                            Dbc                                     //
 
833
//                                                                    //
 
834
////////////////////////////////////////////////////////////////////////
 
835
 
 
836
// It's private, and should never be called, but VC4.0 needs it resolved
 
837
//
 
838
Dbc::~Dbc()
 
839
{
 
840
}
 
841
 
 
842
int Dbc::close()
 
843
{
 
844
        DBC *cursor = this;
 
845
        int err;
 
846
 
 
847
        if ((err = cursor->c_close(cursor)) != 0) {
 
848
                DB_ERROR("Db::close", err, ON_ERROR_UNKNOWN);
 
849
                return (err);
 
850
        }
 
851
        return (0);
 
852
}
 
853
 
 
854
int Dbc::count(db_recno_t *countp, u_int32_t flags_arg)
 
855
{
 
856
        DBC *cursor = this;
 
857
        int err;
 
858
 
 
859
        if ((err = cursor->c_count(cursor, countp, flags_arg)) != 0) {
 
860
                DB_ERROR("Db::count", err, ON_ERROR_UNKNOWN);
 
861
                return (err);
 
862
        }
 
863
        return (0);
 
864
}
 
865
 
 
866
int Dbc::del(u_int32_t flags_arg)
 
867
{
 
868
        DBC *cursor = this;
 
869
        int err;
 
870
 
 
871
        if ((err = cursor->c_del(cursor, flags_arg)) != 0) {
 
872
 
 
873
                // DB_KEYEMPTY is a "normal" return, so should not be
 
874
                // thrown as an error
 
875
                //
 
876
                if (err != DB_KEYEMPTY) {
 
877
                        DB_ERROR("Db::del", err, ON_ERROR_UNKNOWN);
 
878
                        return (err);
 
879
                }
 
880
        }
 
881
        return (err);
 
882
}
 
883
 
 
884
int Dbc::dup(Dbc** cursorp, u_int32_t flags_arg)
 
885
{
 
886
        DBC *cursor = this;
 
887
        DBC *new_cursor = 0;
 
888
        int err;
 
889
 
 
890
        if ((err = cursor->c_dup(cursor, &new_cursor, flags_arg)) != 0) {
 
891
                DB_ERROR("Db::dup", err, ON_ERROR_UNKNOWN);
 
892
                return (err);
 
893
        }
 
894
 
 
895
        // The following cast implies that Dbc can be no larger than DBC
 
896
        *cursorp = (Dbc*)new_cursor;
 
897
        return (0);
 
898
}
 
899
 
 
900
int Dbc::get(Dbt* key, Dbt *data, u_int32_t flags_arg)
 
901
{
 
902
        DBC *cursor = this;
 
903
        int err;
 
904
 
 
905
        if ((err = cursor->c_get(cursor, key, data, flags_arg)) != 0) {
 
906
 
 
907
                // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
 
908
                // so should not be thrown as an error
 
909
                //
 
910
                if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
 
911
                        const char *name = "Dbc::get";
 
912
                        if (err == ENOMEM && DB_OVERFLOWED_DBT(key))
 
913
                                DB_ERROR_DBT(name, key, ON_ERROR_UNKNOWN);
 
914
                        else if (err == ENOMEM && DB_OVERFLOWED_DBT(data))
 
915
                                DB_ERROR_DBT(name, data, ON_ERROR_UNKNOWN);
 
916
                        else
 
917
                                DB_ERROR(name, err, ON_ERROR_UNKNOWN);
 
918
 
 
919
                        return (err);
 
920
                }
 
921
        }
 
922
        return (err);
 
923
}
 
924
 
 
925
int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t flags_arg)
 
926
{
 
927
        DBC *cursor = this;
 
928
        int err;
 
929
 
 
930
        if ((err = cursor->c_pget(cursor, key, pkey, data, flags_arg)) != 0) {
 
931
 
 
932
                // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
 
933
                // so should not be thrown as an error
 
934
                //
 
935
                if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
 
936
                        const char *name = "Dbc::pget";
 
937
                        if (err == ENOMEM && DB_OVERFLOWED_DBT(key))
 
938
                                DB_ERROR_DBT(name, key, ON_ERROR_UNKNOWN);
 
939
                        else if (err == ENOMEM && DB_OVERFLOWED_DBT(data))
 
940
                                DB_ERROR_DBT(name, data, ON_ERROR_UNKNOWN);
 
941
                        else
 
942
                                DB_ERROR(name, err, ON_ERROR_UNKNOWN);
 
943
 
 
944
                        return (err);
 
945
                }
 
946
        }
 
947
        return (err);
 
948
}
 
949
 
 
950
int Dbc::put(Dbt* key, Dbt *data, u_int32_t flags_arg)
 
951
{
 
952
        DBC *cursor = this;
 
953
        int err;
 
954
 
 
955
        if ((err = cursor->c_put(cursor, key, data, flags_arg)) != 0) {
 
956
 
 
957
                // DB_KEYEXIST is a "normal" return, so should not be
 
958
                // thrown as an error
 
959
                //
 
960
                if (err != DB_KEYEXIST) {
 
961
                        DB_ERROR("Dbc::put", err, ON_ERROR_UNKNOWN);
 
962
                        return (err);
 
963
                }
 
964
        }
 
965
        return (err);
 
966
}
 
967
 
 
968
////////////////////////////////////////////////////////////////////////
 
969
//                                                                    //
 
970
//                            Dbt                                 //
 
971
//                                                                    //
 
972
////////////////////////////////////////////////////////////////////////
 
973
 
 
974
Dbt::Dbt()
 
975
{
 
976
        DBT *dbt = this;
 
977
        memset(dbt, 0, sizeof(DBT));
 
978
}
 
979
 
 
980
Dbt::Dbt(void *data_arg, size_t size_arg)
 
981
{
 
982
        DBT *dbt = this;
 
983
        memset(dbt, 0, sizeof(DBT));
 
984
        set_data(data_arg);
 
985
        set_size(size_arg);
 
986
}
 
987
 
 
988
Dbt::~Dbt()
 
989
{
 
990
}
 
991
 
 
992
Dbt::Dbt(const Dbt &that)
 
993
{
 
994
        const DBT *from = &that;
 
995
        DBT *to = this;
 
996
        memcpy(to, from, sizeof(DBT));
 
997
}
 
998
 
 
999
Dbt &Dbt::operator = (const Dbt &that)
 
1000
{
 
1001
        if (this != &that) {
 
1002
                const DBT *from = &that;
 
1003
                DBT *to = this;
 
1004
                memcpy(to, from, sizeof(DBT));
 
1005
        }
 
1006
        return (*this);
 
1007
}