3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 22nd Oct 2001
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
12 This program is free software; you can redistribute it and/or
13 modify it under the same terms as Perl itself.
17 0.2 - No longer bombs out if dbopen returns an error.
18 0.3 - Added some support for multiple btree compares
19 1.0 - Complete support for multiple callbacks added.
20 Fixed a problem with pushing a value onto an empty list.
21 1.01 - Fixed a SunOS core dump problem.
22 The return value from TIEHASH wasn't set to NULL when
23 dbopen returned an error.
24 1.02 - Use ALIAS to define TIEARRAY.
25 Removed some redundant commented code.
26 Merged OS2 code into the main distribution.
27 Allow negative subscripts with RECNO interface.
28 Changed the default flags to O_CREAT|O_RDWR
30 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
31 Dave Hammen, hammen@gothamcity.jsc.nasa.gov
32 1.05 - Added logic to allow prefix & hash types to be specified via
34 1.06 - Minor namespace cleanup: Localized PrintBtree.
35 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
36 1.08 - No change to DB_File.xs
37 1.09 - Default mode for dbopen changed to 0666
38 1.10 - Fixed fd method so that it still returns -1 for
39 in-memory files when db 1.86 is used.
40 1.11 - No change to DB_File.xs
41 1.12 - No change to DB_File.xs
42 1.13 - Tidied up a few casts.
43 1.14 - Made it illegal to tie an associative array to a RECNO
44 database and an ordinary array to a HASH or BTREE database.
45 1.50 - Make work with both DB 1.x or DB 2.x
46 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
47 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
48 undefined value" warning with db_get and db_seq.
49 1.53 - Added DB_RENUMBER to flags for recno.
50 1.54 - Fixed bug in the fd method
51 1.55 - Fix for AIX from Jarkko Hietaniemi
52 1.56 - No change to DB_File.xs
53 1.57 - added the #undef op to allow building with Threads support.
54 1.58 - Fixed a problem with the use of sv_setpvn. When the
55 size is specified as 0, it does a strlen on the data.
56 This was ok for DB 1.x, but isn't for DB 2.x.
57 1.59 - No change to DB_File.xs
58 1.60 - Some code tidy up
59 1.61 - added flagSet macro for DB 2.5.x
60 fixed typo in O_RDONLY test.
61 1.62 - No change to DB_File.xs
62 1.63 - Fix to alllow DB 2.6.x to build.
63 1.64 - Tidied up the 1.x to 2.x flags mapping code.
64 Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
65 to fix a flag mapping problem with O_RDONLY on the Hurd
66 1.65 - Fixed a bug in the PUSH logic.
67 Added BOOT check that using 2.3.4 or greater
68 1.66 - Added DBM filter code
69 1.67 - Backed off the use of newSVpvn.
70 Fixed DBM Filter code for Perl 5.004.
71 Fixed a small memory leak in the filter code.
72 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
73 merged in the 5.005_58 changes
74 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
75 Fixed the R_SETCURSOR bug introduced in 1.68
76 Added a new Perl variable $DB_File::db_ver
77 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
78 GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
79 Added a BOOT check to test for equivalent versions of db.h &
81 1.71 - Support for Berkeley DB version 3.
82 Support for Berkeley DB 2/3's backward compatability mode.
84 1.72 - No change to DB_File.xs
85 1.73 - No change to DB_File.xs
86 1.74 - A call to open needed parenthesised to stop it clashing
88 Added Perl core patches 7703 & 7801.
89 1.75 - Fixed Perl core patch 7703.
90 Added suppport to allow DB_File to be built with
91 Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
93 1.76 - No change to DB_File.xs
94 1.77 - Tidied up a few types used in calling newSVpvn.
95 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
96 1.79 - NEXTKEY ignores the input key.
101 #define PERL_NO_GET_CONTEXT
107 # include "patchlevel.h"
108 # define PERL_REVISION 5
109 # define PERL_VERSION PATCHLEVEL
110 # define PERL_SUBVERSION SUBVERSION
113 #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
115 # define PL_sv_undef sv_undef
120 /* DEFSV appears first in 5.004_56 */
122 # define DEFSV GvSV(defgv)
125 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
126 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
128 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
129 * shortly #included by the <db.h>) __attribute__ to the possibly
130 * already defined __attribute__, for example by GNUC or by Perl. */
132 /* #if DB_VERSION_MAJOR_CFG < 2 */
133 #ifndef DB_VERSION_MAJOR
134 # undef __attribute__
139 /* If Perl has been compiled with Threads support,the symbol op will
140 be defined here. This clashes with a field name in db.h, so get rid of it.
152 /* Wall starts with 5.7.x */
154 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
156 /* Since we dropped the gccish definition of __attribute__ we will want
157 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
158 * all this means that we can't do attribute checking on the DB_File,
160 # ifndef DB_VERSION_MAJOR
163 # define dNOOP extern int Perl___notused
165 /* Ditto for dXSARGS. */
169 I32 ax = mark - PL_stack_base + 1; \
170 I32 items = sp - mark
174 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
176 # define dXSI32 dNOOP
178 #endif /* Perl >= 5.7 */
188 # define newSVpvn(a,b) newSVpv(a,b)
194 #define DBM_FILTERING
197 # define Trace(x) printf x
203 #define DBT_clear(x) Zero(&x, 1, DBT) ;
205 #ifdef DB_VERSION_MAJOR
207 #if DB_VERSION_MAJOR == 2
208 # define BERKELEY_DB_1_OR_2
211 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
212 # define AT_LEAST_DB_3_2
215 /* map version 2 features & constants onto their version 1 equivalent */
220 #define DB_Prefix_t size_t
225 #define DB_Hash_t u_int32_t
227 /* DBTYPE stays the same */
228 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
229 #if DB_VERSION_MAJOR == 2
230 typedef DB_INFO INFO ;
231 #else /* DB_VERSION_MAJOR > 2 */
232 # define DB_FIXEDLEN (0x8000)
233 #endif /* DB_VERSION_MAJOR == 2 */
235 /* version 2 has db_recno_t in place of recno_t */
236 typedef db_recno_t recno_t;
239 #define R_CURSOR DB_SET_RANGE
240 #define R_FIRST DB_FIRST
241 #define R_IAFTER DB_AFTER
242 #define R_IBEFORE DB_BEFORE
243 #define R_LAST DB_LAST
244 #define R_NEXT DB_NEXT
245 #define R_NOOVERWRITE DB_NOOVERWRITE
246 #define R_PREV DB_PREV
248 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
249 # define R_SETCURSOR 0x800000
251 # define R_SETCURSOR (-100)
254 #define R_RECNOSYNC 0
255 #define R_FIXEDLEN DB_FIXEDLEN
259 #define db_HA_hash h_hash
260 #define db_HA_ffactor h_ffactor
261 #define db_HA_nelem h_nelem
262 #define db_HA_bsize db_pagesize
263 #define db_HA_cachesize db_cachesize
264 #define db_HA_lorder db_lorder
266 #define db_BT_compare bt_compare
267 #define db_BT_prefix bt_prefix
268 #define db_BT_flags flags
269 #define db_BT_psize db_pagesize
270 #define db_BT_cachesize db_cachesize
271 #define db_BT_lorder db_lorder
272 #define db_BT_maxkeypage
273 #define db_BT_minkeypage
276 #define db_RE_reclen re_len
277 #define db_RE_flags flags
278 #define db_RE_bval re_pad
279 #define db_RE_bfname re_source
280 #define db_RE_psize db_pagesize
281 #define db_RE_cachesize db_cachesize
282 #define db_RE_lorder db_lorder
286 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
289 #define DBT_flags(x) x.flags = 0
290 #define DB_flags(x, v) x |= v
292 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
293 # define flagSet(flags, bitmask) ((flags) & (bitmask))
295 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
298 #else /* db version 1.x */
300 #define BERKELEY_DB_1
301 #define BERKELEY_DB_1_OR_2
314 # define DB_Prefix_t mDB_Prefix_t
321 # define DB_Hash_t mDB_Hash_t
324 #define db_HA_hash hash.hash
325 #define db_HA_ffactor hash.ffactor
326 #define db_HA_nelem hash.nelem
327 #define db_HA_bsize hash.bsize
328 #define db_HA_cachesize hash.cachesize
329 #define db_HA_lorder hash.lorder
331 #define db_BT_compare btree.compare
332 #define db_BT_prefix btree.prefix
333 #define db_BT_flags btree.flags
334 #define db_BT_psize btree.psize
335 #define db_BT_cachesize btree.cachesize
336 #define db_BT_lorder btree.lorder
337 #define db_BT_maxkeypage btree.maxkeypage
338 #define db_BT_minkeypage btree.minkeypage
340 #define db_RE_reclen recno.reclen
341 #define db_RE_flags recno.flags
342 #define db_RE_bval recno.bval
343 #define db_RE_bfname recno.bfname
344 #define db_RE_psize recno.psize
345 #define db_RE_cachesize recno.cachesize
346 #define db_RE_lorder recno.lorder
350 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
352 #define DB_flags(x, v)
353 #define flagSet(flags, bitmask) ((flags) & (bitmask))
355 #endif /* db version 1 */
359 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
360 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
361 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
363 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
364 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
366 #ifdef DB_VERSION_MAJOR
367 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
368 (db->dbp->close)(db->dbp, 0) )
369 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
370 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
371 ? ((db->cursor)->c_del)(db->cursor, 0) \
372 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
374 #else /* ! DB_VERSION_MAJOR */
376 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
377 #define db_close(db) ((db->dbp)->close)(db->dbp)
378 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
379 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
381 #endif /* ! DB_VERSION_MAJOR */
384 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
393 #ifdef BERKELEY_DB_1_OR_2
396 #ifdef DB_VERSION_MAJOR
400 SV * filter_fetch_key ;
401 SV * filter_store_key ;
402 SV * filter_fetch_value ;
403 SV * filter_store_value ;
405 #endif /* DBM_FILTERING */
409 typedef DB_File_type * DB_File ;
414 #define ckFilter(arg,type,name) \
417 /* printf("filtering %s\n", name) ; */ \
419 croak("recursion detected in %s", name) ; \
420 db->filtering = TRUE ; \
421 save_defsv = newSVsv(DEFSV) ; \
422 sv_setsv(DEFSV, arg) ; \
424 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
425 sv_setsv(arg, DEFSV) ; \
426 sv_setsv(DEFSV, save_defsv) ; \
427 SvREFCNT_dec(save_defsv) ; \
428 db->filtering = FALSE ; \
429 /* printf("end of filtering %s\n", name) ; */ \
434 #define ckFilter(arg,type, name)
436 #endif /* DBM_FILTERING */
438 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
440 #define OutputValue(arg, name) \
441 { if (RETVAL == 0) { \
442 my_sv_setpvn(arg, name.data, name.size) ; \
443 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
447 #define OutputKey(arg, name) \
450 if (db->type != DB_RECNO) { \
451 my_sv_setpvn(arg, name.data, name.size); \
454 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
455 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
459 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
462 extern void __getBerkeleyDBInfo(void);
465 /* Internal Global Data */
466 static recno_t Value ;
467 static recno_t zero = 0 ;
468 static DB_File CurrentDB ;
469 static DBTKEY empty ;
471 #ifdef DB_VERSION_MAJOR
475 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
477 db_put(db, key, value, flags)
486 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
490 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
491 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
493 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
497 memset(&l_key, 0, sizeof(l_key));
498 l_key.data = key.data;
499 l_key.size = key.size;
500 memset(&l_value, 0, sizeof(l_value));
501 l_value.data = value.data;
502 l_value.size = value.size;
504 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
505 (void)temp_cursor->c_close(temp_cursor);
509 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
510 (void)temp_cursor->c_close(temp_cursor);
516 if (flagSet(flags, R_CURSOR)) {
517 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
520 if (flagSet(flags, R_SETCURSOR)) {
521 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
523 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
527 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
531 #endif /* DB_VERSION_MAJOR */
535 #ifdef AT_LEAST_DB_3_2
538 btree_compare(DB * db, const DBT *key1, const DBT *key2)
540 btree_compare(db, key1, key2)
544 #endif /* CAN_PROTOTYPE */
546 #else /* Berkeley DB < 3.2 */
549 btree_compare(const DBT *key1, const DBT *key2)
551 btree_compare(key1, key2)
563 char * data1, * data2 ;
567 data1 = (char *) key1->data ;
568 data2 = (char *) key2->data ;
571 /* As newSVpv will assume that the data pointer is a null terminated C
572 string if the size parameter is 0, make sure that data points to an
573 empty string if the length is 0
586 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
587 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
590 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
595 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
607 #ifdef AT_LEAST_DB_3_2
610 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
612 btree_prefix(db, key1, key2)
618 #else /* Berkeley DB < 3.2 */
621 btree_prefix(const DBT *key1, const DBT *key2)
623 btree_prefix(key1, key2)
634 char * data1, * data2 ;
638 data1 = (char *) key1->data ;
639 data2 = (char *) key2->data ;
642 /* As newSVpv will assume that the data pointer is a null terminated C
643 string if the size parameter is 0, make sure that data points to an
644 empty string if the length is 0
657 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
658 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
661 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
666 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
679 # define HASH_CB_SIZE_TYPE size_t
681 # define HASH_CB_SIZE_TYPE u_int32_t
685 #ifdef AT_LEAST_DB_3_2
688 hash_cb(DB * db, const void *data, u_int32_t size)
690 hash_cb(db, data, size)
693 HASH_CB_SIZE_TYPE size ;
696 #else /* Berkeley DB < 3.2 */
699 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
703 HASH_CB_SIZE_TYPE size ;
720 /* DGH - Next two lines added to fix corrupted stack problem */
726 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
729 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
734 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
746 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
750 PrintHash(INFO *hash)
756 printf ("HASH Info\n") ;
757 printf (" hash = %s\n",
758 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
759 printf (" bsize = %d\n", hash->db_HA_bsize) ;
760 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
761 printf (" nelem = %d\n", hash->db_HA_nelem) ;
762 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
763 printf (" lorder = %d\n", hash->db_HA_lorder) ;
769 PrintRecno(INFO *recno)
775 printf ("RECNO Info\n") ;
776 printf (" flags = %d\n", recno->db_RE_flags) ;
777 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
778 printf (" psize = %d\n", recno->db_RE_psize) ;
779 printf (" lorder = %d\n", recno->db_RE_lorder) ;
780 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
781 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
782 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
787 PrintBtree(INFO *btree)
793 printf ("BTREE Info\n") ;
794 printf (" compare = %s\n",
795 (btree->db_BT_compare ? "redefined" : "default")) ;
796 printf (" prefix = %s\n",
797 (btree->db_BT_prefix ? "redefined" : "default")) ;
798 printf (" flags = %d\n", btree->db_BT_flags) ;
799 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
800 printf (" psize = %d\n", btree->db_BT_psize) ;
801 #ifndef DB_VERSION_MAJOR
802 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
803 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
805 printf (" lorder = %d\n", btree->db_BT_lorder) ;
810 #define PrintRecno(recno)
811 #define PrintHash(hash)
812 #define PrintBtree(btree)
819 GetArrayLength(pTHX_ DB_File db)
831 RETVAL = do_SEQ(db, key, value, R_LAST) ;
833 RETVAL = *(I32 *)key.data ;
834 else /* No key means empty file */
837 return ((I32)RETVAL) ;
842 GetRecnoKey(pTHX_ DB_File db, I32 value)
844 GetRecnoKey(db, value)
850 /* Get the length of the array */
851 I32 length = GetArrayLength(aTHX_ db) ;
853 /* check for attempt to write before start of array */
854 if (length + value + 1 <= 0)
855 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
857 value = length + value + 1 ;
868 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
870 ParseOpenInfo(isHASH, name, flags, mode, sv)
879 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
883 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
884 void * openinfo = NULL ;
885 INFO * info = &RETVAL->info ;
888 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
889 Zero(RETVAL, 1, DB_File_type) ;
891 /* Default to HASH */
893 RETVAL->filtering = 0 ;
894 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
895 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
896 #endif /* DBM_FILTERING */
897 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
898 RETVAL->type = DB_HASH ;
900 /* DGH - Next line added to avoid SEGV on existing hash DB */
903 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
904 RETVAL->in_memory = (name == NULL) ;
909 croak ("type parameter is not a reference") ;
911 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
912 if (svp && SvOK(*svp))
913 action = (HV*) SvRV(*svp) ;
915 croak("internal error") ;
917 if (sv_isa(sv, "DB_File::HASHINFO"))
921 croak("DB_File can only tie an associative array to a DB_HASH database") ;
923 RETVAL->type = DB_HASH ;
924 openinfo = (void*)info ;
926 svp = hv_fetch(action, "hash", 4, FALSE);
928 if (svp && SvOK(*svp))
930 info->db_HA_hash = hash_cb ;
931 RETVAL->hash = newSVsv(*svp) ;
934 info->db_HA_hash = NULL ;
936 svp = hv_fetch(action, "ffactor", 7, FALSE);
937 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
939 svp = hv_fetch(action, "nelem", 5, FALSE);
940 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
942 svp = hv_fetch(action, "bsize", 5, FALSE);
943 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
945 svp = hv_fetch(action, "cachesize", 9, FALSE);
946 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
948 svp = hv_fetch(action, "lorder", 6, FALSE);
949 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
953 else if (sv_isa(sv, "DB_File::BTREEINFO"))
956 croak("DB_File can only tie an associative array to a DB_BTREE database");
958 RETVAL->type = DB_BTREE ;
959 openinfo = (void*)info ;
961 svp = hv_fetch(action, "compare", 7, FALSE);
962 if (svp && SvOK(*svp))
964 info->db_BT_compare = btree_compare ;
965 RETVAL->compare = newSVsv(*svp) ;
968 info->db_BT_compare = NULL ;
970 svp = hv_fetch(action, "prefix", 6, FALSE);
971 if (svp && SvOK(*svp))
973 info->db_BT_prefix = btree_prefix ;
974 RETVAL->prefix = newSVsv(*svp) ;
977 info->db_BT_prefix = NULL ;
979 svp = hv_fetch(action, "flags", 5, FALSE);
980 info->db_BT_flags = svp ? SvIV(*svp) : 0;
982 svp = hv_fetch(action, "cachesize", 9, FALSE);
983 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
985 #ifndef DB_VERSION_MAJOR
986 svp = hv_fetch(action, "minkeypage", 10, FALSE);
987 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
989 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
990 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
993 svp = hv_fetch(action, "psize", 5, FALSE);
994 info->db_BT_psize = svp ? SvIV(*svp) : 0;
996 svp = hv_fetch(action, "lorder", 6, FALSE);
997 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1002 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1005 croak("DB_File can only tie an array to a DB_RECNO database");
1007 RETVAL->type = DB_RECNO ;
1008 openinfo = (void *)info ;
1010 info->db_RE_flags = 0 ;
1012 svp = hv_fetch(action, "flags", 5, FALSE);
1013 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1015 svp = hv_fetch(action, "reclen", 6, FALSE);
1016 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1018 svp = hv_fetch(action, "cachesize", 9, FALSE);
1019 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1021 svp = hv_fetch(action, "psize", 5, FALSE);
1022 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1024 svp = hv_fetch(action, "lorder", 6, FALSE);
1025 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1027 #ifdef DB_VERSION_MAJOR
1028 info->re_source = name ;
1031 svp = hv_fetch(action, "bfname", 6, FALSE);
1032 if (svp && SvOK(*svp)) {
1033 char * ptr = SvPV(*svp,n_a) ;
1034 #ifdef DB_VERSION_MAJOR
1035 name = (char*) n_a ? ptr : NULL ;
1037 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1041 #ifdef DB_VERSION_MAJOR
1044 info->db_RE_bfname = NULL ;
1047 svp = hv_fetch(action, "bval", 4, FALSE);
1048 #ifdef DB_VERSION_MAJOR
1049 if (svp && SvOK(*svp))
1053 value = (int)*SvPV(*svp, n_a) ;
1055 value = SvIV(*svp) ;
1057 if (info->flags & DB_FIXEDLEN) {
1058 info->re_pad = value ;
1059 info->flags |= DB_PAD ;
1062 info->re_delim = value ;
1063 info->flags |= DB_DELIMITER ;
1068 if (svp && SvOK(*svp))
1071 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1073 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1074 DB_flags(info->flags, DB_DELIMITER) ;
1079 if (info->db_RE_flags & R_FIXEDLEN)
1080 info->db_RE_bval = (u_char) ' ' ;
1082 info->db_RE_bval = (u_char) '\n' ;
1083 DB_flags(info->flags, DB_DELIMITER) ;
1088 info->flags |= DB_RENUMBER ;
1094 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1098 /* OS2 Specific Code */
1102 #endif /* __EMX__ */
1105 #ifdef DB_VERSION_MAJOR
1111 /* Map 1.x flags to 2.x flags */
1112 if ((flags & O_CREAT) == O_CREAT)
1113 Flags |= DB_CREATE ;
1116 if (flags == O_RDONLY)
1118 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1120 Flags |= DB_RDONLY ;
1123 if ((flags & O_TRUNC) == O_TRUNC)
1124 Flags |= DB_TRUNCATE ;
1127 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1129 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1130 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1132 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1137 RETVAL->dbp = NULL ;
1142 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1143 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1145 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1146 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1152 #else /* Berkeley DB Version > 2 */
1156 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1161 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1162 Zero(RETVAL, 1, DB_File_type) ;
1164 /* Default to HASH */
1165 #ifdef DBM_FILTERING
1166 RETVAL->filtering = 0 ;
1167 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1168 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1169 #endif /* DBM_FILTERING */
1170 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1171 RETVAL->type = DB_HASH ;
1173 /* DGH - Next line added to avoid SEGV on existing hash DB */
1176 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1177 RETVAL->in_memory = (name == NULL) ;
1179 status = db_create(&RETVAL->dbp, NULL,0) ;
1180 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1182 RETVAL->dbp = NULL ;
1190 croak ("type parameter is not a reference") ;
1192 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1193 if (svp && SvOK(*svp))
1194 action = (HV*) SvRV(*svp) ;
1196 croak("internal error") ;
1198 if (sv_isa(sv, "DB_File::HASHINFO"))
1202 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1204 RETVAL->type = DB_HASH ;
1206 svp = hv_fetch(action, "hash", 4, FALSE);
1208 if (svp && SvOK(*svp))
1210 (void)dbp->set_h_hash(dbp, hash_cb) ;
1211 RETVAL->hash = newSVsv(*svp) ;
1214 svp = hv_fetch(action, "ffactor", 7, FALSE);
1216 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1218 svp = hv_fetch(action, "nelem", 5, FALSE);
1220 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1222 svp = hv_fetch(action, "bsize", 5, FALSE);
1224 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1226 svp = hv_fetch(action, "cachesize", 9, FALSE);
1228 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1230 svp = hv_fetch(action, "lorder", 6, FALSE);
1232 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1236 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1239 croak("DB_File can only tie an associative array to a DB_BTREE database");
1241 RETVAL->type = DB_BTREE ;
1243 svp = hv_fetch(action, "compare", 7, FALSE);
1244 if (svp && SvOK(*svp))
1246 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1247 RETVAL->compare = newSVsv(*svp) ;
1250 svp = hv_fetch(action, "prefix", 6, FALSE);
1251 if (svp && SvOK(*svp))
1253 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1254 RETVAL->prefix = newSVsv(*svp) ;
1257 svp = hv_fetch(action, "flags", 5, FALSE);
1259 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1261 svp = hv_fetch(action, "cachesize", 9, FALSE);
1263 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1265 svp = hv_fetch(action, "psize", 5, FALSE);
1267 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1269 svp = hv_fetch(action, "lorder", 6, FALSE);
1271 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1276 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1281 croak("DB_File can only tie an array to a DB_RECNO database");
1283 RETVAL->type = DB_RECNO ;
1285 svp = hv_fetch(action, "flags", 5, FALSE);
1287 int flags = SvIV(*svp) ;
1288 /* remove FIXDLEN, if present */
1289 if (flags & DB_FIXEDLEN) {
1291 flags &= ~DB_FIXEDLEN ;
1295 svp = hv_fetch(action, "cachesize", 9, FALSE);
1297 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1300 svp = hv_fetch(action, "psize", 5, FALSE);
1302 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1305 svp = hv_fetch(action, "lorder", 6, FALSE);
1307 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1310 svp = hv_fetch(action, "bval", 4, FALSE);
1311 if (svp && SvOK(*svp))
1315 value = (int)*SvPV(*svp, n_a) ;
1317 value = (int)SvIV(*svp) ;
1320 status = dbp->set_re_pad(dbp, value) ;
1323 status = dbp->set_re_delim(dbp, value) ;
1329 svp = hv_fetch(action, "reclen", 6, FALSE);
1331 u_int32_t len = my_SvUV32(*svp) ;
1332 status = dbp->set_re_len(dbp, len) ;
1337 status = dbp->set_re_source(dbp, name) ;
1341 svp = hv_fetch(action, "bfname", 6, FALSE);
1342 if (svp && SvOK(*svp)) {
1343 char * ptr = SvPV(*svp,n_a) ;
1344 name = (char*) n_a ? ptr : NULL ;
1350 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1353 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1358 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1362 u_int32_t Flags = 0 ;
1365 /* Map 1.x flags to 3.x flags */
1366 if ((flags & O_CREAT) == O_CREAT)
1367 Flags |= DB_CREATE ;
1370 if (flags == O_RDONLY)
1372 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1374 Flags |= DB_RDONLY ;
1377 if ((flags & O_TRUNC) == O_TRUNC)
1378 Flags |= DB_TRUNCATE ;
1381 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1383 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1386 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1388 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1391 RETVAL->dbp = NULL ;
1397 #endif /* Berkeley DB Version > 2 */
1399 } /* ParseOpenInfo */
1403 #ifdef CAN_PROTOTYPE
1404 constant(char *name, int arg)
1416 if (strEQ(name, "BTREEMAGIC"))
1422 if (strEQ(name, "BTREEVERSION"))
1424 return BTREEVERSION;
1432 if (strEQ(name, "DB_LOCK"))
1438 if (strEQ(name, "DB_SHMEM"))
1444 if (strEQ(name, "DB_TXN"))
1458 if (strEQ(name, "HASHMAGIC"))
1464 if (strEQ(name, "HASHVERSION"))
1480 if (strEQ(name, "MAX_PAGE_NUMBER"))
1481 #ifdef MAX_PAGE_NUMBER
1482 return (U32)MAX_PAGE_NUMBER;
1486 if (strEQ(name, "MAX_PAGE_OFFSET"))
1487 #ifdef MAX_PAGE_OFFSET
1488 return MAX_PAGE_OFFSET;
1492 if (strEQ(name, "MAX_REC_NUMBER"))
1493 #ifdef MAX_REC_NUMBER
1494 return (U32)MAX_REC_NUMBER;
1508 if (strEQ(name, "RET_ERROR"))
1514 if (strEQ(name, "RET_SPECIAL"))
1520 if (strEQ(name, "RET_SUCCESS"))
1526 if (strEQ(name, "R_CURSOR"))
1532 if (strEQ(name, "R_DUP"))
1538 if (strEQ(name, "R_FIRST"))
1544 if (strEQ(name, "R_FIXEDLEN"))
1550 if (strEQ(name, "R_IAFTER"))
1556 if (strEQ(name, "R_IBEFORE"))
1562 if (strEQ(name, "R_LAST"))
1568 if (strEQ(name, "R_NEXT"))
1574 if (strEQ(name, "R_NOKEY"))
1580 if (strEQ(name, "R_NOOVERWRITE"))
1581 #ifdef R_NOOVERWRITE
1582 return R_NOOVERWRITE;
1586 if (strEQ(name, "R_PREV"))
1592 if (strEQ(name, "R_RECNOSYNC"))
1598 if (strEQ(name, "R_SETCURSOR"))
1604 if (strEQ(name, "R_SNAPSHOT"))
1638 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1642 __getBerkeleyDBInfo() ;
1645 empty.data = &zero ;
1646 empty.size = sizeof(recno_t) ;
1656 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1663 char * name = (char *) NULL ;
1664 SV * sv = (SV *) NULL ;
1667 if (items >= 3 && SvOK(ST(2)))
1668 name = (char*) SvPV(ST(2), n_a) ;
1673 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1674 if (RETVAL->dbp == NULL)
1687 SvREFCNT_dec(db->hash) ;
1689 SvREFCNT_dec(db->compare) ;
1691 SvREFCNT_dec(db->prefix) ;
1692 #ifdef DBM_FILTERING
1693 if (db->filter_fetch_key)
1694 SvREFCNT_dec(db->filter_fetch_key) ;
1695 if (db->filter_store_key)
1696 SvREFCNT_dec(db->filter_store_key) ;
1697 if (db->filter_fetch_value)
1698 SvREFCNT_dec(db->filter_fetch_value) ;
1699 if (db->filter_store_value)
1700 SvREFCNT_dec(db->filter_store_value) ;
1701 #endif /* DBM_FILTERING */
1703 #ifdef DB_VERSION_MAJOR
1710 db_DELETE(db, key, flags=0)
1728 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1734 db_FETCH(db, key, flags=0)
1746 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1747 RETVAL = db_get(db, key, value, flags) ;
1748 ST(0) = sv_newmortal();
1749 OutputValue(ST(0), value)
1753 db_STORE(db, key, value, flags=0)
1775 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1776 ST(0) = sv_newmortal();
1777 OutputKey(ST(0), key) ;
1783 DBTKEY key = NO_INIT
1793 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1794 ST(0) = sv_newmortal();
1795 OutputKey(ST(0), key) ;
1799 # These would be nice for RECNO
1817 #ifdef DB_VERSION_MAJOR
1818 /* get the first value */
1819 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1824 for (i = items-1 ; i > 0 ; --i)
1826 value.data = SvPV(ST(i), n_a) ;
1830 key.size = sizeof(int) ;
1831 #ifdef DB_VERSION_MAJOR
1832 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1834 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1858 /* First get the final value */
1859 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1860 ST(0) = sv_newmortal();
1864 /* the call to del will trash value, so take a copy now */
1865 OutputValue(ST(0), value) ;
1866 RETVAL = db_del(db, key, R_CURSOR) ;
1868 sv_setsv(ST(0), &PL_sv_undef);
1886 /* get the first value */
1887 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1888 ST(0) = sv_newmortal();
1892 /* the call to del will trash value, so take a copy now */
1893 OutputValue(ST(0), value) ;
1894 RETVAL = db_del(db, key, R_CURSOR) ;
1896 sv_setsv (ST(0), &PL_sv_undef) ;
1917 /* Set the Cursor to the Last element */
1918 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1919 #ifndef DB_VERSION_MAJOR
1924 keyval = *(int*)key.data ;
1927 for (i = 1 ; i < items ; ++i)
1929 value.data = SvPV(ST(i), n_a) ;
1932 key.data = &keyval ;
1933 key.size = sizeof(int) ;
1934 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1946 ALIAS: FETCHSIZE = 1
1949 RETVAL = GetArrayLength(aTHX_ db) ;
1955 # Now provide an interface to the rest of the DB functionality
1959 db_del(db, key, flags=0)
1965 RETVAL = db_del(db, key, flags) ;
1966 #ifdef DB_VERSION_MAJOR
1969 else if (RETVAL == DB_NOTFOUND)
1977 db_get(db, key, value, flags=0)
1985 RETVAL = db_get(db, key, value, flags) ;
1986 #ifdef DB_VERSION_MAJOR
1989 else if (RETVAL == DB_NOTFOUND)
1997 db_put(db, key, value, flags=0)
2004 RETVAL = db_put(db, key, value, flags) ;
2005 #ifdef DB_VERSION_MAJOR
2008 else if (RETVAL == DB_KEYEXIST)
2013 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
2020 #ifdef DB_VERSION_MAJOR
2024 status = (db->in_memory
2026 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
2031 RETVAL = (db->in_memory
2033 : ((db->dbp)->fd)(db->dbp) ) ;
2039 db_sync(db, flags=0)
2044 RETVAL = db_sync(db, flags) ;
2045 #ifdef DB_VERSION_MAJOR
2054 db_seq(db, key, value, flags)
2062 RETVAL = db_seq(db, key, value, flags);
2063 #ifdef DB_VERSION_MAJOR
2066 else if (RETVAL == DB_NOTFOUND)
2074 #ifdef DBM_FILTERING
2076 #define setFilter(type) \
2079 RETVAL = sv_mortalcopy(db->type) ; \
2081 if (db->type && (code == &PL_sv_undef)) { \
2082 SvREFCNT_dec(db->type) ; \
2087 sv_setsv(db->type, code) ; \
2089 db->type = newSVsv(code) ; \
2095 filter_fetch_key(db, code)
2098 SV * RETVAL = &PL_sv_undef ;
2100 setFilter(filter_fetch_key) ;
2103 filter_store_key(db, code)
2106 SV * RETVAL = &PL_sv_undef ;
2108 setFilter(filter_store_key) ;
2111 filter_fetch_value(db, code)
2114 SV * RETVAL = &PL_sv_undef ;
2116 setFilter(filter_fetch_value) ;
2119 filter_store_value(db, code)
2122 SV * RETVAL = &PL_sv_undef ;
2124 setFilter(filter_store_value) ;
2126 #endif /* DBM_FILTERING */