📄 berkeleydb.xs
字号:
/* BerkeleyDB.xs -- Perl 5 interface to Berkeley DB version 2, 3 & 4 written by Paul Marquess <pmqs@cpan.org> All comments/suggestions/problems are welcome Copyright (c) 1997-2005 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Please refer to the COPYRIGHT section in Changes: 0.01 - First Alpha Release 0.02 -*/#ifdef __cplusplusextern "C" {#endif#define PERL_POLLUTE#include "EXTERN.h"#include "perl.h"#include "XSUB.h"#include "ppport.h"/* XSUB.h defines a macro called abort *//* This clashes with the txn abort method in Berkeley DB 4.x *//* This is a problem with ActivePerl (at least) */#ifdef _WIN32# ifdef abort# undef abort# endif# ifdef fopen# undef fopen# endif# ifdef fclose# undef fclose# endif# ifdef rename# undef rename# endif# ifdef open# undef open# endif#endif/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be * shortly #included by the <db.h>) __attribute__ to the possibly * already defined __attribute__, for example by GNUC or by Perl. */#undef __attribute__#ifdef USE_PERLIO# define GetFILEptr(sv) PerlIO_findFILE(IoIFP(sv_2io(sv)))#else# define GetFILEptr(sv) IoIFP(sv_2io(sv))#endif#include <db.h>/* Check the version of Berkeley DB */#ifndef DB_VERSION_MAJOR#ifdef HASHMAGIC#error db.h is from Berkeley DB 1.x - need at least Berkeley DB 2.6.4#else#error db.h is not for Berkeley DB at all.#endif#endif#if (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6) ||\ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 6 && DB_VERSION_PATCH < 4)# error db.h is from Berkeley DB 2.0-2.5 - need at least Berkeley DB 2.6.4#endif#if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0)# define IS_DB_3_0_x#endif#if DB_VERSION_MAJOR >= 3# define AT_LEAST_DB_3#endif#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 1)# define AT_LEAST_DB_3_1#endif#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)# define AT_LEAST_DB_3_2#endif#if DB_VERSION_MAJOR > 3 || \ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) ||\ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 2 && DB_VERSION_PATCH >= 6)# define AT_LEAST_DB_3_2_6#endif#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3)# define AT_LEAST_DB_3_3#endif#if DB_VERSION_MAJOR >= 4# define AT_LEAST_DB_4#endif#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)# define AT_LEAST_DB_4_1#endif#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 2)# define AT_LEAST_DB_4_2#endif#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)# define AT_LEAST_DB_4_3#endif#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 4)# define AT_LEAST_DB_4_4#endif#ifdef __cplusplus}#endif#define DBM_FILTERING#define STRICT_CLOSE/* #define ALLOW_RECNO_OFFSET *//* #define TRACE */#if DB_VERSION_MAJOR == 2 && ! defined(DB_LOCK_DEADLOCK)# define DB_LOCK_DEADLOCK EAGAIN#endif /* DB_VERSION_MAJOR == 2 */#if DB_VERSION_MAJOR == 2# define DB_QUEUE 4#endif /* DB_VERSION_MAJOR == 2 */#if DB_VERSION_MAJOR == 2 # define BackRef internal#else# if DB_VERSION_MAJOR == 3 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0)# define BackRef cj_internal# else# define BackRef api_internal# endif#endif#ifdef AT_LEAST_DB_3_2# define DB_callback DB * db,# define getCurrentDB ((BerkeleyDB)db->BackRef) # define saveCurrentDB(db) #else# define DB_callback# define getCurrentDB CurrentDB# define saveCurrentDB(db) CurrentDB = db#endif#if DB_VERSION_MAJOR > 2typedef struct { int db_lorder; size_t db_cachesize; size_t db_pagesize; void *(*db_malloc) __P((size_t)); int (*dup_compare) __P((DB_callback const DBT *, const DBT *)); u_int32_t bt_maxkey; u_int32_t bt_minkey; int (*bt_compare) __P((DB_callback const DBT *, const DBT *)); size_t (*bt_prefix) __P((DB_callback const DBT *, const DBT *)); u_int32_t h_ffactor; u_int32_t h_nelem; u_int32_t (*h_hash) __P((DB_callback const void *, u_int32_t)); int re_pad; int re_delim; u_int32_t re_len; char *re_source;#define DB_DELIMITER 0x0001#define DB_FIXEDLEN 0x0008#define DB_PAD 0x0010 u_int32_t flags; u_int32_t q_extentsize;} DB_INFO ;#endif /* DB_VERSION_MAJOR > 2 */typedef struct { int Status ; /* char ErrBuff[1000] ; */ SV * ErrPrefix ; SV * ErrHandle ; DB_ENV * Env ; int open_dbs ; int TxnMgrStatus ; int active ; bool txn_enabled ; bool opened ; bool cds_enabled; } BerkeleyDB_ENV_type ;typedef struct { DBTYPE type ; bool recno_or_queue ; char * filename ; BerkeleyDB_ENV_type * parent_env ; DB * dbp ; SV * compare ; bool in_compare ; SV * dup_compare ; bool in_dup_compare ; SV * prefix ; bool in_prefix ; SV * hash ; bool in_hash ;#ifdef AT_LEAST_DB_3_3 SV * associated ; bool secondary_db ;#endif bool primary_recno_or_queue ; int Status ; DB_INFO * info ; DBC * cursor ; DB_TXN * txn ; int open_cursors ; u_int32_t partial ; u_int32_t dlen ; u_int32_t doff ; int active ; bool cds_enabled;#ifdef ALLOW_RECNO_OFFSET int array_base ;#endif#ifdef DBM_FILTERING SV * filter_fetch_key ; SV * filter_store_key ; SV * filter_fetch_value ; SV * filter_store_value ; int filtering ;#endif } BerkeleyDB_type;typedef struct { DBTYPE type ; bool recno_or_queue ; char * filename ; DB * dbp ; SV * compare ; SV * dup_compare ; SV * prefix ; SV * hash ;#ifdef AT_LEAST_DB_3_3 SV * associated ; bool secondary_db ;#endif bool primary_recno_or_queue ; int Status ; DB_INFO * info ; DBC * cursor ; DB_TXN * txn ; BerkeleyDB_type * parent_db ; u_int32_t partial ; u_int32_t dlen ; u_int32_t doff ; int active ; bool cds_enabled;#ifdef ALLOW_RECNO_OFFSET int array_base ;#endif#ifdef DBM_FILTERING SV * filter_fetch_key ; SV * filter_store_key ; SV * filter_fetch_value ; SV * filter_store_value ; int filtering ;#endif } BerkeleyDB_Cursor_type;typedef struct { BerkeleyDB_ENV_type * env ; } BerkeleyDB_TxnMgr_type ;#if 1typedef struct { int Status ; DB_TXN * txn ; int active ; } BerkeleyDB_Txn_type ;#elsetypedef DB_TXN BerkeleyDB_Txn_type ;#endiftypedef BerkeleyDB_ENV_type * BerkeleyDB__Env ;typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Raw ;typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Inner ;typedef BerkeleyDB_type * BerkeleyDB ;typedef void * BerkeleyDB__Raw ;typedef BerkeleyDB_type * BerkeleyDB__Common ;typedef BerkeleyDB_type * BerkeleyDB__Common__Raw ;typedef BerkeleyDB_type * BerkeleyDB__Common__Inner ;typedef BerkeleyDB_type * BerkeleyDB__Hash ;typedef BerkeleyDB_type * BerkeleyDB__Hash__Raw ;typedef BerkeleyDB_type * BerkeleyDB__Btree ;typedef BerkeleyDB_type * BerkeleyDB__Btree__Raw ;typedef BerkeleyDB_type * BerkeleyDB__Recno ;typedef BerkeleyDB_type * BerkeleyDB__Recno__Raw ;typedef BerkeleyDB_type * BerkeleyDB__Queue ;typedef BerkeleyDB_type * BerkeleyDB__Queue__Raw ;typedef BerkeleyDB_Cursor_type BerkeleyDB__Cursor_type ;typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor ;typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor__Raw ;typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr ;typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Raw ;typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Inner ;typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn ;typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Raw ;typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Inner ;#if 0typedef DB_LOG * BerkeleyDB__Log ;typedef DB_LOCKTAB * BerkeleyDB__Lock ;#endiftypedef DBT DBTKEY ;typedef DBT DBT_OPT ;typedef DBT DBT_B ;typedef DBT DBTKEY_B ;typedef DBT DBTKEY_Br ;typedef DBT DBTVALUE ;typedef void * PV_or_NULL ;typedef PerlIO * IO_or_NULL ;typedef int DualType ;static voidhash_delete(char * hash, char * key);#ifdef TRACE# define Trace(x) printf x#else# define Trace(x)#endif#ifdef ALLOW_RECNO_OFFSET# define RECNO_BASE db->array_base#else# define RECNO_BASE 1#endif#if DB_VERSION_MAJOR == 2# define flagSet_DB2(i, f) i |= f#else# define flagSet_DB2(i, f)#endif#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5# define flagSet(bitmask) (flags & (bitmask))#else# define flagSet(bitmask) ((flags & DB_OPFLAGS_MASK) == (bitmask))#endif#define ERR_BUFF "BerkeleyDB::Error"#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \ Zero(to,1,typ))#define DBT_clear(x) Zero(&x, 1, DBT) ;#if 1#define getInnerObject(x) (*av_fetch((AV*)SvRV(x), 0, FALSE))#else#define getInnerObject(x) ((SV*)SvRV(sv))#endif#define my_sv_setpvn(sv, d, s) (s ? sv_setpvn(sv, d, s) : sv_setpv(sv, "") )#define SetValue_iv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \ i = SvIV(sv)#define SetValue_io(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \ i = GetFILEptr(sv)#define SetValue_sv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \ i = sv#define SetValue_pv(i, k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \ i = (t)SvPV(sv,PL_na)#define SetValue_pvx(i, k, t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \ i = (t)SvPVX(sv)#define SetValue_ov(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\ IV tmp = SvIV(getInnerObject(sv)) ; \ i = INT2PTR(t, tmp) ; \ }#define SetValue_ovx(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\ HV * hv = (HV *)GetInternalObject(sv); \ SV ** svp = hv_fetch(hv, "db", 2, FALSE);\ IV tmp = SvIV(*svp); \ i = INT2PTR(t, tmp) ; \ }#define SetValue_ovX(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\ IV tmp = SvIV(GetInternalObject(sv));\ i = INT2PTR(t, tmp) ; \ }#define LastDBerror DB_RUNRECOVERY#define setDUALerrno(var, err) \ sv_setnv(var, (double)err) ; \ sv_setpv(var, ((err) ? db_strerror(err) : "")) ;\ SvNOK_on(var);#define OutputValue(arg, name) \ { if (RETVAL == 0) { \ my_sv_setpvn(arg, name.data, name.size) ; \ DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \ } \ }#define OutputValue_B(arg, name) \ { if (RETVAL == 0) { \ if (db->type == DB_BTREE && \ flagSet(DB_GET_RECNO)){ \ sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \ } \ else { \ my_sv_setpvn(arg, name.data, name.size) ; \ } \ DBM_ckFilter(arg, filter_fetch_value, "filter_fetch_value"); \ } \ }#define OutputKey(arg, name) \ { if (RETVAL == 0) \ { \ if (!db->recno_or_queue) { \ my_sv_setpvn(arg, name.data, name.size); \ } \ else \ sv_setiv(arg, (I32)*(I32*)name.data - RECNO_BASE); \ DBM_ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \ } \ }#define OutputKey_B(arg, name) \ { if (RETVAL == 0) \ { \ if (db->recno_or_queue \ || (db->type == DB_BTREE && \ flagSet(DB_GET_RECNO))){ \ sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \ } \ else { \ my_sv_setpvn(arg, name.data, name.size); \ } \ DBM_ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \ } \ }#define OutputKey_Br(arg, name) \ { if (RETVAL == 0) \ { \ if (db->recno_or_queue || db->primary_recno_or_queue \ || (db->type == DB_BTREE && \ flagSet(DB_GET_RECNO))){ \ sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \ } \ else { \ my_sv_setpvn(arg, name.data, name.size); \ } \ DBM_ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \ } \ }#define SetPartial(data,db) \ data.flags = db->partial ; \ data.dlen = db->dlen ; \ data.doff = db->doff ;#define ckActive(active, type) \ { \ if (!active) \ softCrash("%s is already closed", type) ; \ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -