3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 27th April 2000
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2000 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
94 # include "patchlevel.h"
95 # define PERL_REVISION 5
96 # define PERL_VERSION PATCHLEVEL
97 # define PERL_SUBVERSION SUBVERSION
100 #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
102 # define PL_sv_undef sv_undef
107 /* DEFSV appears first in 5.004_56 */
109 # define DEFSV GvSV(defgv)
112 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
113 * shortly #included by the <db.h>) __attribute__ to the possibly
114 * already defined __attribute__, for example by GNUC or by Perl. */
118 /* If Perl has been compiled with Threads support,the symbol op will
119 be defined here. This clashes with a field name in db.h, so get rid of it.
139 # define newSVpvn(a,b) newSVpv(a,b)
145 #define DBM_FILTERING
148 # define Trace(x) printf x
154 #define DBT_clear(x) Zero(&x, 1, DBT) ;
156 #ifdef DB_VERSION_MAJOR
158 #if DB_VERSION_MAJOR == 2
159 # define BERKELEY_DB_1_OR_2
162 /* map version 2 features & constants onto their version 1 equivalent */
167 #define DB_Prefix_t size_t
172 #define DB_Hash_t u_int32_t
174 /* DBTYPE stays the same */
175 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
176 #if DB_VERSION_MAJOR == 2
177 typedef DB_INFO INFO ;
178 #else /* DB_VERSION_MAJOR > 2 */
179 # define DB_FIXEDLEN (0x8000)
180 #endif /* DB_VERSION_MAJOR == 2 */
182 /* version 2 has db_recno_t in place of recno_t */
183 typedef db_recno_t recno_t;
186 #define R_CURSOR DB_SET_RANGE
187 #define R_FIRST DB_FIRST
188 #define R_IAFTER DB_AFTER
189 #define R_IBEFORE DB_BEFORE
190 #define R_LAST DB_LAST
191 #define R_NEXT DB_NEXT
192 #define R_NOOVERWRITE DB_NOOVERWRITE
193 #define R_PREV DB_PREV
195 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
196 # define R_SETCURSOR 0x800000
198 # define R_SETCURSOR (-100)
201 #define R_RECNOSYNC 0
202 #define R_FIXEDLEN DB_FIXEDLEN
206 #define db_HA_hash h_hash
207 #define db_HA_ffactor h_ffactor
208 #define db_HA_nelem h_nelem
209 #define db_HA_bsize db_pagesize
210 #define db_HA_cachesize db_cachesize
211 #define db_HA_lorder db_lorder
213 #define db_BT_compare bt_compare
214 #define db_BT_prefix bt_prefix
215 #define db_BT_flags flags
216 #define db_BT_psize db_pagesize
217 #define db_BT_cachesize db_cachesize
218 #define db_BT_lorder db_lorder
219 #define db_BT_maxkeypage
220 #define db_BT_minkeypage
223 #define db_RE_reclen re_len
224 #define db_RE_flags flags
225 #define db_RE_bval re_pad
226 #define db_RE_bfname re_source
227 #define db_RE_psize db_pagesize
228 #define db_RE_cachesize db_cachesize
229 #define db_RE_lorder db_lorder
233 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
236 #define DBT_flags(x) x.flags = 0
237 #define DB_flags(x, v) x |= v
239 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
240 # define flagSet(flags, bitmask) ((flags) & (bitmask))
242 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
245 #else /* db version 1.x */
247 #define BERKELEY_DB_1_OR_2
260 # define DB_Prefix_t mDB_Prefix_t
267 # define DB_Hash_t mDB_Hash_t
270 #define db_HA_hash hash.hash
271 #define db_HA_ffactor hash.ffactor
272 #define db_HA_nelem hash.nelem
273 #define db_HA_bsize hash.bsize
274 #define db_HA_cachesize hash.cachesize
275 #define db_HA_lorder hash.lorder
277 #define db_BT_compare btree.compare
278 #define db_BT_prefix btree.prefix
279 #define db_BT_flags btree.flags
280 #define db_BT_psize btree.psize
281 #define db_BT_cachesize btree.cachesize
282 #define db_BT_lorder btree.lorder
283 #define db_BT_maxkeypage btree.maxkeypage
284 #define db_BT_minkeypage btree.minkeypage
286 #define db_RE_reclen recno.reclen
287 #define db_RE_flags recno.flags
288 #define db_RE_bval recno.bval
289 #define db_RE_bfname recno.bfname
290 #define db_RE_psize recno.psize
291 #define db_RE_cachesize recno.cachesize
292 #define db_RE_lorder recno.lorder
296 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
298 #define DB_flags(x, v)
299 #define flagSet(flags, bitmask) ((flags) & (bitmask))
301 #endif /* db version 1 */
305 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
306 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
307 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
309 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
310 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
312 #ifdef DB_VERSION_MAJOR
313 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
314 (db->dbp->close)(db->dbp, 0) )
315 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
316 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
317 ? ((db->cursor)->c_del)(db->cursor, 0) \
318 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
320 #else /* ! DB_VERSION_MAJOR */
322 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
323 #define db_close(db) ((db->dbp)->close)(db->dbp)
324 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
325 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
327 #endif /* ! DB_VERSION_MAJOR */
330 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
339 #ifdef BERKELEY_DB_1_OR_2
342 #ifdef DB_VERSION_MAJOR
346 SV * filter_fetch_key ;
347 SV * filter_store_key ;
348 SV * filter_fetch_value ;
349 SV * filter_store_value ;
351 #endif /* DBM_FILTERING */
355 typedef DB_File_type * DB_File ;
360 #define ckFilter(arg,type,name) \
363 /* printf("filtering %s\n", name) ;*/ \
365 croak("recursion detected in %s", name) ; \
366 db->filtering = TRUE ; \
367 save_defsv = newSVsv(DEFSV) ; \
368 sv_setsv(DEFSV, arg) ; \
370 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
371 sv_setsv(arg, DEFSV) ; \
372 sv_setsv(DEFSV, save_defsv) ; \
373 SvREFCNT_dec(save_defsv) ; \
374 db->filtering = FALSE ; \
375 /*printf("end of filtering %s\n", name) ;*/ \
380 #define ckFilter(arg,type, name)
382 #endif /* DBM_FILTERING */
384 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
386 #define OutputValue(arg, name) \
387 { if (RETVAL == 0) { \
388 my_sv_setpvn(arg, name.data, name.size) ; \
389 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
393 #define OutputKey(arg, name) \
396 if (db->type != DB_RECNO) { \
397 my_sv_setpvn(arg, name.data, name.size); \
400 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
401 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
406 /* Internal Global Data */
407 static recno_t Value ;
408 static recno_t zero = 0 ;
409 static DB_File CurrentDB ;
410 static DBTKEY empty ;
412 #ifdef DB_VERSION_MAJOR
416 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
418 db_put(db, key, value, flags)
427 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
431 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
432 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
434 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
438 memset(&l_key, 0, sizeof(l_key));
439 l_key.data = key.data;
440 l_key.size = key.size;
441 memset(&l_value, 0, sizeof(l_value));
442 l_value.data = value.data;
443 l_value.size = value.size;
445 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
446 (void)temp_cursor->c_close(temp_cursor);
450 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
451 (void)temp_cursor->c_close(temp_cursor);
457 if (flagSet(flags, R_CURSOR)) {
458 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
461 if (flagSet(flags, R_SETCURSOR)) {
462 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
464 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
468 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
472 #endif /* DB_VERSION_MAJOR */
477 btree_compare(const DBT *key1, const DBT *key2)
479 btree_compare(key1, key2)
488 void * data1, * data2 ;
496 /* As newSVpv will assume that the data pointer is a null terminated C
497 string if the size parameter is 0, make sure that data points to an
498 empty string if the length is 0
511 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
512 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
515 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
520 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
533 btree_prefix(const DBT *key1, const DBT *key2)
535 btree_prefix(key1, key2)
544 void * data1, * data2 ;
552 /* As newSVpv will assume that the data pointer is a null terminated C
553 string if the size parameter is 0, make sure that data points to an
554 empty string if the length is 0
567 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
568 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
571 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
576 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
587 #ifdef BERKELEY_DB_1_OR_2
588 # define HASH_CB_SIZE_TYPE size_t
590 # define HASH_CB_SIZE_TYPE u_int32_t
595 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
599 HASH_CB_SIZE_TYPE size ;
614 /* DGH - Next two lines added to fix corrupted stack problem */
620 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
623 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
628 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
640 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
644 PrintHash(INFO *hash)
650 printf ("HASH Info\n") ;
651 printf (" hash = %s\n",
652 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
653 printf (" bsize = %d\n", hash->db_HA_bsize) ;
654 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
655 printf (" nelem = %d\n", hash->db_HA_nelem) ;
656 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
657 printf (" lorder = %d\n", hash->db_HA_lorder) ;
663 PrintRecno(INFO *recno)
669 printf ("RECNO Info\n") ;
670 printf (" flags = %d\n", recno->db_RE_flags) ;
671 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
672 printf (" psize = %d\n", recno->db_RE_psize) ;
673 printf (" lorder = %d\n", recno->db_RE_lorder) ;
674 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
675 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
676 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
681 PrintBtree(INFO *btree)
687 printf ("BTREE Info\n") ;
688 printf (" compare = %s\n",
689 (btree->db_BT_compare ? "redefined" : "default")) ;
690 printf (" prefix = %s\n",
691 (btree->db_BT_prefix ? "redefined" : "default")) ;
692 printf (" flags = %d\n", btree->db_BT_flags) ;
693 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
694 printf (" psize = %d\n", btree->db_BT_psize) ;
695 #ifndef DB_VERSION_MAJOR
696 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
697 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
699 printf (" lorder = %d\n", btree->db_BT_lorder) ;
704 #define PrintRecno(recno)
705 #define PrintHash(hash)
706 #define PrintBtree(btree)
713 GetArrayLength(pTHX_ DB_File db)
725 RETVAL = do_SEQ(db, key, value, R_LAST) ;
727 RETVAL = *(I32 *)key.data ;
728 else /* No key means empty file */
731 return ((I32)RETVAL) ;
736 GetRecnoKey(pTHX_ DB_File db, I32 value)
738 GetRecnoKey(db, value)
744 /* Get the length of the array */
745 I32 length = GetArrayLength(aTHX_ db) ;
747 /* check for attempt to write before start of array */
748 if (length + value + 1 <= 0)
749 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
751 value = length + value + 1 ;
762 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
764 ParseOpenInfo(isHASH, name, flags, mode, sv)
773 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
777 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
778 void * openinfo = NULL ;
779 INFO * info = &RETVAL->info ;
782 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
783 Zero(RETVAL, 1, DB_File_type) ;
785 /* Default to HASH */
787 RETVAL->filtering = 0 ;
788 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
789 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
790 #endif /* DBM_FILTERING */
791 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
792 RETVAL->type = DB_HASH ;
794 /* DGH - Next line added to avoid SEGV on existing hash DB */
797 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
798 RETVAL->in_memory = (name == NULL) ;
803 croak ("type parameter is not a reference") ;
805 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
806 if (svp && SvOK(*svp))
807 action = (HV*) SvRV(*svp) ;
809 croak("internal error") ;
811 if (sv_isa(sv, "DB_File::HASHINFO"))
815 croak("DB_File can only tie an associative array to a DB_HASH database") ;
817 RETVAL->type = DB_HASH ;
818 openinfo = (void*)info ;
820 svp = hv_fetch(action, "hash", 4, FALSE);
822 if (svp && SvOK(*svp))
824 info->db_HA_hash = hash_cb ;
825 RETVAL->hash = newSVsv(*svp) ;
828 info->db_HA_hash = NULL ;
830 svp = hv_fetch(action, "ffactor", 7, FALSE);
831 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
833 svp = hv_fetch(action, "nelem", 5, FALSE);
834 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
836 svp = hv_fetch(action, "bsize", 5, FALSE);
837 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
839 svp = hv_fetch(action, "cachesize", 9, FALSE);
840 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
842 svp = hv_fetch(action, "lorder", 6, FALSE);
843 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
847 else if (sv_isa(sv, "DB_File::BTREEINFO"))
850 croak("DB_File can only tie an associative array to a DB_BTREE database");
852 RETVAL->type = DB_BTREE ;
853 openinfo = (void*)info ;
855 svp = hv_fetch(action, "compare", 7, FALSE);
856 if (svp && SvOK(*svp))
858 info->db_BT_compare = btree_compare ;
859 RETVAL->compare = newSVsv(*svp) ;
862 info->db_BT_compare = NULL ;
864 svp = hv_fetch(action, "prefix", 6, FALSE);
865 if (svp && SvOK(*svp))
867 info->db_BT_prefix = btree_prefix ;
868 RETVAL->prefix = newSVsv(*svp) ;
871 info->db_BT_prefix = NULL ;
873 svp = hv_fetch(action, "flags", 5, FALSE);
874 info->db_BT_flags = svp ? SvIV(*svp) : 0;
876 svp = hv_fetch(action, "cachesize", 9, FALSE);
877 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
879 #ifndef DB_VERSION_MAJOR
880 svp = hv_fetch(action, "minkeypage", 10, FALSE);
881 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
883 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
884 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
887 svp = hv_fetch(action, "psize", 5, FALSE);
888 info->db_BT_psize = svp ? SvIV(*svp) : 0;
890 svp = hv_fetch(action, "lorder", 6, FALSE);
891 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
896 else if (sv_isa(sv, "DB_File::RECNOINFO"))
899 croak("DB_File can only tie an array to a DB_RECNO database");
901 RETVAL->type = DB_RECNO ;
902 openinfo = (void *)info ;
904 info->db_RE_flags = 0 ;
906 svp = hv_fetch(action, "flags", 5, FALSE);
907 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
909 svp = hv_fetch(action, "reclen", 6, FALSE);
910 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
912 svp = hv_fetch(action, "cachesize", 9, FALSE);
913 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
915 svp = hv_fetch(action, "psize", 5, FALSE);
916 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
918 svp = hv_fetch(action, "lorder", 6, FALSE);
919 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
921 #ifdef DB_VERSION_MAJOR
922 info->re_source = name ;
925 svp = hv_fetch(action, "bfname", 6, FALSE);
926 if (svp && SvOK(*svp)) {
927 char * ptr = SvPV(*svp,n_a) ;
928 #ifdef DB_VERSION_MAJOR
929 name = (char*) n_a ? ptr : NULL ;
931 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
935 #ifdef DB_VERSION_MAJOR
938 info->db_RE_bfname = NULL ;
941 svp = hv_fetch(action, "bval", 4, FALSE);
942 #ifdef DB_VERSION_MAJOR
943 if (svp && SvOK(*svp))
947 value = (int)*SvPV(*svp, n_a) ;
951 if (info->flags & DB_FIXEDLEN) {
952 info->re_pad = value ;
953 info->flags |= DB_PAD ;
956 info->re_delim = value ;
957 info->flags |= DB_DELIMITER ;
962 if (svp && SvOK(*svp))
965 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
967 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
968 DB_flags(info->flags, DB_DELIMITER) ;
973 if (info->db_RE_flags & R_FIXEDLEN)
974 info->db_RE_bval = (u_char) ' ' ;
976 info->db_RE_bval = (u_char) '\n' ;
977 DB_flags(info->flags, DB_DELIMITER) ;
982 info->flags |= DB_RENUMBER ;
988 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
992 /* OS2 Specific Code */
999 #ifdef DB_VERSION_MAJOR
1005 /* Map 1.x flags to 2.x flags */
1006 if ((flags & O_CREAT) == O_CREAT)
1007 Flags |= DB_CREATE ;
1010 if (flags == O_RDONLY)
1012 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1014 Flags |= DB_RDONLY ;
1017 if ((flags & O_TRUNC) == O_TRUNC)
1018 Flags |= DB_TRUNCATE ;
1021 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1023 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1024 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1026 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1031 RETVAL->dbp = NULL ;
1036 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1037 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1039 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1040 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1046 #else /* Berkeley DB Version > 2 */
1050 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1055 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1056 Zero(RETVAL, 1, DB_File_type) ;
1058 /* Default to HASH */
1059 #ifdef DBM_FILTERING
1060 RETVAL->filtering = 0 ;
1061 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1062 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1063 #endif /* DBM_FILTERING */
1064 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1065 RETVAL->type = DB_HASH ;
1067 /* DGH - Next line added to avoid SEGV on existing hash DB */
1070 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1071 RETVAL->in_memory = (name == NULL) ;
1073 status = db_create(&RETVAL->dbp, NULL,0) ;
1074 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1076 RETVAL->dbp = NULL ;
1084 croak ("type parameter is not a reference") ;
1086 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1087 if (svp && SvOK(*svp))
1088 action = (HV*) SvRV(*svp) ;
1090 croak("internal error") ;
1092 if (sv_isa(sv, "DB_File::HASHINFO"))
1096 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1098 RETVAL->type = DB_HASH ;
1100 svp = hv_fetch(action, "hash", 4, FALSE);
1102 if (svp && SvOK(*svp))
1104 (void)dbp->set_h_hash(dbp, hash_cb) ;
1105 RETVAL->hash = newSVsv(*svp) ;
1108 svp = hv_fetch(action, "ffactor", 7, FALSE);
1110 (void)dbp->set_h_ffactor(dbp, SvIV(*svp)) ;
1112 svp = hv_fetch(action, "nelem", 5, FALSE);
1114 (void)dbp->set_h_nelem(dbp, SvIV(*svp)) ;
1116 svp = hv_fetch(action, "bsize", 5, FALSE);
1118 (void)dbp->set_pagesize(dbp, SvIV(*svp));
1120 svp = hv_fetch(action, "cachesize", 9, FALSE);
1122 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1124 svp = hv_fetch(action, "lorder", 6, FALSE);
1126 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1130 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1133 croak("DB_File can only tie an associative array to a DB_BTREE database");
1135 RETVAL->type = DB_BTREE ;
1137 svp = hv_fetch(action, "compare", 7, FALSE);
1138 if (svp && SvOK(*svp))
1140 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1141 RETVAL->compare = newSVsv(*svp) ;
1144 svp = hv_fetch(action, "prefix", 6, FALSE);
1145 if (svp && SvOK(*svp))
1147 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1148 RETVAL->prefix = newSVsv(*svp) ;
1151 svp = hv_fetch(action, "flags", 5, FALSE);
1153 (void)dbp->set_flags(dbp, SvIV(*svp)) ;
1155 svp = hv_fetch(action, "cachesize", 9, FALSE);
1157 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1159 svp = hv_fetch(action, "psize", 5, FALSE);
1161 (void)dbp->set_pagesize(dbp, SvIV(*svp)) ;
1163 svp = hv_fetch(action, "lorder", 6, FALSE);
1165 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1170 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1175 croak("DB_File can only tie an array to a DB_RECNO database");
1177 RETVAL->type = DB_RECNO ;
1179 svp = hv_fetch(action, "flags", 5, FALSE);
1181 int flags = SvIV(*svp) ;
1182 /* remove FIXDLEN, if present */
1183 if (flags & DB_FIXEDLEN) {
1185 flags &= ~DB_FIXEDLEN ;
1189 svp = hv_fetch(action, "cachesize", 9, FALSE);
1191 status = dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1194 svp = hv_fetch(action, "psize", 5, FALSE);
1196 status = dbp->set_pagesize(dbp, SvIV(*svp)) ;
1199 svp = hv_fetch(action, "lorder", 6, FALSE);
1201 status = dbp->set_lorder(dbp, SvIV(*svp)) ;
1204 svp = hv_fetch(action, "bval", 4, FALSE);
1205 if (svp && SvOK(*svp))
1209 value = (int)*SvPV(*svp, n_a) ;
1211 value = SvIV(*svp) ;
1214 status = dbp->set_re_pad(dbp, value) ;
1217 status = dbp->set_re_delim(dbp, value) ;
1223 svp = hv_fetch(action, "reclen", 6, FALSE);
1225 u_int32_t len = (u_int32_t)SvIV(*svp) ;
1226 status = dbp->set_re_len(dbp, len) ;
1231 status = dbp->set_re_source(dbp, name) ;
1235 svp = hv_fetch(action, "bfname", 6, FALSE);
1236 if (svp && SvOK(*svp)) {
1237 char * ptr = SvPV(*svp,n_a) ;
1238 name = (char*) n_a ? ptr : NULL ;
1244 status = dbp->set_flags(dbp, DB_RENUMBER) ;
1247 (void)dbp->set_flags(dbp, flags) ;
1252 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1259 /* Map 1.x flags to 3.x flags */
1260 if ((flags & O_CREAT) == O_CREAT)
1261 Flags |= DB_CREATE ;
1264 if (flags == O_RDONLY)
1266 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1268 Flags |= DB_RDONLY ;
1271 if ((flags & O_TRUNC) == O_TRUNC)
1272 Flags |= DB_TRUNCATE ;
1275 status = RETVAL->dbp->open(RETVAL->dbp, name, NULL, RETVAL->type,
1277 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1280 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1282 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1285 RETVAL->dbp = NULL ;
1291 #endif /* Berkeley DB Version > 2 */
1293 } /* ParseOpenInfo */
1297 #ifdef CAN_PROTOTYPE
1298 constant(char *name, int arg)
1310 if (strEQ(name, "BTREEMAGIC"))
1316 if (strEQ(name, "BTREEVERSION"))
1318 return BTREEVERSION;
1326 if (strEQ(name, "DB_LOCK"))
1332 if (strEQ(name, "DB_SHMEM"))
1338 if (strEQ(name, "DB_TXN"))
1352 if (strEQ(name, "HASHMAGIC"))
1358 if (strEQ(name, "HASHVERSION"))
1374 if (strEQ(name, "MAX_PAGE_NUMBER"))
1375 #ifdef MAX_PAGE_NUMBER
1376 return (U32)MAX_PAGE_NUMBER;
1380 if (strEQ(name, "MAX_PAGE_OFFSET"))
1381 #ifdef MAX_PAGE_OFFSET
1382 return MAX_PAGE_OFFSET;
1386 if (strEQ(name, "MAX_REC_NUMBER"))
1387 #ifdef MAX_REC_NUMBER
1388 return (U32)MAX_REC_NUMBER;
1402 if (strEQ(name, "RET_ERROR"))
1408 if (strEQ(name, "RET_SPECIAL"))
1414 if (strEQ(name, "RET_SUCCESS"))
1420 if (strEQ(name, "R_CURSOR"))
1426 if (strEQ(name, "R_DUP"))
1432 if (strEQ(name, "R_FIRST"))
1438 if (strEQ(name, "R_FIXEDLEN"))
1444 if (strEQ(name, "R_IAFTER"))
1450 if (strEQ(name, "R_IBEFORE"))
1456 if (strEQ(name, "R_LAST"))
1462 if (strEQ(name, "R_NEXT"))
1468 if (strEQ(name, "R_NOKEY"))
1474 if (strEQ(name, "R_NOOVERWRITE"))
1475 #ifdef R_NOOVERWRITE
1476 return R_NOOVERWRITE;
1480 if (strEQ(name, "R_PREV"))
1486 if (strEQ(name, "R_RECNOSYNC"))
1492 if (strEQ(name, "R_SETCURSOR"))
1498 if (strEQ(name, "R_SNAPSHOT"))
1532 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1536 __getBerkeleyDBInfo() ;
1539 empty.data = &zero ;
1540 empty.size = sizeof(recno_t) ;
1550 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1557 char * name = (char *) NULL ;
1558 SV * sv = (SV *) NULL ;
1561 if (items >= 3 && SvOK(ST(2)))
1562 name = (char*) SvPV(ST(2), n_a) ;
1567 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1568 if (RETVAL->dbp == NULL)
1581 SvREFCNT_dec(db->hash) ;
1583 SvREFCNT_dec(db->compare) ;
1585 SvREFCNT_dec(db->prefix) ;
1586 #ifdef DBM_FILTERING
1587 if (db->filter_fetch_key)
1588 SvREFCNT_dec(db->filter_fetch_key) ;
1589 if (db->filter_store_key)
1590 SvREFCNT_dec(db->filter_store_key) ;
1591 if (db->filter_fetch_value)
1592 SvREFCNT_dec(db->filter_fetch_value) ;
1593 if (db->filter_store_value)
1594 SvREFCNT_dec(db->filter_store_value) ;
1595 #endif /* DBM_FILTERING */
1597 #ifdef DB_VERSION_MAJOR
1604 db_DELETE(db, key, flags=0)
1622 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1628 db_FETCH(db, key, flags=0)
1638 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1639 RETVAL = db_get(db, key, value, flags) ;
1640 ST(0) = sv_newmortal();
1641 OutputValue(ST(0), value)
1645 db_STORE(db, key, value, flags=0)
1665 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1666 ST(0) = sv_newmortal();
1667 OutputKey(ST(0), key) ;
1680 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1681 ST(0) = sv_newmortal();
1682 OutputKey(ST(0), key) ;
1686 # These would be nice for RECNO
1705 #ifdef DB_VERSION_MAJOR
1706 /* get the first value */
1707 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1712 for (i = items-1 ; i > 0 ; --i)
1714 value.data = SvPV(ST(i), n_a) ;
1718 key.size = sizeof(int) ;
1719 #ifdef DB_VERSION_MAJOR
1720 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1722 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1744 /* First get the final value */
1745 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1746 ST(0) = sv_newmortal();
1750 /* the call to del will trash value, so take a copy now */
1751 OutputValue(ST(0), value) ;
1752 RETVAL = db_del(db, key, R_CURSOR) ;
1754 sv_setsv(ST(0), &PL_sv_undef);
1770 /* get the first value */
1771 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1772 ST(0) = sv_newmortal();
1776 /* the call to del will trash value, so take a copy now */
1777 OutputValue(ST(0), value) ;
1778 RETVAL = db_del(db, key, R_CURSOR) ;
1780 sv_setsv (ST(0), &PL_sv_undef) ;
1801 /* Set the Cursor to the Last element */
1802 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1803 #ifndef DB_VERSION_MAJOR
1808 keyval = *(int*)key.data ;
1811 for (i = 1 ; i < items ; ++i)
1813 value.data = SvPV(ST(i), n_a) ;
1816 key.data = &keyval ;
1817 key.size = sizeof(int) ;
1818 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1830 ALIAS: FETCHSIZE = 1
1833 RETVAL = GetArrayLength(aTHX_ db) ;
1839 # Now provide an interface to the rest of the DB functionality
1843 db_del(db, key, flags=0)
1849 RETVAL = db_del(db, key, flags) ;
1850 #ifdef DB_VERSION_MAJOR
1853 else if (RETVAL == DB_NOTFOUND)
1861 db_get(db, key, value, flags=0)
1869 RETVAL = db_get(db, key, value, flags) ;
1870 #ifdef DB_VERSION_MAJOR
1873 else if (RETVAL == DB_NOTFOUND)
1881 db_put(db, key, value, flags=0)
1888 RETVAL = db_put(db, key, value, flags) ;
1889 #ifdef DB_VERSION_MAJOR
1892 else if (RETVAL == DB_KEYEXIST)
1897 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1905 #ifdef DB_VERSION_MAJOR
1907 status = (db->in_memory
1909 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1913 RETVAL = (db->in_memory
1915 : ((db->dbp)->fd)(db->dbp) ) ;
1921 db_sync(db, flags=0)
1926 RETVAL = db_sync(db, flags) ;
1927 #ifdef DB_VERSION_MAJOR
1936 db_seq(db, key, value, flags)
1944 RETVAL = db_seq(db, key, value, flags);
1945 #ifdef DB_VERSION_MAJOR
1948 else if (RETVAL == DB_NOTFOUND)
1956 #ifdef DBM_FILTERING
1958 #define setFilter(type) \
1961 RETVAL = sv_mortalcopy(db->type) ; \
1963 if (db->type && (code == &PL_sv_undef)) { \
1964 SvREFCNT_dec(db->type) ; \
1969 sv_setsv(db->type, code) ; \
1971 db->type = newSVsv(code) ; \
1977 filter_fetch_key(db, code)
1980 SV * RETVAL = &PL_sv_undef ;
1982 setFilter(filter_fetch_key) ;
1985 filter_store_key(db, code)
1988 SV * RETVAL = &PL_sv_undef ;
1990 setFilter(filter_store_key) ;
1993 filter_fetch_value(db, code)
1996 SV * RETVAL = &PL_sv_undef ;
1998 setFilter(filter_fetch_value) ;
2001 filter_store_value(db, code)
2004 SV * RETVAL = &PL_sv_undef ;
2006 setFilter(filter_store_value) ;
2008 #endif /* DBM_FILTERING */