3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <pmqs@cpan.org>
6 last modified 7th August 2004
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2004 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.
98 1.800 - Moved backward compatability code into ppport.h.
99 Use the new constants code.
100 1.801 - No change to DB_File.xs
101 1.802 - No change to DB_File.xs
102 1.803 - FETCH, STORE & DELETE don't map the flags parameter
103 into the equivalent Berkeley DB function anymore.
105 1.805 - recursion detection added to the callbacks
106 Support for 4.1.X added.
107 Filter code can now cope with read-only $_
108 1.806 - recursion detection beefed up.
110 1.808 - leak fixed in ParseOpenInfo
116 #define PERL_NO_GET_CONTEXT
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__
143 /* Wall starts with 5.7.x */
145 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
147 /* Since we dropped the gccish definition of __attribute__ we will want
148 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
149 * all this means that we can't do attribute checking on the DB_File,
151 # ifndef DB_VERSION_MAJOR
154 # define dNOOP extern int Perl___notused
156 /* Ditto for dXSARGS. */
160 I32 ax = mark - PL_stack_base + 1; \
161 I32 items = sp - mark
165 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
167 # define dXSI32 dNOOP
169 #endif /* Perl >= 5.7 */
176 # define Trace(x) printf x
182 #define DBT_clear(x) Zero(&x, 1, DBT) ;
184 #ifdef DB_VERSION_MAJOR
186 #if DB_VERSION_MAJOR == 2
187 # define BERKELEY_DB_1_OR_2
190 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
191 # define AT_LEAST_DB_3_2
194 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
195 # define AT_LEAST_DB_4_1
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, 0)
343 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
344 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
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->aborted && ( 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->aborted && ((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)
380 #ifdef BERKELEY_DB_1_OR_2
383 #ifdef DB_VERSION_MAJOR
386 SV * filter_fetch_key ;
387 SV * filter_store_key ;
388 SV * filter_fetch_value ;
389 SV * filter_store_value ;
394 typedef DB_File_type * DB_File ;
397 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
399 #define OutputValue(arg, name) \
400 { if (RETVAL == 0) { \
402 my_sv_setpvn(arg, name.data, name.size) ; \
406 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
410 #define OutputKey(arg, name) \
414 if (db->type != DB_RECNO) { \
415 my_sv_setpvn(arg, name.data, name.size); \
418 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
422 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
426 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
429 extern void __getBerkeleyDBInfo(void);
432 /* Internal Global Data */
434 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
445 #define Value (MY_CXT.x_Value)
446 #define zero (MY_CXT.x_zero)
447 #define CurrentDB (MY_CXT.x_CurrentDB)
448 #define empty (MY_CXT.x_empty)
450 #define ERR_BUFF "DB_File::Error"
452 #ifdef DB_VERSION_MAJOR
456 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
458 db_put(db, key, value, flags)
467 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
471 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
472 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
474 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
478 memset(&l_key, 0, sizeof(l_key));
479 l_key.data = key.data;
480 l_key.size = key.size;
481 memset(&l_value, 0, sizeof(l_value));
482 l_value.data = value.data;
483 l_value.size = value.size;
485 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
486 (void)temp_cursor->c_close(temp_cursor);
490 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
491 (void)temp_cursor->c_close(temp_cursor);
497 if (flagSet(flags, R_CURSOR)) {
498 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
501 if (flagSet(flags, R_SETCURSOR)) {
502 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
504 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
508 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
512 #endif /* DB_VERSION_MAJOR */
522 #ifdef AT_LEAST_DB_3_2
525 btree_compare(DB * db, const DBT *key1, const DBT *key2)
527 btree_compare(db, key1, key2)
531 #endif /* CAN_PROTOTYPE */
533 #else /* Berkeley DB < 3.2 */
536 btree_compare(const DBT *key1, const DBT *key2)
538 btree_compare(key1, key2)
551 void * data1, * data2 ;
556 if (CurrentDB->in_compare) {
558 croak ("DB_File btree_compare: recursion detected\n") ;
561 data1 = (char *) key1->data ;
562 data2 = (char *) key2->data ;
565 /* As newSVpv will assume that the data pointer is a null terminated C
566 string if the size parameter is 0, make sure that data points to an
567 empty string if the length is 0
578 CurrentDB->in_compare = FALSE;
579 SAVEINT(CurrentDB->in_compare);
580 CurrentDB->in_compare = TRUE;
584 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
585 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
588 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
594 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
608 #ifdef AT_LEAST_DB_3_2
611 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
613 btree_prefix(db, key1, key2)
619 #else /* Berkeley DB < 3.2 */
622 btree_prefix(const DBT *key1, const DBT *key2)
624 btree_prefix(key1, key2)
636 char * data1, * data2 ;
640 if (CurrentDB->in_prefix){
642 croak ("DB_File btree_prefix: recursion detected\n") ;
645 data1 = (char *) key1->data ;
646 data2 = (char *) key2->data ;
649 /* As newSVpv will assume that the data pointer is a null terminated C
650 string if the size parameter is 0, make sure that data points to an
651 empty string if the length is 0
662 CurrentDB->in_prefix = FALSE;
663 SAVEINT(CurrentDB->in_prefix);
664 CurrentDB->in_prefix = TRUE;
668 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
669 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
672 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
678 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
692 # define HASH_CB_SIZE_TYPE size_t
694 # define HASH_CB_SIZE_TYPE u_int32_t
698 #ifdef AT_LEAST_DB_3_2
701 hash_cb(DB * db, const void *data, u_int32_t size)
703 hash_cb(db, data, size)
706 HASH_CB_SIZE_TYPE size ;
709 #else /* Berkeley DB < 3.2 */
712 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
716 HASH_CB_SIZE_TYPE size ;
729 if (CurrentDB->in_hash){
731 croak ("DB_File hash callback: recursion detected\n") ;
739 /* DGH - Next two lines added to fix corrupted stack problem */
743 CurrentDB->in_hash = FALSE;
744 SAVEINT(CurrentDB->in_hash);
745 CurrentDB->in_hash = TRUE;
750 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
753 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
759 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
774 db_errcall_cb(const char * db_errpfx, char * buffer)
776 db_errcall_cb(db_errpfx, buffer)
777 const char * db_errpfx;
784 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
787 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
789 sv_setpv(sv, buffer) ;
794 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
798 PrintHash(INFO *hash)
804 printf ("HASH Info\n") ;
805 printf (" hash = %s\n",
806 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
807 printf (" bsize = %d\n", hash->db_HA_bsize) ;
808 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
809 printf (" nelem = %d\n", hash->db_HA_nelem) ;
810 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
811 printf (" lorder = %d\n", hash->db_HA_lorder) ;
817 PrintRecno(INFO *recno)
823 printf ("RECNO Info\n") ;
824 printf (" flags = %d\n", recno->db_RE_flags) ;
825 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
826 printf (" psize = %d\n", recno->db_RE_psize) ;
827 printf (" lorder = %d\n", recno->db_RE_lorder) ;
828 printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ;
829 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
830 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
835 PrintBtree(INFO *btree)
841 printf ("BTREE Info\n") ;
842 printf (" compare = %s\n",
843 (btree->db_BT_compare ? "redefined" : "default")) ;
844 printf (" prefix = %s\n",
845 (btree->db_BT_prefix ? "redefined" : "default")) ;
846 printf (" flags = %d\n", btree->db_BT_flags) ;
847 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
848 printf (" psize = %d\n", btree->db_BT_psize) ;
849 #ifndef DB_VERSION_MAJOR
850 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
851 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
853 printf (" lorder = %d\n", btree->db_BT_lorder) ;
858 #define PrintRecno(recno)
859 #define PrintHash(hash)
860 #define PrintBtree(btree)
867 GetArrayLength(pTHX_ DB_File db)
879 RETVAL = do_SEQ(db, key, value, R_LAST) ;
881 RETVAL = *(I32 *)key.data ;
882 else /* No key means empty file */
885 return ((I32)RETVAL) ;
890 GetRecnoKey(pTHX_ DB_File db, I32 value)
892 GetRecnoKey(db, value)
898 /* Get the length of the array */
899 I32 length = GetArrayLength(aTHX_ db) ;
901 /* check for attempt to write before start of array */
902 if (length + value + 1 <= 0) {
904 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
907 value = length + value + 1 ;
918 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
920 ParseOpenInfo(isHASH, name, flags, mode, sv)
929 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
933 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
934 void * openinfo = NULL ;
935 INFO * info = &RETVAL->info ;
940 printf("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n",
941 name, flags, mode, sv == NULL) ;
943 Zero(RETVAL, 1, DB_File_type) ;
945 /* Default to HASH */
946 RETVAL->filtering = 0 ;
947 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
948 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
949 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
950 RETVAL->type = DB_HASH ;
952 /* DGH - Next line added to avoid SEGV on existing hash DB */
955 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
956 RETVAL->in_memory = (name == NULL) ;
961 croak ("type parameter is not a reference") ;
963 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
964 if (svp && SvOK(*svp))
965 action = (HV*) SvRV(*svp) ;
967 croak("internal error") ;
969 if (sv_isa(sv, "DB_File::HASHINFO"))
973 croak("DB_File can only tie an associative array to a DB_HASH database") ;
975 RETVAL->type = DB_HASH ;
976 openinfo = (void*)info ;
978 svp = hv_fetch(action, "hash", 4, FALSE);
980 if (svp && SvOK(*svp))
982 info->db_HA_hash = hash_cb ;
983 RETVAL->hash = newSVsv(*svp) ;
986 info->db_HA_hash = NULL ;
988 svp = hv_fetch(action, "ffactor", 7, FALSE);
989 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
991 svp = hv_fetch(action, "nelem", 5, FALSE);
992 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
994 svp = hv_fetch(action, "bsize", 5, FALSE);
995 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
997 svp = hv_fetch(action, "cachesize", 9, FALSE);
998 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
1000 svp = hv_fetch(action, "lorder", 6, FALSE);
1001 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
1005 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1008 croak("DB_File can only tie an associative array to a DB_BTREE database");
1010 RETVAL->type = DB_BTREE ;
1011 openinfo = (void*)info ;
1013 svp = hv_fetch(action, "compare", 7, FALSE);
1014 if (svp && SvOK(*svp))
1016 info->db_BT_compare = btree_compare ;
1017 RETVAL->compare = newSVsv(*svp) ;
1020 info->db_BT_compare = NULL ;
1022 svp = hv_fetch(action, "prefix", 6, FALSE);
1023 if (svp && SvOK(*svp))
1025 info->db_BT_prefix = btree_prefix ;
1026 RETVAL->prefix = newSVsv(*svp) ;
1029 info->db_BT_prefix = NULL ;
1031 svp = hv_fetch(action, "flags", 5, FALSE);
1032 info->db_BT_flags = svp ? SvIV(*svp) : 0;
1034 svp = hv_fetch(action, "cachesize", 9, FALSE);
1035 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
1037 #ifndef DB_VERSION_MAJOR
1038 svp = hv_fetch(action, "minkeypage", 10, FALSE);
1039 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
1041 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
1042 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1045 svp = hv_fetch(action, "psize", 5, FALSE);
1046 info->db_BT_psize = svp ? SvIV(*svp) : 0;
1048 svp = hv_fetch(action, "lorder", 6, FALSE);
1049 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1054 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1057 croak("DB_File can only tie an array to a DB_RECNO database");
1059 RETVAL->type = DB_RECNO ;
1060 openinfo = (void *)info ;
1062 info->db_RE_flags = 0 ;
1064 svp = hv_fetch(action, "flags", 5, FALSE);
1065 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1067 svp = hv_fetch(action, "reclen", 6, FALSE);
1068 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1070 svp = hv_fetch(action, "cachesize", 9, FALSE);
1071 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1073 svp = hv_fetch(action, "psize", 5, FALSE);
1074 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1076 svp = hv_fetch(action, "lorder", 6, FALSE);
1077 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1079 #ifdef DB_VERSION_MAJOR
1080 info->re_source = name ;
1083 svp = hv_fetch(action, "bfname", 6, FALSE);
1084 if (svp && SvOK(*svp)) {
1085 char * ptr = SvPV(*svp,n_a) ;
1086 #ifdef DB_VERSION_MAJOR
1087 name = (char*) n_a ? ptr : NULL ;
1089 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1093 #ifdef DB_VERSION_MAJOR
1096 info->db_RE_bfname = NULL ;
1099 svp = hv_fetch(action, "bval", 4, FALSE);
1100 #ifdef DB_VERSION_MAJOR
1101 if (svp && SvOK(*svp))
1105 value = (int)*SvPV(*svp, n_a) ;
1107 value = SvIV(*svp) ;
1109 if (info->flags & DB_FIXEDLEN) {
1110 info->re_pad = value ;
1111 info->flags |= DB_PAD ;
1114 info->re_delim = value ;
1115 info->flags |= DB_DELIMITER ;
1120 if (svp && SvOK(*svp))
1123 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1125 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1126 DB_flags(info->flags, DB_DELIMITER) ;
1131 if (info->db_RE_flags & R_FIXEDLEN)
1132 info->db_RE_bval = (u_char) ' ' ;
1134 info->db_RE_bval = (u_char) '\n' ;
1135 DB_flags(info->flags, DB_DELIMITER) ;
1140 info->flags |= DB_RENUMBER ;
1146 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1150 /* OS2 Specific Code */
1154 #endif /* __EMX__ */
1157 #ifdef DB_VERSION_MAJOR
1163 /* Map 1.x flags to 2.x flags */
1164 if ((flags & O_CREAT) == O_CREAT)
1165 Flags |= DB_CREATE ;
1168 if (flags == O_RDONLY)
1170 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1172 Flags |= DB_RDONLY ;
1175 if ((flags & O_TRUNC) == O_TRUNC)
1176 Flags |= DB_TRUNCATE ;
1179 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1181 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1182 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1184 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1189 RETVAL->dbp = NULL ;
1194 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1195 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1197 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1198 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1204 #else /* Berkeley DB Version > 2 */
1208 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1214 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1215 Zero(RETVAL, 1, DB_File_type) ;
1217 /* Default to HASH */
1218 RETVAL->filtering = 0 ;
1219 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1220 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1221 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1222 RETVAL->type = DB_HASH ;
1224 /* DGH - Next line added to avoid SEGV on existing hash DB */
1227 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1228 RETVAL->in_memory = (name == NULL) ;
1230 status = db_create(&RETVAL->dbp, NULL,0) ;
1231 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1233 RETVAL->dbp = NULL ;
1241 croak ("type parameter is not a reference") ;
1243 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1244 if (svp && SvOK(*svp))
1245 action = (HV*) SvRV(*svp) ;
1247 croak("internal error") ;
1249 if (sv_isa(sv, "DB_File::HASHINFO"))
1253 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1255 RETVAL->type = DB_HASH ;
1257 svp = hv_fetch(action, "hash", 4, FALSE);
1259 if (svp && SvOK(*svp))
1261 (void)dbp->set_h_hash(dbp, hash_cb) ;
1262 RETVAL->hash = newSVsv(*svp) ;
1265 svp = hv_fetch(action, "ffactor", 7, FALSE);
1267 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1269 svp = hv_fetch(action, "nelem", 5, FALSE);
1271 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1273 svp = hv_fetch(action, "bsize", 5, FALSE);
1275 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1277 svp = hv_fetch(action, "cachesize", 9, FALSE);
1279 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1281 svp = hv_fetch(action, "lorder", 6, FALSE);
1283 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1287 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1290 croak("DB_File can only tie an associative array to a DB_BTREE database");
1292 RETVAL->type = DB_BTREE ;
1294 svp = hv_fetch(action, "compare", 7, FALSE);
1295 if (svp && SvOK(*svp))
1297 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1298 RETVAL->compare = newSVsv(*svp) ;
1301 svp = hv_fetch(action, "prefix", 6, FALSE);
1302 if (svp && SvOK(*svp))
1304 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1305 RETVAL->prefix = newSVsv(*svp) ;
1308 svp = hv_fetch(action, "flags", 5, FALSE);
1310 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1312 svp = hv_fetch(action, "cachesize", 9, FALSE);
1314 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1316 svp = hv_fetch(action, "psize", 5, FALSE);
1318 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1320 svp = hv_fetch(action, "lorder", 6, FALSE);
1322 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1327 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1332 croak("DB_File can only tie an array to a DB_RECNO database");
1334 RETVAL->type = DB_RECNO ;
1336 svp = hv_fetch(action, "flags", 5, FALSE);
1338 int flags = SvIV(*svp) ;
1339 /* remove FIXDLEN, if present */
1340 if (flags & DB_FIXEDLEN) {
1342 flags &= ~DB_FIXEDLEN ;
1346 svp = hv_fetch(action, "cachesize", 9, FALSE);
1348 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1351 svp = hv_fetch(action, "psize", 5, FALSE);
1353 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1356 svp = hv_fetch(action, "lorder", 6, FALSE);
1358 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1361 svp = hv_fetch(action, "bval", 4, FALSE);
1362 if (svp && SvOK(*svp))
1366 value = (int)*SvPV(*svp, n_a) ;
1368 value = (int)SvIV(*svp) ;
1371 status = dbp->set_re_pad(dbp, value) ;
1374 status = dbp->set_re_delim(dbp, value) ;
1380 svp = hv_fetch(action, "reclen", 6, FALSE);
1382 u_int32_t len = my_SvUV32(*svp) ;
1383 status = dbp->set_re_len(dbp, len) ;
1388 status = dbp->set_re_source(dbp, name) ;
1392 svp = hv_fetch(action, "bfname", 6, FALSE);
1393 if (svp && SvOK(*svp)) {
1394 char * ptr = SvPV(*svp,n_a) ;
1395 name = (char*) n_a ? ptr : NULL ;
1401 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1404 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1409 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1413 u_int32_t Flags = 0 ;
1416 /* Map 1.x flags to 3.x flags */
1417 if ((flags & O_CREAT) == O_CREAT)
1418 Flags |= DB_CREATE ;
1421 if (flags == O_RDONLY)
1423 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1425 Flags |= DB_RDONLY ;
1428 if ((flags & O_TRUNC) == O_TRUNC)
1429 Flags |= DB_TRUNCATE ;
1432 #ifdef AT_LEAST_DB_4_1
1433 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1436 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1439 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1442 /* RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;*/
1444 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1446 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1450 RETVAL->dbp = NULL ;
1456 #endif /* Berkeley DB Version > 2 */
1458 } /* ParseOpenInfo */
1461 #include "constants.h"
1463 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1465 INCLUDE: constants.xs
1472 /* SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ; */
1474 __getBerkeleyDBInfo() ;
1477 empty.data = &zero ;
1478 empty.size = sizeof(recno_t) ;
1484 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1491 char * name = (char *) NULL ;
1492 SV * sv = (SV *) NULL ;
1495 if (items >= 3 && SvOK(ST(2)))
1496 name = (char*) SvPV(ST(2), n_a) ;
1501 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1502 if (RETVAL->dbp == NULL) {
1517 Trace(("DESTROY %p\n", db));
1519 Trace(("DESTROY %p done\n", db));
1521 SvREFCNT_dec(db->hash) ;
1523 SvREFCNT_dec(db->compare) ;
1525 SvREFCNT_dec(db->prefix) ;
1526 if (db->filter_fetch_key)
1527 SvREFCNT_dec(db->filter_fetch_key) ;
1528 if (db->filter_store_key)
1529 SvREFCNT_dec(db->filter_store_key) ;
1530 if (db->filter_fetch_value)
1531 SvREFCNT_dec(db->filter_fetch_value) ;
1532 if (db->filter_store_value)
1533 SvREFCNT_dec(db->filter_store_value) ;
1535 #ifdef DB_VERSION_MAJOR
1542 db_DELETE(db, key, flags=0)
1564 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1570 db_FETCH(db, key, flags=0)
1583 RETVAL = db_get(db, key, value, flags) ;
1584 ST(0) = sv_newmortal();
1585 OutputValue(ST(0), value)
1589 db_STORE(db, key, value, flags=0)
1614 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1615 ST(0) = sv_newmortal();
1616 OutputKey(ST(0), key) ;
1622 DBTKEY key = NO_INIT
1633 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1634 ST(0) = sv_newmortal();
1635 OutputKey(ST(0), key) ;
1639 # These would be nice for RECNO
1659 #ifdef DB_VERSION_MAJOR
1660 /* get the first value */
1661 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1666 for (i = items-1 ; i > 0 ; --i)
1668 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1669 value.data = SvPVbyte(ST(i), n_a) ;
1673 key.size = sizeof(int) ;
1674 #ifdef DB_VERSION_MAJOR
1675 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1677 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1703 /* First get the final value */
1704 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1705 ST(0) = sv_newmortal();
1709 /* the call to del will trash value, so take a copy now */
1710 OutputValue(ST(0), value) ;
1711 RETVAL = db_del(db, key, R_CURSOR) ;
1713 sv_setsv(ST(0), &PL_sv_undef);
1733 /* get the first value */
1734 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1735 ST(0) = sv_newmortal();
1739 /* the call to del will trash value, so take a copy now */
1740 OutputValue(ST(0), value) ;
1741 RETVAL = db_del(db, key, R_CURSOR) ;
1743 sv_setsv (ST(0), &PL_sv_undef) ;
1766 /* Set the Cursor to the Last element */
1767 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1768 #ifndef DB_VERSION_MAJOR
1773 keyval = *(int*)key.data ;
1776 for (i = 1 ; i < items ; ++i)
1778 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1779 value.data = SvPVbyte(ST(i), n_a) ;
1782 key.data = &keyval ;
1783 key.size = sizeof(int) ;
1784 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1798 ALIAS: FETCHSIZE = 1
1801 RETVAL = GetArrayLength(aTHX_ db) ;
1807 # Now provide an interface to the rest of the DB functionality
1811 db_del(db, key, flags=0)
1819 RETVAL = db_del(db, key, flags) ;
1820 #ifdef DB_VERSION_MAJOR
1823 else if (RETVAL == DB_NOTFOUND)
1831 db_get(db, key, value, flags=0)
1841 RETVAL = db_get(db, key, value, flags) ;
1842 #ifdef DB_VERSION_MAJOR
1845 else if (RETVAL == DB_NOTFOUND)
1853 db_put(db, key, value, flags=0)
1862 RETVAL = db_put(db, key, value, flags) ;
1863 #ifdef DB_VERSION_MAJOR
1866 else if (RETVAL == DB_KEYEXIST)
1871 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1880 #ifdef DB_VERSION_MAJOR
1884 status = (db->in_memory
1886 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1891 RETVAL = (db->in_memory
1893 : ((db->dbp)->fd)(db->dbp) ) ;
1899 db_sync(db, flags=0)
1906 RETVAL = db_sync(db, flags) ;
1907 #ifdef DB_VERSION_MAJOR
1916 db_seq(db, key, value, flags)
1926 RETVAL = db_seq(db, key, value, flags);
1927 #ifdef DB_VERSION_MAJOR
1930 else if (RETVAL == DB_NOTFOUND)
1939 filter_fetch_key(db, code)
1942 SV * RETVAL = &PL_sv_undef ;
1944 DBM_setFilter(db->filter_fetch_key, code) ;
1947 filter_store_key(db, code)
1950 SV * RETVAL = &PL_sv_undef ;
1952 DBM_setFilter(db->filter_store_key, code) ;
1955 filter_fetch_value(db, code)
1958 SV * RETVAL = &PL_sv_undef ;
1960 DBM_setFilter(db->filter_fetch_value, code) ;
1963 filter_store_value(db, code)
1966 SV * RETVAL = &PL_sv_undef ;
1968 DBM_setFilter(db->filter_store_value, code) ;