3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <pmqs@cpan.org>
6 last modified 22nd October 2002
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.
113 #define PERL_NO_GET_CONTEXT
122 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
123 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
125 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
126 * shortly #included by the <db.h>) __attribute__ to the possibly
127 * already defined __attribute__, for example by GNUC or by Perl. */
129 /* #if DB_VERSION_MAJOR_CFG < 2 */
130 #ifndef DB_VERSION_MAJOR
131 # undef __attribute__
140 /* Wall starts with 5.7.x */
142 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
144 /* Since we dropped the gccish definition of __attribute__ we will want
145 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
146 * all this means that we can't do attribute checking on the DB_File,
148 # ifndef DB_VERSION_MAJOR
151 # define dNOOP extern int Perl___notused
153 /* Ditto for dXSARGS. */
157 I32 ax = mark - PL_stack_base + 1; \
158 I32 items = sp - mark
162 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
164 # define dXSI32 dNOOP
166 #endif /* Perl >= 5.7 */
173 # define Trace(x) printf x
179 #define DBT_clear(x) Zero(&x, 1, DBT) ;
181 #ifdef DB_VERSION_MAJOR
183 #if DB_VERSION_MAJOR == 2
184 # define BERKELEY_DB_1_OR_2
187 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
188 # define AT_LEAST_DB_3_2
191 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
192 # define AT_LEAST_DB_4_1
195 /* map version 2 features & constants onto their version 1 equivalent */
200 #define DB_Prefix_t size_t
205 #define DB_Hash_t u_int32_t
207 /* DBTYPE stays the same */
208 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
209 #if DB_VERSION_MAJOR == 2
210 typedef DB_INFO INFO ;
211 #else /* DB_VERSION_MAJOR > 2 */
212 # define DB_FIXEDLEN (0x8000)
213 #endif /* DB_VERSION_MAJOR == 2 */
215 /* version 2 has db_recno_t in place of recno_t */
216 typedef db_recno_t recno_t;
219 #define R_CURSOR DB_SET_RANGE
220 #define R_FIRST DB_FIRST
221 #define R_IAFTER DB_AFTER
222 #define R_IBEFORE DB_BEFORE
223 #define R_LAST DB_LAST
224 #define R_NEXT DB_NEXT
225 #define R_NOOVERWRITE DB_NOOVERWRITE
226 #define R_PREV DB_PREV
228 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
229 # define R_SETCURSOR 0x800000
231 # define R_SETCURSOR (-100)
234 #define R_RECNOSYNC 0
235 #define R_FIXEDLEN DB_FIXEDLEN
239 #define db_HA_hash h_hash
240 #define db_HA_ffactor h_ffactor
241 #define db_HA_nelem h_nelem
242 #define db_HA_bsize db_pagesize
243 #define db_HA_cachesize db_cachesize
244 #define db_HA_lorder db_lorder
246 #define db_BT_compare bt_compare
247 #define db_BT_prefix bt_prefix
248 #define db_BT_flags flags
249 #define db_BT_psize db_pagesize
250 #define db_BT_cachesize db_cachesize
251 #define db_BT_lorder db_lorder
252 #define db_BT_maxkeypage
253 #define db_BT_minkeypage
256 #define db_RE_reclen re_len
257 #define db_RE_flags flags
258 #define db_RE_bval re_pad
259 #define db_RE_bfname re_source
260 #define db_RE_psize db_pagesize
261 #define db_RE_cachesize db_cachesize
262 #define db_RE_lorder db_lorder
266 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
269 #define DBT_flags(x) x.flags = 0
270 #define DB_flags(x, v) x |= v
272 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
273 # define flagSet(flags, bitmask) ((flags) & (bitmask))
275 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
278 #else /* db version 1.x */
280 #define BERKELEY_DB_1
281 #define BERKELEY_DB_1_OR_2
294 # define DB_Prefix_t mDB_Prefix_t
301 # define DB_Hash_t mDB_Hash_t
304 #define db_HA_hash hash.hash
305 #define db_HA_ffactor hash.ffactor
306 #define db_HA_nelem hash.nelem
307 #define db_HA_bsize hash.bsize
308 #define db_HA_cachesize hash.cachesize
309 #define db_HA_lorder hash.lorder
311 #define db_BT_compare btree.compare
312 #define db_BT_prefix btree.prefix
313 #define db_BT_flags btree.flags
314 #define db_BT_psize btree.psize
315 #define db_BT_cachesize btree.cachesize
316 #define db_BT_lorder btree.lorder
317 #define db_BT_maxkeypage btree.maxkeypage
318 #define db_BT_minkeypage btree.minkeypage
320 #define db_RE_reclen recno.reclen
321 #define db_RE_flags recno.flags
322 #define db_RE_bval recno.bval
323 #define db_RE_bfname recno.bfname
324 #define db_RE_psize recno.psize
325 #define db_RE_cachesize recno.cachesize
326 #define db_RE_lorder recno.lorder
330 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
332 #define DB_flags(x, v)
333 #define flagSet(flags, bitmask) ((flags) & (bitmask))
335 #endif /* db version 1 */
339 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
340 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
341 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
343 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
344 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
346 #ifdef DB_VERSION_MAJOR
347 #define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
348 (db->dbp->close)(db->dbp, 0) ))
349 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
350 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
351 ? ((db->cursor)->c_del)(db->cursor, 0) \
352 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
354 #else /* ! DB_VERSION_MAJOR */
356 #define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
357 #define db_close(db) ((db->dbp)->close)(db->dbp)
358 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
359 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
361 #endif /* ! DB_VERSION_MAJOR */
364 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
377 #ifdef BERKELEY_DB_1_OR_2
380 #ifdef DB_VERSION_MAJOR
383 SV * filter_fetch_key ;
384 SV * filter_store_key ;
385 SV * filter_fetch_value ;
386 SV * filter_store_value ;
391 typedef DB_File_type * DB_File ;
394 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
396 #define OutputValue(arg, name) \
397 { if (RETVAL == 0) { \
398 my_sv_setpvn(arg, name.data, name.size) ; \
401 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
405 #define OutputKey(arg, name) \
408 if (db->type != DB_RECNO) { \
409 my_sv_setpvn(arg, name.data, name.size); \
412 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
415 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
419 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
422 extern void __getBerkeleyDBInfo(void);
425 /* Internal Global Data */
427 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
438 #define Value (MY_CXT.x_Value)
439 #define zero (MY_CXT.x_zero)
440 #define CurrentDB (MY_CXT.x_CurrentDB)
441 #define empty (MY_CXT.x_empty)
443 #define ERR_BUFF "DB_File::Error"
445 #ifdef DB_VERSION_MAJOR
449 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
451 db_put(db, key, value, flags)
460 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
464 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
465 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
467 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
471 memset(&l_key, 0, sizeof(l_key));
472 l_key.data = key.data;
473 l_key.size = key.size;
474 memset(&l_value, 0, sizeof(l_value));
475 l_value.data = value.data;
476 l_value.size = value.size;
478 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
479 (void)temp_cursor->c_close(temp_cursor);
483 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
484 (void)temp_cursor->c_close(temp_cursor);
490 if (flagSet(flags, R_CURSOR)) {
491 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
494 if (flagSet(flags, R_SETCURSOR)) {
495 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
497 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
501 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
505 #endif /* DB_VERSION_MAJOR */
515 #ifdef AT_LEAST_DB_3_2
518 btree_compare(DB * db, const DBT *key1, const DBT *key2)
520 btree_compare(db, key1, key2)
524 #endif /* CAN_PROTOTYPE */
526 #else /* Berkeley DB < 3.2 */
529 btree_compare(const DBT *key1, const DBT *key2)
531 btree_compare(key1, key2)
544 void * data1, * data2 ;
549 if (CurrentDB->in_compare) {
551 croak ("DB_File btree_compare: recursion detected\n") ;
554 data1 = (char *) key1->data ;
555 data2 = (char *) key2->data ;
558 /* As newSVpv will assume that the data pointer is a null terminated C
559 string if the size parameter is 0, make sure that data points to an
560 empty string if the length is 0
571 CurrentDB->in_compare = FALSE;
572 SAVEINT(CurrentDB->in_compare);
573 CurrentDB->in_compare = TRUE;
577 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
578 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
581 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
587 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
601 #ifdef AT_LEAST_DB_3_2
604 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
606 btree_prefix(db, key1, key2)
612 #else /* Berkeley DB < 3.2 */
615 btree_prefix(const DBT *key1, const DBT *key2)
617 btree_prefix(key1, key2)
629 char * data1, * data2 ;
633 if (CurrentDB->in_prefix){
635 croak ("DB_File btree_prefix: recursion detected\n") ;
638 data1 = (char *) key1->data ;
639 data2 = (char *) key2->data ;
642 /* As newSVpv will assume that the data pointer is a null terminated C
643 string if the size parameter is 0, make sure that data points to an
644 empty string if the length is 0
655 CurrentDB->in_prefix = FALSE;
656 SAVEINT(CurrentDB->in_prefix);
657 CurrentDB->in_prefix = TRUE;
661 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
662 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
665 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
671 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
685 # define HASH_CB_SIZE_TYPE size_t
687 # define HASH_CB_SIZE_TYPE u_int32_t
691 #ifdef AT_LEAST_DB_3_2
694 hash_cb(DB * db, const void *data, u_int32_t size)
696 hash_cb(db, data, size)
699 HASH_CB_SIZE_TYPE size ;
702 #else /* Berkeley DB < 3.2 */
705 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
709 HASH_CB_SIZE_TYPE size ;
722 if (CurrentDB->in_hash){
724 croak ("DB_File hash callback: recursion detected\n") ;
732 /* DGH - Next two lines added to fix corrupted stack problem */
736 CurrentDB->in_hash = FALSE;
737 SAVEINT(CurrentDB->in_hash);
738 CurrentDB->in_hash = TRUE;
743 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
746 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
752 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
767 db_errcall_cb(const char * db_errpfx, char * buffer)
769 db_errcall_cb(db_errpfx, buffer)
770 const char * db_errpfx;
777 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
780 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
782 sv_setpv(sv, buffer) ;
787 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
791 PrintHash(INFO *hash)
797 printf ("HASH Info\n") ;
798 printf (" hash = %s\n",
799 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
800 printf (" bsize = %d\n", hash->db_HA_bsize) ;
801 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
802 printf (" nelem = %d\n", hash->db_HA_nelem) ;
803 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
804 printf (" lorder = %d\n", hash->db_HA_lorder) ;
810 PrintRecno(INFO *recno)
816 printf ("RECNO Info\n") ;
817 printf (" flags = %d\n", recno->db_RE_flags) ;
818 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
819 printf (" psize = %d\n", recno->db_RE_psize) ;
820 printf (" lorder = %d\n", recno->db_RE_lorder) ;
821 printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ;
822 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
823 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
828 PrintBtree(INFO *btree)
834 printf ("BTREE Info\n") ;
835 printf (" compare = %s\n",
836 (btree->db_BT_compare ? "redefined" : "default")) ;
837 printf (" prefix = %s\n",
838 (btree->db_BT_prefix ? "redefined" : "default")) ;
839 printf (" flags = %d\n", btree->db_BT_flags) ;
840 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
841 printf (" psize = %d\n", btree->db_BT_psize) ;
842 #ifndef DB_VERSION_MAJOR
843 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
844 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
846 printf (" lorder = %d\n", btree->db_BT_lorder) ;
851 #define PrintRecno(recno)
852 #define PrintHash(hash)
853 #define PrintBtree(btree)
860 GetArrayLength(pTHX_ DB_File db)
872 RETVAL = do_SEQ(db, key, value, R_LAST) ;
874 RETVAL = *(I32 *)key.data ;
875 else /* No key means empty file */
878 return ((I32)RETVAL) ;
883 GetRecnoKey(pTHX_ DB_File db, I32 value)
885 GetRecnoKey(db, value)
891 /* Get the length of the array */
892 I32 length = GetArrayLength(aTHX_ db) ;
894 /* check for attempt to write before start of array */
895 if (length + value + 1 <= 0) {
897 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
900 value = length + value + 1 ;
911 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
913 ParseOpenInfo(isHASH, name, flags, mode, sv)
922 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
926 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
927 void * openinfo = NULL ;
928 INFO * info = &RETVAL->info ;
932 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
933 Zero(RETVAL, 1, DB_File_type) ;
935 /* Default to HASH */
936 RETVAL->filtering = 0 ;
937 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
938 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
939 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
940 RETVAL->type = DB_HASH ;
942 /* DGH - Next line added to avoid SEGV on existing hash DB */
945 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
946 RETVAL->in_memory = (name == NULL) ;
951 croak ("type parameter is not a reference") ;
953 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
954 if (svp && SvOK(*svp))
955 action = (HV*) SvRV(*svp) ;
957 croak("internal error") ;
959 if (sv_isa(sv, "DB_File::HASHINFO"))
963 croak("DB_File can only tie an associative array to a DB_HASH database") ;
965 RETVAL->type = DB_HASH ;
966 openinfo = (void*)info ;
968 svp = hv_fetch(action, "hash", 4, FALSE);
970 if (svp && SvOK(*svp))
972 info->db_HA_hash = hash_cb ;
973 RETVAL->hash = newSVsv(*svp) ;
976 info->db_HA_hash = NULL ;
978 svp = hv_fetch(action, "ffactor", 7, FALSE);
979 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
981 svp = hv_fetch(action, "nelem", 5, FALSE);
982 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
984 svp = hv_fetch(action, "bsize", 5, FALSE);
985 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
987 svp = hv_fetch(action, "cachesize", 9, FALSE);
988 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
990 svp = hv_fetch(action, "lorder", 6, FALSE);
991 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
995 else if (sv_isa(sv, "DB_File::BTREEINFO"))
998 croak("DB_File can only tie an associative array to a DB_BTREE database");
1000 RETVAL->type = DB_BTREE ;
1001 openinfo = (void*)info ;
1003 svp = hv_fetch(action, "compare", 7, FALSE);
1004 if (svp && SvOK(*svp))
1006 info->db_BT_compare = btree_compare ;
1007 RETVAL->compare = newSVsv(*svp) ;
1010 info->db_BT_compare = NULL ;
1012 svp = hv_fetch(action, "prefix", 6, FALSE);
1013 if (svp && SvOK(*svp))
1015 info->db_BT_prefix = btree_prefix ;
1016 RETVAL->prefix = newSVsv(*svp) ;
1019 info->db_BT_prefix = NULL ;
1021 svp = hv_fetch(action, "flags", 5, FALSE);
1022 info->db_BT_flags = svp ? SvIV(*svp) : 0;
1024 svp = hv_fetch(action, "cachesize", 9, FALSE);
1025 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
1027 #ifndef DB_VERSION_MAJOR
1028 svp = hv_fetch(action, "minkeypage", 10, FALSE);
1029 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
1031 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
1032 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1035 svp = hv_fetch(action, "psize", 5, FALSE);
1036 info->db_BT_psize = svp ? SvIV(*svp) : 0;
1038 svp = hv_fetch(action, "lorder", 6, FALSE);
1039 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1044 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1047 croak("DB_File can only tie an array to a DB_RECNO database");
1049 RETVAL->type = DB_RECNO ;
1050 openinfo = (void *)info ;
1052 info->db_RE_flags = 0 ;
1054 svp = hv_fetch(action, "flags", 5, FALSE);
1055 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1057 svp = hv_fetch(action, "reclen", 6, FALSE);
1058 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1060 svp = hv_fetch(action, "cachesize", 9, FALSE);
1061 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1063 svp = hv_fetch(action, "psize", 5, FALSE);
1064 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1066 svp = hv_fetch(action, "lorder", 6, FALSE);
1067 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1069 #ifdef DB_VERSION_MAJOR
1070 info->re_source = name ;
1073 svp = hv_fetch(action, "bfname", 6, FALSE);
1074 if (svp && SvOK(*svp)) {
1075 char * ptr = SvPV(*svp,n_a) ;
1076 #ifdef DB_VERSION_MAJOR
1077 name = (char*) n_a ? ptr : NULL ;
1079 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1083 #ifdef DB_VERSION_MAJOR
1086 info->db_RE_bfname = NULL ;
1089 svp = hv_fetch(action, "bval", 4, FALSE);
1090 #ifdef DB_VERSION_MAJOR
1091 if (svp && SvOK(*svp))
1095 value = (int)*SvPV(*svp, n_a) ;
1097 value = SvIV(*svp) ;
1099 if (info->flags & DB_FIXEDLEN) {
1100 info->re_pad = value ;
1101 info->flags |= DB_PAD ;
1104 info->re_delim = value ;
1105 info->flags |= DB_DELIMITER ;
1110 if (svp && SvOK(*svp))
1113 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1115 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1116 DB_flags(info->flags, DB_DELIMITER) ;
1121 if (info->db_RE_flags & R_FIXEDLEN)
1122 info->db_RE_bval = (u_char) ' ' ;
1124 info->db_RE_bval = (u_char) '\n' ;
1125 DB_flags(info->flags, DB_DELIMITER) ;
1130 info->flags |= DB_RENUMBER ;
1136 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1140 /* OS2 Specific Code */
1144 #endif /* __EMX__ */
1147 #ifdef DB_VERSION_MAJOR
1153 /* Map 1.x flags to 2.x flags */
1154 if ((flags & O_CREAT) == O_CREAT)
1155 Flags |= DB_CREATE ;
1158 if (flags == O_RDONLY)
1160 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1162 Flags |= DB_RDONLY ;
1165 if ((flags & O_TRUNC) == O_TRUNC)
1166 Flags |= DB_TRUNCATE ;
1169 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1171 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1172 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1174 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1179 RETVAL->dbp = NULL ;
1184 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1185 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1187 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1188 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1194 #else /* Berkeley DB Version > 2 */
1198 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1204 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1205 Zero(RETVAL, 1, DB_File_type) ;
1207 /* Default to HASH */
1208 RETVAL->filtering = 0 ;
1209 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1210 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1211 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1212 RETVAL->type = DB_HASH ;
1214 /* DGH - Next line added to avoid SEGV on existing hash DB */
1217 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1218 RETVAL->in_memory = (name == NULL) ;
1220 status = db_create(&RETVAL->dbp, NULL,0) ;
1221 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1223 RETVAL->dbp = NULL ;
1231 croak ("type parameter is not a reference") ;
1233 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1234 if (svp && SvOK(*svp))
1235 action = (HV*) SvRV(*svp) ;
1237 croak("internal error") ;
1239 if (sv_isa(sv, "DB_File::HASHINFO"))
1243 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1245 RETVAL->type = DB_HASH ;
1247 svp = hv_fetch(action, "hash", 4, FALSE);
1249 if (svp && SvOK(*svp))
1251 (void)dbp->set_h_hash(dbp, hash_cb) ;
1252 RETVAL->hash = newSVsv(*svp) ;
1255 svp = hv_fetch(action, "ffactor", 7, FALSE);
1257 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1259 svp = hv_fetch(action, "nelem", 5, FALSE);
1261 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1263 svp = hv_fetch(action, "bsize", 5, FALSE);
1265 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1267 svp = hv_fetch(action, "cachesize", 9, FALSE);
1269 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1271 svp = hv_fetch(action, "lorder", 6, FALSE);
1273 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1277 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1280 croak("DB_File can only tie an associative array to a DB_BTREE database");
1282 RETVAL->type = DB_BTREE ;
1284 svp = hv_fetch(action, "compare", 7, FALSE);
1285 if (svp && SvOK(*svp))
1287 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1288 RETVAL->compare = newSVsv(*svp) ;
1291 svp = hv_fetch(action, "prefix", 6, FALSE);
1292 if (svp && SvOK(*svp))
1294 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1295 RETVAL->prefix = newSVsv(*svp) ;
1298 svp = hv_fetch(action, "flags", 5, FALSE);
1300 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1302 svp = hv_fetch(action, "cachesize", 9, FALSE);
1304 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1306 svp = hv_fetch(action, "psize", 5, FALSE);
1308 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1310 svp = hv_fetch(action, "lorder", 6, FALSE);
1312 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1317 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1322 croak("DB_File can only tie an array to a DB_RECNO database");
1324 RETVAL->type = DB_RECNO ;
1326 svp = hv_fetch(action, "flags", 5, FALSE);
1328 int flags = SvIV(*svp) ;
1329 /* remove FIXDLEN, if present */
1330 if (flags & DB_FIXEDLEN) {
1332 flags &= ~DB_FIXEDLEN ;
1336 svp = hv_fetch(action, "cachesize", 9, FALSE);
1338 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1341 svp = hv_fetch(action, "psize", 5, FALSE);
1343 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1346 svp = hv_fetch(action, "lorder", 6, FALSE);
1348 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1351 svp = hv_fetch(action, "bval", 4, FALSE);
1352 if (svp && SvOK(*svp))
1356 value = (int)*SvPV(*svp, n_a) ;
1358 value = (int)SvIV(*svp) ;
1361 status = dbp->set_re_pad(dbp, value) ;
1364 status = dbp->set_re_delim(dbp, value) ;
1370 svp = hv_fetch(action, "reclen", 6, FALSE);
1372 u_int32_t len = my_SvUV32(*svp) ;
1373 status = dbp->set_re_len(dbp, len) ;
1378 status = dbp->set_re_source(dbp, name) ;
1382 svp = hv_fetch(action, "bfname", 6, FALSE);
1383 if (svp && SvOK(*svp)) {
1384 char * ptr = SvPV(*svp,n_a) ;
1385 name = (char*) n_a ? ptr : NULL ;
1391 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1394 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1399 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1403 u_int32_t Flags = 0 ;
1406 /* Map 1.x flags to 3.x flags */
1407 if ((flags & O_CREAT) == O_CREAT)
1408 Flags |= DB_CREATE ;
1411 if (flags == O_RDONLY)
1413 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1415 Flags |= DB_RDONLY ;
1418 if ((flags & O_TRUNC) == O_TRUNC)
1419 Flags |= DB_TRUNCATE ;
1422 #ifdef AT_LEAST_DB_4_1
1423 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1426 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1429 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1432 /* RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;*/
1434 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1436 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1440 RETVAL->dbp = NULL ;
1446 #endif /* Berkeley DB Version > 2 */
1448 } /* ParseOpenInfo */
1451 #include "constants.h"
1453 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1455 INCLUDE: constants.xs
1462 /* SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ; */
1464 __getBerkeleyDBInfo() ;
1467 empty.data = &zero ;
1468 empty.size = sizeof(recno_t) ;
1474 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1481 char * name = (char *) NULL ;
1482 SV * sv = (SV *) NULL ;
1485 if (items >= 3 && SvOK(ST(2)))
1486 name = (char*) SvPV(ST(2), n_a) ;
1491 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1492 if (RETVAL->dbp == NULL)
1505 Trace(("DESTROY %p\n", db));
1507 Trace(("DESTROY %p done\n", db));
1509 SvREFCNT_dec(db->hash) ;
1511 SvREFCNT_dec(db->compare) ;
1513 SvREFCNT_dec(db->prefix) ;
1514 if (db->filter_fetch_key)
1515 SvREFCNT_dec(db->filter_fetch_key) ;
1516 if (db->filter_store_key)
1517 SvREFCNT_dec(db->filter_store_key) ;
1518 if (db->filter_fetch_value)
1519 SvREFCNT_dec(db->filter_fetch_value) ;
1520 if (db->filter_store_value)
1521 SvREFCNT_dec(db->filter_store_value) ;
1523 #ifdef DB_VERSION_MAJOR
1530 db_DELETE(db, key, flags=0)
1552 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1558 db_FETCH(db, key, flags=0)
1571 RETVAL = db_get(db, key, value, flags) ;
1572 ST(0) = sv_newmortal();
1573 OutputValue(ST(0), value)
1577 db_STORE(db, key, value, flags=0)
1602 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1603 ST(0) = sv_newmortal();
1604 OutputKey(ST(0), key) ;
1610 DBTKEY key = NO_INIT
1621 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1622 ST(0) = sv_newmortal();
1623 OutputKey(ST(0), key) ;
1627 # These would be nice for RECNO
1647 #ifdef DB_VERSION_MAJOR
1648 /* get the first value */
1649 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1654 for (i = items-1 ; i > 0 ; --i)
1656 value.data = SvPV(ST(i), n_a) ;
1660 key.size = sizeof(int) ;
1661 #ifdef DB_VERSION_MAJOR
1662 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1664 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1690 /* First get the final value */
1691 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1692 ST(0) = sv_newmortal();
1696 /* the call to del will trash value, so take a copy now */
1697 OutputValue(ST(0), value) ;
1698 RETVAL = db_del(db, key, R_CURSOR) ;
1700 sv_setsv(ST(0), &PL_sv_undef);
1720 /* get the first value */
1721 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1722 ST(0) = sv_newmortal();
1726 /* the call to del will trash value, so take a copy now */
1727 OutputValue(ST(0), value) ;
1728 RETVAL = db_del(db, key, R_CURSOR) ;
1730 sv_setsv (ST(0), &PL_sv_undef) ;
1753 /* Set the Cursor to the Last element */
1754 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1755 #ifndef DB_VERSION_MAJOR
1760 keyval = *(int*)key.data ;
1763 for (i = 1 ; i < items ; ++i)
1765 value.data = SvPV(ST(i), n_a) ;
1768 key.data = &keyval ;
1769 key.size = sizeof(int) ;
1770 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1784 ALIAS: FETCHSIZE = 1
1787 RETVAL = GetArrayLength(aTHX_ db) ;
1793 # Now provide an interface to the rest of the DB functionality
1797 db_del(db, key, flags=0)
1805 RETVAL = db_del(db, key, flags) ;
1806 #ifdef DB_VERSION_MAJOR
1809 else if (RETVAL == DB_NOTFOUND)
1817 db_get(db, key, value, flags=0)
1827 RETVAL = db_get(db, key, value, flags) ;
1828 #ifdef DB_VERSION_MAJOR
1831 else if (RETVAL == DB_NOTFOUND)
1839 db_put(db, key, value, flags=0)
1848 RETVAL = db_put(db, key, value, flags) ;
1849 #ifdef DB_VERSION_MAJOR
1852 else if (RETVAL == DB_KEYEXIST)
1857 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1866 #ifdef DB_VERSION_MAJOR
1870 status = (db->in_memory
1872 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1877 RETVAL = (db->in_memory
1879 : ((db->dbp)->fd)(db->dbp) ) ;
1885 db_sync(db, flags=0)
1892 RETVAL = db_sync(db, flags) ;
1893 #ifdef DB_VERSION_MAJOR
1902 db_seq(db, key, value, flags)
1912 RETVAL = db_seq(db, key, value, flags);
1913 #ifdef DB_VERSION_MAJOR
1916 else if (RETVAL == DB_NOTFOUND)
1925 filter_fetch_key(db, code)
1928 SV * RETVAL = &PL_sv_undef ;
1930 DBM_setFilter(db->filter_fetch_key, code) ;
1933 filter_store_key(db, code)
1936 SV * RETVAL = &PL_sv_undef ;
1938 DBM_setFilter(db->filter_store_key, code) ;
1941 filter_fetch_value(db, code)
1944 SV * RETVAL = &PL_sv_undef ;
1946 DBM_setFilter(db->filter_fetch_value, code) ;
1949 filter_store_value(db, code)
1952 SV * RETVAL = &PL_sv_undef ;
1954 DBM_setFilter(db->filter_store_value, code) ;