3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <pmqs@cpan.org>
6 last modified 22nd December 2003
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2003 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
114 #define PERL_NO_GET_CONTEXT
123 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
124 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
126 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
127 * shortly #included by the <db.h>) __attribute__ to the possibly
128 * already defined __attribute__, for example by GNUC or by Perl. */
130 /* #if DB_VERSION_MAJOR_CFG < 2 */
131 #ifndef DB_VERSION_MAJOR
132 # undef __attribute__
141 /* Wall starts with 5.7.x */
143 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
145 /* Since we dropped the gccish definition of __attribute__ we will want
146 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
147 * all this means that we can't do attribute checking on the DB_File,
149 # ifndef DB_VERSION_MAJOR
152 # define dNOOP extern int Perl___notused
154 /* Ditto for dXSARGS. */
158 I32 ax = mark - PL_stack_base + 1; \
159 I32 items = sp - mark
163 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
165 # define dXSI32 dNOOP
167 #endif /* Perl >= 5.7 */
174 # define Trace(x) printf x
180 #define DBT_clear(x) Zero(&x, 1, DBT) ;
182 #ifdef DB_VERSION_MAJOR
184 #if DB_VERSION_MAJOR == 2
185 # define BERKELEY_DB_1_OR_2
188 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
189 # define AT_LEAST_DB_3_2
192 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
193 # define AT_LEAST_DB_4_1
196 /* map version 2 features & constants onto their version 1 equivalent */
201 #define DB_Prefix_t size_t
206 #define DB_Hash_t u_int32_t
208 /* DBTYPE stays the same */
209 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
210 #if DB_VERSION_MAJOR == 2
211 typedef DB_INFO INFO ;
212 #else /* DB_VERSION_MAJOR > 2 */
213 # define DB_FIXEDLEN (0x8000)
214 #endif /* DB_VERSION_MAJOR == 2 */
216 /* version 2 has db_recno_t in place of recno_t */
217 typedef db_recno_t recno_t;
220 #define R_CURSOR DB_SET_RANGE
221 #define R_FIRST DB_FIRST
222 #define R_IAFTER DB_AFTER
223 #define R_IBEFORE DB_BEFORE
224 #define R_LAST DB_LAST
225 #define R_NEXT DB_NEXT
226 #define R_NOOVERWRITE DB_NOOVERWRITE
227 #define R_PREV DB_PREV
229 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
230 # define R_SETCURSOR 0x800000
232 # define R_SETCURSOR (-100)
235 #define R_RECNOSYNC 0
236 #define R_FIXEDLEN DB_FIXEDLEN
240 #define db_HA_hash h_hash
241 #define db_HA_ffactor h_ffactor
242 #define db_HA_nelem h_nelem
243 #define db_HA_bsize db_pagesize
244 #define db_HA_cachesize db_cachesize
245 #define db_HA_lorder db_lorder
247 #define db_BT_compare bt_compare
248 #define db_BT_prefix bt_prefix
249 #define db_BT_flags flags
250 #define db_BT_psize db_pagesize
251 #define db_BT_cachesize db_cachesize
252 #define db_BT_lorder db_lorder
253 #define db_BT_maxkeypage
254 #define db_BT_minkeypage
257 #define db_RE_reclen re_len
258 #define db_RE_flags flags
259 #define db_RE_bval re_pad
260 #define db_RE_bfname re_source
261 #define db_RE_psize db_pagesize
262 #define db_RE_cachesize db_cachesize
263 #define db_RE_lorder db_lorder
267 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
270 #define DBT_flags(x) x.flags = 0
271 #define DB_flags(x, v) x |= v
273 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
274 # define flagSet(flags, bitmask) ((flags) & (bitmask))
276 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
279 #else /* db version 1.x */
281 #define BERKELEY_DB_1
282 #define BERKELEY_DB_1_OR_2
295 # define DB_Prefix_t mDB_Prefix_t
302 # define DB_Hash_t mDB_Hash_t
305 #define db_HA_hash hash.hash
306 #define db_HA_ffactor hash.ffactor
307 #define db_HA_nelem hash.nelem
308 #define db_HA_bsize hash.bsize
309 #define db_HA_cachesize hash.cachesize
310 #define db_HA_lorder hash.lorder
312 #define db_BT_compare btree.compare
313 #define db_BT_prefix btree.prefix
314 #define db_BT_flags btree.flags
315 #define db_BT_psize btree.psize
316 #define db_BT_cachesize btree.cachesize
317 #define db_BT_lorder btree.lorder
318 #define db_BT_maxkeypage btree.maxkeypage
319 #define db_BT_minkeypage btree.minkeypage
321 #define db_RE_reclen recno.reclen
322 #define db_RE_flags recno.flags
323 #define db_RE_bval recno.bval
324 #define db_RE_bfname recno.bfname
325 #define db_RE_psize recno.psize
326 #define db_RE_cachesize recno.cachesize
327 #define db_RE_lorder recno.lorder
331 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
333 #define DB_flags(x, v)
334 #define flagSet(flags, bitmask) ((flags) & (bitmask))
336 #endif /* db version 1 */
340 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
341 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
342 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
344 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
345 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
347 #ifdef DB_VERSION_MAJOR
348 #define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
349 (db->dbp->close)(db->dbp, 0) ))
350 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
351 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
352 ? ((db->cursor)->c_del)(db->cursor, 0) \
353 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
355 #else /* ! DB_VERSION_MAJOR */
357 #define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
358 #define db_close(db) ((db->dbp)->close)(db->dbp)
359 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
360 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
362 #endif /* ! DB_VERSION_MAJOR */
365 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
378 #ifdef BERKELEY_DB_1_OR_2
381 #ifdef DB_VERSION_MAJOR
384 SV * filter_fetch_key ;
385 SV * filter_store_key ;
386 SV * filter_fetch_value ;
387 SV * filter_store_value ;
392 typedef DB_File_type * DB_File ;
395 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
397 #define OutputValue(arg, name) \
398 { if (RETVAL == 0) { \
399 my_sv_setpvn(arg, name.data, name.size) ; \
403 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
407 #define OutputKey(arg, name) \
410 if (db->type != DB_RECNO) { \
411 my_sv_setpvn(arg, name.data, name.size); \
414 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
418 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
422 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
425 extern void __getBerkeleyDBInfo(void);
428 /* Internal Global Data */
430 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
441 #define Value (MY_CXT.x_Value)
442 #define zero (MY_CXT.x_zero)
443 #define CurrentDB (MY_CXT.x_CurrentDB)
444 #define empty (MY_CXT.x_empty)
446 #define ERR_BUFF "DB_File::Error"
448 #ifdef DB_VERSION_MAJOR
452 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
454 db_put(db, key, value, flags)
463 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
467 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
468 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
470 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
474 memset(&l_key, 0, sizeof(l_key));
475 l_key.data = key.data;
476 l_key.size = key.size;
477 memset(&l_value, 0, sizeof(l_value));
478 l_value.data = value.data;
479 l_value.size = value.size;
481 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
482 (void)temp_cursor->c_close(temp_cursor);
486 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
487 (void)temp_cursor->c_close(temp_cursor);
493 if (flagSet(flags, R_CURSOR)) {
494 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
497 if (flagSet(flags, R_SETCURSOR)) {
498 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
500 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
504 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
508 #endif /* DB_VERSION_MAJOR */
518 #ifdef AT_LEAST_DB_3_2
521 btree_compare(DB * db, const DBT *key1, const DBT *key2)
523 btree_compare(db, key1, key2)
527 #endif /* CAN_PROTOTYPE */
529 #else /* Berkeley DB < 3.2 */
532 btree_compare(const DBT *key1, const DBT *key2)
534 btree_compare(key1, key2)
547 void * data1, * data2 ;
552 if (CurrentDB->in_compare) {
554 croak ("DB_File btree_compare: recursion detected\n") ;
557 data1 = (char *) key1->data ;
558 data2 = (char *) key2->data ;
561 /* As newSVpv will assume that the data pointer is a null terminated C
562 string if the size parameter is 0, make sure that data points to an
563 empty string if the length is 0
574 CurrentDB->in_compare = FALSE;
575 SAVEINT(CurrentDB->in_compare);
576 CurrentDB->in_compare = TRUE;
580 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
581 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
584 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
590 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
604 #ifdef AT_LEAST_DB_3_2
607 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
609 btree_prefix(db, key1, key2)
615 #else /* Berkeley DB < 3.2 */
618 btree_prefix(const DBT *key1, const DBT *key2)
620 btree_prefix(key1, key2)
632 char * data1, * data2 ;
636 if (CurrentDB->in_prefix){
638 croak ("DB_File btree_prefix: recursion detected\n") ;
641 data1 = (char *) key1->data ;
642 data2 = (char *) key2->data ;
645 /* As newSVpv will assume that the data pointer is a null terminated C
646 string if the size parameter is 0, make sure that data points to an
647 empty string if the length is 0
658 CurrentDB->in_prefix = FALSE;
659 SAVEINT(CurrentDB->in_prefix);
660 CurrentDB->in_prefix = TRUE;
664 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
665 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
668 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
674 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
688 # define HASH_CB_SIZE_TYPE size_t
690 # define HASH_CB_SIZE_TYPE u_int32_t
694 #ifdef AT_LEAST_DB_3_2
697 hash_cb(DB * db, const void *data, u_int32_t size)
699 hash_cb(db, data, size)
702 HASH_CB_SIZE_TYPE size ;
705 #else /* Berkeley DB < 3.2 */
708 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
712 HASH_CB_SIZE_TYPE size ;
725 if (CurrentDB->in_hash){
727 croak ("DB_File hash callback: recursion detected\n") ;
735 /* DGH - Next two lines added to fix corrupted stack problem */
739 CurrentDB->in_hash = FALSE;
740 SAVEINT(CurrentDB->in_hash);
741 CurrentDB->in_hash = TRUE;
746 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
749 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
755 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
770 db_errcall_cb(const char * db_errpfx, char * buffer)
772 db_errcall_cb(db_errpfx, buffer)
773 const char * db_errpfx;
780 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
783 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
785 sv_setpv(sv, buffer) ;
790 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
794 PrintHash(INFO *hash)
800 printf ("HASH Info\n") ;
801 printf (" hash = %s\n",
802 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
803 printf (" bsize = %d\n", hash->db_HA_bsize) ;
804 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
805 printf (" nelem = %d\n", hash->db_HA_nelem) ;
806 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
807 printf (" lorder = %d\n", hash->db_HA_lorder) ;
813 PrintRecno(INFO *recno)
819 printf ("RECNO Info\n") ;
820 printf (" flags = %d\n", recno->db_RE_flags) ;
821 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
822 printf (" psize = %d\n", recno->db_RE_psize) ;
823 printf (" lorder = %d\n", recno->db_RE_lorder) ;
824 printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ;
825 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
826 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
831 PrintBtree(INFO *btree)
837 printf ("BTREE Info\n") ;
838 printf (" compare = %s\n",
839 (btree->db_BT_compare ? "redefined" : "default")) ;
840 printf (" prefix = %s\n",
841 (btree->db_BT_prefix ? "redefined" : "default")) ;
842 printf (" flags = %d\n", btree->db_BT_flags) ;
843 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
844 printf (" psize = %d\n", btree->db_BT_psize) ;
845 #ifndef DB_VERSION_MAJOR
846 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
847 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
849 printf (" lorder = %d\n", btree->db_BT_lorder) ;
854 #define PrintRecno(recno)
855 #define PrintHash(hash)
856 #define PrintBtree(btree)
863 GetArrayLength(pTHX_ DB_File db)
875 RETVAL = do_SEQ(db, key, value, R_LAST) ;
877 RETVAL = *(I32 *)key.data ;
878 else /* No key means empty file */
881 return ((I32)RETVAL) ;
886 GetRecnoKey(pTHX_ DB_File db, I32 value)
888 GetRecnoKey(db, value)
894 /* Get the length of the array */
895 I32 length = GetArrayLength(aTHX_ db) ;
897 /* check for attempt to write before start of array */
898 if (length + value + 1 <= 0) {
900 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
903 value = length + value + 1 ;
914 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
916 ParseOpenInfo(isHASH, name, flags, mode, sv)
925 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
929 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
930 void * openinfo = NULL ;
931 INFO * info = &RETVAL->info ;
935 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
936 Zero(RETVAL, 1, DB_File_type) ;
938 /* Default to HASH */
939 RETVAL->filtering = 0 ;
940 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
941 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
942 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
943 RETVAL->type = DB_HASH ;
945 /* DGH - Next line added to avoid SEGV on existing hash DB */
948 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
949 RETVAL->in_memory = (name == NULL) ;
954 croak ("type parameter is not a reference") ;
956 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
957 if (svp && SvOK(*svp))
958 action = (HV*) SvRV(*svp) ;
960 croak("internal error") ;
962 if (sv_isa(sv, "DB_File::HASHINFO"))
966 croak("DB_File can only tie an associative array to a DB_HASH database") ;
968 RETVAL->type = DB_HASH ;
969 openinfo = (void*)info ;
971 svp = hv_fetch(action, "hash", 4, FALSE);
973 if (svp && SvOK(*svp))
975 info->db_HA_hash = hash_cb ;
976 RETVAL->hash = newSVsv(*svp) ;
979 info->db_HA_hash = NULL ;
981 svp = hv_fetch(action, "ffactor", 7, FALSE);
982 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
984 svp = hv_fetch(action, "nelem", 5, FALSE);
985 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
987 svp = hv_fetch(action, "bsize", 5, FALSE);
988 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
990 svp = hv_fetch(action, "cachesize", 9, FALSE);
991 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
993 svp = hv_fetch(action, "lorder", 6, FALSE);
994 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
998 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1001 croak("DB_File can only tie an associative array to a DB_BTREE database");
1003 RETVAL->type = DB_BTREE ;
1004 openinfo = (void*)info ;
1006 svp = hv_fetch(action, "compare", 7, FALSE);
1007 if (svp && SvOK(*svp))
1009 info->db_BT_compare = btree_compare ;
1010 RETVAL->compare = newSVsv(*svp) ;
1013 info->db_BT_compare = NULL ;
1015 svp = hv_fetch(action, "prefix", 6, FALSE);
1016 if (svp && SvOK(*svp))
1018 info->db_BT_prefix = btree_prefix ;
1019 RETVAL->prefix = newSVsv(*svp) ;
1022 info->db_BT_prefix = NULL ;
1024 svp = hv_fetch(action, "flags", 5, FALSE);
1025 info->db_BT_flags = svp ? SvIV(*svp) : 0;
1027 svp = hv_fetch(action, "cachesize", 9, FALSE);
1028 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
1030 #ifndef DB_VERSION_MAJOR
1031 svp = hv_fetch(action, "minkeypage", 10, FALSE);
1032 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
1034 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
1035 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1038 svp = hv_fetch(action, "psize", 5, FALSE);
1039 info->db_BT_psize = svp ? SvIV(*svp) : 0;
1041 svp = hv_fetch(action, "lorder", 6, FALSE);
1042 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1047 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1050 croak("DB_File can only tie an array to a DB_RECNO database");
1052 RETVAL->type = DB_RECNO ;
1053 openinfo = (void *)info ;
1055 info->db_RE_flags = 0 ;
1057 svp = hv_fetch(action, "flags", 5, FALSE);
1058 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1060 svp = hv_fetch(action, "reclen", 6, FALSE);
1061 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1063 svp = hv_fetch(action, "cachesize", 9, FALSE);
1064 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1066 svp = hv_fetch(action, "psize", 5, FALSE);
1067 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1069 svp = hv_fetch(action, "lorder", 6, FALSE);
1070 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1072 #ifdef DB_VERSION_MAJOR
1073 info->re_source = name ;
1076 svp = hv_fetch(action, "bfname", 6, FALSE);
1077 if (svp && SvOK(*svp)) {
1078 char * ptr = SvPV(*svp,n_a) ;
1079 #ifdef DB_VERSION_MAJOR
1080 name = (char*) n_a ? ptr : NULL ;
1082 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1086 #ifdef DB_VERSION_MAJOR
1089 info->db_RE_bfname = NULL ;
1092 svp = hv_fetch(action, "bval", 4, FALSE);
1093 #ifdef DB_VERSION_MAJOR
1094 if (svp && SvOK(*svp))
1098 value = (int)*SvPV(*svp, n_a) ;
1100 value = SvIV(*svp) ;
1102 if (info->flags & DB_FIXEDLEN) {
1103 info->re_pad = value ;
1104 info->flags |= DB_PAD ;
1107 info->re_delim = value ;
1108 info->flags |= DB_DELIMITER ;
1113 if (svp && SvOK(*svp))
1116 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1118 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1119 DB_flags(info->flags, DB_DELIMITER) ;
1124 if (info->db_RE_flags & R_FIXEDLEN)
1125 info->db_RE_bval = (u_char) ' ' ;
1127 info->db_RE_bval = (u_char) '\n' ;
1128 DB_flags(info->flags, DB_DELIMITER) ;
1133 info->flags |= DB_RENUMBER ;
1139 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1143 /* OS2 Specific Code */
1147 #endif /* __EMX__ */
1150 #ifdef DB_VERSION_MAJOR
1156 /* Map 1.x flags to 2.x flags */
1157 if ((flags & O_CREAT) == O_CREAT)
1158 Flags |= DB_CREATE ;
1161 if (flags == O_RDONLY)
1163 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1165 Flags |= DB_RDONLY ;
1168 if ((flags & O_TRUNC) == O_TRUNC)
1169 Flags |= DB_TRUNCATE ;
1172 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1174 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1175 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1177 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1182 RETVAL->dbp = NULL ;
1187 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1188 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1190 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1191 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1197 #else /* Berkeley DB Version > 2 */
1201 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1207 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1208 Zero(RETVAL, 1, DB_File_type) ;
1210 /* Default to HASH */
1211 RETVAL->filtering = 0 ;
1212 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1213 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1214 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1215 RETVAL->type = DB_HASH ;
1217 /* DGH - Next line added to avoid SEGV on existing hash DB */
1220 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1221 RETVAL->in_memory = (name == NULL) ;
1223 status = db_create(&RETVAL->dbp, NULL,0) ;
1224 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1226 RETVAL->dbp = NULL ;
1234 croak ("type parameter is not a reference") ;
1236 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1237 if (svp && SvOK(*svp))
1238 action = (HV*) SvRV(*svp) ;
1240 croak("internal error") ;
1242 if (sv_isa(sv, "DB_File::HASHINFO"))
1246 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1248 RETVAL->type = DB_HASH ;
1250 svp = hv_fetch(action, "hash", 4, FALSE);
1252 if (svp && SvOK(*svp))
1254 (void)dbp->set_h_hash(dbp, hash_cb) ;
1255 RETVAL->hash = newSVsv(*svp) ;
1258 svp = hv_fetch(action, "ffactor", 7, FALSE);
1260 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1262 svp = hv_fetch(action, "nelem", 5, FALSE);
1264 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1266 svp = hv_fetch(action, "bsize", 5, FALSE);
1268 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1270 svp = hv_fetch(action, "cachesize", 9, FALSE);
1272 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1274 svp = hv_fetch(action, "lorder", 6, FALSE);
1276 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1280 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1283 croak("DB_File can only tie an associative array to a DB_BTREE database");
1285 RETVAL->type = DB_BTREE ;
1287 svp = hv_fetch(action, "compare", 7, FALSE);
1288 if (svp && SvOK(*svp))
1290 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1291 RETVAL->compare = newSVsv(*svp) ;
1294 svp = hv_fetch(action, "prefix", 6, FALSE);
1295 if (svp && SvOK(*svp))
1297 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1298 RETVAL->prefix = newSVsv(*svp) ;
1301 svp = hv_fetch(action, "flags", 5, FALSE);
1303 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1305 svp = hv_fetch(action, "cachesize", 9, FALSE);
1307 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1309 svp = hv_fetch(action, "psize", 5, FALSE);
1311 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1313 svp = hv_fetch(action, "lorder", 6, FALSE);
1315 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1320 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1325 croak("DB_File can only tie an array to a DB_RECNO database");
1327 RETVAL->type = DB_RECNO ;
1329 svp = hv_fetch(action, "flags", 5, FALSE);
1331 int flags = SvIV(*svp) ;
1332 /* remove FIXDLEN, if present */
1333 if (flags & DB_FIXEDLEN) {
1335 flags &= ~DB_FIXEDLEN ;
1339 svp = hv_fetch(action, "cachesize", 9, FALSE);
1341 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1344 svp = hv_fetch(action, "psize", 5, FALSE);
1346 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1349 svp = hv_fetch(action, "lorder", 6, FALSE);
1351 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1354 svp = hv_fetch(action, "bval", 4, FALSE);
1355 if (svp && SvOK(*svp))
1359 value = (int)*SvPV(*svp, n_a) ;
1361 value = (int)SvIV(*svp) ;
1364 status = dbp->set_re_pad(dbp, value) ;
1367 status = dbp->set_re_delim(dbp, value) ;
1373 svp = hv_fetch(action, "reclen", 6, FALSE);
1375 u_int32_t len = my_SvUV32(*svp) ;
1376 status = dbp->set_re_len(dbp, len) ;
1381 status = dbp->set_re_source(dbp, name) ;
1385 svp = hv_fetch(action, "bfname", 6, FALSE);
1386 if (svp && SvOK(*svp)) {
1387 char * ptr = SvPV(*svp,n_a) ;
1388 name = (char*) n_a ? ptr : NULL ;
1394 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1397 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1402 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1406 u_int32_t Flags = 0 ;
1409 /* Map 1.x flags to 3.x flags */
1410 if ((flags & O_CREAT) == O_CREAT)
1411 Flags |= DB_CREATE ;
1414 if (flags == O_RDONLY)
1416 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1418 Flags |= DB_RDONLY ;
1421 if ((flags & O_TRUNC) == O_TRUNC)
1422 Flags |= DB_TRUNCATE ;
1425 #ifdef AT_LEAST_DB_4_1
1426 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1429 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1432 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1435 /* RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;*/
1437 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1439 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1443 RETVAL->dbp = NULL ;
1449 #endif /* Berkeley DB Version > 2 */
1451 } /* ParseOpenInfo */
1454 #include "constants.h"
1456 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1458 INCLUDE: constants.xs
1465 /* SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ; */
1467 __getBerkeleyDBInfo() ;
1470 empty.data = &zero ;
1471 empty.size = sizeof(recno_t) ;
1477 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1484 char * name = (char *) NULL ;
1485 SV * sv = (SV *) NULL ;
1488 if (items >= 3 && SvOK(ST(2)))
1489 name = (char*) SvPV(ST(2), n_a) ;
1494 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1495 if (RETVAL->dbp == NULL) {
1510 Trace(("DESTROY %p\n", db));
1512 Trace(("DESTROY %p done\n", db));
1514 SvREFCNT_dec(db->hash) ;
1516 SvREFCNT_dec(db->compare) ;
1518 SvREFCNT_dec(db->prefix) ;
1519 if (db->filter_fetch_key)
1520 SvREFCNT_dec(db->filter_fetch_key) ;
1521 if (db->filter_store_key)
1522 SvREFCNT_dec(db->filter_store_key) ;
1523 if (db->filter_fetch_value)
1524 SvREFCNT_dec(db->filter_fetch_value) ;
1525 if (db->filter_store_value)
1526 SvREFCNT_dec(db->filter_store_value) ;
1528 #ifdef DB_VERSION_MAJOR
1535 db_DELETE(db, key, flags=0)
1557 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1563 db_FETCH(db, key, flags=0)
1576 RETVAL = db_get(db, key, value, flags) ;
1577 ST(0) = sv_newmortal();
1578 OutputValue(ST(0), value)
1582 db_STORE(db, key, value, flags=0)
1607 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1608 ST(0) = sv_newmortal();
1609 OutputKey(ST(0), key) ;
1615 DBTKEY key = NO_INIT
1626 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1627 ST(0) = sv_newmortal();
1628 OutputKey(ST(0), key) ;
1632 # These would be nice for RECNO
1652 #ifdef DB_VERSION_MAJOR
1653 /* get the first value */
1654 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1659 for (i = items-1 ; i > 0 ; --i)
1661 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1662 value.data = SvPVbyte(ST(i), n_a) ;
1666 key.size = sizeof(int) ;
1667 #ifdef DB_VERSION_MAJOR
1668 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1670 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1696 /* First get the final value */
1697 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1698 ST(0) = sv_newmortal();
1702 /* the call to del will trash value, so take a copy now */
1703 OutputValue(ST(0), value) ;
1704 RETVAL = db_del(db, key, R_CURSOR) ;
1706 sv_setsv(ST(0), &PL_sv_undef);
1726 /* get the first value */
1727 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1728 ST(0) = sv_newmortal();
1732 /* the call to del will trash value, so take a copy now */
1733 OutputValue(ST(0), value) ;
1734 RETVAL = db_del(db, key, R_CURSOR) ;
1736 sv_setsv (ST(0), &PL_sv_undef) ;
1759 /* Set the Cursor to the Last element */
1760 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1761 #ifndef DB_VERSION_MAJOR
1766 keyval = *(int*)key.data ;
1769 for (i = 1 ; i < items ; ++i)
1771 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1772 value.data = SvPVbyte(ST(i), n_a) ;
1775 key.data = &keyval ;
1776 key.size = sizeof(int) ;
1777 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1791 ALIAS: FETCHSIZE = 1
1794 RETVAL = GetArrayLength(aTHX_ db) ;
1800 # Now provide an interface to the rest of the DB functionality
1804 db_del(db, key, flags=0)
1812 RETVAL = db_del(db, key, flags) ;
1813 #ifdef DB_VERSION_MAJOR
1816 else if (RETVAL == DB_NOTFOUND)
1824 db_get(db, key, value, flags=0)
1834 RETVAL = db_get(db, key, value, flags) ;
1835 #ifdef DB_VERSION_MAJOR
1838 else if (RETVAL == DB_NOTFOUND)
1846 db_put(db, key, value, flags=0)
1855 RETVAL = db_put(db, key, value, flags) ;
1856 #ifdef DB_VERSION_MAJOR
1859 else if (RETVAL == DB_KEYEXIST)
1864 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1873 #ifdef DB_VERSION_MAJOR
1877 status = (db->in_memory
1879 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1884 RETVAL = (db->in_memory
1886 : ((db->dbp)->fd)(db->dbp) ) ;
1892 db_sync(db, flags=0)
1899 RETVAL = db_sync(db, flags) ;
1900 #ifdef DB_VERSION_MAJOR
1909 db_seq(db, key, value, flags)
1919 RETVAL = db_seq(db, key, value, flags);
1920 #ifdef DB_VERSION_MAJOR
1923 else if (RETVAL == DB_NOTFOUND)
1932 filter_fetch_key(db, code)
1935 SV * RETVAL = &PL_sv_undef ;
1937 DBM_setFilter(db->filter_fetch_key, code) ;
1940 filter_store_key(db, code)
1943 SV * RETVAL = &PL_sv_undef ;
1945 DBM_setFilter(db->filter_store_key, code) ;
1948 filter_fetch_value(db, code)
1951 SV * RETVAL = &PL_sv_undef ;
1953 DBM_setFilter(db->filter_fetch_value, code) ;
1956 filter_store_value(db, code)
1959 SV * RETVAL = &PL_sv_undef ;
1961 DBM_setFilter(db->filter_store_value, code) ;