3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 26th April 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.
98 #define PERL_NO_GET_CONTEXT
104 # include "patchlevel.h"
105 # define PERL_REVISION 5
106 # define PERL_VERSION PATCHLEVEL
107 # define PERL_SUBVERSION SUBVERSION
110 #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
112 # define PL_sv_undef sv_undef
117 /* DEFSV appears first in 5.004_56 */
119 # define DEFSV GvSV(defgv)
122 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
123 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
125 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
126 * shortly #included by the <db.h>) __attribute__ to the possibly
127 * already defined __attribute__, for example by GNUC or by Perl. */
129 #if DB_VERSION_MAJOR_CFG < 2
133 /* Since we dropped the gccish definition of __attribute__ we will want
134 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
135 * all this means that we can't do attribute checking on the DB_File,
138 #define dNOOP extern int Perl___notused
142 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
146 /* If Perl has been compiled with Threads support,the symbol op will
147 be defined here. This clashes with a field name in db.h, so get rid of it.
160 extern void __getBerkeleyDBInfo(void);
171 # define newSVpvn(a,b) newSVpv(a,b)
177 #define DBM_FILTERING
180 # define Trace(x) printf x
186 #define DBT_clear(x) Zero(&x, 1, DBT) ;
188 #ifdef DB_VERSION_MAJOR
190 #if DB_VERSION_MAJOR == 2
191 # define BERKELEY_DB_1_OR_2
194 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
195 # define AT_LEAST_DB_3_2
198 /* map version 2 features & constants onto their version 1 equivalent */
203 #define DB_Prefix_t size_t
208 #define DB_Hash_t u_int32_t
210 /* DBTYPE stays the same */
211 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
212 #if DB_VERSION_MAJOR == 2
213 typedef DB_INFO INFO ;
214 #else /* DB_VERSION_MAJOR > 2 */
215 # define DB_FIXEDLEN (0x8000)
216 #endif /* DB_VERSION_MAJOR == 2 */
218 /* version 2 has db_recno_t in place of recno_t */
219 typedef db_recno_t recno_t;
222 #define R_CURSOR DB_SET_RANGE
223 #define R_FIRST DB_FIRST
224 #define R_IAFTER DB_AFTER
225 #define R_IBEFORE DB_BEFORE
226 #define R_LAST DB_LAST
227 #define R_NEXT DB_NEXT
228 #define R_NOOVERWRITE DB_NOOVERWRITE
229 #define R_PREV DB_PREV
231 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
232 # define R_SETCURSOR 0x800000
234 # define R_SETCURSOR (-100)
237 #define R_RECNOSYNC 0
238 #define R_FIXEDLEN DB_FIXEDLEN
242 #define db_HA_hash h_hash
243 #define db_HA_ffactor h_ffactor
244 #define db_HA_nelem h_nelem
245 #define db_HA_bsize db_pagesize
246 #define db_HA_cachesize db_cachesize
247 #define db_HA_lorder db_lorder
249 #define db_BT_compare bt_compare
250 #define db_BT_prefix bt_prefix
251 #define db_BT_flags flags
252 #define db_BT_psize db_pagesize
253 #define db_BT_cachesize db_cachesize
254 #define db_BT_lorder db_lorder
255 #define db_BT_maxkeypage
256 #define db_BT_minkeypage
259 #define db_RE_reclen re_len
260 #define db_RE_flags flags
261 #define db_RE_bval re_pad
262 #define db_RE_bfname re_source
263 #define db_RE_psize db_pagesize
264 #define db_RE_cachesize db_cachesize
265 #define db_RE_lorder db_lorder
269 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
272 #define DBT_flags(x) x.flags = 0
273 #define DB_flags(x, v) x |= v
275 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
276 # define flagSet(flags, bitmask) ((flags) & (bitmask))
278 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
281 #else /* db version 1.x */
283 #define BERKELEY_DB_1
284 #define BERKELEY_DB_1_OR_2
297 # define DB_Prefix_t mDB_Prefix_t
304 # define DB_Hash_t mDB_Hash_t
307 #define db_HA_hash hash.hash
308 #define db_HA_ffactor hash.ffactor
309 #define db_HA_nelem hash.nelem
310 #define db_HA_bsize hash.bsize
311 #define db_HA_cachesize hash.cachesize
312 #define db_HA_lorder hash.lorder
314 #define db_BT_compare btree.compare
315 #define db_BT_prefix btree.prefix
316 #define db_BT_flags btree.flags
317 #define db_BT_psize btree.psize
318 #define db_BT_cachesize btree.cachesize
319 #define db_BT_lorder btree.lorder
320 #define db_BT_maxkeypage btree.maxkeypage
321 #define db_BT_minkeypage btree.minkeypage
323 #define db_RE_reclen recno.reclen
324 #define db_RE_flags recno.flags
325 #define db_RE_bval recno.bval
326 #define db_RE_bfname recno.bfname
327 #define db_RE_psize recno.psize
328 #define db_RE_cachesize recno.cachesize
329 #define db_RE_lorder recno.lorder
333 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
335 #define DB_flags(x, v)
336 #define flagSet(flags, bitmask) ((flags) & (bitmask))
338 #endif /* db version 1 */
342 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
343 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
344 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
346 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
347 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
349 #ifdef DB_VERSION_MAJOR
350 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
351 (db->dbp->close)(db->dbp, 0) )
352 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
353 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
354 ? ((db->cursor)->c_del)(db->cursor, 0) \
355 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
357 #else /* ! DB_VERSION_MAJOR */
359 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
360 #define db_close(db) ((db->dbp)->close)(db->dbp)
361 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
362 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
364 #endif /* ! DB_VERSION_MAJOR */
367 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
376 #ifdef BERKELEY_DB_1_OR_2
379 #ifdef DB_VERSION_MAJOR
383 SV * filter_fetch_key ;
384 SV * filter_store_key ;
385 SV * filter_fetch_value ;
386 SV * filter_store_value ;
388 #endif /* DBM_FILTERING */
392 typedef DB_File_type * DB_File ;
397 #define ckFilter(arg,type,name) \
400 /* printf("filtering %s\n", name) ;*/ \
402 croak("recursion detected in %s", name) ; \
403 db->filtering = TRUE ; \
404 save_defsv = newSVsv(DEFSV) ; \
405 sv_setsv(DEFSV, arg) ; \
407 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
408 sv_setsv(arg, DEFSV) ; \
409 sv_setsv(DEFSV, save_defsv) ; \
410 SvREFCNT_dec(save_defsv) ; \
411 db->filtering = FALSE ; \
412 /*printf("end of filtering %s\n", name) ;*/ \
417 #define ckFilter(arg,type, name)
419 #endif /* DBM_FILTERING */
421 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
423 #define OutputValue(arg, name) \
424 { if (RETVAL == 0) { \
425 my_sv_setpvn(arg, name.data, name.size) ; \
426 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
430 #define OutputKey(arg, name) \
433 if (db->type != DB_RECNO) { \
434 my_sv_setpvn(arg, name.data, name.size); \
437 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
438 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
443 /* Internal Global Data */
444 static recno_t Value ;
445 static recno_t zero = 0 ;
446 static DB_File CurrentDB ;
447 static DBTKEY empty ;
449 #ifdef DB_VERSION_MAJOR
453 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
455 db_put(db, key, value, flags)
464 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
468 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
469 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
471 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
475 memset(&l_key, 0, sizeof(l_key));
476 l_key.data = key.data;
477 l_key.size = key.size;
478 memset(&l_value, 0, sizeof(l_value));
479 l_value.data = value.data;
480 l_value.size = value.size;
482 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
483 (void)temp_cursor->c_close(temp_cursor);
487 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
488 (void)temp_cursor->c_close(temp_cursor);
494 if (flagSet(flags, R_CURSOR)) {
495 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
498 if (flagSet(flags, R_SETCURSOR)) {
499 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
501 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
505 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
509 #endif /* DB_VERSION_MAJOR */
513 #ifdef AT_LEAST_DB_3_2
516 btree_compare(DB * db, const DBT *key1, const DBT *key2)
518 btree_compare(db, key1, key2)
522 #endif /* CAN_PROTOTYPE */
524 #else /* Berkeley DB < 3.2 */
527 btree_compare(const DBT *key1, const DBT *key2)
529 btree_compare(key1, key2)
541 char * data1, * data2 ;
545 data1 = (char *) key1->data ;
546 data2 = (char *) key2->data ;
549 /* As newSVpv will assume that the data pointer is a null terminated C
550 string if the size parameter is 0, make sure that data points to an
551 empty string if the length is 0
564 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
565 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
568 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
573 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
585 #ifdef AT_LEAST_DB_3_2
588 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
590 btree_prefix(db, key1, key2)
596 #else /* Berkeley DB < 3.2 */
599 btree_prefix(const DBT *key1, const DBT *key2)
601 btree_prefix(key1, key2)
612 char * data1, * data2 ;
616 data1 = (char *) key1->data ;
617 data2 = (char *) key2->data ;
620 /* As newSVpv will assume that the data pointer is a null terminated C
621 string if the size parameter is 0, make sure that data points to an
622 empty string if the length is 0
635 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
636 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
639 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
644 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
657 # define HASH_CB_SIZE_TYPE size_t
659 # define HASH_CB_SIZE_TYPE u_int32_t
663 #ifdef AT_LEAST_DB_3_2
666 hash_cb(DB * db, const void *data, u_int32_t size)
668 hash_cb(db, data, size)
671 HASH_CB_SIZE_TYPE size ;
674 #else /* Berkeley DB < 3.2 */
677 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
681 HASH_CB_SIZE_TYPE size ;
698 /* DGH - Next two lines added to fix corrupted stack problem */
704 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
707 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
712 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
724 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
728 PrintHash(INFO *hash)
734 printf ("HASH Info\n") ;
735 printf (" hash = %s\n",
736 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
737 printf (" bsize = %d\n", hash->db_HA_bsize) ;
738 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
739 printf (" nelem = %d\n", hash->db_HA_nelem) ;
740 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
741 printf (" lorder = %d\n", hash->db_HA_lorder) ;
747 PrintRecno(INFO *recno)
753 printf ("RECNO Info\n") ;
754 printf (" flags = %d\n", recno->db_RE_flags) ;
755 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
756 printf (" psize = %d\n", recno->db_RE_psize) ;
757 printf (" lorder = %d\n", recno->db_RE_lorder) ;
758 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
759 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
760 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
765 PrintBtree(INFO *btree)
771 printf ("BTREE Info\n") ;
772 printf (" compare = %s\n",
773 (btree->db_BT_compare ? "redefined" : "default")) ;
774 printf (" prefix = %s\n",
775 (btree->db_BT_prefix ? "redefined" : "default")) ;
776 printf (" flags = %d\n", btree->db_BT_flags) ;
777 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
778 printf (" psize = %d\n", btree->db_BT_psize) ;
779 #ifndef DB_VERSION_MAJOR
780 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
781 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
783 printf (" lorder = %d\n", btree->db_BT_lorder) ;
788 #define PrintRecno(recno)
789 #define PrintHash(hash)
790 #define PrintBtree(btree)
797 GetArrayLength(pTHX_ DB_File db)
809 RETVAL = do_SEQ(db, key, value, R_LAST) ;
811 RETVAL = *(I32 *)key.data ;
812 else /* No key means empty file */
815 return ((I32)RETVAL) ;
820 GetRecnoKey(pTHX_ DB_File db, I32 value)
822 GetRecnoKey(db, value)
828 /* Get the length of the array */
829 I32 length = GetArrayLength(aTHX_ db) ;
831 /* check for attempt to write before start of array */
832 if (length + value + 1 <= 0)
833 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
835 value = length + value + 1 ;
846 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
848 ParseOpenInfo(isHASH, name, flags, mode, sv)
857 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
861 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
862 void * openinfo = NULL ;
863 INFO * info = &RETVAL->info ;
866 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
867 Zero(RETVAL, 1, DB_File_type) ;
869 /* Default to HASH */
871 RETVAL->filtering = 0 ;
872 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
873 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
874 #endif /* DBM_FILTERING */
875 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
876 RETVAL->type = DB_HASH ;
878 /* DGH - Next line added to avoid SEGV on existing hash DB */
881 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
882 RETVAL->in_memory = (name == NULL) ;
887 croak ("type parameter is not a reference") ;
889 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
890 if (svp && SvOK(*svp))
891 action = (HV*) SvRV(*svp) ;
893 croak("internal error") ;
895 if (sv_isa(sv, "DB_File::HASHINFO"))
899 croak("DB_File can only tie an associative array to a DB_HASH database") ;
901 RETVAL->type = DB_HASH ;
902 openinfo = (void*)info ;
904 svp = hv_fetch(action, "hash", 4, FALSE);
906 if (svp && SvOK(*svp))
908 info->db_HA_hash = hash_cb ;
909 RETVAL->hash = newSVsv(*svp) ;
912 info->db_HA_hash = NULL ;
914 svp = hv_fetch(action, "ffactor", 7, FALSE);
915 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
917 svp = hv_fetch(action, "nelem", 5, FALSE);
918 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
920 svp = hv_fetch(action, "bsize", 5, FALSE);
921 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
923 svp = hv_fetch(action, "cachesize", 9, FALSE);
924 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
926 svp = hv_fetch(action, "lorder", 6, FALSE);
927 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
931 else if (sv_isa(sv, "DB_File::BTREEINFO"))
934 croak("DB_File can only tie an associative array to a DB_BTREE database");
936 RETVAL->type = DB_BTREE ;
937 openinfo = (void*)info ;
939 svp = hv_fetch(action, "compare", 7, FALSE);
940 if (svp && SvOK(*svp))
942 info->db_BT_compare = btree_compare ;
943 RETVAL->compare = newSVsv(*svp) ;
946 info->db_BT_compare = NULL ;
948 svp = hv_fetch(action, "prefix", 6, FALSE);
949 if (svp && SvOK(*svp))
951 info->db_BT_prefix = btree_prefix ;
952 RETVAL->prefix = newSVsv(*svp) ;
955 info->db_BT_prefix = NULL ;
957 svp = hv_fetch(action, "flags", 5, FALSE);
958 info->db_BT_flags = svp ? SvIV(*svp) : 0;
960 svp = hv_fetch(action, "cachesize", 9, FALSE);
961 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
963 #ifndef DB_VERSION_MAJOR
964 svp = hv_fetch(action, "minkeypage", 10, FALSE);
965 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
967 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
968 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
971 svp = hv_fetch(action, "psize", 5, FALSE);
972 info->db_BT_psize = svp ? SvIV(*svp) : 0;
974 svp = hv_fetch(action, "lorder", 6, FALSE);
975 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
980 else if (sv_isa(sv, "DB_File::RECNOINFO"))
983 croak("DB_File can only tie an array to a DB_RECNO database");
985 RETVAL->type = DB_RECNO ;
986 openinfo = (void *)info ;
988 info->db_RE_flags = 0 ;
990 svp = hv_fetch(action, "flags", 5, FALSE);
991 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
993 svp = hv_fetch(action, "reclen", 6, FALSE);
994 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
996 svp = hv_fetch(action, "cachesize", 9, FALSE);
997 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
999 svp = hv_fetch(action, "psize", 5, FALSE);
1000 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1002 svp = hv_fetch(action, "lorder", 6, FALSE);
1003 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1005 #ifdef DB_VERSION_MAJOR
1006 info->re_source = name ;
1009 svp = hv_fetch(action, "bfname", 6, FALSE);
1010 if (svp && SvOK(*svp)) {
1011 char * ptr = SvPV(*svp,n_a) ;
1012 #ifdef DB_VERSION_MAJOR
1013 name = (char*) n_a ? ptr : NULL ;
1015 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1019 #ifdef DB_VERSION_MAJOR
1022 info->db_RE_bfname = NULL ;
1025 svp = hv_fetch(action, "bval", 4, FALSE);
1026 #ifdef DB_VERSION_MAJOR
1027 if (svp && SvOK(*svp))
1031 value = (int)*SvPV(*svp, n_a) ;
1033 value = SvIV(*svp) ;
1035 if (info->flags & DB_FIXEDLEN) {
1036 info->re_pad = value ;
1037 info->flags |= DB_PAD ;
1040 info->re_delim = value ;
1041 info->flags |= DB_DELIMITER ;
1046 if (svp && SvOK(*svp))
1049 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1051 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1052 DB_flags(info->flags, DB_DELIMITER) ;
1057 if (info->db_RE_flags & R_FIXEDLEN)
1058 info->db_RE_bval = (u_char) ' ' ;
1060 info->db_RE_bval = (u_char) '\n' ;
1061 DB_flags(info->flags, DB_DELIMITER) ;
1066 info->flags |= DB_RENUMBER ;
1072 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1076 /* OS2 Specific Code */
1080 #endif /* __EMX__ */
1083 #ifdef DB_VERSION_MAJOR
1089 /* Map 1.x flags to 2.x flags */
1090 if ((flags & O_CREAT) == O_CREAT)
1091 Flags |= DB_CREATE ;
1094 if (flags == O_RDONLY)
1096 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1098 Flags |= DB_RDONLY ;
1101 if ((flags & O_TRUNC) == O_TRUNC)
1102 Flags |= DB_TRUNCATE ;
1105 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1107 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1108 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1110 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1115 RETVAL->dbp = NULL ;
1120 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1121 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1123 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1124 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1130 #else /* Berkeley DB Version > 2 */
1134 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1139 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1140 Zero(RETVAL, 1, DB_File_type) ;
1142 /* Default to HASH */
1143 #ifdef DBM_FILTERING
1144 RETVAL->filtering = 0 ;
1145 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1146 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1147 #endif /* DBM_FILTERING */
1148 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1149 RETVAL->type = DB_HASH ;
1151 /* DGH - Next line added to avoid SEGV on existing hash DB */
1154 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1155 RETVAL->in_memory = (name == NULL) ;
1157 status = db_create(&RETVAL->dbp, NULL,0) ;
1158 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1160 RETVAL->dbp = NULL ;
1168 croak ("type parameter is not a reference") ;
1170 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1171 if (svp && SvOK(*svp))
1172 action = (HV*) SvRV(*svp) ;
1174 croak("internal error") ;
1176 if (sv_isa(sv, "DB_File::HASHINFO"))
1180 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1182 RETVAL->type = DB_HASH ;
1184 svp = hv_fetch(action, "hash", 4, FALSE);
1186 if (svp && SvOK(*svp))
1188 (void)dbp->set_h_hash(dbp, hash_cb) ;
1189 RETVAL->hash = newSVsv(*svp) ;
1192 svp = hv_fetch(action, "ffactor", 7, FALSE);
1194 (void)dbp->set_h_ffactor(dbp, SvIV(*svp)) ;
1196 svp = hv_fetch(action, "nelem", 5, FALSE);
1198 (void)dbp->set_h_nelem(dbp, SvIV(*svp)) ;
1200 svp = hv_fetch(action, "bsize", 5, FALSE);
1202 (void)dbp->set_pagesize(dbp, SvIV(*svp));
1204 svp = hv_fetch(action, "cachesize", 9, FALSE);
1206 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1208 svp = hv_fetch(action, "lorder", 6, FALSE);
1210 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1214 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1217 croak("DB_File can only tie an associative array to a DB_BTREE database");
1219 RETVAL->type = DB_BTREE ;
1221 svp = hv_fetch(action, "compare", 7, FALSE);
1222 if (svp && SvOK(*svp))
1224 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1225 RETVAL->compare = newSVsv(*svp) ;
1228 svp = hv_fetch(action, "prefix", 6, FALSE);
1229 if (svp && SvOK(*svp))
1231 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1232 RETVAL->prefix = newSVsv(*svp) ;
1235 svp = hv_fetch(action, "flags", 5, FALSE);
1237 (void)dbp->set_flags(dbp, SvIV(*svp)) ;
1239 svp = hv_fetch(action, "cachesize", 9, FALSE);
1241 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1243 svp = hv_fetch(action, "psize", 5, FALSE);
1245 (void)dbp->set_pagesize(dbp, SvIV(*svp)) ;
1247 svp = hv_fetch(action, "lorder", 6, FALSE);
1249 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1254 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1259 croak("DB_File can only tie an array to a DB_RECNO database");
1261 RETVAL->type = DB_RECNO ;
1263 svp = hv_fetch(action, "flags", 5, FALSE);
1265 int flags = SvIV(*svp) ;
1266 /* remove FIXDLEN, if present */
1267 if (flags & DB_FIXEDLEN) {
1269 flags &= ~DB_FIXEDLEN ;
1273 svp = hv_fetch(action, "cachesize", 9, FALSE);
1275 status = dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1278 svp = hv_fetch(action, "psize", 5, FALSE);
1280 status = dbp->set_pagesize(dbp, SvIV(*svp)) ;
1283 svp = hv_fetch(action, "lorder", 6, FALSE);
1285 status = dbp->set_lorder(dbp, SvIV(*svp)) ;
1288 svp = hv_fetch(action, "bval", 4, FALSE);
1289 if (svp && SvOK(*svp))
1293 value = (int)*SvPV(*svp, n_a) ;
1295 value = SvIV(*svp) ;
1298 status = dbp->set_re_pad(dbp, value) ;
1301 status = dbp->set_re_delim(dbp, value) ;
1307 svp = hv_fetch(action, "reclen", 6, FALSE);
1309 u_int32_t len = (u_int32_t)SvIV(*svp) ;
1310 status = dbp->set_re_len(dbp, len) ;
1315 status = dbp->set_re_source(dbp, name) ;
1319 svp = hv_fetch(action, "bfname", 6, FALSE);
1320 if (svp && SvOK(*svp)) {
1321 char * ptr = SvPV(*svp,n_a) ;
1322 name = (char*) n_a ? ptr : NULL ;
1328 status = dbp->set_flags(dbp, DB_RENUMBER) ;
1331 (void)dbp->set_flags(dbp, flags) ;
1336 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1343 /* Map 1.x flags to 3.x flags */
1344 if ((flags & O_CREAT) == O_CREAT)
1345 Flags |= DB_CREATE ;
1348 if (flags == O_RDONLY)
1350 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1352 Flags |= DB_RDONLY ;
1355 if ((flags & O_TRUNC) == O_TRUNC)
1356 Flags |= DB_TRUNCATE ;
1359 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1361 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1364 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1366 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1369 RETVAL->dbp = NULL ;
1375 #endif /* Berkeley DB Version > 2 */
1377 } /* ParseOpenInfo */
1381 #ifdef CAN_PROTOTYPE
1382 constant(char *name, int arg)
1394 if (strEQ(name, "BTREEMAGIC"))
1400 if (strEQ(name, "BTREEVERSION"))
1402 return BTREEVERSION;
1410 if (strEQ(name, "DB_LOCK"))
1416 if (strEQ(name, "DB_SHMEM"))
1422 if (strEQ(name, "DB_TXN"))
1436 if (strEQ(name, "HASHMAGIC"))
1442 if (strEQ(name, "HASHVERSION"))
1458 if (strEQ(name, "MAX_PAGE_NUMBER"))
1459 #ifdef MAX_PAGE_NUMBER
1460 return (U32)MAX_PAGE_NUMBER;
1464 if (strEQ(name, "MAX_PAGE_OFFSET"))
1465 #ifdef MAX_PAGE_OFFSET
1466 return MAX_PAGE_OFFSET;
1470 if (strEQ(name, "MAX_REC_NUMBER"))
1471 #ifdef MAX_REC_NUMBER
1472 return (U32)MAX_REC_NUMBER;
1486 if (strEQ(name, "RET_ERROR"))
1492 if (strEQ(name, "RET_SPECIAL"))
1498 if (strEQ(name, "RET_SUCCESS"))
1504 if (strEQ(name, "R_CURSOR"))
1510 if (strEQ(name, "R_DUP"))
1516 if (strEQ(name, "R_FIRST"))
1522 if (strEQ(name, "R_FIXEDLEN"))
1528 if (strEQ(name, "R_IAFTER"))
1534 if (strEQ(name, "R_IBEFORE"))
1540 if (strEQ(name, "R_LAST"))
1546 if (strEQ(name, "R_NEXT"))
1552 if (strEQ(name, "R_NOKEY"))
1558 if (strEQ(name, "R_NOOVERWRITE"))
1559 #ifdef R_NOOVERWRITE
1560 return R_NOOVERWRITE;
1564 if (strEQ(name, "R_PREV"))
1570 if (strEQ(name, "R_RECNOSYNC"))
1576 if (strEQ(name, "R_SETCURSOR"))
1582 if (strEQ(name, "R_SNAPSHOT"))
1616 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1620 __getBerkeleyDBInfo() ;
1623 empty.data = &zero ;
1624 empty.size = sizeof(recno_t) ;
1634 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1641 char * name = (char *) NULL ;
1642 SV * sv = (SV *) NULL ;
1645 if (items >= 3 && SvOK(ST(2)))
1646 name = (char*) SvPV(ST(2), n_a) ;
1651 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1652 if (RETVAL->dbp == NULL)
1665 SvREFCNT_dec(db->hash) ;
1667 SvREFCNT_dec(db->compare) ;
1669 SvREFCNT_dec(db->prefix) ;
1670 #ifdef DBM_FILTERING
1671 if (db->filter_fetch_key)
1672 SvREFCNT_dec(db->filter_fetch_key) ;
1673 if (db->filter_store_key)
1674 SvREFCNT_dec(db->filter_store_key) ;
1675 if (db->filter_fetch_value)
1676 SvREFCNT_dec(db->filter_fetch_value) ;
1677 if (db->filter_store_value)
1678 SvREFCNT_dec(db->filter_store_value) ;
1679 #endif /* DBM_FILTERING */
1681 #ifdef DB_VERSION_MAJOR
1688 db_DELETE(db, key, flags=0)
1706 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1712 db_FETCH(db, key, flags=0)
1724 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1725 RETVAL = db_get(db, key, value, flags) ;
1726 ST(0) = sv_newmortal();
1727 OutputValue(ST(0), value)
1731 db_STORE(db, key, value, flags=0)
1753 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1754 ST(0) = sv_newmortal();
1755 OutputKey(ST(0), key) ;
1770 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1771 ST(0) = sv_newmortal();
1772 OutputKey(ST(0), key) ;
1776 # These would be nice for RECNO
1794 #ifdef DB_VERSION_MAJOR
1795 /* get the first value */
1796 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1801 for (i = items-1 ; i > 0 ; --i)
1803 value.data = SvPV(ST(i), n_a) ;
1807 key.size = sizeof(int) ;
1808 #ifdef DB_VERSION_MAJOR
1809 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1811 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1835 /* First get the final value */
1836 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1837 ST(0) = sv_newmortal();
1841 /* the call to del will trash value, so take a copy now */
1842 OutputValue(ST(0), value) ;
1843 RETVAL = db_del(db, key, R_CURSOR) ;
1845 sv_setsv(ST(0), &PL_sv_undef);
1863 /* get the first value */
1864 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1865 ST(0) = sv_newmortal();
1869 /* the call to del will trash value, so take a copy now */
1870 OutputValue(ST(0), value) ;
1871 RETVAL = db_del(db, key, R_CURSOR) ;
1873 sv_setsv (ST(0), &PL_sv_undef) ;
1894 /* Set the Cursor to the Last element */
1895 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1896 #ifndef DB_VERSION_MAJOR
1901 keyval = *(int*)key.data ;
1904 for (i = 1 ; i < items ; ++i)
1906 value.data = SvPV(ST(i), n_a) ;
1909 key.data = &keyval ;
1910 key.size = sizeof(int) ;
1911 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1923 ALIAS: FETCHSIZE = 1
1926 RETVAL = GetArrayLength(aTHX_ db) ;
1932 # Now provide an interface to the rest of the DB functionality
1936 db_del(db, key, flags=0)
1942 RETVAL = db_del(db, key, flags) ;
1943 #ifdef DB_VERSION_MAJOR
1946 else if (RETVAL == DB_NOTFOUND)
1954 db_get(db, key, value, flags=0)
1962 RETVAL = db_get(db, key, value, flags) ;
1963 #ifdef DB_VERSION_MAJOR
1966 else if (RETVAL == DB_NOTFOUND)
1974 db_put(db, key, value, flags=0)
1981 RETVAL = db_put(db, key, value, flags) ;
1982 #ifdef DB_VERSION_MAJOR
1985 else if (RETVAL == DB_KEYEXIST)
1990 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1998 #ifdef DB_VERSION_MAJOR
2000 status = (db->in_memory
2002 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
2006 RETVAL = (db->in_memory
2008 : ((db->dbp)->fd)(db->dbp) ) ;
2014 db_sync(db, flags=0)
2019 RETVAL = db_sync(db, flags) ;
2020 #ifdef DB_VERSION_MAJOR
2029 db_seq(db, key, value, flags)
2037 RETVAL = db_seq(db, key, value, flags);
2038 #ifdef DB_VERSION_MAJOR
2041 else if (RETVAL == DB_NOTFOUND)
2049 #ifdef DBM_FILTERING
2051 #define setFilter(type) \
2054 RETVAL = sv_mortalcopy(db->type) ; \
2056 if (db->type && (code == &PL_sv_undef)) { \
2057 SvREFCNT_dec(db->type) ; \
2062 sv_setsv(db->type, code) ; \
2064 db->type = newSVsv(code) ; \
2070 filter_fetch_key(db, code)
2073 SV * RETVAL = &PL_sv_undef ;
2075 setFilter(filter_fetch_key) ;
2078 filter_store_key(db, code)
2081 SV * RETVAL = &PL_sv_undef ;
2083 setFilter(filter_store_key) ;
2086 filter_fetch_value(db, code)
2089 SV * RETVAL = &PL_sv_undef ;
2091 setFilter(filter_fetch_value) ;
2094 filter_store_value(db, code)
2097 SV * RETVAL = &PL_sv_undef ;
2099 setFilter(filter_store_value) ;
2101 #endif /* DBM_FILTERING */