3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
6 last modified 23rd June 1994
9 All comments/suggestions/problems are welcome
37 #define db_DESTROY(db) (db->close)(db)
38 #define db_DELETE(db, key, flags) (db->del)(db, &key, flags)
39 #define db_STORE(db, key, value, flags) (db->put)(db, &key, &value, flags)
40 #define db_FETCH(db, key, flags) (db->get)(db, &key, &value, flags)
42 #define db_close(db) (db->close)(db)
43 #define db_del(db, key, flags) (db->del)(db, &key, flags)
44 #define db_fd(db) (db->fd)(db)
45 #define db_put(db, key, value, flags) (db->put)(db, &key, &value, flags)
46 #define db_get(db, key, value, flags) (db->get)(db, &key, &value, flags)
47 #define db_seq(db, key, value, flags) (db->seq)(db, &key, &value, flags)
48 #define db_sync(db, flags) (db->sync)(db, flags)
51 #define OutputValue(arg, name) \
52 { if (RETVAL == 0) sv_setpvn(arg, name.data, name.size) ; }
54 #define OutputKey(arg, name) \
57 if (db->close != DB_recno_close) \
58 sv_setpvn(arg, name.data, name.size); \
60 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
64 /* Internal Global Data */
66 static recno_t Value ;
67 static int (*DB_recno_close)() = NULL ;
69 static CallBackInfo hash_callback = { 0 } ;
70 static CallBackInfo compare_callback = { 0 } ;
71 static CallBackInfo prefix_callback = { 0 } ;
75 btree_compare(key1, key2)
80 void * data1, * data2 ;
87 /* As newSVpv will assume that the data pointer is a null terminated C
88 string if the size parameter is 0, make sure that data points to an
89 empty string if the length is 0
101 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
102 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
105 count = perl_call_sv(compare_callback.sub, G_SCALAR);
110 croak ("DB_File btree_compare: expected 1 return value from %s, got %d\n", count) ;
122 btree_prefix(key1, key2)
127 void * data1, * data2 ;
134 /* As newSVpv will assume that the data pointer is a null terminated C
135 string if the size parameter is 0, make sure that data points to an
136 empty string if the length is 0
148 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
149 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
152 count = perl_call_sv(prefix_callback.sub, G_SCALAR);
157 croak ("DB_File btree_prefix: expected 1 return value from %s, got %d\n", count) ;
181 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
184 count = perl_call_sv(hash_callback.sub, G_SCALAR);
189 croak ("DB_File hash_cb: expected 1 return value from %s, got %d\n", count) ;
207 printf ("HASH Info\n") ;
208 printf (" hash = %s\n", (hash.hash != NULL ? "redefined" : "default")) ;
209 printf (" bsize = %d\n", hash.bsize) ;
210 printf (" ffactor = %d\n", hash.ffactor) ;
211 printf (" nelem = %d\n", hash.nelem) ;
212 printf (" cachesize = %d\n", hash.cachesize) ;
213 printf (" lorder = %d\n", hash.lorder) ;
221 printf ("RECNO Info\n") ;
222 printf (" flags = %d\n", recno.flags) ;
223 printf (" cachesize = %d\n", recno.cachesize) ;
224 printf (" psize = %d\n", recno.psize) ;
225 printf (" lorder = %d\n", recno.lorder) ;
226 printf (" reclen = %d\n", recno.reclen) ;
227 printf (" bval = %d\n", recno.bval) ;
228 printf (" bfname = %s\n", recno.bfname) ;
234 printf ("BTREE Info\n") ;
235 printf (" compare = %s\n", (btree.compare ? "redefined" : "default")) ;
236 printf (" prefix = %s\n", (btree.prefix ? "redefined" : "default")) ;
237 printf (" flags = %d\n", btree.flags) ;
238 printf (" cachesize = %d\n", btree.cachesize) ;
239 printf (" psize = %d\n", btree.psize) ;
240 printf (" maxkeypage = %d\n", btree.maxkeypage) ;
241 printf (" minkeypage = %d\n", btree.minkeypage) ;
242 printf (" lorder = %d\n", btree.lorder) ;
247 #define PrintRecno(recno)
248 #define PrintHash(hash)
249 #define PrintBtree(btree)
262 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
264 RETVAL = *(I32 *)key.data ;
265 else if (RETVAL == 1) /* No key means empty file */
272 ParseOpenInfo(name, flags, mode, sv, string)
283 void * openinfo = NULL ;
284 DBTYPE type = DB_HASH ;
290 croak ("type parameter is not a reference") ;
292 action = (HV*)SvRV(sv);
293 if (sv_isa(sv, "DB_File::HASHINFO"))
296 openinfo = (void*)&info ;
298 svp = hv_fetch(action, "hash", 4, FALSE);
300 if (svp && SvOK(*svp))
302 info.hash.hash = hash_cb ;
303 hash_callback.sub = *svp ;
306 info.hash.hash = NULL ;
308 svp = hv_fetch(action, "bsize", 5, FALSE);
309 info.hash.bsize = svp ? SvIV(*svp) : 0;
311 svp = hv_fetch(action, "ffactor", 7, FALSE);
312 info.hash.ffactor = svp ? SvIV(*svp) : 0;
314 svp = hv_fetch(action, "nelem", 5, FALSE);
315 info.hash.nelem = svp ? SvIV(*svp) : 0;
317 svp = hv_fetch(action, "cachesize", 9, FALSE);
318 info.hash.cachesize = svp ? SvIV(*svp) : 0;
320 svp = hv_fetch(action, "lorder", 6, FALSE);
321 info.hash.lorder = svp ? SvIV(*svp) : 0;
325 else if (sv_isa(sv, "DB_File::BTREEINFO"))
328 openinfo = (void*)&info ;
330 svp = hv_fetch(action, "compare", 7, FALSE);
331 if (svp && SvOK(*svp))
333 info.btree.compare = btree_compare ;
334 compare_callback.sub = *svp ;
337 info.btree.compare = NULL ;
339 svp = hv_fetch(action, "prefix", 6, FALSE);
340 if (svp && SvOK(*svp))
342 info.btree.prefix = btree_prefix ;
343 prefix_callback.sub = *svp ;
346 info.btree.prefix = NULL ;
348 svp = hv_fetch(action, "flags", 5, FALSE);
349 info.btree.flags = svp ? SvIV(*svp) : 0;
351 svp = hv_fetch(action, "cachesize", 9, FALSE);
352 info.btree.cachesize = svp ? SvIV(*svp) : 0;
354 svp = hv_fetch(action, "minkeypage", 10, FALSE);
355 info.btree.minkeypage = svp ? SvIV(*svp) : 0;
357 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
358 info.btree.maxkeypage = svp ? SvIV(*svp) : 0;
360 svp = hv_fetch(action, "psize", 5, FALSE);
361 info.btree.psize = svp ? SvIV(*svp) : 0;
363 svp = hv_fetch(action, "lorder", 6, FALSE);
364 info.btree.lorder = svp ? SvIV(*svp) : 0;
369 else if (sv_isa(sv, "DB_File::RECNOINFO"))
372 openinfo = (void *)&info ;
374 svp = hv_fetch(action, "flags", 5, FALSE);
375 info.recno.flags = (u_long) svp ? SvIV(*svp) : 0;
377 svp = hv_fetch(action, "cachesize", 9, FALSE);
378 info.recno.cachesize = (u_int) svp ? SvIV(*svp) : 0;
380 svp = hv_fetch(action, "psize", 5, FALSE);
381 info.recno.psize = (int) svp ? SvIV(*svp) : 0;
383 svp = hv_fetch(action, "lorder", 6, FALSE);
384 info.recno.lorder = (int) svp ? SvIV(*svp) : 0;
386 svp = hv_fetch(action, "reclen", 6, FALSE);
387 info.recno.reclen = (size_t) svp ? SvIV(*svp) : 0;
389 svp = hv_fetch(action, "bval", 4, FALSE);
390 if (svp && SvOK(*svp))
393 info.recno.bval = (u_char)*SvPV(*svp, na) ;
395 info.recno.bval = (u_char)(unsigned long) SvIV(*svp) ;
399 if (info.recno.flags & R_FIXEDLEN)
400 info.recno.bval = (u_char) ' ' ;
402 info.recno.bval = (u_char) '\n' ;
405 svp = hv_fetch(action, "bfname", 6, FALSE);
406 info.recno.bfname = (char *) svp ? SvPV(*svp,na) : 0;
411 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
415 RETVAL = dbopen(name, flags, mode, type, openinfo) ;
418 croak("DB_File::%s failed, reason: %s", string, Strerror(errno)) ;
420 /* kludge mode on: RETVAL->type for DB_RECNO is set to DB_BTREE
421 so remember a DB_RECNO by saving the address
422 of one of it's internal routines
424 if (type == DB_RECNO)
425 DB_recno_close = RETVAL->close ;
436 croak("DB_File::%s not implemented on this architecture", s);
450 if (strEQ(name, "BTREEMAGIC"))
456 if (strEQ(name, "BTREEVERSION"))
466 if (strEQ(name, "DB_LOCK"))
472 if (strEQ(name, "DB_SHMEM"))
478 if (strEQ(name, "DB_TXN"))
492 if (strEQ(name, "HASHMAGIC"))
498 if (strEQ(name, "HASHVERSION"))
514 if (strEQ(name, "MAX_PAGE_NUMBER"))
515 #ifdef MAX_PAGE_NUMBER
516 return (U32)MAX_PAGE_NUMBER;
520 if (strEQ(name, "MAX_PAGE_OFFSET"))
521 #ifdef MAX_PAGE_OFFSET
522 return MAX_PAGE_OFFSET;
526 if (strEQ(name, "MAX_REC_NUMBER"))
527 #ifdef MAX_REC_NUMBER
528 return (U32)MAX_REC_NUMBER;
542 if (strEQ(name, "RET_ERROR"))
548 if (strEQ(name, "RET_SPECIAL"))
554 if (strEQ(name, "RET_SUCCESS"))
560 if (strEQ(name, "R_CURSOR"))
566 if (strEQ(name, "R_DUP"))
572 if (strEQ(name, "R_FIRST"))
578 if (strEQ(name, "R_FIXEDLEN"))
584 if (strEQ(name, "R_IAFTER"))
590 if (strEQ(name, "R_IBEFORE"))
596 if (strEQ(name, "R_LAST"))
602 if (strEQ(name, "R_NEXT"))
608 if (strEQ(name, "R_NOKEY"))
614 if (strEQ(name, "R_NOOVERWRITE"))
616 return R_NOOVERWRITE;
620 if (strEQ(name, "R_PREV"))
626 if (strEQ(name, "R_RECNOSYNC"))
632 if (strEQ(name, "R_SETCURSOR"))
638 if (strEQ(name, "R_SNAPSHOT"))
662 if (strEQ(name, "__R_UNUSED"))
678 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
687 db_TIEHASH(dbtype, name=undef, flags=O_RDWR, mode=0640, type=DB_HASH)
693 char * name = (char *) NULL ;
694 SV * sv = (SV *) NULL ;
696 if (items >= 2 && SvOK(ST(1)))
697 name = (char*) SvPV(ST(1), na) ;
702 RETVAL = ParseOpenInfo(name, flags, mode, sv, "new") ;
708 newXS("DB_File::TIEARRAY", XS_DB_File_db_TIEHASH, file);
716 db_DELETE(db, key, flags=0)
722 db_FETCH(db, key, flags=0)
730 RETVAL = (db->get)(db, &key, &value, flags) ;
731 ST(0) = sv_newmortal();
733 sv_setpvn(ST(0), value.data, value.size);
737 db_STORE(db, key, value, flags=0)
752 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
753 ST(0) = sv_newmortal();
756 if (db->type != DB_RECNO)
757 sv_setpvn(ST(0), key.data, key.size);
759 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
771 RETVAL = (db->seq)(db, &key, &value, R_NEXT) ;
772 ST(0) = sv_newmortal();
775 if (db->type != DB_RECNO)
776 sv_setpvn(ST(0), key.data, key.size);
778 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
783 # These would be nice for RECNO
797 for (i = items-1 ; i > 0 ; --i)
799 value.data = SvPV(ST(i), na) ;
803 key.size = sizeof(int) ;
804 RETVAL = (db->put)(db, &key, &value, R_IBEFORE) ;
820 /* First get the final value */
821 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
822 ST(0) = sv_newmortal();
826 RETVAL = (db->del)(db, &key, R_CURSOR) ;
828 sv_setpvn(ST(0), value.data, value.size);
840 /* get the first value */
841 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
842 ST(0) = sv_newmortal();
846 RETVAL = (db->del)(db, &key, R_CURSOR) ;
848 sv_setpvn(ST(0), value.data, value.size);
862 /* Set the Cursor to the Last element */
863 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
866 /* for (i = 1 ; i < items ; ++i) */
867 for (i = items - 1 ; i > 0 ; --i)
869 value.data = SvPV(ST(i), na) ;
871 RETVAL = (db->put)(db, &key, &value, R_IAFTER) ;
885 RETVAL = GetArrayLength(db) ;
891 # Now provide an interface to the rest of the DB functionality
895 db_del(db, key, flags=0)
902 db_get(db, key, value, flags=0)
911 db_put(db, key, value, flags=0)
917 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
930 db_seq(db, key, value, flags)