3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 26th April 2001
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2001 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.
103 # include "patchlevel.h"
104 # define PERL_REVISION 5
105 # define PERL_VERSION PATCHLEVEL
106 # define PERL_SUBVERSION SUBVERSION
109 #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
111 # define PL_sv_undef sv_undef
116 /* DEFSV appears first in 5.004_56 */
118 # define DEFSV GvSV(defgv)
121 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
122 * shortly #included by the <db.h>) __attribute__ to the possibly
123 * already defined __attribute__, for example by GNUC or by Perl. */
127 /* Since we dropped the gccish definition of __attribute__ we will want
128 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
129 * all this means that we can't do attribute checking on the DB_File,
132 #define dNOOP extern int Perl___notused
134 /* If Perl has been compiled with Threads support,the symbol op will
135 be defined here. This clashes with a field name in db.h, so get rid of it.
148 extern void __getBerkeleyDBInfo(void);
159 # define newSVpvn(a,b) newSVpv(a,b)
165 #define DBM_FILTERING
168 # define Trace(x) printf x
174 #define DBT_clear(x) Zero(&x, 1, DBT) ;
176 #ifdef DB_VERSION_MAJOR
178 #if DB_VERSION_MAJOR == 2
179 # define BERKELEY_DB_1_OR_2
182 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
183 # define AT_LEAST_DB_3_2
186 /* map version 2 features & constants onto their version 1 equivalent */
191 #define DB_Prefix_t size_t
196 #define DB_Hash_t u_int32_t
198 /* DBTYPE stays the same */
199 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
200 #if DB_VERSION_MAJOR == 2
201 typedef DB_INFO INFO ;
202 #else /* DB_VERSION_MAJOR > 2 */
203 # define DB_FIXEDLEN (0x8000)
204 #endif /* DB_VERSION_MAJOR == 2 */
206 /* version 2 has db_recno_t in place of recno_t */
207 typedef db_recno_t recno_t;
210 #define R_CURSOR DB_SET_RANGE
211 #define R_FIRST DB_FIRST
212 #define R_IAFTER DB_AFTER
213 #define R_IBEFORE DB_BEFORE
214 #define R_LAST DB_LAST
215 #define R_NEXT DB_NEXT
216 #define R_NOOVERWRITE DB_NOOVERWRITE
217 #define R_PREV DB_PREV
219 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
220 # define R_SETCURSOR 0x800000
222 # define R_SETCURSOR (-100)
225 #define R_RECNOSYNC 0
226 #define R_FIXEDLEN DB_FIXEDLEN
230 #define db_HA_hash h_hash
231 #define db_HA_ffactor h_ffactor
232 #define db_HA_nelem h_nelem
233 #define db_HA_bsize db_pagesize
234 #define db_HA_cachesize db_cachesize
235 #define db_HA_lorder db_lorder
237 #define db_BT_compare bt_compare
238 #define db_BT_prefix bt_prefix
239 #define db_BT_flags flags
240 #define db_BT_psize db_pagesize
241 #define db_BT_cachesize db_cachesize
242 #define db_BT_lorder db_lorder
243 #define db_BT_maxkeypage
244 #define db_BT_minkeypage
247 #define db_RE_reclen re_len
248 #define db_RE_flags flags
249 #define db_RE_bval re_pad
250 #define db_RE_bfname re_source
251 #define db_RE_psize db_pagesize
252 #define db_RE_cachesize db_cachesize
253 #define db_RE_lorder db_lorder
257 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
260 #define DBT_flags(x) x.flags = 0
261 #define DB_flags(x, v) x |= v
263 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
264 # define flagSet(flags, bitmask) ((flags) & (bitmask))
266 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
269 #else /* db version 1.x */
271 #define BERKELEY_DB_1
272 #define BERKELEY_DB_1_OR_2
285 # define DB_Prefix_t mDB_Prefix_t
292 # define DB_Hash_t mDB_Hash_t
295 #define db_HA_hash hash.hash
296 #define db_HA_ffactor hash.ffactor
297 #define db_HA_nelem hash.nelem
298 #define db_HA_bsize hash.bsize
299 #define db_HA_cachesize hash.cachesize
300 #define db_HA_lorder hash.lorder
302 #define db_BT_compare btree.compare
303 #define db_BT_prefix btree.prefix
304 #define db_BT_flags btree.flags
305 #define db_BT_psize btree.psize
306 #define db_BT_cachesize btree.cachesize
307 #define db_BT_lorder btree.lorder
308 #define db_BT_maxkeypage btree.maxkeypage
309 #define db_BT_minkeypage btree.minkeypage
311 #define db_RE_reclen recno.reclen
312 #define db_RE_flags recno.flags
313 #define db_RE_bval recno.bval
314 #define db_RE_bfname recno.bfname
315 #define db_RE_psize recno.psize
316 #define db_RE_cachesize recno.cachesize
317 #define db_RE_lorder recno.lorder
321 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
323 #define DB_flags(x, v)
324 #define flagSet(flags, bitmask) ((flags) & (bitmask))
326 #endif /* db version 1 */
330 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
331 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
332 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
334 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
335 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
337 #ifdef DB_VERSION_MAJOR
338 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
339 (db->dbp->close)(db->dbp, 0) )
340 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
341 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
342 ? ((db->cursor)->c_del)(db->cursor, 0) \
343 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
345 #else /* ! DB_VERSION_MAJOR */
347 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
348 #define db_close(db) ((db->dbp)->close)(db->dbp)
349 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
350 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
352 #endif /* ! DB_VERSION_MAJOR */
355 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
364 #ifdef BERKELEY_DB_1_OR_2
367 #ifdef DB_VERSION_MAJOR
371 SV * filter_fetch_key ;
372 SV * filter_store_key ;
373 SV * filter_fetch_value ;
374 SV * filter_store_value ;
376 #endif /* DBM_FILTERING */
380 typedef DB_File_type * DB_File ;
385 #define ckFilter(arg,type,name) \
388 /* printf("filtering %s\n", name) ;*/ \
390 croak("recursion detected in %s", name) ; \
391 db->filtering = TRUE ; \
392 save_defsv = newSVsv(DEFSV) ; \
393 sv_setsv(DEFSV, arg) ; \
395 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
396 sv_setsv(arg, DEFSV) ; \
397 sv_setsv(DEFSV, save_defsv) ; \
398 SvREFCNT_dec(save_defsv) ; \
399 db->filtering = FALSE ; \
400 /*printf("end of filtering %s\n", name) ;*/ \
405 #define ckFilter(arg,type, name)
407 #endif /* DBM_FILTERING */
409 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
411 #define OutputValue(arg, name) \
412 { if (RETVAL == 0) { \
413 my_sv_setpvn(arg, name.data, name.size) ; \
414 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
418 #define OutputKey(arg, name) \
421 if (db->type != DB_RECNO) { \
422 my_sv_setpvn(arg, name.data, name.size); \
425 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
426 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
431 /* Internal Global Data */
432 static recno_t Value ;
433 static recno_t zero = 0 ;
434 static DB_File CurrentDB ;
435 static DBTKEY empty ;
437 #ifdef DB_VERSION_MAJOR
441 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
443 db_put(db, key, value, flags)
452 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
456 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
457 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
459 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
463 memset(&l_key, 0, sizeof(l_key));
464 l_key.data = key.data;
465 l_key.size = key.size;
466 memset(&l_value, 0, sizeof(l_value));
467 l_value.data = value.data;
468 l_value.size = value.size;
470 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
471 (void)temp_cursor->c_close(temp_cursor);
475 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
476 (void)temp_cursor->c_close(temp_cursor);
482 if (flagSet(flags, R_CURSOR)) {
483 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
486 if (flagSet(flags, R_SETCURSOR)) {
487 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
489 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
493 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
497 #endif /* DB_VERSION_MAJOR */
501 #ifdef AT_LEAST_DB_3_2
504 btree_compare(DB * db, const DBT *key1, const DBT *key2)
506 btree_compare(db, key1, key2)
510 #endif /* CAN_PROTOTYPE */
512 #else /* Berkeley DB < 3.2 */
515 btree_compare(const DBT *key1, const DBT *key2)
517 btree_compare(key1, key2)
529 char * data1, * data2 ;
533 data1 = (char *) key1->data ;
534 data2 = (char *) key2->data ;
537 /* As newSVpv will assume that the data pointer is a null terminated C
538 string if the size parameter is 0, make sure that data points to an
539 empty string if the length is 0
552 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
553 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
556 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
561 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
573 #ifdef AT_LEAST_DB_3_2
576 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
578 btree_prefix(db, key1, key2)
584 #else /* Berkeley DB < 3.2 */
587 btree_prefix(const DBT *key1, const DBT *key2)
589 btree_prefix(key1, key2)
600 char * data1, * data2 ;
604 data1 = (char *) key1->data ;
605 data2 = (char *) key2->data ;
608 /* As newSVpv will assume that the data pointer is a null terminated C
609 string if the size parameter is 0, make sure that data points to an
610 empty string if the length is 0
623 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
624 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
627 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
632 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
645 # define HASH_CB_SIZE_TYPE size_t
647 # define HASH_CB_SIZE_TYPE u_int32_t
651 #ifdef AT_LEAST_DB_3_2
654 hash_cb(DB * db, const void *data, u_int32_t size)
656 hash_cb(db, data, size)
659 HASH_CB_SIZE_TYPE size ;
662 #else /* Berkeley DB < 3.2 */
665 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
669 HASH_CB_SIZE_TYPE size ;
686 /* DGH - Next two lines added to fix corrupted stack problem */
692 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
695 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
700 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
712 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
716 PrintHash(INFO *hash)
722 printf ("HASH Info\n") ;
723 printf (" hash = %s\n",
724 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
725 printf (" bsize = %d\n", hash->db_HA_bsize) ;
726 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
727 printf (" nelem = %d\n", hash->db_HA_nelem) ;
728 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
729 printf (" lorder = %d\n", hash->db_HA_lorder) ;
735 PrintRecno(INFO *recno)
741 printf ("RECNO Info\n") ;
742 printf (" flags = %d\n", recno->db_RE_flags) ;
743 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
744 printf (" psize = %d\n", recno->db_RE_psize) ;
745 printf (" lorder = %d\n", recno->db_RE_lorder) ;
746 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
747 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
748 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
753 PrintBtree(INFO *btree)
759 printf ("BTREE Info\n") ;
760 printf (" compare = %s\n",
761 (btree->db_BT_compare ? "redefined" : "default")) ;
762 printf (" prefix = %s\n",
763 (btree->db_BT_prefix ? "redefined" : "default")) ;
764 printf (" flags = %d\n", btree->db_BT_flags) ;
765 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
766 printf (" psize = %d\n", btree->db_BT_psize) ;
767 #ifndef DB_VERSION_MAJOR
768 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
769 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
771 printf (" lorder = %d\n", btree->db_BT_lorder) ;
776 #define PrintRecno(recno)
777 #define PrintHash(hash)
778 #define PrintBtree(btree)
785 GetArrayLength(pTHX_ DB_File db)
797 RETVAL = do_SEQ(db, key, value, R_LAST) ;
799 RETVAL = *(I32 *)key.data ;
800 else /* No key means empty file */
803 return ((I32)RETVAL) ;
808 GetRecnoKey(pTHX_ DB_File db, I32 value)
810 GetRecnoKey(db, value)
816 /* Get the length of the array */
817 I32 length = GetArrayLength(aTHX_ db) ;
819 /* check for attempt to write before start of array */
820 if (length + value + 1 <= 0)
821 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
823 value = length + value + 1 ;
834 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
836 ParseOpenInfo(isHASH, name, flags, mode, sv)
845 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
849 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
850 void * openinfo = NULL ;
851 INFO * info = &RETVAL->info ;
854 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
855 Zero(RETVAL, 1, DB_File_type) ;
857 /* Default to HASH */
859 RETVAL->filtering = 0 ;
860 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
861 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
862 #endif /* DBM_FILTERING */
863 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
864 RETVAL->type = DB_HASH ;
866 /* DGH - Next line added to avoid SEGV on existing hash DB */
869 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
870 RETVAL->in_memory = (name == NULL) ;
875 croak ("type parameter is not a reference") ;
877 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
878 if (svp && SvOK(*svp))
879 action = (HV*) SvRV(*svp) ;
881 croak("internal error") ;
883 if (sv_isa(sv, "DB_File::HASHINFO"))
887 croak("DB_File can only tie an associative array to a DB_HASH database") ;
889 RETVAL->type = DB_HASH ;
890 openinfo = (void*)info ;
892 svp = hv_fetch(action, "hash", 4, FALSE);
894 if (svp && SvOK(*svp))
896 info->db_HA_hash = hash_cb ;
897 RETVAL->hash = newSVsv(*svp) ;
900 info->db_HA_hash = NULL ;
902 svp = hv_fetch(action, "ffactor", 7, FALSE);
903 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
905 svp = hv_fetch(action, "nelem", 5, FALSE);
906 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
908 svp = hv_fetch(action, "bsize", 5, FALSE);
909 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
911 svp = hv_fetch(action, "cachesize", 9, FALSE);
912 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
914 svp = hv_fetch(action, "lorder", 6, FALSE);
915 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
919 else if (sv_isa(sv, "DB_File::BTREEINFO"))
922 croak("DB_File can only tie an associative array to a DB_BTREE database");
924 RETVAL->type = DB_BTREE ;
925 openinfo = (void*)info ;
927 svp = hv_fetch(action, "compare", 7, FALSE);
928 if (svp && SvOK(*svp))
930 info->db_BT_compare = btree_compare ;
931 RETVAL->compare = newSVsv(*svp) ;
934 info->db_BT_compare = NULL ;
936 svp = hv_fetch(action, "prefix", 6, FALSE);
937 if (svp && SvOK(*svp))
939 info->db_BT_prefix = btree_prefix ;
940 RETVAL->prefix = newSVsv(*svp) ;
943 info->db_BT_prefix = NULL ;
945 svp = hv_fetch(action, "flags", 5, FALSE);
946 info->db_BT_flags = svp ? SvIV(*svp) : 0;
948 svp = hv_fetch(action, "cachesize", 9, FALSE);
949 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
951 #ifndef DB_VERSION_MAJOR
952 svp = hv_fetch(action, "minkeypage", 10, FALSE);
953 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
955 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
956 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
959 svp = hv_fetch(action, "psize", 5, FALSE);
960 info->db_BT_psize = svp ? SvIV(*svp) : 0;
962 svp = hv_fetch(action, "lorder", 6, FALSE);
963 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
968 else if (sv_isa(sv, "DB_File::RECNOINFO"))
971 croak("DB_File can only tie an array to a DB_RECNO database");
973 RETVAL->type = DB_RECNO ;
974 openinfo = (void *)info ;
976 info->db_RE_flags = 0 ;
978 svp = hv_fetch(action, "flags", 5, FALSE);
979 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
981 svp = hv_fetch(action, "reclen", 6, FALSE);
982 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
984 svp = hv_fetch(action, "cachesize", 9, FALSE);
985 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
987 svp = hv_fetch(action, "psize", 5, FALSE);
988 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
990 svp = hv_fetch(action, "lorder", 6, FALSE);
991 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
993 #ifdef DB_VERSION_MAJOR
994 info->re_source = name ;
997 svp = hv_fetch(action, "bfname", 6, FALSE);
998 if (svp && SvOK(*svp)) {
999 char * ptr = SvPV(*svp,n_a) ;
1000 #ifdef DB_VERSION_MAJOR
1001 name = (char*) n_a ? ptr : NULL ;
1003 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1007 #ifdef DB_VERSION_MAJOR
1010 info->db_RE_bfname = NULL ;
1013 svp = hv_fetch(action, "bval", 4, FALSE);
1014 #ifdef DB_VERSION_MAJOR
1015 if (svp && SvOK(*svp))
1019 value = (int)*SvPV(*svp, n_a) ;
1021 value = SvIV(*svp) ;
1023 if (info->flags & DB_FIXEDLEN) {
1024 info->re_pad = value ;
1025 info->flags |= DB_PAD ;
1028 info->re_delim = value ;
1029 info->flags |= DB_DELIMITER ;
1034 if (svp && SvOK(*svp))
1037 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1039 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1040 DB_flags(info->flags, DB_DELIMITER) ;
1045 if (info->db_RE_flags & R_FIXEDLEN)
1046 info->db_RE_bval = (u_char) ' ' ;
1048 info->db_RE_bval = (u_char) '\n' ;
1049 DB_flags(info->flags, DB_DELIMITER) ;
1054 info->flags |= DB_RENUMBER ;
1060 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1064 /* OS2 Specific Code */
1068 #endif /* __EMX__ */
1071 #ifdef DB_VERSION_MAJOR
1077 /* Map 1.x flags to 2.x flags */
1078 if ((flags & O_CREAT) == O_CREAT)
1079 Flags |= DB_CREATE ;
1082 if (flags == O_RDONLY)
1084 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1086 Flags |= DB_RDONLY ;
1089 if ((flags & O_TRUNC) == O_TRUNC)
1090 Flags |= DB_TRUNCATE ;
1093 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1095 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1096 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1098 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1103 RETVAL->dbp = NULL ;
1108 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1109 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1111 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1112 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1118 #else /* Berkeley DB Version > 2 */
1122 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1127 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1128 Zero(RETVAL, 1, DB_File_type) ;
1130 /* Default to HASH */
1131 #ifdef DBM_FILTERING
1132 RETVAL->filtering = 0 ;
1133 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1134 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1135 #endif /* DBM_FILTERING */
1136 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1137 RETVAL->type = DB_HASH ;
1139 /* DGH - Next line added to avoid SEGV on existing hash DB */
1142 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1143 RETVAL->in_memory = (name == NULL) ;
1145 status = db_create(&RETVAL->dbp, NULL,0) ;
1146 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1148 RETVAL->dbp = NULL ;
1156 croak ("type parameter is not a reference") ;
1158 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1159 if (svp && SvOK(*svp))
1160 action = (HV*) SvRV(*svp) ;
1162 croak("internal error") ;
1164 if (sv_isa(sv, "DB_File::HASHINFO"))
1168 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1170 RETVAL->type = DB_HASH ;
1172 svp = hv_fetch(action, "hash", 4, FALSE);
1174 if (svp && SvOK(*svp))
1176 (void)dbp->set_h_hash(dbp, hash_cb) ;
1177 RETVAL->hash = newSVsv(*svp) ;
1180 svp = hv_fetch(action, "ffactor", 7, FALSE);
1182 (void)dbp->set_h_ffactor(dbp, SvIV(*svp)) ;
1184 svp = hv_fetch(action, "nelem", 5, FALSE);
1186 (void)dbp->set_h_nelem(dbp, SvIV(*svp)) ;
1188 svp = hv_fetch(action, "bsize", 5, FALSE);
1190 (void)dbp->set_pagesize(dbp, SvIV(*svp));
1192 svp = hv_fetch(action, "cachesize", 9, FALSE);
1194 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1196 svp = hv_fetch(action, "lorder", 6, FALSE);
1198 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1202 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1205 croak("DB_File can only tie an associative array to a DB_BTREE database");
1207 RETVAL->type = DB_BTREE ;
1209 svp = hv_fetch(action, "compare", 7, FALSE);
1210 if (svp && SvOK(*svp))
1212 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1213 RETVAL->compare = newSVsv(*svp) ;
1216 svp = hv_fetch(action, "prefix", 6, FALSE);
1217 if (svp && SvOK(*svp))
1219 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1220 RETVAL->prefix = newSVsv(*svp) ;
1223 svp = hv_fetch(action, "flags", 5, FALSE);
1225 (void)dbp->set_flags(dbp, SvIV(*svp)) ;
1227 svp = hv_fetch(action, "cachesize", 9, FALSE);
1229 (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1231 svp = hv_fetch(action, "psize", 5, FALSE);
1233 (void)dbp->set_pagesize(dbp, SvIV(*svp)) ;
1235 svp = hv_fetch(action, "lorder", 6, FALSE);
1237 (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
1242 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1247 croak("DB_File can only tie an array to a DB_RECNO database");
1249 RETVAL->type = DB_RECNO ;
1251 svp = hv_fetch(action, "flags", 5, FALSE);
1253 int flags = SvIV(*svp) ;
1254 /* remove FIXDLEN, if present */
1255 if (flags & DB_FIXEDLEN) {
1257 flags &= ~DB_FIXEDLEN ;
1261 svp = hv_fetch(action, "cachesize", 9, FALSE);
1263 status = dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
1266 svp = hv_fetch(action, "psize", 5, FALSE);
1268 status = dbp->set_pagesize(dbp, SvIV(*svp)) ;
1271 svp = hv_fetch(action, "lorder", 6, FALSE);
1273 status = dbp->set_lorder(dbp, SvIV(*svp)) ;
1276 svp = hv_fetch(action, "bval", 4, FALSE);
1277 if (svp && SvOK(*svp))
1281 value = (int)*SvPV(*svp, n_a) ;
1283 value = SvIV(*svp) ;
1286 status = dbp->set_re_pad(dbp, value) ;
1289 status = dbp->set_re_delim(dbp, value) ;
1295 svp = hv_fetch(action, "reclen", 6, FALSE);
1297 u_int32_t len = (u_int32_t)SvIV(*svp) ;
1298 status = dbp->set_re_len(dbp, len) ;
1303 status = dbp->set_re_source(dbp, name) ;
1307 svp = hv_fetch(action, "bfname", 6, FALSE);
1308 if (svp && SvOK(*svp)) {
1309 char * ptr = SvPV(*svp,n_a) ;
1310 name = (char*) n_a ? ptr : NULL ;
1316 status = dbp->set_flags(dbp, DB_RENUMBER) ;
1319 (void)dbp->set_flags(dbp, flags) ;
1324 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1331 /* Map 1.x flags to 3.x flags */
1332 if ((flags & O_CREAT) == O_CREAT)
1333 Flags |= DB_CREATE ;
1336 if (flags == O_RDONLY)
1338 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1340 Flags |= DB_RDONLY ;
1343 if ((flags & O_TRUNC) == O_TRUNC)
1344 Flags |= DB_TRUNCATE ;
1347 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1349 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1352 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1354 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1357 RETVAL->dbp = NULL ;
1363 #endif /* Berkeley DB Version > 2 */
1365 } /* ParseOpenInfo */
1369 #ifdef CAN_PROTOTYPE
1370 constant(char *name, int arg)
1382 if (strEQ(name, "BTREEMAGIC"))
1388 if (strEQ(name, "BTREEVERSION"))
1390 return BTREEVERSION;
1398 if (strEQ(name, "DB_LOCK"))
1404 if (strEQ(name, "DB_SHMEM"))
1410 if (strEQ(name, "DB_TXN"))
1424 if (strEQ(name, "HASHMAGIC"))
1430 if (strEQ(name, "HASHVERSION"))
1446 if (strEQ(name, "MAX_PAGE_NUMBER"))
1447 #ifdef MAX_PAGE_NUMBER
1448 return (U32)MAX_PAGE_NUMBER;
1452 if (strEQ(name, "MAX_PAGE_OFFSET"))
1453 #ifdef MAX_PAGE_OFFSET
1454 return MAX_PAGE_OFFSET;
1458 if (strEQ(name, "MAX_REC_NUMBER"))
1459 #ifdef MAX_REC_NUMBER
1460 return (U32)MAX_REC_NUMBER;
1474 if (strEQ(name, "RET_ERROR"))
1480 if (strEQ(name, "RET_SPECIAL"))
1486 if (strEQ(name, "RET_SUCCESS"))
1492 if (strEQ(name, "R_CURSOR"))
1498 if (strEQ(name, "R_DUP"))
1504 if (strEQ(name, "R_FIRST"))
1510 if (strEQ(name, "R_FIXEDLEN"))
1516 if (strEQ(name, "R_IAFTER"))
1522 if (strEQ(name, "R_IBEFORE"))
1528 if (strEQ(name, "R_LAST"))
1534 if (strEQ(name, "R_NEXT"))
1540 if (strEQ(name, "R_NOKEY"))
1546 if (strEQ(name, "R_NOOVERWRITE"))
1547 #ifdef R_NOOVERWRITE
1548 return R_NOOVERWRITE;
1552 if (strEQ(name, "R_PREV"))
1558 if (strEQ(name, "R_RECNOSYNC"))
1564 if (strEQ(name, "R_SETCURSOR"))
1570 if (strEQ(name, "R_SNAPSHOT"))
1604 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1608 __getBerkeleyDBInfo() ;
1611 empty.data = &zero ;
1612 empty.size = sizeof(recno_t) ;
1622 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1629 char * name = (char *) NULL ;
1630 SV * sv = (SV *) NULL ;
1633 if (items >= 3 && SvOK(ST(2)))
1634 name = (char*) SvPV(ST(2), n_a) ;
1639 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1640 if (RETVAL->dbp == NULL)
1653 SvREFCNT_dec(db->hash) ;
1655 SvREFCNT_dec(db->compare) ;
1657 SvREFCNT_dec(db->prefix) ;
1658 #ifdef DBM_FILTERING
1659 if (db->filter_fetch_key)
1660 SvREFCNT_dec(db->filter_fetch_key) ;
1661 if (db->filter_store_key)
1662 SvREFCNT_dec(db->filter_store_key) ;
1663 if (db->filter_fetch_value)
1664 SvREFCNT_dec(db->filter_fetch_value) ;
1665 if (db->filter_store_value)
1666 SvREFCNT_dec(db->filter_store_value) ;
1667 #endif /* DBM_FILTERING */
1669 #ifdef DB_VERSION_MAJOR
1676 db_DELETE(db, key, flags=0)
1694 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1700 db_FETCH(db, key, flags=0)
1710 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1711 RETVAL = db_get(db, key, value, flags) ;
1712 ST(0) = sv_newmortal();
1713 OutputValue(ST(0), value)
1717 db_STORE(db, key, value, flags=0)
1737 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1738 ST(0) = sv_newmortal();
1739 OutputKey(ST(0), key) ;
1752 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1753 ST(0) = sv_newmortal();
1754 OutputKey(ST(0), key) ;
1758 # These would be nice for RECNO
1777 #ifdef DB_VERSION_MAJOR
1778 /* get the first value */
1779 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1784 for (i = items-1 ; i > 0 ; --i)
1786 value.data = SvPV(ST(i), n_a) ;
1790 key.size = sizeof(int) ;
1791 #ifdef DB_VERSION_MAJOR
1792 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1794 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1816 /* First get the final value */
1817 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1818 ST(0) = sv_newmortal();
1822 /* the call to del will trash value, so take a copy now */
1823 OutputValue(ST(0), value) ;
1824 RETVAL = db_del(db, key, R_CURSOR) ;
1826 sv_setsv(ST(0), &PL_sv_undef);
1842 /* get the first value */
1843 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1844 ST(0) = sv_newmortal();
1848 /* the call to del will trash value, so take a copy now */
1849 OutputValue(ST(0), value) ;
1850 RETVAL = db_del(db, key, R_CURSOR) ;
1852 sv_setsv (ST(0), &PL_sv_undef) ;
1873 /* Set the Cursor to the Last element */
1874 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1875 #ifndef DB_VERSION_MAJOR
1880 keyval = *(int*)key.data ;
1883 for (i = 1 ; i < items ; ++i)
1885 value.data = SvPV(ST(i), n_a) ;
1888 key.data = &keyval ;
1889 key.size = sizeof(int) ;
1890 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1902 ALIAS: FETCHSIZE = 1
1905 RETVAL = GetArrayLength(aTHX_ db) ;
1911 # Now provide an interface to the rest of the DB functionality
1915 db_del(db, key, flags=0)
1921 RETVAL = db_del(db, key, flags) ;
1922 #ifdef DB_VERSION_MAJOR
1925 else if (RETVAL == DB_NOTFOUND)
1933 db_get(db, key, value, flags=0)
1941 RETVAL = db_get(db, key, value, flags) ;
1942 #ifdef DB_VERSION_MAJOR
1945 else if (RETVAL == DB_NOTFOUND)
1953 db_put(db, key, value, flags=0)
1960 RETVAL = db_put(db, key, value, flags) ;
1961 #ifdef DB_VERSION_MAJOR
1964 else if (RETVAL == DB_KEYEXIST)
1969 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1977 #ifdef DB_VERSION_MAJOR
1979 status = (db->in_memory
1981 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1985 RETVAL = (db->in_memory
1987 : ((db->dbp)->fd)(db->dbp) ) ;
1993 db_sync(db, flags=0)
1998 RETVAL = db_sync(db, flags) ;
1999 #ifdef DB_VERSION_MAJOR
2008 db_seq(db, key, value, flags)
2016 RETVAL = db_seq(db, key, value, flags);
2017 #ifdef DB_VERSION_MAJOR
2020 else if (RETVAL == DB_NOTFOUND)
2028 #ifdef DBM_FILTERING
2030 #define setFilter(type) \
2033 RETVAL = sv_mortalcopy(db->type) ; \
2035 if (db->type && (code == &PL_sv_undef)) { \
2036 SvREFCNT_dec(db->type) ; \
2041 sv_setsv(db->type, code) ; \
2043 db->type = newSVsv(code) ; \
2049 filter_fetch_key(db, code)
2052 SV * RETVAL = &PL_sv_undef ;
2054 setFilter(filter_fetch_key) ;
2057 filter_store_key(db, code)
2060 SV * RETVAL = &PL_sv_undef ;
2062 setFilter(filter_store_key) ;
2065 filter_fetch_value(db, code)
2068 SV * RETVAL = &PL_sv_undef ;
2070 setFilter(filter_fetch_value) ;
2073 filter_store_value(db, code)
2076 SV * RETVAL = &PL_sv_undef ;
2078 setFilter(filter_store_value) ;
2080 #endif /* DBM_FILTERING */