📄 berkeleydb.xs
字号:
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) ; \ }#define ckActive_Environment(a) ckActive(a, "Environment")#define ckActive_TxnMgr(a) ckActive(a, "Transaction Manager")#define ckActive_Transaction(a) ckActive(a, "Transaction")#define ckActive_Database(a) ckActive(a, "Database")#define ckActive_Cursor(a) ckActive(a, "Cursor")#define dieIfEnvOpened(e, m) if (e->opened) softCrash("Cannot call method BerkeleyDB::Env::%s after environment has been opened", m); #define isSTDOUT_ERR(f) ((f) == stdout || (f) == stderr)/* Internal Global Data */#define MY_CXT_KEY "BerkeleyDB::_guts" XS_VERSIONtypedef struct { db_recno_t x_Value; db_recno_t x_zero; DBTKEY x_empty;#ifndef AT_LEAST_DB_3_2 BerkeleyDB x_CurrentDB;#endif} my_cxt_t;START_MY_CXT#define Value (MY_CXT.x_Value)#define zero (MY_CXT.x_zero)#define empty (MY_CXT.x_empty) #ifdef AT_LEAST_DB_3_2# define CurrentDB ((BerkeleyDB)db->BackRef) #else# define CurrentDB (MY_CXT.x_CurrentDB)#endif#ifdef AT_LEAST_DB_3_2# define getCurrentDB ((BerkeleyDB)db->BackRef) # define saveCurrentDB(db) #else# define getCurrentDB (MY_CXT.x_CurrentDB)# define saveCurrentDB(db) (MY_CXT.x_CurrentDB) = db#endif#if 0static char ErrBuff[1000] ;#endif#ifdef AT_LEAST_DB_3_3# if PERL_REVISION == 5 && PERL_VERSION <= 4/* saferealloc in perl5.004 will croak if it is given a NULL pointer*/void *MyRealloc(void * ptr, size_t size){ if (ptr == NULL ) return safemalloc(size) ; else return saferealloc(ptr, size) ;}# else# define MyRealloc saferealloc# endif#endifstatic char *my_strdup(const char *s){ if (s == NULL) return NULL ; { MEM_SIZE l = strlen(s) + 1; char *s1 = (char *)safemalloc(l); Copy(s, s1, (MEM_SIZE)l, char); return s1; }}#if DB_VERSION_MAJOR == 2static char *db_strerror(int err){ if (err == 0) return "" ; if (err > 0) return Strerror(err) ; switch (err) { case DB_INCOMPLETE: return ("DB_INCOMPLETE: Sync was unable to complete"); case DB_KEYEMPTY: return ("DB_KEYEMPTY: Non-existent key/data pair"); case DB_KEYEXIST: return ("DB_KEYEXIST: Key/data pair already exists"); case DB_LOCK_DEADLOCK: return ( "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock"); case DB_LOCK_NOTGRANTED: return ("DB_LOCK_NOTGRANTED: Lock not granted"); case DB_LOCK_NOTHELD: return ("DB_LOCK_NOTHELD: Lock not held by locker"); case DB_NOTFOUND: return ("DB_NOTFOUND: No matching key/data pair found"); case DB_RUNRECOVERY: return ("DB_RUNRECOVERY: Fatal error, run database recovery"); default: return "Unknown Error" ; }}#endif /* DB_VERSION_MAJOR == 2 */#ifdef TRACE#if DB_VERSION_MAJOR > 2static char *my_db_strerror(int err){ static char buffer[1000] ; SV * sv = perl_get_sv(ERR_BUFF, FALSE) ; sprintf(buffer, "%d: %s", err, db_strerror(err)) ; if (err && sv) { strcat(buffer, ", ") ; strcat(buffer, SvPVX(sv)) ; } return buffer;}#endif#endifstatic voidclose_everything(void){ dTHR; Trace(("close_everything\n")) ; /* Abort All Transactions */ { BerkeleyDB__Txn__Raw tid ; HE * he ; I32 len ; HV * hv = perl_get_hv("BerkeleyDB::Term::Txn", TRUE); int all = 0 ; int closed = 0 ; (void)hv_iterinit(hv) ; Trace(("BerkeleyDB::Term::close_all_txns dirty=%d\n", PL_dirty)) ; while ( (he = hv_iternext(hv)) ) { tid = * (BerkeleyDB__Txn__Raw *) hv_iterkey(he, &len) ; Trace((" Aborting Transaction [%d] in [%d] Active [%d]\n", tid->txn, tid, tid->active)); if (tid->active) {#ifdef AT_LEAST_DB_4 tid->txn->abort(tid->txn) ;#else txn_abort(tid->txn);#endif ++ closed ; } tid->active = FALSE ; ++ all ; } Trace(("End of BerkeleyDB::Term::close_all_txns aborted %d of %d transactios\n",closed, all)) ; } /* Close All Cursors */ { BerkeleyDB__Cursor db ; HE * he ; I32 len ; HV * hv = perl_get_hv("BerkeleyDB::Term::Cursor", TRUE); int all = 0 ; int closed = 0 ; (void) hv_iterinit(hv) ; Trace(("BerkeleyDB::Term::close_all_cursors \n")) ; while ( (he = hv_iternext(hv)) ) { db = * (BerkeleyDB__Cursor*) hv_iterkey(he, &len) ; Trace((" Closing Cursor [%d] in [%d] Active [%d]\n", db->cursor, db, db->active)); if (db->active) { ((db->cursor)->c_close)(db->cursor) ; ++ closed ; } db->active = FALSE ; ++ all ; } Trace(("End of BerkeleyDB::Term::close_all_cursors closed %d of %d cursors\n",closed, all)) ; } /* Close All Databases */ { BerkeleyDB db ; HE * he ; I32 len ; HV * hv = perl_get_hv("BerkeleyDB::Term::Db", TRUE); int all = 0 ; int closed = 0 ; (void)hv_iterinit(hv) ; Trace(("BerkeleyDB::Term::close_all_dbs\n" )) ; while ( (he = hv_iternext(hv)) ) { db = * (BerkeleyDB*) hv_iterkey(he, &len) ; Trace((" Closing Database [%d] in [%d] Active [%d]\n", db->dbp, db, db->active)); if (db->active) { (db->dbp->close)(db->dbp, 0) ; ++ closed ; } db->active = FALSE ; ++ all ; } Trace(("End of BerkeleyDB::Term::close_all_dbs closed %d of %d dbs\n",closed, all)) ; } /* Close All Environments */ { BerkeleyDB__Env env ; HE * he ; I32 len ; HV * hv = perl_get_hv("BerkeleyDB::Term::Env", TRUE); int all = 0 ; int closed = 0 ; (void)hv_iterinit(hv) ; Trace(("BerkeleyDB::Term::close_all_envs\n")) ; while ( (he = hv_iternext(hv)) ) { env = * (BerkeleyDB__Env*) hv_iterkey(he, &len) ; Trace((" Closing Environment [%d] in [%d] Active [%d]\n", env->Env, env, env->active)); if (env->active) {#if DB_VERSION_MAJOR == 2 db_appexit(env->Env) ;#else (env->Env->close)(env->Env, 0) ;#endif ++ closed ; } env->active = FALSE ; ++ all ; } Trace(("End of BerkeleyDB::Term::close_all_envs closed %d of %d dbs\n",closed, all)) ; } Trace(("end close_everything\n")) ;}static voiddestroyDB(BerkeleyDB db){ dTHR; if (! PL_dirty && db->active) { if (db->parent_env && db->parent_env->open_dbs) -- db->parent_env->open_dbs ; -- db->open_cursors ; ((db->dbp)->close)(db->dbp, 0) ; } if (db->hash) SvREFCNT_dec(db->hash) ; if (db->compare) SvREFCNT_dec(db->compare) ; if (db->dup_compare) SvREFCNT_dec(db->dup_compare) ;#ifdef AT_LEAST_DB_3_3 if (db->associated && !db->secondary_db) SvREFCNT_dec(db->associated) ;#endif if (db->prefix) SvREFCNT_dec(db->prefix) ;#ifdef DBM_FILTERING if (db->filter_fetch_key) SvREFCNT_dec(db->filter_fetch_key) ; if (db->filter_store_key) SvREFCNT_dec(db->filter_store_key) ; if (db->filter_fetch_value) SvREFCNT_dec(db->filter_fetch_value) ; if (db->filter_store_value) SvREFCNT_dec(db->filter_store_value) ;#endif hash_delete("BerkeleyDB::Term::Db", (char *)db) ; if (db->filename) Safefree(db->filename) ; Safefree(db) ;}static intsoftCrash(const char *pat, ...){ char buffer1 [500] ; char buffer2 [500] ; va_list args; va_start(args, pat); Trace(("softCrash: %s\n", pat)) ;#define ABORT_PREFIX "BerkeleyDB Aborting: " /* buffer = (char*) safemalloc(strlen(pat) + strlen(ABORT_PREFIX) + 1) ; */ strcpy(buffer1, ABORT_PREFIX) ; strcat(buffer1, pat) ; vsprintf(buffer2, buffer1, args) ; croak(buffer2); /* NOTREACHED */ va_end(args); return 1 ;}static I32GetArrayLength(BerkeleyDB db){ DBT key ; DBT value ; int RETVAL = 0 ; DBC * cursor ; DBT_clear(key) ; DBT_clear(value) ;#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor) == 0 )#else if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor, 0) == 0 )#endif { RETVAL = cursor->c_get(cursor, &key, &value, DB_LAST) ; if (RETVAL == 0) RETVAL = *(I32 *)key.data ; else /* No key means empty file */ RETVAL = 0 ; cursor->c_close(cursor) ; } Trace(("GetArrayLength got %d\n", RETVAL)) ; return ((I32)RETVAL) ;}#if 0#define GetRecnoKey(db, value) _GetRecnoKey(db, value)static db_recno_t_GetRecnoKey(BerkeleyDB db, I32 value){ Trace(("GetRecnoKey start value = %d\n", value)) ; if (db->recno_or_queue && value < 0) { /* Get the length of the array */ I32 length = GetArrayLength(db) ; /* check for attempt to write before start of array */ if (length + value + RECNO_BASE <= 0) softCrash("Modification of non-creatable array value attempted, subscript %ld", (long)value) ; value = length + value + RECNO_BASE ; } else ++ value ; Trace(("GetRecnoKey end value = %d\n", value)) ; return value ;}#else /* ! 0 */#if 0#ifdef ALLOW_RECNO_OFFSET#define GetRecnoKey(db, value) _GetRecnoKey(db, value)static db_recno_t_GetRecnoKey(BerkeleyDB db, I32 value){ if (value + RECNO_BASE < 1) softCrash("key value %d < base (%d)", (value), RECNO_BASE?0:1) ; return value + RECNO_BASE ;}#else#endif /* ALLOW_RECNO_OFFSET */#endif /* 0 */#define GetRecnoKey(db, value) ((value) + RECNO_BASE )#endif /* 0 */#if 0static SV *GetInternalObject(SV * sv){ SV * info = (SV*) NULL ; SV * s ; MAGIC * mg ; Trace(("in GetInternalObject %d\n", sv)) ; if (sv == NULL || !SvROK(sv)) return NULL ; s = SvRV(sv) ; if (SvMAGICAL(s)) { if (SvTYPE(s) == SVt_PVHV || SvTYPE(s) == SVt_PVAV) mg = mg_find(s, 'P') ; else mg = mg_find(s, 'q') ; /* all this testing is probably overkill, but till I know more about global destruction it stays. */ /* if (mg && mg->mg_obj && SvRV(mg->mg_obj) && SvPVX(SvRV(mg->mg_obj))) */ if (mg && mg->mg_obj && SvRV(mg->mg_obj) ) info = SvRV(mg->mg_obj) ; else info = s ; } Trace(("end of GetInternalObject %d\n", info)) ; return info ;}#endifstatic intbtree_compare(DB_callback const DBT * key1, const DBT * key2 ){#ifdef dTHX dTHX;#endif dSP ; dMY_CXT ; char * data1, * data2 ; int retval ; int count ; /* BerkeleyDB keepDB = getCurrentDB ; */ Trace(("In btree_compare \n")) ; data1 = (char*) key1->data ; data2 = (char*) key2->data ;#ifndef newSVpvn /* As newSVpv will assume that the data pointer is a null terminated C string if the size parameter is 0, make sure that data points to an empty string if the length is 0 */ if (key1->size == 0) data1 = "" ; if (key2->size == 0) data2 = "" ;#endif ENTER ; SAVETMPS; /* SAVESPTR(CurrentDB); */ PUSHMARK(SP) ; EXTEND(SP,2) ; PUSHs(sv_2mortal(newSVpvn(data1,key1->size))); PUSHs(sv_2mortal(newSVpvn(data2,key2->size))); PUTBACK ; count = perl_call_sv(getCurrentDB->compare, G_SCALAR); SPAGAIN ; if (count != 1) softCrash ("in btree_compare - expected 1 return value from compare sub, got %d", count) ; retval = POPi ; PUTBACK ; FREETMPS ; LEAVE ; /* CurrentDB = keepDB ; */ return (retval) ;}static intdup_compare(DB_callback const DBT * key1, const DBT * key2 ){#ifdef dTHX dTHX;#endif dSP ; dMY_CXT ; char * data1, * data2 ; int retval ; int count ; /* BerkeleyDB keepDB = CurrentDB ; */ Trace(("In dup_compare \n")) ; if (!getCurrentDB) softCrash("Internal Error - No CurrentDB in dup_compare") ; if (getCurrentDB->dup_compare == NULL) softCrash("in dup_compare: no callback specified for database '%s'", getCurrentDB->filename) ; data1 = (char*) key1->data ; data2 = (char*) key2->data ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -