1b39c5158Smillert /* 2b39c5158Smillert 3b39c5158Smillert DB_File.xs -- Perl 5 interface to Berkeley DB 4b39c5158Smillert 56fb12b70Safresh1 Written by Paul Marquess <pmqs@cpan.org> 6b39c5158Smillert 7b39c5158Smillert All comments/suggestions/problems are welcome 8b39c5158Smillert 9*3d61058aSafresh1 Copyright (c) 1995-2023 Paul Marquess. All rights reserved. 10b39c5158Smillert This program is free software; you can redistribute it and/or 11b39c5158Smillert modify it under the same terms as Perl itself. 12b39c5158Smillert 13b39c5158Smillert Changes: 14b39c5158Smillert 0.1 - Initial Release 15b39c5158Smillert 0.2 - No longer bombs out if dbopen returns an error. 16b39c5158Smillert 0.3 - Added some support for multiple btree compares 17b39c5158Smillert 1.0 - Complete support for multiple callbacks added. 18b39c5158Smillert Fixed a problem with pushing a value onto an empty list. 19b39c5158Smillert 1.01 - Fixed a SunOS core dump problem. 20b39c5158Smillert The return value from TIEHASH wasn't set to NULL when 21b39c5158Smillert dbopen returned an error. 22b39c5158Smillert 1.02 - Use ALIAS to define TIEARRAY. 23b39c5158Smillert Removed some redundant commented code. 24b39c5158Smillert Merged OS2 code into the main distribution. 25b39c5158Smillert Allow negative subscripts with RECNO interface. 26b39c5158Smillert Changed the default flags to O_CREAT|O_RDWR 27b39c5158Smillert 1.03 - Added EXISTS 28b39c5158Smillert 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by 29b39c5158Smillert Dave Hammen, hammen@gothamcity.jsc.nasa.gov 30b39c5158Smillert 1.05 - Added logic to allow prefix & hash types to be specified via 31b39c5158Smillert Makefile.PL 32b39c5158Smillert 1.06 - Minor namespace cleanup: Localized PrintBtree. 33b39c5158Smillert 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n". 34b39c5158Smillert 1.08 - No change to DB_File.xs 35b39c5158Smillert 1.09 - Default mode for dbopen changed to 0666 36b39c5158Smillert 1.10 - Fixed fd method so that it still returns -1 for 37b39c5158Smillert in-memory files when db 1.86 is used. 38b39c5158Smillert 1.11 - No change to DB_File.xs 39b39c5158Smillert 1.12 - No change to DB_File.xs 40b39c5158Smillert 1.13 - Tidied up a few casts. 41b39c5158Smillert 1.14 - Made it illegal to tie an associative array to a RECNO 42b39c5158Smillert database and an ordinary array to a HASH or BTREE database. 43b39c5158Smillert 1.50 - Make work with both DB 1.x or DB 2.x 44b39c5158Smillert 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent 45b39c5158Smillert 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of 46b39c5158Smillert undefined value" warning with db_get and db_seq. 47b39c5158Smillert 1.53 - Added DB_RENUMBER to flags for recno. 48b39c5158Smillert 1.54 - Fixed bug in the fd method 49b39c5158Smillert 1.55 - Fix for AIX from Jarkko Hietaniemi 50b39c5158Smillert 1.56 - No change to DB_File.xs 51b39c5158Smillert 1.57 - added the #undef op to allow building with Threads support. 52b39c5158Smillert 1.58 - Fixed a problem with the use of sv_setpvn. When the 53b39c5158Smillert size is specified as 0, it does a strlen on the data. 54b39c5158Smillert This was ok for DB 1.x, but isn't for DB 2.x. 55b39c5158Smillert 1.59 - No change to DB_File.xs 56b39c5158Smillert 1.60 - Some code tidy up 57b39c5158Smillert 1.61 - added flagSet macro for DB 2.5.x 58b39c5158Smillert fixed typo in O_RDONLY test. 59b39c5158Smillert 1.62 - No change to DB_File.xs 60b39c5158Smillert 1.63 - Fix to alllow DB 2.6.x to build. 61b39c5158Smillert 1.64 - Tidied up the 1.x to 2.x flags mapping code. 62b39c5158Smillert Added a patch from Mark Kettenis <kettenis@wins.uva.nl> 63b39c5158Smillert to fix a flag mapping problem with O_RDONLY on the Hurd 64b39c5158Smillert 1.65 - Fixed a bug in the PUSH logic. 65b39c5158Smillert Added BOOT check that using 2.3.4 or greater 66b39c5158Smillert 1.66 - Added DBM filter code 67b39c5158Smillert 1.67 - Backed off the use of newSVpvn. 68b39c5158Smillert Fixed DBM Filter code for Perl 5.004. 69b39c5158Smillert Fixed a small memory leak in the filter code. 70898184e3Ssthen 1.68 - fixed backward compatibility bug with R_IAFTER & R_IBEFORE 71b39c5158Smillert merged in the 5.005_58 changes 72b39c5158Smillert 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly. 73b39c5158Smillert Fixed the R_SETCURSOR bug introduced in 1.68 74b39c5158Smillert Added a new Perl variable $DB_File::db_ver 75b39c5158Smillert 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with 76b39c5158Smillert GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons. 77b39c5158Smillert Added a BOOT check to test for equivalent versions of db.h & 78b39c5158Smillert libdb.a/so. 79b39c5158Smillert 1.71 - Support for Berkeley DB version 3. 80898184e3Ssthen Support for Berkeley DB 2/3's backward compatibility mode. 81b39c5158Smillert Rewrote push 82b39c5158Smillert 1.72 - No change to DB_File.xs 83b39c5158Smillert 1.73 - No change to DB_File.xs 84b39c5158Smillert 1.74 - A call to open needed parenthesised to stop it clashing 85b39c5158Smillert with a win32 macro. 86b39c5158Smillert Added Perl core patches 7703 & 7801. 87b39c5158Smillert 1.75 - Fixed Perl core patch 7703. 88898184e3Ssthen Added support to allow DB_File to be built with 89b39c5158Smillert Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb 90b39c5158Smillert needed to be changed. 91b39c5158Smillert 1.76 - No change to DB_File.xs 92b39c5158Smillert 1.77 - Tidied up a few types used in calling newSVpvn. 93b39c5158Smillert 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included. 94b39c5158Smillert 1.79 - NEXTKEY ignores the input key. 95b39c5158Smillert Added lots of casts 96898184e3Ssthen 1.800 - Moved backward compatibility code into ppport.h. 97b39c5158Smillert Use the new constants code. 98b39c5158Smillert 1.801 - No change to DB_File.xs 99b39c5158Smillert 1.802 - No change to DB_File.xs 100b39c5158Smillert 1.803 - FETCH, STORE & DELETE don't map the flags parameter 101b39c5158Smillert into the equivalent Berkeley DB function anymore. 102b39c5158Smillert 1.804 - no change. 103b39c5158Smillert 1.805 - recursion detection added to the callbacks 104b39c5158Smillert Support for 4.1.X added. 105b39c5158Smillert Filter code can now cope with read-only $_ 106b39c5158Smillert 1.806 - recursion detection beefed up. 107b39c5158Smillert 1.807 - no change 108b39c5158Smillert 1.808 - leak fixed in ParseOpenInfo 109b39c5158Smillert 1.809 - no change 110b39c5158Smillert 1.810 - no change 111b39c5158Smillert 1.811 - no change 112b39c5158Smillert 1.812 - no change 113b39c5158Smillert 1.813 - no change 114b39c5158Smillert 1.814 - no change 115b39c5158Smillert 1.814 - C++ casting fixes 116b39c5158Smillert 117b39c5158Smillert */ 118b39c5158Smillert 119b39c5158Smillert #define PERL_NO_GET_CONTEXT 120b39c5158Smillert #include "EXTERN.h" 121b39c5158Smillert #include "perl.h" 122b39c5158Smillert #include "XSUB.h" 123b39c5158Smillert 124b39c5158Smillert #ifdef _NOT_CORE 125b39c5158Smillert # include "ppport.h" 126b39c5158Smillert #endif 127b39c5158Smillert 128b8851fccSafresh1 int DB_File___unused() { return 0; } 129b8851fccSafresh1 130b39c5158Smillert /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and 131b39c5158Smillert DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */ 132b39c5158Smillert 133b39c5158Smillert /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be 134b39c5158Smillert * shortly #included by the <db.h>) __attribute__ to the possibly 135b39c5158Smillert * already defined __attribute__, for example by GNUC or by Perl. */ 136b39c5158Smillert 137b39c5158Smillert /* #if DB_VERSION_MAJOR_CFG < 2 */ 138b39c5158Smillert #ifndef DB_VERSION_MAJOR 139b39c5158Smillert # undef __attribute__ 140b39c5158Smillert #endif 141b39c5158Smillert 142b39c5158Smillert #ifdef COMPAT185 143b39c5158Smillert # include <db_185.h> 144b39c5158Smillert #else 1456fb12b70Safresh1 1466fb12b70Safresh1 /* Uncomment one of the lines below */ 1476fb12b70Safresh1 /* See the section "At least one secondary cursor must be specified to DB->join" 1486fb12b70Safresh1 in the README file for the circumstances where you need to uncomment one 1496fb12b70Safresh1 of the two lines below. 1506fb12b70Safresh1 */ 1516fb12b70Safresh1 1526fb12b70Safresh1 /* #define time_t __time64_t */ 1536fb12b70Safresh1 /* #define time_t __time32_t */ 1546fb12b70Safresh1 155b39c5158Smillert # include <db.h> 156b39c5158Smillert #endif 157b39c5158Smillert 158b8851fccSafresh1 #ifndef PERL_UNUSED_ARG 159b8851fccSafresh1 # define PERL_UNUSED_ARG(x) ((void)x) 160b8851fccSafresh1 #endif 161b8851fccSafresh1 162b39c5158Smillert /* Wall starts with 5.7.x */ 163b39c5158Smillert 164b39c5158Smillert #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7) 165b39c5158Smillert 166b39c5158Smillert /* Since we dropped the gccish definition of __attribute__ we will want 167b39c5158Smillert * to redefine dNOOP, however (so that dTHX continues to work). Yes, 168b39c5158Smillert * all this means that we can't do attribute checking on the DB_File, 169b39c5158Smillert * boo, hiss. */ 170b39c5158Smillert # ifndef DB_VERSION_MAJOR 171b39c5158Smillert 172b39c5158Smillert # undef dNOOP 173b8851fccSafresh1 # ifdef __cplusplus 174b8851fccSafresh1 # define dNOOP (void)0 175b8851fccSafresh1 # else 176b8851fccSafresh1 # define dNOOP extern int DB_File___notused() 177b8851fccSafresh1 # endif 178b39c5158Smillert 179b39c5158Smillert /* Ditto for dXSARGS. */ 180b39c5158Smillert # undef dXSARGS 181b39c5158Smillert # define dXSARGS \ 182b39c5158Smillert dSP; dMARK; \ 183b39c5158Smillert I32 ax = mark - PL_stack_base + 1; \ 184b39c5158Smillert I32 items = sp - mark 185b39c5158Smillert 186b39c5158Smillert # endif 187b39c5158Smillert 188b39c5158Smillert /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */ 189b39c5158Smillert # undef dXSI32 190b39c5158Smillert # define dXSI32 dNOOP 191b39c5158Smillert 192b39c5158Smillert #endif /* Perl >= 5.7 */ 193b39c5158Smillert 194b39c5158Smillert #include <fcntl.h> 195b39c5158Smillert 196b39c5158Smillert /* #define TRACE */ 197b39c5158Smillert 198b39c5158Smillert #ifdef TRACE 199b39c5158Smillert # define Trace(x) printf x 200b39c5158Smillert #else 201b39c5158Smillert # define Trace(x) 202b39c5158Smillert #endif 203b39c5158Smillert 204b39c5158Smillert 205b39c5158Smillert #define DBT_clear(x) Zero(&x, 1, DBT) ; 206b39c5158Smillert 207b39c5158Smillert #ifdef DB_VERSION_MAJOR 208b39c5158Smillert 209b39c5158Smillert #if DB_VERSION_MAJOR == 2 210b39c5158Smillert # define BERKELEY_DB_1_OR_2 211b39c5158Smillert #endif 212b39c5158Smillert 213b39c5158Smillert #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2) 214b39c5158Smillert # define AT_LEAST_DB_3_2 215b39c5158Smillert #endif 216b39c5158Smillert 217b39c5158Smillert #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3) 218b39c5158Smillert # define AT_LEAST_DB_3_3 219b39c5158Smillert #endif 220b39c5158Smillert 221b39c5158Smillert #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) 222b39c5158Smillert # define AT_LEAST_DB_4_1 223b39c5158Smillert #endif 224b39c5158Smillert 225b39c5158Smillert #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) 226b39c5158Smillert # define AT_LEAST_DB_4_3 227b39c5158Smillert #endif 228b39c5158Smillert 2296fb12b70Safresh1 #if DB_VERSION_MAJOR >= 6 2306fb12b70Safresh1 # define AT_LEAST_DB_6_0 2316fb12b70Safresh1 #endif 2326fb12b70Safresh1 233b39c5158Smillert #ifdef AT_LEAST_DB_3_3 234b39c5158Smillert # define WANT_ERROR 235b39c5158Smillert #endif 236b39c5158Smillert 237b39c5158Smillert /* map version 2 features & constants onto their version 1 equivalent */ 238b39c5158Smillert 239b39c5158Smillert #ifdef DB_Prefix_t 240b39c5158Smillert # undef DB_Prefix_t 241b39c5158Smillert #endif 242b39c5158Smillert #define DB_Prefix_t size_t 243b39c5158Smillert 244b39c5158Smillert #ifdef DB_Hash_t 245b39c5158Smillert # undef DB_Hash_t 246b39c5158Smillert #endif 247b39c5158Smillert #define DB_Hash_t u_int32_t 248b39c5158Smillert 249b39c5158Smillert /* DBTYPE stays the same */ 250b39c5158Smillert /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */ 251b39c5158Smillert #if DB_VERSION_MAJOR == 2 252b39c5158Smillert typedef DB_INFO INFO ; 253b39c5158Smillert #else /* DB_VERSION_MAJOR > 2 */ 254b39c5158Smillert # define DB_FIXEDLEN (0x8000) 255b39c5158Smillert #endif /* DB_VERSION_MAJOR == 2 */ 256b39c5158Smillert 257b39c5158Smillert /* version 2 has db_recno_t in place of recno_t */ 258b39c5158Smillert typedef db_recno_t recno_t; 259b39c5158Smillert 260b39c5158Smillert 261b39c5158Smillert #define R_CURSOR DB_SET_RANGE 262b39c5158Smillert #define R_FIRST DB_FIRST 263b39c5158Smillert #define R_IAFTER DB_AFTER 264b39c5158Smillert #define R_IBEFORE DB_BEFORE 265b39c5158Smillert #define R_LAST DB_LAST 266b39c5158Smillert #define R_NEXT DB_NEXT 267b39c5158Smillert #define R_NOOVERWRITE DB_NOOVERWRITE 268b39c5158Smillert #define R_PREV DB_PREV 269b39c5158Smillert 270b39c5158Smillert #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5 271b39c5158Smillert # define R_SETCURSOR 0x800000 272b39c5158Smillert #else 2739f11ffb7Safresh1 # define R_SETCURSOR (DB_OPFLAGS_MASK) 274b39c5158Smillert #endif 275b39c5158Smillert 276b39c5158Smillert #define R_RECNOSYNC 0 277b39c5158Smillert #define R_FIXEDLEN DB_FIXEDLEN 278b39c5158Smillert #define R_DUP DB_DUP 279b39c5158Smillert 280b39c5158Smillert 281b39c5158Smillert #define db_HA_hash h_hash 282b39c5158Smillert #define db_HA_ffactor h_ffactor 283b39c5158Smillert #define db_HA_nelem h_nelem 284b39c5158Smillert #define db_HA_bsize db_pagesize 285b39c5158Smillert #define db_HA_cachesize db_cachesize 286b39c5158Smillert #define db_HA_lorder db_lorder 287b39c5158Smillert 288b39c5158Smillert #define db_BT_compare bt_compare 289b39c5158Smillert #define db_BT_prefix bt_prefix 290b39c5158Smillert #define db_BT_flags flags 291b39c5158Smillert #define db_BT_psize db_pagesize 292b39c5158Smillert #define db_BT_cachesize db_cachesize 293b39c5158Smillert #define db_BT_lorder db_lorder 294b39c5158Smillert #define db_BT_maxkeypage 295b39c5158Smillert #define db_BT_minkeypage 296b39c5158Smillert 297b39c5158Smillert 298b39c5158Smillert #define db_RE_reclen re_len 299b39c5158Smillert #define db_RE_flags flags 300b39c5158Smillert #define db_RE_bval re_pad 301b39c5158Smillert #define db_RE_bfname re_source 302b39c5158Smillert #define db_RE_psize db_pagesize 303b39c5158Smillert #define db_RE_cachesize db_cachesize 304b39c5158Smillert #define db_RE_lorder db_lorder 305b39c5158Smillert 306b39c5158Smillert #define TXN NULL, 307b39c5158Smillert 308b39c5158Smillert #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag) 309b39c5158Smillert 310b39c5158Smillert 311b39c5158Smillert #define DBT_flags(x) x.flags = 0 312b39c5158Smillert #define DB_flags(x, v) x |= v 313b39c5158Smillert 314b39c5158Smillert #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5 315b39c5158Smillert # define flagSet(flags, bitmask) ((flags) & (bitmask)) 316b39c5158Smillert #else 317b8851fccSafresh1 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (u_int)(bitmask)) 318b39c5158Smillert #endif 319b39c5158Smillert 320b39c5158Smillert #else /* db version 1.x */ 321b39c5158Smillert 322b39c5158Smillert #define BERKELEY_DB_1 323b39c5158Smillert #define BERKELEY_DB_1_OR_2 324b39c5158Smillert 325b39c5158Smillert typedef union INFO { 326b39c5158Smillert HASHINFO hash ; 327b39c5158Smillert RECNOINFO recno ; 328b39c5158Smillert BTREEINFO btree ; 329b39c5158Smillert } INFO ; 330b39c5158Smillert 331b39c5158Smillert 332b39c5158Smillert #ifdef mDB_Prefix_t 333b39c5158Smillert # ifdef DB_Prefix_t 334b39c5158Smillert # undef DB_Prefix_t 335b39c5158Smillert # endif 336b39c5158Smillert # define DB_Prefix_t mDB_Prefix_t 337b39c5158Smillert #endif 338b39c5158Smillert 339b39c5158Smillert #ifdef mDB_Hash_t 340b39c5158Smillert # ifdef DB_Hash_t 341b39c5158Smillert # undef DB_Hash_t 342b39c5158Smillert # endif 343b39c5158Smillert # define DB_Hash_t mDB_Hash_t 344b39c5158Smillert #endif 345b39c5158Smillert 346b39c5158Smillert #define db_HA_hash hash.hash 347b39c5158Smillert #define db_HA_ffactor hash.ffactor 348b39c5158Smillert #define db_HA_nelem hash.nelem 349b39c5158Smillert #define db_HA_bsize hash.bsize 350b39c5158Smillert #define db_HA_cachesize hash.cachesize 351b39c5158Smillert #define db_HA_lorder hash.lorder 352b39c5158Smillert 353b39c5158Smillert #define db_BT_compare btree.compare 354b39c5158Smillert #define db_BT_prefix btree.prefix 355b39c5158Smillert #define db_BT_flags btree.flags 356b39c5158Smillert #define db_BT_psize btree.psize 357b39c5158Smillert #define db_BT_cachesize btree.cachesize 358b39c5158Smillert #define db_BT_lorder btree.lorder 359b39c5158Smillert #define db_BT_maxkeypage btree.maxkeypage 360b39c5158Smillert #define db_BT_minkeypage btree.minkeypage 361b39c5158Smillert 362b39c5158Smillert #define db_RE_reclen recno.reclen 363b39c5158Smillert #define db_RE_flags recno.flags 364b39c5158Smillert #define db_RE_bval recno.bval 365b39c5158Smillert #define db_RE_bfname recno.bfname 366b39c5158Smillert #define db_RE_psize recno.psize 367b39c5158Smillert #define db_RE_cachesize recno.cachesize 368b39c5158Smillert #define db_RE_lorder recno.lorder 369b39c5158Smillert 370b39c5158Smillert #define TXN 371b39c5158Smillert 372b39c5158Smillert #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag) 373b39c5158Smillert #define DBT_flags(x) 374b39c5158Smillert #define DB_flags(x, v) 375b39c5158Smillert #define flagSet(flags, bitmask) ((flags) & (bitmask)) 376b39c5158Smillert 377b39c5158Smillert #endif /* db version 1 */ 378b39c5158Smillert 379b39c5158Smillert 380b39c5158Smillert 381b39c5158Smillert #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0) 382b39c5158Smillert #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0) 383b39c5158Smillert #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0) 384b39c5158Smillert 385b39c5158Smillert #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags) 386b39c5158Smillert #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) 387b39c5158Smillert 388b39c5158Smillert #ifdef DB_VERSION_MAJOR 389b39c5158Smillert #define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\ 390b39c5158Smillert (db->dbp->close)(db->dbp, 0) )) 391b39c5158Smillert #define db_close(db) ((db->dbp)->close)(db->dbp, 0) 392b39c5158Smillert #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \ 393b39c5158Smillert ? ((db->cursor)->c_del)(db->cursor, 0) \ 394b39c5158Smillert : ((db->dbp)->del)(db->dbp, NULL, &key, flags) ) 395b39c5158Smillert 396b39c5158Smillert #else /* ! DB_VERSION_MAJOR */ 397b39c5158Smillert 398b39c5158Smillert #define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp)) 399b39c5158Smillert #define db_close(db) ((db->dbp)->close)(db->dbp) 400b39c5158Smillert #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags) 401b39c5158Smillert #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags) 402b39c5158Smillert 403b39c5158Smillert #endif /* ! DB_VERSION_MAJOR */ 404b39c5158Smillert 405b39c5158Smillert 406b39c5158Smillert #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags) 407b39c5158Smillert 408b39c5158Smillert typedef struct { 409b39c5158Smillert DBTYPE type ; 410b39c5158Smillert DB * dbp ; 411b39c5158Smillert SV * compare ; 412b39c5158Smillert bool in_compare ; 413b39c5158Smillert SV * prefix ; 414b39c5158Smillert bool in_prefix ; 415b39c5158Smillert SV * hash ; 416b39c5158Smillert bool in_hash ; 417b39c5158Smillert bool aborted ; 418b39c5158Smillert int in_memory ; 419b39c5158Smillert #ifdef BERKELEY_DB_1_OR_2 420b39c5158Smillert INFO info ; 421b39c5158Smillert #endif 422b39c5158Smillert #ifdef DB_VERSION_MAJOR 423b39c5158Smillert DBC * cursor ; 424b39c5158Smillert #endif 425b39c5158Smillert SV * filter_fetch_key ; 426b39c5158Smillert SV * filter_store_key ; 427b39c5158Smillert SV * filter_fetch_value ; 428b39c5158Smillert SV * filter_store_value ; 429b39c5158Smillert int filtering ; 430b39c5158Smillert 431b39c5158Smillert } DB_File_type; 432b39c5158Smillert 433b39c5158Smillert typedef DB_File_type * DB_File ; 434b39c5158Smillert typedef DBT DBTKEY ; 435b39c5158Smillert 436b39c5158Smillert #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (const char *)""), s) 437b39c5158Smillert 438b39c5158Smillert #define OutputValue(arg, name) \ 439b39c5158Smillert { if (RETVAL == 0) { \ 440b39c5158Smillert SvGETMAGIC(arg) ; \ 441b39c5158Smillert my_sv_setpvn(arg, (const char *)name.data, name.size) ; \ 442b39c5158Smillert TAINT; \ 443b39c5158Smillert SvTAINTED_on(arg); \ 444b39c5158Smillert SvUTF8_off(arg); \ 445b39c5158Smillert DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \ 446b39c5158Smillert } \ 447b39c5158Smillert } 448b39c5158Smillert 449b39c5158Smillert #define OutputKey(arg, name) \ 450b39c5158Smillert { if (RETVAL == 0) \ 451b39c5158Smillert { \ 452b39c5158Smillert SvGETMAGIC(arg) ; \ 453b39c5158Smillert if (db->type != DB_RECNO) { \ 454b39c5158Smillert my_sv_setpvn(arg, (const char *)name.data, name.size); \ 455b39c5158Smillert } \ 456b39c5158Smillert else \ 457b39c5158Smillert sv_setiv(arg, (I32)*(I32*)name.data - 1); \ 458b39c5158Smillert TAINT; \ 459b39c5158Smillert SvTAINTED_on(arg); \ 460b39c5158Smillert SvUTF8_off(arg); \ 461b39c5158Smillert DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \ 462b39c5158Smillert } \ 463b39c5158Smillert } 464b39c5158Smillert 46556d68f1eSafresh1 /* Macro err_close only for use in croak_and_free */ 46656d68f1eSafresh1 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */ 46756d68f1eSafresh1 # define err_close(r) 46856d68f1eSafresh1 #else 46956d68f1eSafresh1 # define err_close(r) db_close(r) 47056d68f1eSafresh1 #endif 47156d68f1eSafresh1 47256d68f1eSafresh1 /* Macro croak_and_free only for use in ParseOpenInfo */ 47356d68f1eSafresh1 #define croak_and_free(x) \ 47456d68f1eSafresh1 do \ 47556d68f1eSafresh1 { \ 476eac174f2Safresh1 if (RETVAL->dbp) { err_close(RETVAL) ; } \ 47756d68f1eSafresh1 Safefree(RETVAL); \ 47856d68f1eSafresh1 croak(x); \ 47956d68f1eSafresh1 } while (0) 48056d68f1eSafresh1 481b39c5158Smillert #define my_SvUV32(sv) ((u_int32_t)SvUV(sv)) 482b39c5158Smillert 483b39c5158Smillert #ifdef CAN_PROTOTYPE 484b39c5158Smillert extern void __getBerkeleyDBInfo(void); 485b39c5158Smillert #endif 486b39c5158Smillert 487b39c5158Smillert /* Internal Global Data */ 488b39c5158Smillert 489b39c5158Smillert #define MY_CXT_KEY "DB_File::_guts" XS_VERSION 490b39c5158Smillert 491b39c5158Smillert typedef struct { 492b39c5158Smillert recno_t x_Value; 493b39c5158Smillert recno_t x_zero; 494b39c5158Smillert DB_File x_CurrentDB; 495b39c5158Smillert DBTKEY x_empty; 496b39c5158Smillert } my_cxt_t; 497b39c5158Smillert 498b39c5158Smillert START_MY_CXT 499b39c5158Smillert 500b39c5158Smillert #define Value (MY_CXT.x_Value) 501b39c5158Smillert #define zero (MY_CXT.x_zero) 502b39c5158Smillert #define CurrentDB (MY_CXT.x_CurrentDB) 503b39c5158Smillert #define empty (MY_CXT.x_empty) 504b39c5158Smillert 505b39c5158Smillert #define ERR_BUFF "DB_File::Error" 506b39c5158Smillert 507b39c5158Smillert #ifdef DB_VERSION_MAJOR 508b39c5158Smillert 509b39c5158Smillert static int 510b39c5158Smillert #ifdef CAN_PROTOTYPE 511b39c5158Smillert db_put(DB_File db, DBTKEY key, DBT value, u_int flags) 512b39c5158Smillert #else 513b39c5158Smillert db_put(db, key, value, flags) 514b39c5158Smillert DB_File db ; 515b39c5158Smillert DBTKEY key ; 516b39c5158Smillert DBT value ; 517b39c5158Smillert u_int flags ; 518b39c5158Smillert #endif 519b39c5158Smillert { 520b39c5158Smillert int status ; 521b39c5158Smillert 522b39c5158Smillert if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) { 523b39c5158Smillert DBC * temp_cursor ; 524b39c5158Smillert DBT l_key, l_value; 525b39c5158Smillert 526b39c5158Smillert #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 527b39c5158Smillert if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0) 528b39c5158Smillert #else 529b39c5158Smillert if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0) 530b39c5158Smillert #endif 531b39c5158Smillert return (-1) ; 532b39c5158Smillert 533b39c5158Smillert memset(&l_key, 0, sizeof(l_key)); 534b39c5158Smillert l_key.data = key.data; 535b39c5158Smillert l_key.size = key.size; 536b39c5158Smillert memset(&l_value, 0, sizeof(l_value)); 537b39c5158Smillert l_value.data = value.data; 538b39c5158Smillert l_value.size = value.size; 539b39c5158Smillert 540b39c5158Smillert if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) { 541b39c5158Smillert (void)temp_cursor->c_close(temp_cursor); 542b39c5158Smillert return (-1); 543b39c5158Smillert } 544b39c5158Smillert 545b39c5158Smillert status = temp_cursor->c_put(temp_cursor, &key, &value, flags); 546b39c5158Smillert (void)temp_cursor->c_close(temp_cursor); 547b39c5158Smillert 548b39c5158Smillert return (status) ; 549b39c5158Smillert } 550b39c5158Smillert 551b39c5158Smillert 552b39c5158Smillert if (flagSet(flags, R_CURSOR)) { 553b39c5158Smillert return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT); 554b39c5158Smillert } 555b39c5158Smillert if (flagSet(flags, R_SETCURSOR)) { 556b39c5158Smillert if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0) 557b39c5158Smillert return -1 ; 558b39c5158Smillert return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE); 559b39c5158Smillert } 560b39c5158Smillert 561b39c5158Smillert return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ; 562b39c5158Smillert 563b39c5158Smillert } 564b39c5158Smillert 565b39c5158Smillert #endif /* DB_VERSION_MAJOR */ 566b39c5158Smillert 567b39c5158Smillert static void 568b39c5158Smillert tidyUp(DB_File db) 569b39c5158Smillert { 570b39c5158Smillert db->aborted = TRUE ; 571b39c5158Smillert } 572b39c5158Smillert 573b39c5158Smillert 574b39c5158Smillert static int 5756fb12b70Safresh1 5766fb12b70Safresh1 #ifdef AT_LEAST_DB_6_0 5776fb12b70Safresh1 #ifdef CAN_PROTOTYPE 5786fb12b70Safresh1 btree_compare(DB * db, const DBT *key1, const DBT *key2, size_t* locp) 5796fb12b70Safresh1 #else 5806fb12b70Safresh1 btree_compare(db, key1, key2, locp) 5816fb12b70Safresh1 DB * db ; 5826fb12b70Safresh1 const DBT * key1 ; 5836fb12b70Safresh1 const DBT * key2 ; 5846fb12b70Safresh1 size_t* locp; 5856fb12b70Safresh1 #endif /* CAN_PROTOTYPE */ 5866fb12b70Safresh1 5876fb12b70Safresh1 #else /* Berkeley DB < 6.0 */ 588b39c5158Smillert #ifdef AT_LEAST_DB_3_2 589b39c5158Smillert 590b39c5158Smillert #ifdef CAN_PROTOTYPE 591b39c5158Smillert btree_compare(DB * db, const DBT *key1, const DBT *key2) 592b39c5158Smillert #else 593b39c5158Smillert btree_compare(db, key1, key2) 594b39c5158Smillert DB * db ; 595b39c5158Smillert const DBT * key1 ; 596b39c5158Smillert const DBT * key2 ; 597b39c5158Smillert #endif /* CAN_PROTOTYPE */ 598b39c5158Smillert 599b39c5158Smillert #else /* Berkeley DB < 3.2 */ 600b39c5158Smillert 601b39c5158Smillert #ifdef CAN_PROTOTYPE 602b39c5158Smillert btree_compare(const DBT *key1, const DBT *key2) 603b39c5158Smillert #else 604b39c5158Smillert btree_compare(key1, key2) 605b39c5158Smillert const DBT * key1 ; 606b39c5158Smillert const DBT * key2 ; 607b39c5158Smillert #endif 608b39c5158Smillert 609b39c5158Smillert #endif 6106fb12b70Safresh1 #endif 611b39c5158Smillert 612b39c5158Smillert { 613b39c5158Smillert #ifdef dTHX 614b39c5158Smillert dTHX; 615b39c5158Smillert #endif 616b39c5158Smillert dSP ; 617b39c5158Smillert dMY_CXT ; 618b39c5158Smillert void * data1, * data2 ; 619b39c5158Smillert int retval ; 620b39c5158Smillert int count ; 621b39c5158Smillert 622b8851fccSafresh1 #ifdef AT_LEAST_DB_3_2 623b8851fccSafresh1 PERL_UNUSED_ARG(db); 624b8851fccSafresh1 #endif 6259f11ffb7Safresh1 #ifdef AT_LEAST_DB_6_0 6269f11ffb7Safresh1 PERL_UNUSED_ARG(locp); 6279f11ffb7Safresh1 #endif 628b39c5158Smillert 629b39c5158Smillert if (CurrentDB->in_compare) { 630b39c5158Smillert tidyUp(CurrentDB); 631b39c5158Smillert croak ("DB_File btree_compare: recursion detected\n") ; 632b39c5158Smillert } 633b39c5158Smillert 634b39c5158Smillert data1 = (char *) key1->data ; 635b39c5158Smillert data2 = (char *) key2->data ; 636b39c5158Smillert 637b39c5158Smillert #ifndef newSVpvn 638b39c5158Smillert /* As newSVpv will assume that the data pointer is a null terminated C 639b39c5158Smillert string if the size parameter is 0, make sure that data points to an 640b39c5158Smillert empty string if the length is 0 641b39c5158Smillert */ 642b39c5158Smillert if (key1->size == 0) 643b39c5158Smillert data1 = "" ; 644b39c5158Smillert if (key2->size == 0) 645b39c5158Smillert data2 = "" ; 646b39c5158Smillert #endif 647b39c5158Smillert 648b39c5158Smillert ENTER ; 649b39c5158Smillert SAVETMPS; 650b39c5158Smillert SAVESPTR(CurrentDB); 651b39c5158Smillert CurrentDB->in_compare = FALSE; 652b39c5158Smillert SAVEINT(CurrentDB->in_compare); 653b39c5158Smillert CurrentDB->in_compare = TRUE; 654b39c5158Smillert 655b39c5158Smillert PUSHMARK(SP) ; 656b39c5158Smillert EXTEND(SP,2) ; 657b39c5158Smillert PUSHs(sv_2mortal(newSVpvn((const char*)data1,key1->size))); 658b39c5158Smillert PUSHs(sv_2mortal(newSVpvn((const char*)data2,key2->size))); 659b39c5158Smillert PUTBACK ; 660b39c5158Smillert 661b39c5158Smillert count = perl_call_sv(CurrentDB->compare, G_SCALAR); 662b39c5158Smillert 663b39c5158Smillert SPAGAIN ; 664b39c5158Smillert 665b39c5158Smillert if (count != 1){ 666b39c5158Smillert tidyUp(CurrentDB); 667b39c5158Smillert croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ; 668b39c5158Smillert } 669b39c5158Smillert 670b39c5158Smillert retval = POPi ; 671b39c5158Smillert 672b39c5158Smillert PUTBACK ; 673b39c5158Smillert FREETMPS ; 674b39c5158Smillert LEAVE ; 675b39c5158Smillert 676b39c5158Smillert return (retval) ; 677b39c5158Smillert 678b39c5158Smillert } 679b39c5158Smillert 680b39c5158Smillert static DB_Prefix_t 681b39c5158Smillert #ifdef AT_LEAST_DB_3_2 682b39c5158Smillert 683b39c5158Smillert #ifdef CAN_PROTOTYPE 684b39c5158Smillert btree_prefix(DB * db, const DBT *key1, const DBT *key2) 685b39c5158Smillert #else 686b39c5158Smillert btree_prefix(db, key1, key2) 687b39c5158Smillert Db * db ; 688b39c5158Smillert const DBT * key1 ; 689b39c5158Smillert const DBT * key2 ; 690b39c5158Smillert #endif 691b39c5158Smillert 692b39c5158Smillert #else /* Berkeley DB < 3.2 */ 693b39c5158Smillert 694b39c5158Smillert #ifdef CAN_PROTOTYPE 695b39c5158Smillert btree_prefix(const DBT *key1, const DBT *key2) 696b39c5158Smillert #else 697b39c5158Smillert btree_prefix(key1, key2) 698b39c5158Smillert const DBT * key1 ; 699b39c5158Smillert const DBT * key2 ; 700b39c5158Smillert #endif 701b39c5158Smillert 702b39c5158Smillert #endif 703b39c5158Smillert { 704b39c5158Smillert #ifdef dTHX 705b39c5158Smillert dTHX; 706b39c5158Smillert #endif 707b39c5158Smillert dSP ; 708b39c5158Smillert dMY_CXT ; 709b39c5158Smillert char * data1, * data2 ; 710b39c5158Smillert int retval ; 711b39c5158Smillert int count ; 712b39c5158Smillert 713b8851fccSafresh1 #ifdef AT_LEAST_DB_3_2 714b8851fccSafresh1 PERL_UNUSED_ARG(db); 715b8851fccSafresh1 #endif 716b8851fccSafresh1 717b39c5158Smillert if (CurrentDB->in_prefix){ 718b39c5158Smillert tidyUp(CurrentDB); 719b39c5158Smillert croak ("DB_File btree_prefix: recursion detected\n") ; 720b39c5158Smillert } 721b39c5158Smillert 722b39c5158Smillert data1 = (char *) key1->data ; 723b39c5158Smillert data2 = (char *) key2->data ; 724b39c5158Smillert 725b39c5158Smillert #ifndef newSVpvn 726b39c5158Smillert /* As newSVpv will assume that the data pointer is a null terminated C 727b39c5158Smillert string if the size parameter is 0, make sure that data points to an 728b39c5158Smillert empty string if the length is 0 729b39c5158Smillert */ 730b39c5158Smillert if (key1->size == 0) 731b39c5158Smillert data1 = "" ; 732b39c5158Smillert if (key2->size == 0) 733b39c5158Smillert data2 = "" ; 734b39c5158Smillert #endif 735b39c5158Smillert 736b39c5158Smillert ENTER ; 737b39c5158Smillert SAVETMPS; 738b39c5158Smillert SAVESPTR(CurrentDB); 739b39c5158Smillert CurrentDB->in_prefix = FALSE; 740b39c5158Smillert SAVEINT(CurrentDB->in_prefix); 741b39c5158Smillert CurrentDB->in_prefix = TRUE; 742b39c5158Smillert 743b39c5158Smillert PUSHMARK(SP) ; 744b39c5158Smillert EXTEND(SP,2) ; 745b39c5158Smillert PUSHs(sv_2mortal(newSVpvn(data1,key1->size))); 746b39c5158Smillert PUSHs(sv_2mortal(newSVpvn(data2,key2->size))); 747b39c5158Smillert PUTBACK ; 748b39c5158Smillert 749b39c5158Smillert count = perl_call_sv(CurrentDB->prefix, G_SCALAR); 750b39c5158Smillert 751b39c5158Smillert SPAGAIN ; 752b39c5158Smillert 753b39c5158Smillert if (count != 1){ 754b39c5158Smillert tidyUp(CurrentDB); 755b39c5158Smillert croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ; 756b39c5158Smillert } 757b39c5158Smillert 758b39c5158Smillert retval = POPi ; 759b39c5158Smillert 760b39c5158Smillert PUTBACK ; 761b39c5158Smillert FREETMPS ; 762b39c5158Smillert LEAVE ; 763b39c5158Smillert 764b39c5158Smillert return (retval) ; 765b39c5158Smillert } 766b39c5158Smillert 767b39c5158Smillert 768b39c5158Smillert #ifdef BERKELEY_DB_1 769b39c5158Smillert # define HASH_CB_SIZE_TYPE size_t 770b39c5158Smillert #else 771b39c5158Smillert # define HASH_CB_SIZE_TYPE u_int32_t 772b39c5158Smillert #endif 773b39c5158Smillert 774b39c5158Smillert static DB_Hash_t 775b39c5158Smillert #ifdef AT_LEAST_DB_3_2 776b39c5158Smillert 777b39c5158Smillert #ifdef CAN_PROTOTYPE 778b39c5158Smillert hash_cb(DB * db, const void *data, u_int32_t size) 779b39c5158Smillert #else 780b39c5158Smillert hash_cb(db, data, size) 781b39c5158Smillert DB * db ; 782b39c5158Smillert const void * data ; 783b39c5158Smillert HASH_CB_SIZE_TYPE size ; 784b39c5158Smillert #endif 785b39c5158Smillert 786b39c5158Smillert #else /* Berkeley DB < 3.2 */ 787b39c5158Smillert 788b39c5158Smillert #ifdef CAN_PROTOTYPE 789b39c5158Smillert hash_cb(const void *data, HASH_CB_SIZE_TYPE size) 790b39c5158Smillert #else 791b39c5158Smillert hash_cb(data, size) 792b39c5158Smillert const void * data ; 793b39c5158Smillert HASH_CB_SIZE_TYPE size ; 794b39c5158Smillert #endif 795b39c5158Smillert 796b39c5158Smillert #endif 797b39c5158Smillert { 798b39c5158Smillert #ifdef dTHX 799b39c5158Smillert dTHX; 800b39c5158Smillert #endif 801b39c5158Smillert dSP ; 802b39c5158Smillert dMY_CXT; 803b39c5158Smillert int retval = 0; 804b39c5158Smillert int count ; 805b39c5158Smillert 806b8851fccSafresh1 #ifdef AT_LEAST_DB_3_2 807b8851fccSafresh1 PERL_UNUSED_ARG(db); 808b8851fccSafresh1 #endif 809b8851fccSafresh1 810b39c5158Smillert if (CurrentDB->in_hash){ 811b39c5158Smillert tidyUp(CurrentDB); 812b39c5158Smillert croak ("DB_File hash callback: recursion detected\n") ; 813b39c5158Smillert } 814b39c5158Smillert 815b39c5158Smillert #ifndef newSVpvn 816b39c5158Smillert if (size == 0) 817b39c5158Smillert data = "" ; 818b39c5158Smillert #endif 819b39c5158Smillert 820b39c5158Smillert /* DGH - Next two lines added to fix corrupted stack problem */ 821b39c5158Smillert ENTER ; 822b39c5158Smillert SAVETMPS; 823b39c5158Smillert SAVESPTR(CurrentDB); 824b39c5158Smillert CurrentDB->in_hash = FALSE; 825b39c5158Smillert SAVEINT(CurrentDB->in_hash); 826b39c5158Smillert CurrentDB->in_hash = TRUE; 827b39c5158Smillert 828b39c5158Smillert PUSHMARK(SP) ; 829b39c5158Smillert 830b39c5158Smillert 831b39c5158Smillert XPUSHs(sv_2mortal(newSVpvn((char*)data,size))); 832b39c5158Smillert PUTBACK ; 833b39c5158Smillert 834b39c5158Smillert count = perl_call_sv(CurrentDB->hash, G_SCALAR); 835b39c5158Smillert 836b39c5158Smillert SPAGAIN ; 837b39c5158Smillert 838b39c5158Smillert if (count != 1){ 839b39c5158Smillert tidyUp(CurrentDB); 840b39c5158Smillert croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ; 841b39c5158Smillert } 842b39c5158Smillert 843b39c5158Smillert retval = POPi ; 844b39c5158Smillert 845b39c5158Smillert PUTBACK ; 846b39c5158Smillert FREETMPS ; 847b39c5158Smillert LEAVE ; 848b39c5158Smillert 849b39c5158Smillert return (retval) ; 850b39c5158Smillert } 851b39c5158Smillert 852b39c5158Smillert #ifdef WANT_ERROR 853b39c5158Smillert 854b39c5158Smillert static void 855b39c5158Smillert #ifdef AT_LEAST_DB_4_3 856b39c5158Smillert db_errcall_cb(const DB_ENV* dbenv, const char * db_errpfx, const char * buffer) 857b39c5158Smillert #else 858b39c5158Smillert db_errcall_cb(const char * db_errpfx, char * buffer) 859b39c5158Smillert #endif 860b39c5158Smillert { 861b39c5158Smillert #ifdef dTHX 862b39c5158Smillert dTHX; 863b39c5158Smillert #endif 864b39c5158Smillert SV * sv = perl_get_sv(ERR_BUFF, FALSE) ; 865b8851fccSafresh1 #ifdef AT_LEAST_DB_4_3 866b8851fccSafresh1 PERL_UNUSED_ARG(dbenv); 867b8851fccSafresh1 #endif 868b39c5158Smillert if (sv) { 869b39c5158Smillert if (db_errpfx) 870b39c5158Smillert sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ; 871b39c5158Smillert else 872b39c5158Smillert sv_setpv(sv, buffer) ; 873b39c5158Smillert } 874b39c5158Smillert } 875b39c5158Smillert #endif 876b39c5158Smillert 877b39c5158Smillert #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2) 878b39c5158Smillert 879b39c5158Smillert static void 880b39c5158Smillert #ifdef CAN_PROTOTYPE 881b39c5158Smillert PrintHash(INFO *hash) 882b39c5158Smillert #else 883b39c5158Smillert PrintHash(hash) 884b39c5158Smillert INFO * hash ; 885b39c5158Smillert #endif 886b39c5158Smillert { 887b39c5158Smillert printf ("HASH Info\n") ; 888b39c5158Smillert printf (" hash = %s\n", 889b39c5158Smillert (hash->db_HA_hash != NULL ? "redefined" : "default")) ; 890b39c5158Smillert printf (" bsize = %d\n", hash->db_HA_bsize) ; 891b39c5158Smillert printf (" ffactor = %d\n", hash->db_HA_ffactor) ; 892b39c5158Smillert printf (" nelem = %d\n", hash->db_HA_nelem) ; 893b39c5158Smillert printf (" cachesize = %d\n", hash->db_HA_cachesize) ; 894b39c5158Smillert printf (" lorder = %d\n", hash->db_HA_lorder) ; 895b39c5158Smillert 896b39c5158Smillert } 897b39c5158Smillert 898b39c5158Smillert static void 899b39c5158Smillert #ifdef CAN_PROTOTYPE 900b39c5158Smillert PrintRecno(INFO *recno) 901b39c5158Smillert #else 902b39c5158Smillert PrintRecno(recno) 903b39c5158Smillert INFO * recno ; 904b39c5158Smillert #endif 905b39c5158Smillert { 906b39c5158Smillert printf ("RECNO Info\n") ; 907b39c5158Smillert printf (" flags = %d\n", recno->db_RE_flags) ; 908b39c5158Smillert printf (" cachesize = %d\n", recno->db_RE_cachesize) ; 909b39c5158Smillert printf (" psize = %d\n", recno->db_RE_psize) ; 910b39c5158Smillert printf (" lorder = %d\n", recno->db_RE_lorder) ; 911b39c5158Smillert printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ; 912b39c5158Smillert printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ; 913b39c5158Smillert printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ; 914b39c5158Smillert } 915b39c5158Smillert 916b39c5158Smillert static void 917b39c5158Smillert #ifdef CAN_PROTOTYPE 918b39c5158Smillert PrintBtree(INFO *btree) 919b39c5158Smillert #else 920b39c5158Smillert PrintBtree(btree) 921b39c5158Smillert INFO * btree ; 922b39c5158Smillert #endif 923b39c5158Smillert { 924b39c5158Smillert printf ("BTREE Info\n") ; 925b39c5158Smillert printf (" compare = %s\n", 926b39c5158Smillert (btree->db_BT_compare ? "redefined" : "default")) ; 927b39c5158Smillert printf (" prefix = %s\n", 928b39c5158Smillert (btree->db_BT_prefix ? "redefined" : "default")) ; 929b39c5158Smillert printf (" flags = %d\n", btree->db_BT_flags) ; 930b39c5158Smillert printf (" cachesize = %d\n", btree->db_BT_cachesize) ; 931b39c5158Smillert printf (" psize = %d\n", btree->db_BT_psize) ; 932b39c5158Smillert #ifndef DB_VERSION_MAJOR 933b39c5158Smillert printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ; 934b39c5158Smillert printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ; 935b39c5158Smillert #endif 936b39c5158Smillert printf (" lorder = %d\n", btree->db_BT_lorder) ; 937b39c5158Smillert } 938b39c5158Smillert 939b39c5158Smillert #else 940b39c5158Smillert 941b39c5158Smillert #define PrintRecno(recno) 942b39c5158Smillert #define PrintHash(hash) 943b39c5158Smillert #define PrintBtree(btree) 944b39c5158Smillert 945b39c5158Smillert #endif /* TRACE */ 946b39c5158Smillert 947b39c5158Smillert 948b39c5158Smillert static I32 949b39c5158Smillert #ifdef CAN_PROTOTYPE 950b39c5158Smillert GetArrayLength(pTHX_ DB_File db) 951b39c5158Smillert #else 952b39c5158Smillert GetArrayLength(db) 953b39c5158Smillert DB_File db ; 954b39c5158Smillert #endif 955b39c5158Smillert { 956b39c5158Smillert DBT key ; 957b39c5158Smillert DBT value ; 958b39c5158Smillert int RETVAL ; 959b39c5158Smillert 960b39c5158Smillert DBT_clear(key) ; 961b39c5158Smillert DBT_clear(value) ; 962b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_LAST) ; 963b39c5158Smillert if (RETVAL == 0) 964b39c5158Smillert RETVAL = *(I32 *)key.data ; 965b39c5158Smillert else /* No key means empty file */ 966b39c5158Smillert RETVAL = 0 ; 967b39c5158Smillert 968b39c5158Smillert return ((I32)RETVAL) ; 969b39c5158Smillert } 970b39c5158Smillert 971b39c5158Smillert static recno_t 972b39c5158Smillert #ifdef CAN_PROTOTYPE 973b39c5158Smillert GetRecnoKey(pTHX_ DB_File db, I32 value) 974b39c5158Smillert #else 975b39c5158Smillert GetRecnoKey(db, value) 976b39c5158Smillert DB_File db ; 977b39c5158Smillert I32 value ; 978b39c5158Smillert #endif 979b39c5158Smillert { 980b39c5158Smillert if (value < 0) { 981b39c5158Smillert /* Get the length of the array */ 982b39c5158Smillert I32 length = GetArrayLength(aTHX_ db) ; 983b39c5158Smillert 984b39c5158Smillert /* check for attempt to write before start of array */ 985b39c5158Smillert if (length + value + 1 <= 0) { 986b39c5158Smillert tidyUp(db); 987b39c5158Smillert croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ; 988b39c5158Smillert } 989b39c5158Smillert 990b39c5158Smillert value = length + value + 1 ; 991b39c5158Smillert } 992b39c5158Smillert else 993b39c5158Smillert ++ value ; 994b39c5158Smillert 995b39c5158Smillert return value ; 996b39c5158Smillert } 997b39c5158Smillert 998b39c5158Smillert 999b39c5158Smillert static DB_File 1000b39c5158Smillert #ifdef CAN_PROTOTYPE 1001b39c5158Smillert ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv) 1002b39c5158Smillert #else 1003b39c5158Smillert ParseOpenInfo(isHASH, name, flags, mode, sv) 1004b39c5158Smillert int isHASH ; 1005b39c5158Smillert char * name ; 1006b39c5158Smillert int flags ; 1007b39c5158Smillert int mode ; 1008b39c5158Smillert SV * sv ; 1009b39c5158Smillert #endif 1010b39c5158Smillert { 1011b39c5158Smillert 1012b39c5158Smillert #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */ 1013b39c5158Smillert 1014b39c5158Smillert SV ** svp; 1015b39c5158Smillert HV * action ; 1016b39c5158Smillert DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ; 1017b39c5158Smillert void * openinfo = NULL ; 1018b39c5158Smillert INFO * info = &RETVAL->info ; 1019b39c5158Smillert STRLEN n_a; 1020b39c5158Smillert dMY_CXT; 1021b39c5158Smillert 1022b39c5158Smillert #ifdef TRACE 1023b39c5158Smillert printf("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n", 1024b39c5158Smillert name, flags, mode, sv == NULL) ; 1025b39c5158Smillert #endif 1026b39c5158Smillert Zero(RETVAL, 1, DB_File_type) ; 1027b39c5158Smillert 1028b39c5158Smillert /* Default to HASH */ 1029b39c5158Smillert RETVAL->filtering = 0 ; 1030b39c5158Smillert RETVAL->filter_fetch_key = RETVAL->filter_store_key = 1031b39c5158Smillert RETVAL->filter_fetch_value = RETVAL->filter_store_value = 1032b39c5158Smillert RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ; 1033b39c5158Smillert RETVAL->type = DB_HASH ; 1034b39c5158Smillert 1035b39c5158Smillert /* DGH - Next line added to avoid SEGV on existing hash DB */ 1036b39c5158Smillert CurrentDB = RETVAL; 1037b39c5158Smillert 1038b39c5158Smillert /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */ 1039b39c5158Smillert RETVAL->in_memory = (name == NULL) ; 1040b39c5158Smillert 1041b39c5158Smillert if (sv) 1042b39c5158Smillert { 1043b39c5158Smillert if (! SvROK(sv) ) 104456d68f1eSafresh1 croak_and_free("type parameter is not a reference") ; 1045b39c5158Smillert 1046b39c5158Smillert svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ; 1047b39c5158Smillert if (svp && SvOK(*svp)) 1048b39c5158Smillert action = (HV*) SvRV(*svp) ; 1049b39c5158Smillert else 105056d68f1eSafresh1 croak_and_free("internal error") ; 1051b39c5158Smillert 1052b39c5158Smillert if (sv_isa(sv, "DB_File::HASHINFO")) 1053b39c5158Smillert { 1054b39c5158Smillert 1055b39c5158Smillert if (!isHASH) 105656d68f1eSafresh1 croak_and_free("DB_File can only tie an associative array to a DB_HASH database") ; 1057b39c5158Smillert 1058b39c5158Smillert RETVAL->type = DB_HASH ; 1059b39c5158Smillert openinfo = (void*)info ; 1060b39c5158Smillert 1061b39c5158Smillert svp = hv_fetch(action, "hash", 4, FALSE); 1062b39c5158Smillert 1063b39c5158Smillert if (svp && SvOK(*svp)) 1064b39c5158Smillert { 1065b39c5158Smillert info->db_HA_hash = hash_cb ; 1066b39c5158Smillert RETVAL->hash = newSVsv(*svp) ; 1067b39c5158Smillert } 1068b39c5158Smillert else 1069b39c5158Smillert info->db_HA_hash = NULL ; 1070b39c5158Smillert 1071b39c5158Smillert svp = hv_fetch(action, "ffactor", 7, FALSE); 1072b39c5158Smillert info->db_HA_ffactor = svp ? SvIV(*svp) : 0; 1073b39c5158Smillert 1074b39c5158Smillert svp = hv_fetch(action, "nelem", 5, FALSE); 1075b39c5158Smillert info->db_HA_nelem = svp ? SvIV(*svp) : 0; 1076b39c5158Smillert 1077b39c5158Smillert svp = hv_fetch(action, "bsize", 5, FALSE); 1078b39c5158Smillert info->db_HA_bsize = svp ? SvIV(*svp) : 0; 1079b39c5158Smillert 1080b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1081b39c5158Smillert info->db_HA_cachesize = svp ? SvIV(*svp) : 0; 1082b39c5158Smillert 1083b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1084b39c5158Smillert info->db_HA_lorder = svp ? SvIV(*svp) : 0; 1085b39c5158Smillert 1086b39c5158Smillert PrintHash(info) ; 1087b39c5158Smillert } 1088b39c5158Smillert else if (sv_isa(sv, "DB_File::BTREEINFO")) 1089b39c5158Smillert { 1090b39c5158Smillert if (!isHASH) 109156d68f1eSafresh1 croak_and_free("DB_File can only tie an associative array to a DB_BTREE database"); 1092b39c5158Smillert 1093b39c5158Smillert RETVAL->type = DB_BTREE ; 1094b39c5158Smillert openinfo = (void*)info ; 1095b39c5158Smillert 1096b39c5158Smillert svp = hv_fetch(action, "compare", 7, FALSE); 1097b39c5158Smillert if (svp && SvOK(*svp)) 1098b39c5158Smillert { 1099b39c5158Smillert info->db_BT_compare = btree_compare ; 1100b39c5158Smillert RETVAL->compare = newSVsv(*svp) ; 1101b39c5158Smillert } 1102b39c5158Smillert else 1103b39c5158Smillert info->db_BT_compare = NULL ; 1104b39c5158Smillert 1105b39c5158Smillert svp = hv_fetch(action, "prefix", 6, FALSE); 1106b39c5158Smillert if (svp && SvOK(*svp)) 1107b39c5158Smillert { 1108b39c5158Smillert info->db_BT_prefix = btree_prefix ; 1109b39c5158Smillert RETVAL->prefix = newSVsv(*svp) ; 1110b39c5158Smillert } 1111b39c5158Smillert else 1112b39c5158Smillert info->db_BT_prefix = NULL ; 1113b39c5158Smillert 1114b39c5158Smillert svp = hv_fetch(action, "flags", 5, FALSE); 1115b39c5158Smillert info->db_BT_flags = svp ? SvIV(*svp) : 0; 1116b39c5158Smillert 1117b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1118b39c5158Smillert info->db_BT_cachesize = svp ? SvIV(*svp) : 0; 1119b39c5158Smillert 1120b39c5158Smillert #ifndef DB_VERSION_MAJOR 1121b39c5158Smillert svp = hv_fetch(action, "minkeypage", 10, FALSE); 1122b39c5158Smillert info->btree.minkeypage = svp ? SvIV(*svp) : 0; 1123b39c5158Smillert 1124b39c5158Smillert svp = hv_fetch(action, "maxkeypage", 10, FALSE); 1125b39c5158Smillert info->btree.maxkeypage = svp ? SvIV(*svp) : 0; 1126b39c5158Smillert #endif 1127b39c5158Smillert 1128b39c5158Smillert svp = hv_fetch(action, "psize", 5, FALSE); 1129b39c5158Smillert info->db_BT_psize = svp ? SvIV(*svp) : 0; 1130b39c5158Smillert 1131b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1132b39c5158Smillert info->db_BT_lorder = svp ? SvIV(*svp) : 0; 1133b39c5158Smillert 1134b39c5158Smillert PrintBtree(info) ; 1135b39c5158Smillert 1136b39c5158Smillert } 1137b39c5158Smillert else if (sv_isa(sv, "DB_File::RECNOINFO")) 1138b39c5158Smillert { 1139b39c5158Smillert if (isHASH) 114056d68f1eSafresh1 croak_and_free("DB_File can only tie an array to a DB_RECNO database"); 1141b39c5158Smillert 1142b39c5158Smillert RETVAL->type = DB_RECNO ; 1143b39c5158Smillert openinfo = (void *)info ; 1144b39c5158Smillert 1145b39c5158Smillert info->db_RE_flags = 0 ; 1146b39c5158Smillert 1147b39c5158Smillert svp = hv_fetch(action, "flags", 5, FALSE); 1148b39c5158Smillert info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0); 1149b39c5158Smillert 1150b39c5158Smillert svp = hv_fetch(action, "reclen", 6, FALSE); 1151b39c5158Smillert info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0); 1152b39c5158Smillert 1153b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1154b39c5158Smillert info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0); 1155b39c5158Smillert 1156b39c5158Smillert svp = hv_fetch(action, "psize", 5, FALSE); 1157b39c5158Smillert info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0); 1158b39c5158Smillert 1159b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1160b39c5158Smillert info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0); 1161b39c5158Smillert 1162b39c5158Smillert #ifdef DB_VERSION_MAJOR 1163b39c5158Smillert info->re_source = name ; 1164b39c5158Smillert name = NULL ; 1165b39c5158Smillert #endif 1166b39c5158Smillert svp = hv_fetch(action, "bfname", 6, FALSE); 1167b39c5158Smillert if (svp && SvOK(*svp)) { 1168b39c5158Smillert char * ptr = SvPV(*svp,n_a) ; 1169b39c5158Smillert #ifdef DB_VERSION_MAJOR 1170b39c5158Smillert name = (char*) n_a ? ptr : NULL ; 1171b39c5158Smillert #else 1172b39c5158Smillert info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ; 1173b39c5158Smillert #endif 1174b39c5158Smillert } 1175b39c5158Smillert else 1176b39c5158Smillert #ifdef DB_VERSION_MAJOR 1177b39c5158Smillert name = NULL ; 1178b39c5158Smillert #else 1179b39c5158Smillert info->db_RE_bfname = NULL ; 1180b39c5158Smillert #endif 1181b39c5158Smillert 1182b39c5158Smillert svp = hv_fetch(action, "bval", 4, FALSE); 1183b39c5158Smillert #ifdef DB_VERSION_MAJOR 1184b39c5158Smillert if (svp && SvOK(*svp)) 1185b39c5158Smillert { 1186b39c5158Smillert int value ; 1187b39c5158Smillert if (SvPOK(*svp)) 1188b39c5158Smillert value = (int)*SvPV(*svp, n_a) ; 1189b39c5158Smillert else 1190b39c5158Smillert value = SvIV(*svp) ; 1191b39c5158Smillert 1192b39c5158Smillert if (info->flags & DB_FIXEDLEN) { 1193b39c5158Smillert info->re_pad = value ; 1194b39c5158Smillert info->flags |= DB_PAD ; 1195b39c5158Smillert } 1196b39c5158Smillert else { 1197b39c5158Smillert info->re_delim = value ; 1198b39c5158Smillert info->flags |= DB_DELIMITER ; 1199b39c5158Smillert } 1200b39c5158Smillert 1201b39c5158Smillert } 1202b39c5158Smillert #else 1203b39c5158Smillert if (svp && SvOK(*svp)) 1204b39c5158Smillert { 1205b39c5158Smillert if (SvPOK(*svp)) 1206b39c5158Smillert info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ; 1207b39c5158Smillert else 1208b39c5158Smillert info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ; 1209b39c5158Smillert DB_flags(info->flags, DB_DELIMITER) ; 1210b39c5158Smillert 1211b39c5158Smillert } 1212b39c5158Smillert else 1213b39c5158Smillert { 1214b39c5158Smillert if (info->db_RE_flags & R_FIXEDLEN) 1215b39c5158Smillert info->db_RE_bval = (u_char) ' ' ; 1216b39c5158Smillert else 1217b39c5158Smillert info->db_RE_bval = (u_char) '\n' ; 1218b39c5158Smillert DB_flags(info->flags, DB_DELIMITER) ; 1219b39c5158Smillert } 1220b39c5158Smillert #endif 1221b39c5158Smillert 1222b39c5158Smillert #ifdef DB_RENUMBER 1223b39c5158Smillert info->flags |= DB_RENUMBER ; 1224b39c5158Smillert #endif 1225b39c5158Smillert 1226b39c5158Smillert PrintRecno(info) ; 1227b39c5158Smillert } 1228b39c5158Smillert else 122956d68f1eSafresh1 croak_and_free("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO"); 1230b39c5158Smillert } 1231b39c5158Smillert 1232b39c5158Smillert 1233b39c5158Smillert /* OS2 Specific Code */ 1234b39c5158Smillert #ifdef OS2 1235b39c5158Smillert #ifdef __EMX__ 1236b39c5158Smillert flags |= O_BINARY; 1237b39c5158Smillert #endif /* __EMX__ */ 1238b39c5158Smillert #endif /* OS2 */ 1239b39c5158Smillert 1240b39c5158Smillert #ifdef DB_VERSION_MAJOR 1241b39c5158Smillert 1242b39c5158Smillert { 1243b39c5158Smillert int Flags = 0 ; 1244b39c5158Smillert int status ; 1245b39c5158Smillert 1246b39c5158Smillert /* Map 1.x flags to 2.x flags */ 1247b39c5158Smillert if ((flags & O_CREAT) == O_CREAT) 1248b39c5158Smillert Flags |= DB_CREATE ; 1249b39c5158Smillert 1250b39c5158Smillert #if O_RDONLY == 0 1251b39c5158Smillert if (flags == O_RDONLY) 1252b39c5158Smillert #else 1253b39c5158Smillert if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR) 1254b39c5158Smillert #endif 1255b39c5158Smillert Flags |= DB_RDONLY ; 1256b39c5158Smillert 1257b39c5158Smillert #ifdef O_TRUNC 1258b39c5158Smillert if ((flags & O_TRUNC) == O_TRUNC) 1259b39c5158Smillert Flags |= DB_TRUNCATE ; 1260b39c5158Smillert #endif 1261b39c5158Smillert 1262b39c5158Smillert status = db_open(name, RETVAL->type, Flags, mode, NULL, (DB_INFO*)openinfo, &RETVAL->dbp) ; 1263b39c5158Smillert if (status == 0) 1264b39c5158Smillert #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 1265b39c5158Smillert status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ; 1266b39c5158Smillert #else 126756d68f1eSafresh1 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor, 0) ; 1268b39c5158Smillert #endif 1269b39c5158Smillert 1270b39c5158Smillert if (status) 1271b39c5158Smillert RETVAL->dbp = NULL ; 1272b39c5158Smillert } 1273b39c5158Smillert #else 1274b39c5158Smillert 1275b39c5158Smillert #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2 1276b39c5158Smillert RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ; 1277b39c5158Smillert #else 1278b39c5158Smillert RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ; 1279b39c5158Smillert #endif /* DB_LIBRARY_COMPATIBILITY_API */ 1280b39c5158Smillert 1281b39c5158Smillert #endif 1282b39c5158Smillert 1283b39c5158Smillert return (RETVAL) ; 1284b39c5158Smillert 1285b39c5158Smillert #else /* Berkeley DB Version > 2 */ 1286b39c5158Smillert 1287b39c5158Smillert SV ** svp; 1288b39c5158Smillert HV * action ; 1289b39c5158Smillert DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ; 1290b39c5158Smillert DB * dbp ; 1291b39c5158Smillert STRLEN n_a; 1292b39c5158Smillert int status ; 1293b39c5158Smillert dMY_CXT; 1294b39c5158Smillert 129556d68f1eSafresh1 Trace(("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n",\ 129656d68f1eSafresh1 name, flags, mode, sv == NULL)) ; 1297b39c5158Smillert Zero(RETVAL, 1, DB_File_type) ; 1298b39c5158Smillert 1299b39c5158Smillert /* Default to HASH */ 1300b39c5158Smillert RETVAL->filtering = 0 ; 1301b39c5158Smillert RETVAL->filter_fetch_key = RETVAL->filter_store_key = 1302b39c5158Smillert RETVAL->filter_fetch_value = RETVAL->filter_store_value = 1303b39c5158Smillert RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ; 1304b39c5158Smillert RETVAL->type = DB_HASH ; 1305b39c5158Smillert 1306b39c5158Smillert /* DGH - Next line added to avoid SEGV on existing hash DB */ 1307b39c5158Smillert CurrentDB = RETVAL; 1308b39c5158Smillert 1309b39c5158Smillert /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */ 1310b39c5158Smillert RETVAL->in_memory = (name == NULL) ; 1311b39c5158Smillert 1312b39c5158Smillert status = db_create(&RETVAL->dbp, NULL,0) ; 131356d68f1eSafresh1 Trace(("db_create returned %d %s\n", status, db_strerror(status))) ; 1314b39c5158Smillert if (status) { 1315b39c5158Smillert RETVAL->dbp = NULL ; 1316b39c5158Smillert return (RETVAL) ; 1317b39c5158Smillert } 1318b39c5158Smillert dbp = RETVAL->dbp ; 1319b39c5158Smillert 1320b39c5158Smillert #ifdef WANT_ERROR 1321b39c5158Smillert RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ; 1322b39c5158Smillert #endif 1323b39c5158Smillert if (sv) 1324b39c5158Smillert { 1325b39c5158Smillert if (! SvROK(sv) ) 132656d68f1eSafresh1 croak_and_free("type parameter is not a reference") ; 1327b39c5158Smillert 1328b39c5158Smillert svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ; 1329b39c5158Smillert if (svp && SvOK(*svp)) 1330b39c5158Smillert action = (HV*) SvRV(*svp) ; 1331b39c5158Smillert else 133256d68f1eSafresh1 croak_and_free("internal error") ; 1333b39c5158Smillert 1334b39c5158Smillert if (sv_isa(sv, "DB_File::HASHINFO")) 1335b39c5158Smillert { 1336b39c5158Smillert 1337b39c5158Smillert if (!isHASH) 133856d68f1eSafresh1 croak_and_free("DB_File can only tie an associative array to a DB_HASH database") ; 1339b39c5158Smillert 1340b39c5158Smillert RETVAL->type = DB_HASH ; 1341b39c5158Smillert 1342b39c5158Smillert svp = hv_fetch(action, "hash", 4, FALSE); 1343b39c5158Smillert 1344b39c5158Smillert if (svp && SvOK(*svp)) 1345b39c5158Smillert { 1346b39c5158Smillert (void)dbp->set_h_hash(dbp, hash_cb) ; 1347b39c5158Smillert RETVAL->hash = newSVsv(*svp) ; 1348b39c5158Smillert } 1349b39c5158Smillert 1350b39c5158Smillert svp = hv_fetch(action, "ffactor", 7, FALSE); 1351b39c5158Smillert if (svp) 1352b39c5158Smillert (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ; 1353b39c5158Smillert 1354b39c5158Smillert svp = hv_fetch(action, "nelem", 5, FALSE); 1355b39c5158Smillert if (svp) 1356b39c5158Smillert (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ; 1357b39c5158Smillert 1358b39c5158Smillert svp = hv_fetch(action, "bsize", 5, FALSE); 1359b39c5158Smillert if (svp) 1360b39c5158Smillert (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)); 1361b39c5158Smillert 1362b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1363b39c5158Smillert if (svp) 1364b39c5158Smillert (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ; 1365b39c5158Smillert 1366b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1367b39c5158Smillert if (svp) 1368b39c5158Smillert (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ; 1369b39c5158Smillert 1370b39c5158Smillert PrintHash(info) ; 1371b39c5158Smillert } 1372b39c5158Smillert else if (sv_isa(sv, "DB_File::BTREEINFO")) 1373b39c5158Smillert { 1374b39c5158Smillert if (!isHASH) 137556d68f1eSafresh1 croak_and_free("DB_File can only tie an associative array to a DB_BTREE database"); 1376b39c5158Smillert 1377b39c5158Smillert RETVAL->type = DB_BTREE ; 1378b39c5158Smillert 1379b39c5158Smillert svp = hv_fetch(action, "compare", 7, FALSE); 1380b39c5158Smillert if (svp && SvOK(*svp)) 1381b39c5158Smillert { 1382b39c5158Smillert (void)dbp->set_bt_compare(dbp, btree_compare) ; 1383b39c5158Smillert RETVAL->compare = newSVsv(*svp) ; 1384b39c5158Smillert } 1385b39c5158Smillert 1386b39c5158Smillert svp = hv_fetch(action, "prefix", 6, FALSE); 1387b39c5158Smillert if (svp && SvOK(*svp)) 1388b39c5158Smillert { 1389b39c5158Smillert (void)dbp->set_bt_prefix(dbp, btree_prefix) ; 1390b39c5158Smillert RETVAL->prefix = newSVsv(*svp) ; 1391b39c5158Smillert } 1392b39c5158Smillert 1393b39c5158Smillert svp = hv_fetch(action, "flags", 5, FALSE); 1394b39c5158Smillert if (svp) 1395b39c5158Smillert (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ; 1396b39c5158Smillert 1397b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1398b39c5158Smillert if (svp) 1399b39c5158Smillert (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ; 1400b39c5158Smillert 1401b39c5158Smillert svp = hv_fetch(action, "psize", 5, FALSE); 1402b39c5158Smillert if (svp) 1403b39c5158Smillert (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ; 1404b39c5158Smillert 1405b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1406b39c5158Smillert if (svp) 1407b39c5158Smillert (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ; 1408b39c5158Smillert 1409b39c5158Smillert PrintBtree(info) ; 1410b39c5158Smillert 1411b39c5158Smillert } 1412b39c5158Smillert else if (sv_isa(sv, "DB_File::RECNOINFO")) 1413b39c5158Smillert { 1414b39c5158Smillert int fixed = FALSE ; 1415b39c5158Smillert 1416b39c5158Smillert if (isHASH) 141756d68f1eSafresh1 croak_and_free("DB_File can only tie an array to a DB_RECNO database"); 1418b39c5158Smillert 1419b39c5158Smillert RETVAL->type = DB_RECNO ; 1420b39c5158Smillert 1421b39c5158Smillert svp = hv_fetch(action, "flags", 5, FALSE); 1422b39c5158Smillert if (svp) { 1423b39c5158Smillert int flags = SvIV(*svp) ; 1424b39c5158Smillert /* remove FIXDLEN, if present */ 1425b39c5158Smillert if (flags & DB_FIXEDLEN) { 1426b39c5158Smillert fixed = TRUE ; 1427b39c5158Smillert flags &= ~DB_FIXEDLEN ; 1428b39c5158Smillert } 1429b39c5158Smillert } 1430b39c5158Smillert 1431b39c5158Smillert svp = hv_fetch(action, "cachesize", 9, FALSE); 1432b39c5158Smillert if (svp) { 1433b39c5158Smillert status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ; 1434b39c5158Smillert } 1435b39c5158Smillert 1436b39c5158Smillert svp = hv_fetch(action, "psize", 5, FALSE); 1437b39c5158Smillert if (svp) { 1438b39c5158Smillert status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ; 1439b39c5158Smillert } 1440b39c5158Smillert 1441b39c5158Smillert svp = hv_fetch(action, "lorder", 6, FALSE); 1442b39c5158Smillert if (svp) { 1443b39c5158Smillert status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ; 1444b39c5158Smillert } 1445b39c5158Smillert 1446b39c5158Smillert svp = hv_fetch(action, "bval", 4, FALSE); 1447b39c5158Smillert if (svp && SvOK(*svp)) 1448b39c5158Smillert { 1449b39c5158Smillert int value ; 1450b39c5158Smillert if (SvPOK(*svp)) 1451b39c5158Smillert value = (int)*SvPV(*svp, n_a) ; 1452b39c5158Smillert else 1453b39c5158Smillert value = (int)SvIV(*svp) ; 1454b39c5158Smillert 1455b39c5158Smillert if (fixed) { 14569f11ffb7Safresh1 (void)dbp->set_re_pad(dbp, value) ; 1457b39c5158Smillert } 1458b39c5158Smillert else { 14599f11ffb7Safresh1 (void)dbp->set_re_delim(dbp, value) ; 1460b39c5158Smillert } 1461b39c5158Smillert 1462b39c5158Smillert } 1463b39c5158Smillert 1464b39c5158Smillert if (fixed) { 1465b39c5158Smillert svp = hv_fetch(action, "reclen", 6, FALSE); 1466b39c5158Smillert if (svp) { 1467b39c5158Smillert u_int32_t len = my_SvUV32(*svp) ; 14689f11ffb7Safresh1 (void)dbp->set_re_len(dbp, len) ; 1469b39c5158Smillert } 1470b39c5158Smillert } 1471b39c5158Smillert 1472b39c5158Smillert if (name != NULL) { 14739f11ffb7Safresh1 (void)dbp->set_re_source(dbp, name) ; 1474b39c5158Smillert name = NULL ; 1475b39c5158Smillert } 1476b39c5158Smillert 1477b39c5158Smillert svp = hv_fetch(action, "bfname", 6, FALSE); 1478b39c5158Smillert if (svp && SvOK(*svp)) { 1479b39c5158Smillert char * ptr = SvPV(*svp,n_a) ; 1480b39c5158Smillert name = (char*) n_a ? ptr : NULL ; 1481b39c5158Smillert } 1482b39c5158Smillert else 1483b39c5158Smillert name = NULL ; 1484b39c5158Smillert 1485b39c5158Smillert 14869f11ffb7Safresh1 (void)dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ; 1487b39c5158Smillert 1488b39c5158Smillert if (flags){ 1489b39c5158Smillert (void)dbp->set_flags(dbp, (u_int32_t)flags) ; 1490b39c5158Smillert } 1491b39c5158Smillert PrintRecno(info) ; 1492b39c5158Smillert } 1493b39c5158Smillert else 149456d68f1eSafresh1 croak_and_free("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO"); 1495b39c5158Smillert } 1496b39c5158Smillert 1497b39c5158Smillert { 1498b39c5158Smillert u_int32_t Flags = 0 ; 1499b39c5158Smillert int status ; 1500b39c5158Smillert 1501b39c5158Smillert /* Map 1.x flags to 3.x flags */ 1502b39c5158Smillert if ((flags & O_CREAT) == O_CREAT) 1503b39c5158Smillert Flags |= DB_CREATE ; 1504b39c5158Smillert 1505b39c5158Smillert #if O_RDONLY == 0 1506b39c5158Smillert if (flags == O_RDONLY) 1507b39c5158Smillert #else 1508b39c5158Smillert if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR) 1509b39c5158Smillert #endif 1510b39c5158Smillert Flags |= DB_RDONLY ; 1511b39c5158Smillert 1512b39c5158Smillert #ifdef O_TRUNC 1513b39c5158Smillert if ((flags & O_TRUNC) == O_TRUNC) 1514b39c5158Smillert Flags |= DB_TRUNCATE ; 1515b39c5158Smillert #endif 1516b39c5158Smillert 1517b39c5158Smillert #ifdef AT_LEAST_DB_4_4 1518b39c5158Smillert /* need this for recno */ 1519b39c5158Smillert if ((flags & O_TRUNC) == O_TRUNC) 1520b39c5158Smillert Flags |= DB_CREATE ; 1521b39c5158Smillert #endif 1522b39c5158Smillert 1523b39c5158Smillert #ifdef AT_LEAST_DB_4_1 1524b39c5158Smillert status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type, 1525b39c5158Smillert Flags, mode) ; 1526b39c5158Smillert #else 1527b39c5158Smillert status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type, 1528b39c5158Smillert Flags, mode) ; 1529b39c5158Smillert #endif 153056d68f1eSafresh1 Trace(("open returned %d %s\n", status, db_strerror(status))) ; 1531b39c5158Smillert 1532b39c5158Smillert if (status == 0) { 1533b39c5158Smillert 153456d68f1eSafresh1 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor, 0) ; 153556d68f1eSafresh1 Trace(("cursor returned %d %s\n", status, db_strerror(status))) ; 1536b39c5158Smillert } 1537b39c5158Smillert 1538b39c5158Smillert if (status) 15396fb12b70Safresh1 { 15406fb12b70Safresh1 db_close(RETVAL); /* close **dbp handle to prevent mem.leak */ 1541b39c5158Smillert RETVAL->dbp = NULL ; 15426fb12b70Safresh1 } 1543b39c5158Smillert } 1544b39c5158Smillert 1545b39c5158Smillert return (RETVAL) ; 1546b39c5158Smillert 1547b39c5158Smillert #endif /* Berkeley DB Version > 2 */ 1548b39c5158Smillert 1549b39c5158Smillert } /* ParseOpenInfo */ 1550b39c5158Smillert 1551b39c5158Smillert 1552b39c5158Smillert #include "constants.h" 1553b39c5158Smillert 1554b39c5158Smillert MODULE = DB_File PACKAGE = DB_File PREFIX = db_ 1555b39c5158Smillert 1556b39c5158Smillert INCLUDE: constants.xs 1557b39c5158Smillert 1558b39c5158Smillert BOOT: 1559b39c5158Smillert { 1560b39c5158Smillert #ifdef dTHX 1561b39c5158Smillert dTHX; 1562b39c5158Smillert #endif 1563b39c5158Smillert #ifdef WANT_ERROR 1564b39c5158Smillert SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ; 1565b39c5158Smillert #endif 1566b39c5158Smillert MY_CXT_INIT; 1567b8851fccSafresh1 #ifdef WANT_ERROR 1568b8851fccSafresh1 PERL_UNUSED_VAR(sv_err); /* huh? we just retrieved it... */ 1569b8851fccSafresh1 #endif 1570b39c5158Smillert __getBerkeleyDBInfo() ; 1571b39c5158Smillert 1572b39c5158Smillert DBT_clear(empty) ; 1573b39c5158Smillert empty.data = &zero ; 1574b39c5158Smillert empty.size = sizeof(recno_t) ; 1575b39c5158Smillert } 1576b39c5158Smillert 1577b39c5158Smillert 1578b39c5158Smillert 1579b39c5158Smillert DB_File 1580b39c5158Smillert db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH) 1581b39c5158Smillert int isHASH 1582b39c5158Smillert char * dbtype 1583b39c5158Smillert int flags 1584b39c5158Smillert int mode 1585b39c5158Smillert CODE: 1586b39c5158Smillert { 1587b39c5158Smillert char * name = (char *) NULL ; 1588b39c5158Smillert SV * sv = (SV *) NULL ; 1589b39c5158Smillert STRLEN n_a; 159056d68f1eSafresh1 Trace(("In db_DoTie_\n")); 1591b39c5158Smillert 1592b39c5158Smillert if (items >= 3 && SvOK(ST(2))) 1593b39c5158Smillert name = (char*) SvPV(ST(2), n_a) ; 1594b39c5158Smillert 1595b39c5158Smillert if (items == 6) 1596b39c5158Smillert sv = ST(5) ; 1597b39c5158Smillert 1598b39c5158Smillert RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ; 15996fb12b70Safresh1 Trace(("db_DoTie_ %p\n", RETVAL)); 1600b39c5158Smillert if (RETVAL->dbp == NULL) { 1601b39c5158Smillert Safefree(RETVAL); 1602b39c5158Smillert RETVAL = NULL ; 1603b39c5158Smillert } 1604b39c5158Smillert } 1605b39c5158Smillert OUTPUT: 1606b39c5158Smillert RETVAL 1607b39c5158Smillert 1608b39c5158Smillert int 1609b39c5158Smillert db_DESTROY(db) 1610b39c5158Smillert DB_File db 1611b39c5158Smillert PREINIT: 1612b39c5158Smillert dMY_CXT; 1613b39c5158Smillert INIT: 1614b39c5158Smillert CurrentDB = db ; 1615b39c5158Smillert Trace(("DESTROY %p\n", db)); 1616b39c5158Smillert CLEANUP: 1617b39c5158Smillert Trace(("DESTROY %p done\n", db)); 1618b39c5158Smillert if (db->hash) 1619b39c5158Smillert SvREFCNT_dec(db->hash) ; 1620b39c5158Smillert if (db->compare) 1621b39c5158Smillert SvREFCNT_dec(db->compare) ; 1622b39c5158Smillert if (db->prefix) 1623b39c5158Smillert SvREFCNT_dec(db->prefix) ; 1624b39c5158Smillert if (db->filter_fetch_key) 1625b39c5158Smillert SvREFCNT_dec(db->filter_fetch_key) ; 1626b39c5158Smillert if (db->filter_store_key) 1627b39c5158Smillert SvREFCNT_dec(db->filter_store_key) ; 1628b39c5158Smillert if (db->filter_fetch_value) 1629b39c5158Smillert SvREFCNT_dec(db->filter_fetch_value) ; 1630b39c5158Smillert if (db->filter_store_value) 1631b39c5158Smillert SvREFCNT_dec(db->filter_store_value) ; 1632b39c5158Smillert safefree(db) ; 1633b39c5158Smillert #ifdef DB_VERSION_MAJOR 1634b39c5158Smillert if (RETVAL > 0) 1635b39c5158Smillert RETVAL = -1 ; 1636b39c5158Smillert #endif 1637b39c5158Smillert 1638b39c5158Smillert 1639b39c5158Smillert int 1640b39c5158Smillert db_DELETE(db, key, flags=0) 1641b39c5158Smillert DB_File db 1642b39c5158Smillert DBTKEY key 1643b39c5158Smillert u_int flags 1644b39c5158Smillert PREINIT: 1645b39c5158Smillert dMY_CXT; 1646b39c5158Smillert INIT: 1647b8851fccSafresh1 (void)flags; 1648b39c5158Smillert CurrentDB = db ; 1649b39c5158Smillert 1650b39c5158Smillert 1651b39c5158Smillert int 1652b39c5158Smillert db_EXISTS(db, key) 1653b39c5158Smillert DB_File db 1654b39c5158Smillert DBTKEY key 1655b39c5158Smillert PREINIT: 1656b39c5158Smillert dMY_CXT; 1657b39c5158Smillert CODE: 1658b39c5158Smillert { 1659b39c5158Smillert DBT value ; 1660b39c5158Smillert 1661b39c5158Smillert DBT_clear(value) ; 1662b39c5158Smillert CurrentDB = db ; 1663b39c5158Smillert RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ; 1664b39c5158Smillert } 1665b39c5158Smillert OUTPUT: 1666b39c5158Smillert RETVAL 1667b39c5158Smillert 1668b39c5158Smillert void 1669b39c5158Smillert db_FETCH(db, key, flags=0) 1670b39c5158Smillert DB_File db 1671b39c5158Smillert DBTKEY key 1672b39c5158Smillert u_int flags 1673b39c5158Smillert PREINIT: 1674b39c5158Smillert dMY_CXT ; 1675b39c5158Smillert int RETVAL ; 1676b39c5158Smillert CODE: 1677b39c5158Smillert { 1678b39c5158Smillert DBT value ; 1679b39c5158Smillert 1680b39c5158Smillert DBT_clear(value) ; 1681b39c5158Smillert CurrentDB = db ; 1682b39c5158Smillert RETVAL = db_get(db, key, value, flags) ; 1683b39c5158Smillert ST(0) = sv_newmortal(); 1684b39c5158Smillert OutputValue(ST(0), value) 1685b39c5158Smillert } 1686b39c5158Smillert 1687b39c5158Smillert int 1688b39c5158Smillert db_STORE(db, key, value, flags=0) 1689b39c5158Smillert DB_File db 1690b39c5158Smillert DBTKEY key 1691b39c5158Smillert DBT value 1692b39c5158Smillert u_int flags 1693b39c5158Smillert PREINIT: 1694b39c5158Smillert dMY_CXT; 1695b39c5158Smillert INIT: 1696b8851fccSafresh1 (void)flags; 1697b39c5158Smillert CurrentDB = db ; 1698b39c5158Smillert 1699b39c5158Smillert 1700b39c5158Smillert void 1701b39c5158Smillert db_FIRSTKEY(db) 1702b39c5158Smillert DB_File db 1703b39c5158Smillert PREINIT: 1704b39c5158Smillert dMY_CXT ; 1705b39c5158Smillert int RETVAL ; 1706b39c5158Smillert CODE: 1707b39c5158Smillert { 1708b39c5158Smillert DBTKEY key ; 1709b39c5158Smillert DBT value ; 1710b39c5158Smillert 1711b39c5158Smillert DBT_clear(key) ; 1712b39c5158Smillert DBT_clear(value) ; 1713b39c5158Smillert CurrentDB = db ; 1714b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_FIRST) ; 1715b39c5158Smillert ST(0) = sv_newmortal(); 1716b39c5158Smillert OutputKey(ST(0), key) ; 1717b39c5158Smillert } 1718b39c5158Smillert 1719b39c5158Smillert void 1720b39c5158Smillert db_NEXTKEY(db, key) 1721b39c5158Smillert DB_File db 1722b39c5158Smillert DBTKEY key = NO_INIT 1723b39c5158Smillert PREINIT: 1724b39c5158Smillert dMY_CXT ; 1725b39c5158Smillert int RETVAL ; 1726b39c5158Smillert CODE: 1727b39c5158Smillert { 1728b39c5158Smillert DBT value ; 1729b39c5158Smillert 1730b39c5158Smillert DBT_clear(key) ; 1731b39c5158Smillert DBT_clear(value) ; 1732b39c5158Smillert CurrentDB = db ; 1733b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_NEXT) ; 1734b39c5158Smillert ST(0) = sv_newmortal(); 1735b39c5158Smillert OutputKey(ST(0), key) ; 1736b39c5158Smillert } 1737b39c5158Smillert 1738b39c5158Smillert # 1739b39c5158Smillert # These would be nice for RECNO 1740b39c5158Smillert # 1741b39c5158Smillert 1742b39c5158Smillert int 1743b39c5158Smillert unshift(db, ...) 1744b39c5158Smillert DB_File db 1745b39c5158Smillert ALIAS: UNSHIFT = 1 1746b39c5158Smillert PREINIT: 1747b39c5158Smillert dMY_CXT; 1748b39c5158Smillert CODE: 1749b39c5158Smillert { 1750b39c5158Smillert DBTKEY key ; 1751b39c5158Smillert DBT value ; 1752b39c5158Smillert int i ; 1753b39c5158Smillert int One ; 1754b39c5158Smillert STRLEN n_a; 1755b39c5158Smillert 1756b39c5158Smillert DBT_clear(key) ; 1757b39c5158Smillert DBT_clear(value) ; 1758b39c5158Smillert CurrentDB = db ; 1759b39c5158Smillert #ifdef DB_VERSION_MAJOR 1760b39c5158Smillert /* get the first value */ 1761b39c5158Smillert RETVAL = do_SEQ(db, key, value, DB_FIRST) ; 1762b39c5158Smillert RETVAL = 0 ; 1763b39c5158Smillert #else 1764b39c5158Smillert RETVAL = -1 ; 1765b39c5158Smillert #endif 1766b39c5158Smillert for (i = items-1 ; i > 0 ; --i) 1767b39c5158Smillert { 1768b39c5158Smillert DBM_ckFilter(ST(i), filter_store_value, "filter_store_value"); 1769b39c5158Smillert value.data = SvPVbyte(ST(i), n_a) ; 1770b39c5158Smillert value.size = n_a ; 1771b39c5158Smillert One = 1 ; 1772b39c5158Smillert key.data = &One ; 1773b39c5158Smillert key.size = sizeof(int) ; 1774b39c5158Smillert #ifdef DB_VERSION_MAJOR 1775b39c5158Smillert RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ; 1776b39c5158Smillert #else 1777b39c5158Smillert RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ; 1778b39c5158Smillert #endif 1779b39c5158Smillert if (RETVAL != 0) 1780b39c5158Smillert break; 1781b39c5158Smillert } 1782b39c5158Smillert } 1783b39c5158Smillert OUTPUT: 1784b39c5158Smillert RETVAL 1785b39c5158Smillert 1786b39c5158Smillert void 1787b39c5158Smillert pop(db) 1788b39c5158Smillert DB_File db 1789b39c5158Smillert PREINIT: 1790b39c5158Smillert dMY_CXT; 1791b39c5158Smillert ALIAS: POP = 1 1792b39c5158Smillert PREINIT: 1793b39c5158Smillert I32 RETVAL; 1794b39c5158Smillert CODE: 1795b39c5158Smillert { 1796b39c5158Smillert DBTKEY key ; 1797b39c5158Smillert DBT value ; 1798b39c5158Smillert 1799b39c5158Smillert DBT_clear(key) ; 1800b39c5158Smillert DBT_clear(value) ; 1801b39c5158Smillert CurrentDB = db ; 1802b39c5158Smillert 1803b39c5158Smillert /* First get the final value */ 1804b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_LAST) ; 1805b39c5158Smillert ST(0) = sv_newmortal(); 1806b39c5158Smillert /* Now delete it */ 1807b39c5158Smillert if (RETVAL == 0) 1808b39c5158Smillert { 1809b39c5158Smillert /* the call to del will trash value, so take a copy now */ 1810b39c5158Smillert OutputValue(ST(0), value) ; 1811b39c5158Smillert RETVAL = db_del(db, key, R_CURSOR) ; 1812b39c5158Smillert if (RETVAL != 0) 1813b39c5158Smillert sv_setsv(ST(0), &PL_sv_undef); 1814b39c5158Smillert } 1815b39c5158Smillert } 1816b39c5158Smillert 1817b39c5158Smillert void 1818b39c5158Smillert shift(db) 1819b39c5158Smillert DB_File db 1820b39c5158Smillert PREINIT: 1821b39c5158Smillert dMY_CXT; 1822b39c5158Smillert ALIAS: SHIFT = 1 1823b39c5158Smillert PREINIT: 1824b39c5158Smillert I32 RETVAL; 1825b39c5158Smillert CODE: 1826b39c5158Smillert { 1827b39c5158Smillert DBT value ; 1828b39c5158Smillert DBTKEY key ; 1829b39c5158Smillert 1830b39c5158Smillert DBT_clear(key) ; 1831b39c5158Smillert DBT_clear(value) ; 1832b39c5158Smillert CurrentDB = db ; 1833b39c5158Smillert /* get the first value */ 1834b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_FIRST) ; 1835b39c5158Smillert ST(0) = sv_newmortal(); 1836b39c5158Smillert /* Now delete it */ 1837b39c5158Smillert if (RETVAL == 0) 1838b39c5158Smillert { 1839b39c5158Smillert /* the call to del will trash value, so take a copy now */ 1840b39c5158Smillert OutputValue(ST(0), value) ; 1841b39c5158Smillert RETVAL = db_del(db, key, R_CURSOR) ; 1842b39c5158Smillert if (RETVAL != 0) 1843b39c5158Smillert sv_setsv (ST(0), &PL_sv_undef) ; 1844b39c5158Smillert } 1845b39c5158Smillert } 1846b39c5158Smillert 1847b39c5158Smillert 1848b39c5158Smillert I32 1849b39c5158Smillert push(db, ...) 1850b39c5158Smillert DB_File db 1851b39c5158Smillert PREINIT: 1852b39c5158Smillert dMY_CXT; 1853b39c5158Smillert ALIAS: PUSH = 1 1854b39c5158Smillert CODE: 1855b39c5158Smillert { 1856b39c5158Smillert DBTKEY key ; 1857b39c5158Smillert DBT value ; 1858b39c5158Smillert DB * Db = db->dbp ; 1859b39c5158Smillert int i ; 1860b39c5158Smillert STRLEN n_a; 1861b39c5158Smillert int keyval ; 1862b39c5158Smillert 1863b39c5158Smillert DBT_flags(key) ; 1864b39c5158Smillert DBT_flags(value) ; 1865b39c5158Smillert CurrentDB = db ; 1866b39c5158Smillert /* Set the Cursor to the Last element */ 1867b39c5158Smillert RETVAL = do_SEQ(db, key, value, R_LAST) ; 1868b39c5158Smillert #ifndef DB_VERSION_MAJOR 1869b39c5158Smillert if (RETVAL >= 0) 1870b39c5158Smillert #endif 1871b39c5158Smillert { 1872b39c5158Smillert if (RETVAL == 0) 1873b39c5158Smillert keyval = *(int*)key.data ; 1874b39c5158Smillert else 1875b39c5158Smillert keyval = 0 ; 1876b39c5158Smillert for (i = 1 ; i < items ; ++i) 1877b39c5158Smillert { 1878b39c5158Smillert DBM_ckFilter(ST(i), filter_store_value, "filter_store_value"); 1879b39c5158Smillert value.data = SvPVbyte(ST(i), n_a) ; 1880b39c5158Smillert value.size = n_a ; 1881b39c5158Smillert ++ keyval ; 1882b39c5158Smillert key.data = &keyval ; 1883b39c5158Smillert key.size = sizeof(int) ; 1884b39c5158Smillert RETVAL = (Db->put)(Db, TXN &key, &value, 0) ; 1885b39c5158Smillert if (RETVAL != 0) 1886b39c5158Smillert break; 1887b39c5158Smillert } 1888b39c5158Smillert } 1889b39c5158Smillert } 1890b39c5158Smillert OUTPUT: 1891b39c5158Smillert RETVAL 1892b39c5158Smillert 1893b39c5158Smillert I32 1894b39c5158Smillert length(db) 1895b39c5158Smillert DB_File db 1896b39c5158Smillert PREINIT: 1897b39c5158Smillert dMY_CXT; 1898b39c5158Smillert ALIAS: FETCHSIZE = 1 1899b39c5158Smillert CODE: 1900b39c5158Smillert CurrentDB = db ; 1901b39c5158Smillert RETVAL = GetArrayLength(aTHX_ db) ; 1902b39c5158Smillert OUTPUT: 1903b39c5158Smillert RETVAL 1904b39c5158Smillert 1905b39c5158Smillert 1906b39c5158Smillert # 1907b39c5158Smillert # Now provide an interface to the rest of the DB functionality 1908b39c5158Smillert # 1909b39c5158Smillert 1910b39c5158Smillert int 1911b39c5158Smillert db_del(db, key, flags=0) 1912b39c5158Smillert DB_File db 1913b39c5158Smillert DBTKEY key 1914b39c5158Smillert u_int flags 1915b39c5158Smillert PREINIT: 1916b39c5158Smillert dMY_CXT; 1917b39c5158Smillert CODE: 1918b39c5158Smillert CurrentDB = db ; 1919b39c5158Smillert RETVAL = db_del(db, key, flags) ; 1920b39c5158Smillert #ifdef DB_VERSION_MAJOR 1921b39c5158Smillert if (RETVAL > 0) 1922b39c5158Smillert RETVAL = -1 ; 1923b39c5158Smillert else if (RETVAL == DB_NOTFOUND) 1924b39c5158Smillert RETVAL = 1 ; 1925b39c5158Smillert #endif 1926b39c5158Smillert OUTPUT: 1927b39c5158Smillert RETVAL 1928b39c5158Smillert 1929b39c5158Smillert 1930b39c5158Smillert int 1931b39c5158Smillert db_get(db, key, value, flags=0) 1932b39c5158Smillert DB_File db 1933b39c5158Smillert DBTKEY key 1934b39c5158Smillert DBT value = NO_INIT 1935b39c5158Smillert u_int flags 1936b39c5158Smillert PREINIT: 1937b39c5158Smillert dMY_CXT; 1938b39c5158Smillert CODE: 1939b39c5158Smillert CurrentDB = db ; 1940b39c5158Smillert DBT_clear(value) ; 1941b39c5158Smillert RETVAL = db_get(db, key, value, flags) ; 1942b39c5158Smillert #ifdef DB_VERSION_MAJOR 1943b39c5158Smillert if (RETVAL > 0) 1944b39c5158Smillert RETVAL = -1 ; 1945b39c5158Smillert else if (RETVAL == DB_NOTFOUND) 1946b39c5158Smillert RETVAL = 1 ; 1947b39c5158Smillert #endif 1948b39c5158Smillert OUTPUT: 1949b39c5158Smillert RETVAL 1950b39c5158Smillert value 1951b39c5158Smillert 1952b39c5158Smillert int 1953b39c5158Smillert db_put(db, key, value, flags=0) 1954b39c5158Smillert DB_File db 1955b39c5158Smillert DBTKEY key 1956b39c5158Smillert DBT value 1957b39c5158Smillert u_int flags 1958b39c5158Smillert PREINIT: 1959b39c5158Smillert dMY_CXT; 1960b39c5158Smillert CODE: 1961b39c5158Smillert CurrentDB = db ; 1962b39c5158Smillert RETVAL = db_put(db, key, value, flags) ; 1963b39c5158Smillert #ifdef DB_VERSION_MAJOR 1964b39c5158Smillert if (RETVAL > 0) 1965b39c5158Smillert RETVAL = -1 ; 1966b39c5158Smillert else if (RETVAL == DB_KEYEXIST) 1967b39c5158Smillert RETVAL = 1 ; 1968b39c5158Smillert #endif 1969b39c5158Smillert OUTPUT: 1970b39c5158Smillert RETVAL 1971b39c5158Smillert key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key); 1972b39c5158Smillert 1973b39c5158Smillert int 1974b39c5158Smillert db_fd(db) 1975b39c5158Smillert DB_File db 1976b39c5158Smillert PREINIT: 1977b39c5158Smillert dMY_CXT ; 1978b39c5158Smillert CODE: 1979b39c5158Smillert CurrentDB = db ; 1980b39c5158Smillert #ifdef DB_VERSION_MAJOR 1981b39c5158Smillert RETVAL = -1 ; 1982b39c5158Smillert { 1983b39c5158Smillert int status = 0 ; 1984b39c5158Smillert status = (db->in_memory 1985b39c5158Smillert ? -1 1986b39c5158Smillert : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ; 1987b39c5158Smillert if (status != 0) 1988b39c5158Smillert RETVAL = -1 ; 1989b39c5158Smillert } 1990b39c5158Smillert #else 1991b39c5158Smillert RETVAL = (db->in_memory 1992b39c5158Smillert ? -1 1993b39c5158Smillert : ((db->dbp)->fd)(db->dbp) ) ; 1994b39c5158Smillert #endif 1995b39c5158Smillert OUTPUT: 1996b39c5158Smillert RETVAL 1997b39c5158Smillert 1998b39c5158Smillert int 1999b39c5158Smillert db_sync(db, flags=0) 2000b39c5158Smillert DB_File db 2001b39c5158Smillert u_int flags 2002b39c5158Smillert PREINIT: 2003b39c5158Smillert dMY_CXT; 2004b39c5158Smillert CODE: 2005b39c5158Smillert CurrentDB = db ; 2006b39c5158Smillert RETVAL = db_sync(db, flags) ; 2007b39c5158Smillert #ifdef DB_VERSION_MAJOR 2008b39c5158Smillert if (RETVAL > 0) 2009b39c5158Smillert RETVAL = -1 ; 2010b39c5158Smillert #endif 2011b39c5158Smillert OUTPUT: 2012b39c5158Smillert RETVAL 2013b39c5158Smillert 2014b39c5158Smillert 2015b39c5158Smillert int 2016b39c5158Smillert db_seq(db, key, value, flags) 2017b39c5158Smillert DB_File db 2018b39c5158Smillert DBTKEY key 2019b39c5158Smillert DBT value = NO_INIT 2020b39c5158Smillert u_int flags 2021b39c5158Smillert PREINIT: 2022b39c5158Smillert dMY_CXT; 2023b39c5158Smillert CODE: 2024b39c5158Smillert CurrentDB = db ; 2025b39c5158Smillert DBT_clear(value) ; 2026b39c5158Smillert RETVAL = db_seq(db, key, value, flags); 2027b39c5158Smillert #ifdef DB_VERSION_MAJOR 2028b39c5158Smillert if (RETVAL > 0) 2029b39c5158Smillert RETVAL = -1 ; 2030b39c5158Smillert else if (RETVAL == DB_NOTFOUND) 2031b39c5158Smillert RETVAL = 1 ; 2032b39c5158Smillert #endif 2033b39c5158Smillert OUTPUT: 2034b39c5158Smillert RETVAL 2035b39c5158Smillert key 2036b39c5158Smillert value 2037b39c5158Smillert 2038b39c5158Smillert SV * 2039b39c5158Smillert filter_fetch_key(db, code) 2040b39c5158Smillert DB_File db 2041b39c5158Smillert SV * code 2042b39c5158Smillert SV * RETVAL = &PL_sv_undef ; 2043b39c5158Smillert CODE: 2044b39c5158Smillert DBM_setFilter(db->filter_fetch_key, code) ; 2045b39c5158Smillert 2046b39c5158Smillert SV * 2047b39c5158Smillert filter_store_key(db, code) 2048b39c5158Smillert DB_File db 2049b39c5158Smillert SV * code 2050b39c5158Smillert SV * RETVAL = &PL_sv_undef ; 2051b39c5158Smillert CODE: 2052b39c5158Smillert DBM_setFilter(db->filter_store_key, code) ; 2053b39c5158Smillert 2054b39c5158Smillert SV * 2055b39c5158Smillert filter_fetch_value(db, code) 2056b39c5158Smillert DB_File db 2057b39c5158Smillert SV * code 2058b39c5158Smillert SV * RETVAL = &PL_sv_undef ; 2059b39c5158Smillert CODE: 2060b39c5158Smillert DBM_setFilter(db->filter_fetch_value, code) ; 2061b39c5158Smillert 2062b39c5158Smillert SV * 2063b39c5158Smillert filter_store_value(db, code) 2064b39c5158Smillert DB_File db 2065b39c5158Smillert SV * code 2066b39c5158Smillert SV * RETVAL = &PL_sv_undef ; 2067b39c5158Smillert CODE: 2068b39c5158Smillert DBM_setFilter(db->filter_store_value, code) ; 2069