3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
6 last modified 27th Nov 1996
9 All comments/suggestions/problems are welcome
13 0.2 - No longer bombs out if dbopen returns an error.
14 0.3 - Added some support for multiple btree compares
15 1.0 - Complete support for multiple callbacks added.
16 Fixed a problem with pushing a value onto an empty list.
17 1.01 - Fixed a SunOS core dump problem.
18 The return value from TIEHASH wasn't set to NULL when
19 dbopen returned an error.
20 1.02 - Use ALIAS to define TIEARRAY.
21 Removed some redundant commented code.
22 Merged OS2 code into the main distribution.
23 Allow negative subscripts with RECNO interface.
24 Changed the default flags to O_CREAT|O_RDWR
26 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
27 Dave Hammen, hammen@gothamcity.jsc.nasa.gov
28 1.05 - Added logic to allow prefix & hash types to be specified via
30 1.06 - Minor namespace cleanup: Localized PrintBtree.
46 #define DB_Prefix_t mDB_Prefix_t
53 #define DB_Hash_t mDB_Hash_t
71 typedef DB_File_type * DB_File ;
77 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
78 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
79 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
80 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, &key, &value, flags)
82 #define db_close(db) ((db->dbp)->close)(db->dbp)
83 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
84 #define db_fd(db) ((db->dbp)->fd)(db->dbp)
85 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
86 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, &key, &value, flags)
87 #define db_seq(db, key, value, flags) ((db->dbp)->seq)(db->dbp, &key, &value, flags)
88 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
91 #define OutputValue(arg, name) \
92 { if (RETVAL == 0) { \
93 sv_setpvn(arg, name.data, name.size) ; \
97 #define OutputKey(arg, name) \
100 if (db->type != DB_RECNO) { \
101 sv_setpvn(arg, name.data, name.size); \
104 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
108 /* Internal Global Data */
109 static recno_t Value ;
110 static DB_File CurrentDB ;
111 static recno_t zero = 0 ;
112 static DBTKEY empty = { &zero, sizeof(recno_t) } ;
116 btree_compare(key1, key2)
121 void * data1, * data2 ;
128 /* As newSVpv will assume that the data pointer is a null terminated C
129 string if the size parameter is 0, make sure that data points to an
130 empty string if the length is 0
142 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
143 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
146 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
151 croak ("DB_File btree_compare: expected 1 return value from %s, got %d\n", count) ;
163 btree_prefix(key1, key2)
168 void * data1, * data2 ;
175 /* As newSVpv will assume that the data pointer is a null terminated C
176 string if the size parameter is 0, make sure that data points to an
177 empty string if the length is 0
189 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
190 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
193 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
198 croak ("DB_File btree_prefix: expected 1 return value from %s, got %d\n", count) ;
221 /* DGH - Next two lines added to fix corrupted stack problem */
227 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
230 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
235 croak ("DB_File hash_cb: expected 1 return value from %s, got %d\n", count) ;
253 printf ("HASH Info\n") ;
254 printf (" hash = %s\n", (hash->hash != NULL ? "redefined" : "default")) ;
255 printf (" bsize = %d\n", hash->bsize) ;
256 printf (" ffactor = %d\n", hash->ffactor) ;
257 printf (" nelem = %d\n", hash->nelem) ;
258 printf (" cachesize = %d\n", hash->cachesize) ;
259 printf (" lorder = %d\n", hash->lorder) ;
267 printf ("RECNO Info\n") ;
268 printf (" flags = %d\n", recno->flags) ;
269 printf (" cachesize = %d\n", recno->cachesize) ;
270 printf (" psize = %d\n", recno->psize) ;
271 printf (" lorder = %d\n", recno->lorder) ;
272 printf (" reclen = %d\n", recno->reclen) ;
273 printf (" bval = %d\n", recno->bval) ;
274 printf (" bfname = %d [%s]\n", recno->bfname, recno->bfname) ;
281 printf ("BTREE Info\n") ;
282 printf (" compare = %s\n", (btree->compare ? "redefined" : "default")) ;
283 printf (" prefix = %s\n", (btree->prefix ? "redefined" : "default")) ;
284 printf (" flags = %d\n", btree->flags) ;
285 printf (" cachesize = %d\n", btree->cachesize) ;
286 printf (" psize = %d\n", btree->psize) ;
287 printf (" maxkeypage = %d\n", btree->maxkeypage) ;
288 printf (" minkeypage = %d\n", btree->minkeypage) ;
289 printf (" lorder = %d\n", btree->lorder) ;
294 #define PrintRecno(recno)
295 #define PrintHash(hash)
296 #define PrintBtree(btree)
309 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
311 RETVAL = *(I32 *)key.data ;
312 else if (RETVAL == 1) /* No key means empty file */
319 GetRecnoKey(db, value)
324 /* Get the length of the array */
325 I32 length = GetArrayLength(db->dbp) ;
327 /* check for attempt to write before start of array */
328 if (length + value + 1 <= 0)
329 croak("Modification of non-creatable array value attempted, subscript %d", value) ;
331 value = length + value + 1 ;
340 ParseOpenInfo(name, flags, mode, sv)
348 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
349 void * openinfo = NULL ;
350 union INFO * info = &RETVAL->info ;
352 /* Default to HASH */
353 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
354 RETVAL->type = DB_HASH ;
356 /* DGH - Next line added to avoid SEGV on existing hash DB */
362 croak ("type parameter is not a reference") ;
364 action = (HV*)SvRV(sv);
366 if (sv_isa(sv, "DB_File::HASHINFO"))
368 RETVAL->type = DB_HASH ;
369 openinfo = (void*)info ;
371 svp = hv_fetch(action, "hash", 4, FALSE);
373 if (svp && SvOK(*svp))
375 info->hash.hash = hash_cb ;
376 RETVAL->hash = newSVsv(*svp) ;
379 info->hash.hash = NULL ;
381 svp = hv_fetch(action, "bsize", 5, FALSE);
382 info->hash.bsize = svp ? SvIV(*svp) : 0;
384 svp = hv_fetch(action, "ffactor", 7, FALSE);
385 info->hash.ffactor = svp ? SvIV(*svp) : 0;
387 svp = hv_fetch(action, "nelem", 5, FALSE);
388 info->hash.nelem = svp ? SvIV(*svp) : 0;
390 svp = hv_fetch(action, "cachesize", 9, FALSE);
391 info->hash.cachesize = svp ? SvIV(*svp) : 0;
393 svp = hv_fetch(action, "lorder", 6, FALSE);
394 info->hash.lorder = svp ? SvIV(*svp) : 0;
398 else if (sv_isa(sv, "DB_File::BTREEINFO"))
400 RETVAL->type = DB_BTREE ;
401 openinfo = (void*)info ;
403 svp = hv_fetch(action, "compare", 7, FALSE);
404 if (svp && SvOK(*svp))
406 info->btree.compare = btree_compare ;
407 RETVAL->compare = newSVsv(*svp) ;
410 info->btree.compare = NULL ;
412 svp = hv_fetch(action, "prefix", 6, FALSE);
413 if (svp && SvOK(*svp))
415 info->btree.prefix = btree_prefix ;
416 RETVAL->prefix = newSVsv(*svp) ;
419 info->btree.prefix = NULL ;
421 svp = hv_fetch(action, "flags", 5, FALSE);
422 info->btree.flags = svp ? SvIV(*svp) : 0;
424 svp = hv_fetch(action, "cachesize", 9, FALSE);
425 info->btree.cachesize = svp ? SvIV(*svp) : 0;
427 svp = hv_fetch(action, "minkeypage", 10, FALSE);
428 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
430 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
431 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
433 svp = hv_fetch(action, "psize", 5, FALSE);
434 info->btree.psize = svp ? SvIV(*svp) : 0;
436 svp = hv_fetch(action, "lorder", 6, FALSE);
437 info->btree.lorder = svp ? SvIV(*svp) : 0;
442 else if (sv_isa(sv, "DB_File::RECNOINFO"))
444 RETVAL->type = DB_RECNO ;
445 openinfo = (void *)info ;
447 svp = hv_fetch(action, "flags", 5, FALSE);
448 info->recno.flags = (u_long) svp ? SvIV(*svp) : 0;
450 svp = hv_fetch(action, "cachesize", 9, FALSE);
451 info->recno.cachesize = (u_int) svp ? SvIV(*svp) : 0;
453 svp = hv_fetch(action, "psize", 5, FALSE);
454 info->recno.psize = (int) svp ? SvIV(*svp) : 0;
456 svp = hv_fetch(action, "lorder", 6, FALSE);
457 info->recno.lorder = (int) svp ? SvIV(*svp) : 0;
459 svp = hv_fetch(action, "reclen", 6, FALSE);
460 info->recno.reclen = (size_t) svp ? SvIV(*svp) : 0;
462 svp = hv_fetch(action, "bval", 4, FALSE);
463 if (svp && SvOK(*svp))
466 info->recno.bval = (u_char)*SvPV(*svp, na) ;
468 info->recno.bval = (u_char)(unsigned long) SvIV(*svp) ;
472 if (info->recno.flags & R_FIXEDLEN)
473 info->recno.bval = (u_char) ' ' ;
475 info->recno.bval = (u_char) '\n' ;
478 svp = hv_fetch(action, "bfname", 6, FALSE);
480 char * ptr = SvPV(*svp,na) ;
481 info->recno.bfname = (char*) na ? ptr : 0 ;
487 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
491 /* OS2 Specific Code */
498 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
508 croak("DB_File::%s not implemented on this architecture", s);
522 if (strEQ(name, "BTREEMAGIC"))
528 if (strEQ(name, "BTREEVERSION"))
538 if (strEQ(name, "DB_LOCK"))
544 if (strEQ(name, "DB_SHMEM"))
550 if (strEQ(name, "DB_TXN"))
564 if (strEQ(name, "HASHMAGIC"))
570 if (strEQ(name, "HASHVERSION"))
586 if (strEQ(name, "MAX_PAGE_NUMBER"))
587 #ifdef MAX_PAGE_NUMBER
588 return (U32)MAX_PAGE_NUMBER;
592 if (strEQ(name, "MAX_PAGE_OFFSET"))
593 #ifdef MAX_PAGE_OFFSET
594 return MAX_PAGE_OFFSET;
598 if (strEQ(name, "MAX_REC_NUMBER"))
599 #ifdef MAX_REC_NUMBER
600 return (U32)MAX_REC_NUMBER;
614 if (strEQ(name, "RET_ERROR"))
620 if (strEQ(name, "RET_SPECIAL"))
626 if (strEQ(name, "RET_SUCCESS"))
632 if (strEQ(name, "R_CURSOR"))
638 if (strEQ(name, "R_DUP"))
644 if (strEQ(name, "R_FIRST"))
650 if (strEQ(name, "R_FIXEDLEN"))
656 if (strEQ(name, "R_IAFTER"))
662 if (strEQ(name, "R_IBEFORE"))
668 if (strEQ(name, "R_LAST"))
674 if (strEQ(name, "R_NEXT"))
680 if (strEQ(name, "R_NOKEY"))
686 if (strEQ(name, "R_NOOVERWRITE"))
688 return R_NOOVERWRITE;
692 if (strEQ(name, "R_PREV"))
698 if (strEQ(name, "R_RECNOSYNC"))
704 if (strEQ(name, "R_SETCURSOR"))
710 if (strEQ(name, "R_SNAPSHOT"))
734 if (strEQ(name, "__R_UNUSED"))
750 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
759 db_DoTie_(dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0640, type=DB_HASH)
765 char * name = (char *) NULL ;
766 SV * sv = (SV *) NULL ;
768 if (items >= 2 && SvOK(ST(1)))
769 name = (char*) SvPV(ST(1), na) ;
774 RETVAL = ParseOpenInfo(name, flags, mode, sv) ;
775 if (RETVAL->dbp == NULL)
788 SvREFCNT_dec(db->hash) ;
790 SvREFCNT_dec(db->compare) ;
792 SvREFCNT_dec(db->prefix) ;
797 db_DELETE(db, key, flags=0)
814 RETVAL = (((db->dbp)->get)(db->dbp, &key, &value, 0) == 0) ;
820 db_FETCH(db, key, flags=0)
829 RETVAL = ((db->dbp)->get)(db->dbp, &key, &value, flags) ;
830 ST(0) = sv_newmortal();
832 sv_setpvn(ST(0), value.data, value.size);
836 db_STORE(db, key, value, flags=0)
855 RETVAL = (Db->seq)(Db, &key, &value, R_FIRST) ;
856 ST(0) = sv_newmortal();
859 if (Db->type != DB_RECNO)
860 sv_setpvn(ST(0), key.data, key.size);
862 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
876 RETVAL = (Db->seq)(Db, &key, &value, R_NEXT) ;
877 ST(0) = sv_newmortal();
880 if (Db->type != DB_RECNO)
881 sv_setpvn(ST(0), key.data, key.size);
883 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
888 # These would be nice for RECNO
904 for (i = items-1 ; i > 0 ; --i)
906 value.data = SvPV(ST(i), na) ;
910 key.size = sizeof(int) ;
911 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
929 /* First get the final value */
930 RETVAL = (Db->seq)(Db, &key, &value, R_LAST) ;
931 ST(0) = sv_newmortal();
935 /* the call to del will trash value, so take a copy now */
936 sv_setpvn(ST(0), value.data, value.size);
937 RETVAL = (Db->del)(Db, &key, R_CURSOR) ;
939 sv_setsv(ST(0), &sv_undef);
953 /* get the first value */
954 RETVAL = (Db->seq)(Db, &key, &value, R_FIRST) ;
955 ST(0) = sv_newmortal();
959 /* the call to del will trash value, so take a copy now */
960 sv_setpvn(ST(0), value.data, value.size);
961 RETVAL = (Db->del)(Db, &key, R_CURSOR) ;
963 sv_setsv (ST(0), &sv_undef) ;
974 DBTKEY * keyptr = &key ;
980 /* Set the Cursor to the Last element */
981 RETVAL = (Db->seq)(Db, &key, &value, R_LAST) ;
986 for (i = items - 1 ; i > 0 ; --i)
988 value.data = SvPV(ST(i), na) ;
990 RETVAL = (Db->put)(Db, keyptr, &value, R_IAFTER) ;
1005 RETVAL = GetArrayLength(db->dbp) ;
1011 # Now provide an interface to the rest of the DB functionality
1015 db_del(db, key, flags=0)
1024 db_get(db, key, value, flags=0)
1035 db_put(db, key, value, flags=0)
1043 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
1052 db_sync(db, flags=0)
1060 db_seq(db, key, value, flags)