3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <pmqs@cpan.org>
6 last modified 12th March 2005
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2005 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
118 #define PERL_NO_GET_CONTEXT
127 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
128 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
130 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
131 * shortly #included by the <db.h>) __attribute__ to the possibly
132 * already defined __attribute__, for example by GNUC or by Perl. */
134 /* #if DB_VERSION_MAJOR_CFG < 2 */
135 #ifndef DB_VERSION_MAJOR
136 # undef __attribute__
145 /* Wall starts with 5.7.x */
147 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
149 /* Since we dropped the gccish definition of __attribute__ we will want
150 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
151 * all this means that we can't do attribute checking on the DB_File,
153 # ifndef DB_VERSION_MAJOR
156 # define dNOOP extern int Perl___notused
158 /* Ditto for dXSARGS. */
162 I32 ax = mark - PL_stack_base + 1; \
163 I32 items = sp - mark
167 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
169 # define dXSI32 dNOOP
171 #endif /* Perl >= 5.7 */
178 # define Trace(x) printf x
184 #define DBT_clear(x) Zero(&x, 1, DBT) ;
186 #ifdef DB_VERSION_MAJOR
188 #if DB_VERSION_MAJOR == 2
189 # define BERKELEY_DB_1_OR_2
192 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
193 # define AT_LEAST_DB_3_2
196 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
197 # define AT_LEAST_DB_4_1
200 /* map version 2 features & constants onto their version 1 equivalent */
205 #define DB_Prefix_t size_t
210 #define DB_Hash_t u_int32_t
212 /* DBTYPE stays the same */
213 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
214 #if DB_VERSION_MAJOR == 2
215 typedef DB_INFO INFO ;
216 #else /* DB_VERSION_MAJOR > 2 */
217 # define DB_FIXEDLEN (0x8000)
218 #endif /* DB_VERSION_MAJOR == 2 */
220 /* version 2 has db_recno_t in place of recno_t */
221 typedef db_recno_t recno_t;
224 #define R_CURSOR DB_SET_RANGE
225 #define R_FIRST DB_FIRST
226 #define R_IAFTER DB_AFTER
227 #define R_IBEFORE DB_BEFORE
228 #define R_LAST DB_LAST
229 #define R_NEXT DB_NEXT
230 #define R_NOOVERWRITE DB_NOOVERWRITE
231 #define R_PREV DB_PREV
233 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
234 # define R_SETCURSOR 0x800000
236 # define R_SETCURSOR (-100)
239 #define R_RECNOSYNC 0
240 #define R_FIXEDLEN DB_FIXEDLEN
244 #define db_HA_hash h_hash
245 #define db_HA_ffactor h_ffactor
246 #define db_HA_nelem h_nelem
247 #define db_HA_bsize db_pagesize
248 #define db_HA_cachesize db_cachesize
249 #define db_HA_lorder db_lorder
251 #define db_BT_compare bt_compare
252 #define db_BT_prefix bt_prefix
253 #define db_BT_flags flags
254 #define db_BT_psize db_pagesize
255 #define db_BT_cachesize db_cachesize
256 #define db_BT_lorder db_lorder
257 #define db_BT_maxkeypage
258 #define db_BT_minkeypage
261 #define db_RE_reclen re_len
262 #define db_RE_flags flags
263 #define db_RE_bval re_pad
264 #define db_RE_bfname re_source
265 #define db_RE_psize db_pagesize
266 #define db_RE_cachesize db_cachesize
267 #define db_RE_lorder db_lorder
271 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
274 #define DBT_flags(x) x.flags = 0
275 #define DB_flags(x, v) x |= v
277 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
278 # define flagSet(flags, bitmask) ((flags) & (bitmask))
280 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
283 #else /* db version 1.x */
285 #define BERKELEY_DB_1
286 #define BERKELEY_DB_1_OR_2
299 # define DB_Prefix_t mDB_Prefix_t
306 # define DB_Hash_t mDB_Hash_t
309 #define db_HA_hash hash.hash
310 #define db_HA_ffactor hash.ffactor
311 #define db_HA_nelem hash.nelem
312 #define db_HA_bsize hash.bsize
313 #define db_HA_cachesize hash.cachesize
314 #define db_HA_lorder hash.lorder
316 #define db_BT_compare btree.compare
317 #define db_BT_prefix btree.prefix
318 #define db_BT_flags btree.flags
319 #define db_BT_psize btree.psize
320 #define db_BT_cachesize btree.cachesize
321 #define db_BT_lorder btree.lorder
322 #define db_BT_maxkeypage btree.maxkeypage
323 #define db_BT_minkeypage btree.minkeypage
325 #define db_RE_reclen recno.reclen
326 #define db_RE_flags recno.flags
327 #define db_RE_bval recno.bval
328 #define db_RE_bfname recno.bfname
329 #define db_RE_psize recno.psize
330 #define db_RE_cachesize recno.cachesize
331 #define db_RE_lorder recno.lorder
335 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
337 #define DB_flags(x, v)
338 #define flagSet(flags, bitmask) ((flags) & (bitmask))
340 #endif /* db version 1 */
344 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
345 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
346 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
348 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
349 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
351 #ifdef DB_VERSION_MAJOR
352 #define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
353 (db->dbp->close)(db->dbp, 0) ))
354 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
355 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
356 ? ((db->cursor)->c_del)(db->cursor, 0) \
357 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
359 #else /* ! DB_VERSION_MAJOR */
361 #define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
362 #define db_close(db) ((db->dbp)->close)(db->dbp)
363 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
364 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
366 #endif /* ! DB_VERSION_MAJOR */
369 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
382 #ifdef BERKELEY_DB_1_OR_2
385 #ifdef DB_VERSION_MAJOR
388 SV * filter_fetch_key ;
389 SV * filter_store_key ;
390 SV * filter_fetch_value ;
391 SV * filter_store_value ;
396 typedef DB_File_type * DB_File ;
399 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
401 #define OutputValue(arg, name) \
402 { if (RETVAL == 0) { \
404 my_sv_setpvn(arg, name.data, name.size) ; \
408 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
412 #define OutputKey(arg, name) \
416 if (db->type != DB_RECNO) { \
417 my_sv_setpvn(arg, name.data, name.size); \
420 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
424 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
428 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
431 extern void __getBerkeleyDBInfo(void);
434 /* Internal Global Data */
436 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
447 #define Value (MY_CXT.x_Value)
448 #define zero (MY_CXT.x_zero)
449 #define CurrentDB (MY_CXT.x_CurrentDB)
450 #define empty (MY_CXT.x_empty)
452 #define ERR_BUFF "DB_File::Error"
454 #ifdef DB_VERSION_MAJOR
458 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
460 db_put(db, key, value, flags)
469 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
473 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
474 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
476 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
480 memset(&l_key, 0, sizeof(l_key));
481 l_key.data = key.data;
482 l_key.size = key.size;
483 memset(&l_value, 0, sizeof(l_value));
484 l_value.data = value.data;
485 l_value.size = value.size;
487 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
488 (void)temp_cursor->c_close(temp_cursor);
492 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
493 (void)temp_cursor->c_close(temp_cursor);
499 if (flagSet(flags, R_CURSOR)) {
500 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
503 if (flagSet(flags, R_SETCURSOR)) {
504 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
506 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
510 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
514 #endif /* DB_VERSION_MAJOR */
524 #ifdef AT_LEAST_DB_3_2
527 btree_compare(DB * db, const DBT *key1, const DBT *key2)
529 btree_compare(db, key1, key2)
533 #endif /* CAN_PROTOTYPE */
535 #else /* Berkeley DB < 3.2 */
538 btree_compare(const DBT *key1, const DBT *key2)
540 btree_compare(key1, key2)
553 void * data1, * data2 ;
558 if (CurrentDB->in_compare) {
560 croak ("DB_File btree_compare: recursion detected\n") ;
563 data1 = (char *) key1->data ;
564 data2 = (char *) key2->data ;
567 /* As newSVpv will assume that the data pointer is a null terminated C
568 string if the size parameter is 0, make sure that data points to an
569 empty string if the length is 0
580 CurrentDB->in_compare = FALSE;
581 SAVEINT(CurrentDB->in_compare);
582 CurrentDB->in_compare = TRUE;
586 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
587 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
590 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
596 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
610 #ifdef AT_LEAST_DB_3_2
613 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
615 btree_prefix(db, key1, key2)
621 #else /* Berkeley DB < 3.2 */
624 btree_prefix(const DBT *key1, const DBT *key2)
626 btree_prefix(key1, key2)
638 char * data1, * data2 ;
642 if (CurrentDB->in_prefix){
644 croak ("DB_File btree_prefix: recursion detected\n") ;
647 data1 = (char *) key1->data ;
648 data2 = (char *) key2->data ;
651 /* As newSVpv will assume that the data pointer is a null terminated C
652 string if the size parameter is 0, make sure that data points to an
653 empty string if the length is 0
664 CurrentDB->in_prefix = FALSE;
665 SAVEINT(CurrentDB->in_prefix);
666 CurrentDB->in_prefix = TRUE;
670 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
671 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
674 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
680 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
694 # define HASH_CB_SIZE_TYPE size_t
696 # define HASH_CB_SIZE_TYPE u_int32_t
700 #ifdef AT_LEAST_DB_3_2
703 hash_cb(DB * db, const void *data, u_int32_t size)
705 hash_cb(db, data, size)
708 HASH_CB_SIZE_TYPE size ;
711 #else /* Berkeley DB < 3.2 */
714 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
718 HASH_CB_SIZE_TYPE size ;
731 if (CurrentDB->in_hash){
733 croak ("DB_File hash callback: recursion detected\n") ;
741 /* DGH - Next two lines added to fix corrupted stack problem */
745 CurrentDB->in_hash = FALSE;
746 SAVEINT(CurrentDB->in_hash);
747 CurrentDB->in_hash = TRUE;
752 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
755 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
761 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
776 db_errcall_cb(const char * db_errpfx, char * buffer)
778 db_errcall_cb(db_errpfx, buffer)
779 const char * db_errpfx;
786 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
789 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
791 sv_setpv(sv, buffer) ;
796 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
800 PrintHash(INFO *hash)
806 printf ("HASH Info\n") ;
807 printf (" hash = %s\n",
808 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
809 printf (" bsize = %d\n", hash->db_HA_bsize) ;
810 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
811 printf (" nelem = %d\n", hash->db_HA_nelem) ;
812 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
813 printf (" lorder = %d\n", hash->db_HA_lorder) ;
819 PrintRecno(INFO *recno)
825 printf ("RECNO Info\n") ;
826 printf (" flags = %d\n", recno->db_RE_flags) ;
827 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
828 printf (" psize = %d\n", recno->db_RE_psize) ;
829 printf (" lorder = %d\n", recno->db_RE_lorder) ;
830 printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ;
831 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
832 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
837 PrintBtree(INFO *btree)
843 printf ("BTREE Info\n") ;
844 printf (" compare = %s\n",
845 (btree->db_BT_compare ? "redefined" : "default")) ;
846 printf (" prefix = %s\n",
847 (btree->db_BT_prefix ? "redefined" : "default")) ;
848 printf (" flags = %d\n", btree->db_BT_flags) ;
849 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
850 printf (" psize = %d\n", btree->db_BT_psize) ;
851 #ifndef DB_VERSION_MAJOR
852 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
853 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
855 printf (" lorder = %d\n", btree->db_BT_lorder) ;
860 #define PrintRecno(recno)
861 #define PrintHash(hash)
862 #define PrintBtree(btree)
869 GetArrayLength(pTHX_ DB_File db)
881 RETVAL = do_SEQ(db, key, value, R_LAST) ;
883 RETVAL = *(I32 *)key.data ;
884 else /* No key means empty file */
887 return ((I32)RETVAL) ;
892 GetRecnoKey(pTHX_ DB_File db, I32 value)
894 GetRecnoKey(db, value)
900 /* Get the length of the array */
901 I32 length = GetArrayLength(aTHX_ db) ;
903 /* check for attempt to write before start of array */
904 if (length + value + 1 <= 0) {
906 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
909 value = length + value + 1 ;
920 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
922 ParseOpenInfo(isHASH, name, flags, mode, sv)
931 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
935 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
936 void * openinfo = NULL ;
937 INFO * info = &RETVAL->info ;
942 printf("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n",
943 name, flags, mode, sv == NULL) ;
945 Zero(RETVAL, 1, DB_File_type) ;
947 /* Default to HASH */
948 RETVAL->filtering = 0 ;
949 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
950 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
951 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
952 RETVAL->type = DB_HASH ;
954 /* DGH - Next line added to avoid SEGV on existing hash DB */
957 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
958 RETVAL->in_memory = (name == NULL) ;
963 croak ("type parameter is not a reference") ;
965 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
966 if (svp && SvOK(*svp))
967 action = (HV*) SvRV(*svp) ;
969 croak("internal error") ;
971 if (sv_isa(sv, "DB_File::HASHINFO"))
975 croak("DB_File can only tie an associative array to a DB_HASH database") ;
977 RETVAL->type = DB_HASH ;
978 openinfo = (void*)info ;
980 svp = hv_fetch(action, "hash", 4, FALSE);
982 if (svp && SvOK(*svp))
984 info->db_HA_hash = hash_cb ;
985 RETVAL->hash = newSVsv(*svp) ;
988 info->db_HA_hash = NULL ;
990 svp = hv_fetch(action, "ffactor", 7, FALSE);
991 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
993 svp = hv_fetch(action, "nelem", 5, FALSE);
994 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
996 svp = hv_fetch(action, "bsize", 5, FALSE);
997 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
999 svp = hv_fetch(action, "cachesize", 9, FALSE);
1000 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
1002 svp = hv_fetch(action, "lorder", 6, FALSE);
1003 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
1007 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1010 croak("DB_File can only tie an associative array to a DB_BTREE database");
1012 RETVAL->type = DB_BTREE ;
1013 openinfo = (void*)info ;
1015 svp = hv_fetch(action, "compare", 7, FALSE);
1016 if (svp && SvOK(*svp))
1018 info->db_BT_compare = btree_compare ;
1019 RETVAL->compare = newSVsv(*svp) ;
1022 info->db_BT_compare = NULL ;
1024 svp = hv_fetch(action, "prefix", 6, FALSE);
1025 if (svp && SvOK(*svp))
1027 info->db_BT_prefix = btree_prefix ;
1028 RETVAL->prefix = newSVsv(*svp) ;
1031 info->db_BT_prefix = NULL ;
1033 svp = hv_fetch(action, "flags", 5, FALSE);
1034 info->db_BT_flags = svp ? SvIV(*svp) : 0;
1036 svp = hv_fetch(action, "cachesize", 9, FALSE);
1037 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
1039 #ifndef DB_VERSION_MAJOR
1040 svp = hv_fetch(action, "minkeypage", 10, FALSE);
1041 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
1043 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
1044 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1047 svp = hv_fetch(action, "psize", 5, FALSE);
1048 info->db_BT_psize = svp ? SvIV(*svp) : 0;
1050 svp = hv_fetch(action, "lorder", 6, FALSE);
1051 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1056 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1059 croak("DB_File can only tie an array to a DB_RECNO database");
1061 RETVAL->type = DB_RECNO ;
1062 openinfo = (void *)info ;
1064 info->db_RE_flags = 0 ;
1066 svp = hv_fetch(action, "flags", 5, FALSE);
1067 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1069 svp = hv_fetch(action, "reclen", 6, FALSE);
1070 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1072 svp = hv_fetch(action, "cachesize", 9, FALSE);
1073 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1075 svp = hv_fetch(action, "psize", 5, FALSE);
1076 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1078 svp = hv_fetch(action, "lorder", 6, FALSE);
1079 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1081 #ifdef DB_VERSION_MAJOR
1082 info->re_source = name ;
1085 svp = hv_fetch(action, "bfname", 6, FALSE);
1086 if (svp && SvOK(*svp)) {
1087 char * ptr = SvPV(*svp,n_a) ;
1088 #ifdef DB_VERSION_MAJOR
1089 name = (char*) n_a ? ptr : NULL ;
1091 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1095 #ifdef DB_VERSION_MAJOR
1098 info->db_RE_bfname = NULL ;
1101 svp = hv_fetch(action, "bval", 4, FALSE);
1102 #ifdef DB_VERSION_MAJOR
1103 if (svp && SvOK(*svp))
1107 value = (int)*SvPV(*svp, n_a) ;
1109 value = SvIV(*svp) ;
1111 if (info->flags & DB_FIXEDLEN) {
1112 info->re_pad = value ;
1113 info->flags |= DB_PAD ;
1116 info->re_delim = value ;
1117 info->flags |= DB_DELIMITER ;
1122 if (svp && SvOK(*svp))
1125 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1127 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1128 DB_flags(info->flags, DB_DELIMITER) ;
1133 if (info->db_RE_flags & R_FIXEDLEN)
1134 info->db_RE_bval = (u_char) ' ' ;
1136 info->db_RE_bval = (u_char) '\n' ;
1137 DB_flags(info->flags, DB_DELIMITER) ;
1142 info->flags |= DB_RENUMBER ;
1148 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1152 /* OS2 Specific Code */
1156 #endif /* __EMX__ */
1159 #ifdef DB_VERSION_MAJOR
1165 /* Map 1.x flags to 2.x flags */
1166 if ((flags & O_CREAT) == O_CREAT)
1167 Flags |= DB_CREATE ;
1170 if (flags == O_RDONLY)
1172 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1174 Flags |= DB_RDONLY ;
1177 if ((flags & O_TRUNC) == O_TRUNC)
1178 Flags |= DB_TRUNCATE ;
1181 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1183 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1184 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1186 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1191 RETVAL->dbp = NULL ;
1196 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1197 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1199 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1200 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1206 #else /* Berkeley DB Version > 2 */
1210 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1216 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1217 Zero(RETVAL, 1, DB_File_type) ;
1219 /* Default to HASH */
1220 RETVAL->filtering = 0 ;
1221 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1222 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1223 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1224 RETVAL->type = DB_HASH ;
1226 /* DGH - Next line added to avoid SEGV on existing hash DB */
1229 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1230 RETVAL->in_memory = (name == NULL) ;
1232 status = db_create(&RETVAL->dbp, NULL,0) ;
1233 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1235 RETVAL->dbp = NULL ;
1243 croak ("type parameter is not a reference") ;
1245 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1246 if (svp && SvOK(*svp))
1247 action = (HV*) SvRV(*svp) ;
1249 croak("internal error") ;
1251 if (sv_isa(sv, "DB_File::HASHINFO"))
1255 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1257 RETVAL->type = DB_HASH ;
1259 svp = hv_fetch(action, "hash", 4, FALSE);
1261 if (svp && SvOK(*svp))
1263 (void)dbp->set_h_hash(dbp, hash_cb) ;
1264 RETVAL->hash = newSVsv(*svp) ;
1267 svp = hv_fetch(action, "ffactor", 7, FALSE);
1269 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1271 svp = hv_fetch(action, "nelem", 5, FALSE);
1273 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1275 svp = hv_fetch(action, "bsize", 5, FALSE);
1277 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1279 svp = hv_fetch(action, "cachesize", 9, FALSE);
1281 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1283 svp = hv_fetch(action, "lorder", 6, FALSE);
1285 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1289 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1292 croak("DB_File can only tie an associative array to a DB_BTREE database");
1294 RETVAL->type = DB_BTREE ;
1296 svp = hv_fetch(action, "compare", 7, FALSE);
1297 if (svp && SvOK(*svp))
1299 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1300 RETVAL->compare = newSVsv(*svp) ;
1303 svp = hv_fetch(action, "prefix", 6, FALSE);
1304 if (svp && SvOK(*svp))
1306 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1307 RETVAL->prefix = newSVsv(*svp) ;
1310 svp = hv_fetch(action, "flags", 5, FALSE);
1312 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1314 svp = hv_fetch(action, "cachesize", 9, FALSE);
1316 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1318 svp = hv_fetch(action, "psize", 5, FALSE);
1320 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1322 svp = hv_fetch(action, "lorder", 6, FALSE);
1324 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1329 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1334 croak("DB_File can only tie an array to a DB_RECNO database");
1336 RETVAL->type = DB_RECNO ;
1338 svp = hv_fetch(action, "flags", 5, FALSE);
1340 int flags = SvIV(*svp) ;
1341 /* remove FIXDLEN, if present */
1342 if (flags & DB_FIXEDLEN) {
1344 flags &= ~DB_FIXEDLEN ;
1348 svp = hv_fetch(action, "cachesize", 9, FALSE);
1350 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1353 svp = hv_fetch(action, "psize", 5, FALSE);
1355 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1358 svp = hv_fetch(action, "lorder", 6, FALSE);
1360 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1363 svp = hv_fetch(action, "bval", 4, FALSE);
1364 if (svp && SvOK(*svp))
1368 value = (int)*SvPV(*svp, n_a) ;
1370 value = (int)SvIV(*svp) ;
1373 status = dbp->set_re_pad(dbp, value) ;
1376 status = dbp->set_re_delim(dbp, value) ;
1382 svp = hv_fetch(action, "reclen", 6, FALSE);
1384 u_int32_t len = my_SvUV32(*svp) ;
1385 status = dbp->set_re_len(dbp, len) ;
1390 status = dbp->set_re_source(dbp, name) ;
1394 svp = hv_fetch(action, "bfname", 6, FALSE);
1395 if (svp && SvOK(*svp)) {
1396 char * ptr = SvPV(*svp,n_a) ;
1397 name = (char*) n_a ? ptr : NULL ;
1403 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1406 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1411 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1415 u_int32_t Flags = 0 ;
1418 /* Map 1.x flags to 3.x flags */
1419 if ((flags & O_CREAT) == O_CREAT)
1420 Flags |= DB_CREATE ;
1423 if (flags == O_RDONLY)
1425 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1427 Flags |= DB_RDONLY ;
1430 if ((flags & O_TRUNC) == O_TRUNC)
1431 Flags |= DB_TRUNCATE ;
1434 #ifdef AT_LEAST_DB_4_1
1435 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1438 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1441 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1444 /* RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;*/
1446 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1448 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1452 RETVAL->dbp = NULL ;
1458 #endif /* Berkeley DB Version > 2 */
1460 } /* ParseOpenInfo */
1463 #include "constants.h"
1465 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1467 INCLUDE: constants.xs
1474 /* SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ; */
1476 __getBerkeleyDBInfo() ;
1479 empty.data = &zero ;
1480 empty.size = sizeof(recno_t) ;
1486 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1493 char * name = (char *) NULL ;
1494 SV * sv = (SV *) NULL ;
1497 if (items >= 3 && SvOK(ST(2)))
1498 name = (char*) SvPV(ST(2), n_a) ;
1503 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1504 if (RETVAL->dbp == NULL) {
1519 Trace(("DESTROY %p\n", db));
1521 Trace(("DESTROY %p done\n", db));
1523 SvREFCNT_dec(db->hash) ;
1525 SvREFCNT_dec(db->compare) ;
1527 SvREFCNT_dec(db->prefix) ;
1528 if (db->filter_fetch_key)
1529 SvREFCNT_dec(db->filter_fetch_key) ;
1530 if (db->filter_store_key)
1531 SvREFCNT_dec(db->filter_store_key) ;
1532 if (db->filter_fetch_value)
1533 SvREFCNT_dec(db->filter_fetch_value) ;
1534 if (db->filter_store_value)
1535 SvREFCNT_dec(db->filter_store_value) ;
1537 #ifdef DB_VERSION_MAJOR
1544 db_DELETE(db, key, flags=0)
1566 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1572 db_FETCH(db, key, flags=0)
1585 RETVAL = db_get(db, key, value, flags) ;
1586 ST(0) = sv_newmortal();
1587 OutputValue(ST(0), value)
1591 db_STORE(db, key, value, flags=0)
1616 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1617 ST(0) = sv_newmortal();
1618 OutputKey(ST(0), key) ;
1624 DBTKEY key = NO_INIT
1635 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1636 ST(0) = sv_newmortal();
1637 OutputKey(ST(0), key) ;
1641 # These would be nice for RECNO
1661 #ifdef DB_VERSION_MAJOR
1662 /* get the first value */
1663 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1668 for (i = items-1 ; i > 0 ; --i)
1670 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1671 value.data = SvPVbyte(ST(i), n_a) ;
1675 key.size = sizeof(int) ;
1676 #ifdef DB_VERSION_MAJOR
1677 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1679 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1705 /* First get the final value */
1706 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1707 ST(0) = sv_newmortal();
1711 /* the call to del will trash value, so take a copy now */
1712 OutputValue(ST(0), value) ;
1713 RETVAL = db_del(db, key, R_CURSOR) ;
1715 sv_setsv(ST(0), &PL_sv_undef);
1735 /* get the first value */
1736 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1737 ST(0) = sv_newmortal();
1741 /* the call to del will trash value, so take a copy now */
1742 OutputValue(ST(0), value) ;
1743 RETVAL = db_del(db, key, R_CURSOR) ;
1745 sv_setsv (ST(0), &PL_sv_undef) ;
1768 /* Set the Cursor to the Last element */
1769 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1770 #ifndef DB_VERSION_MAJOR
1775 keyval = *(int*)key.data ;
1778 for (i = 1 ; i < items ; ++i)
1780 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1781 value.data = SvPVbyte(ST(i), n_a) ;
1784 key.data = &keyval ;
1785 key.size = sizeof(int) ;
1786 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1800 ALIAS: FETCHSIZE = 1
1803 RETVAL = GetArrayLength(aTHX_ db) ;
1809 # Now provide an interface to the rest of the DB functionality
1813 db_del(db, key, flags=0)
1821 RETVAL = db_del(db, key, flags) ;
1822 #ifdef DB_VERSION_MAJOR
1825 else if (RETVAL == DB_NOTFOUND)
1833 db_get(db, key, value, flags=0)
1843 RETVAL = db_get(db, key, value, flags) ;
1844 #ifdef DB_VERSION_MAJOR
1847 else if (RETVAL == DB_NOTFOUND)
1855 db_put(db, key, value, flags=0)
1864 RETVAL = db_put(db, key, value, flags) ;
1865 #ifdef DB_VERSION_MAJOR
1868 else if (RETVAL == DB_KEYEXIST)
1873 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1882 #ifdef DB_VERSION_MAJOR
1886 status = (db->in_memory
1888 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1893 RETVAL = (db->in_memory
1895 : ((db->dbp)->fd)(db->dbp) ) ;
1901 db_sync(db, flags=0)
1908 RETVAL = db_sync(db, flags) ;
1909 #ifdef DB_VERSION_MAJOR
1918 db_seq(db, key, value, flags)
1928 RETVAL = db_seq(db, key, value, flags);
1929 #ifdef DB_VERSION_MAJOR
1932 else if (RETVAL == DB_NOTFOUND)
1941 filter_fetch_key(db, code)
1944 SV * RETVAL = &PL_sv_undef ;
1946 DBM_setFilter(db->filter_fetch_key, code) ;
1949 filter_store_key(db, code)
1952 SV * RETVAL = &PL_sv_undef ;
1954 DBM_setFilter(db->filter_store_key, code) ;
1957 filter_fetch_value(db, code)
1960 SV * RETVAL = &PL_sv_undef ;
1962 DBM_setFilter(db->filter_fetch_value, code) ;
1965 filter_store_value(db, code)
1968 SV * RETVAL = &PL_sv_undef ;
1970 DBM_setFilter(db->filter_store_value, code) ;