#include "bdb.h" static void mark_lsn(struct dblsnst *lsnst) { rb_gc_mark(lsnst->env); } static void free_lsn(struct dblsnst *lsnst) { if (BDB_VALID(lsnst->env, T_DATA)) { bdb_clean_env(lsnst->env, lsnst->self); } #if BDB_VERSION >= 40000 if (lsnst->cursor && BDB_VALID(lsnst->env, T_DATA)) { bdb_ENV *envst; Data_Get_Struct(lsnst->env, bdb_ENV, envst); if (envst->envp) { lsnst->cursor->close(lsnst->cursor, 0); } lsnst->cursor = 0; } #endif if (lsnst->lsn) free(lsnst->lsn); free(lsnst); } VALUE bdb_makelsn(VALUE env) { bdb_ENV *envst; struct dblsnst *lsnst; VALUE res; GetEnvDB(env, envst); res = Data_Make_Struct(bdb_cLsn, struct dblsnst, mark_lsn, free_lsn, lsnst); lsnst->env = env; lsnst->lsn = ALLOC(DB_LSN); lsnst->self = res; return res; } static VALUE bdb_s_log_put_internal(VALUE obj, VALUE a, int flag) { bdb_ENV *envst; VALUE ret; DBT data; struct dblsnst *lsnst; GetEnvDB(obj, envst); if (TYPE(a) != T_STRING) a = rb_str_to_str(a); ret = bdb_makelsn(obj); Data_Get_Struct(ret, struct dblsnst, lsnst); data.data = StringValuePtr(a); data.size = RSTRING_LEN(a); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_put(envst->envp->lg_info, lsnst->lsn, &data, flag)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_put(envst->envp, lsnst->lsn, &data, flag)); #else bdb_test_error(log_put(envst->envp, lsnst->lsn, &data, flag)); #endif #endif return ret; } static VALUE bdb_s_log_put(int argc, VALUE *argv, VALUE obj) { VALUE a, b; int flag = 0; if (argc == 0 || argc > 2) { rb_raise(bdb_eFatal, "Invalid number of arguments"); } #ifdef DB_CHECKPOINT flag = DB_CHECKPOINT; #endif if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flag = NUM2INT(b); } return bdb_s_log_put_internal(obj, a, flag); } static VALUE bdb_s_log_checkpoint(VALUE obj, VALUE a) { #ifdef DB_CHECKPOINT return bdb_s_log_put_internal(obj, a, DB_CHECKPOINT); #else rb_warning("BDB::CHECKPOINT is obsolete"); return bdb_s_log_put_internal(obj, a, 0); #endif } static VALUE bdb_s_log_flush(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; if (argc == 0) { GetEnvDB(obj, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_flush(envst->envp->lg_info, NULL)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_flush(envst->envp, NULL)); #else bdb_test_error(log_flush(envst->envp, NULL)); #endif #endif return obj; } else if (argc == 1) { return bdb_s_log_put_internal(obj, argv[0], DB_FLUSH); } else { rb_raise(bdb_eFatal, "Invalid number of arguments"); } } static VALUE bdb_s_log_curlsn(VALUE obj, VALUE a) { #ifdef DB_CURSLN return bdb_s_log_put_internal(obj, a, DB_CURLSN); #else rb_warning("BDB::CURLSN is obsolete"); return bdb_s_log_put_internal(obj, a, 0); #endif } static VALUE bdb_env_log_stat(int argc, VALUE *argv, VALUE obj) { DB_LOG_STAT *bdb_stat; bdb_ENV *envst; VALUE res, b; int flags; GetEnvDB(obj, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } bdb_test_error(log_stat(envst->envp->lg_info, &bdb_stat, 0)); #else #if BDB_VERSION >= 40000 flags = 0; if (rb_scan_args(argc, argv, "01", &b) == 1) { flags = NUM2INT(b); } bdb_test_error(envst->envp->log_stat(envst->envp, &bdb_stat, flags)); #else if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } #if BDB_VERSION < 30300 bdb_test_error(log_stat(envst->envp, &bdb_stat, 0)); #else bdb_test_error(log_stat(envst->envp, &bdb_stat)); #endif #endif #endif res = rb_hash_new(); rb_hash_aset(res, rb_tainted_str_new2("st_magic"), INT2NUM(bdb_stat->st_magic)); rb_hash_aset(res, rb_tainted_str_new2("st_version"), INT2NUM(bdb_stat->st_version)); rb_hash_aset(res, rb_tainted_str_new2("st_regsize"), INT2NUM(bdb_stat->st_regsize)); rb_hash_aset(res, rb_tainted_str_new2("st_mode"), INT2NUM(bdb_stat->st_mode)); #if BDB_VERSION < 30000 rb_hash_aset(res, rb_tainted_str_new2("st_refcnt"), INT2NUM(bdb_stat->st_refcnt)); #else rb_hash_aset(res, rb_tainted_str_new2("st_lg_bsize"), INT2NUM(bdb_stat->st_lg_bsize)); #endif #if BDB_VERSION >= 40100 rb_hash_aset(res, rb_tainted_str_new2("st_lg_size"), INT2NUM(bdb_stat->st_lg_size)); rb_hash_aset(res, rb_tainted_str_new2("st_lg_max"), INT2NUM(bdb_stat->st_lg_size)); #else rb_hash_aset(res, rb_tainted_str_new2("st_lg_max"), INT2NUM(bdb_stat->st_lg_max)); #endif rb_hash_aset(res, rb_tainted_str_new2("st_w_mbytes"), INT2NUM(bdb_stat->st_w_mbytes)); rb_hash_aset(res, rb_tainted_str_new2("st_w_bytes"), INT2NUM(bdb_stat->st_w_bytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wc_mbytes"), INT2NUM(bdb_stat->st_wc_mbytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wc_bytes"), INT2NUM(bdb_stat->st_wc_bytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wcount"), INT2NUM(bdb_stat->st_wcount)); #if BDB_VERSION >= 30000 rb_hash_aset(res, rb_tainted_str_new2("st_wcount_fill"), INT2NUM(bdb_stat->st_wcount_fill)); #endif rb_hash_aset(res, rb_tainted_str_new2("st_scount"), INT2NUM(bdb_stat->st_scount)); rb_hash_aset(res, rb_tainted_str_new2("st_cur_file"), INT2NUM(bdb_stat->st_cur_file)); rb_hash_aset(res, rb_tainted_str_new2("st_cur_offset"), INT2NUM(bdb_stat->st_cur_offset)); rb_hash_aset(res, rb_tainted_str_new2("st_region_wait"), INT2NUM(bdb_stat->st_region_wait)); rb_hash_aset(res, rb_tainted_str_new2("st_region_nowait"), INT2NUM(bdb_stat->st_region_nowait)); #if BDB_VERSION >= 40000 rb_hash_aset(res, rb_tainted_str_new2("st_disk_file"), INT2NUM(bdb_stat->st_disk_file)); rb_hash_aset(res, rb_tainted_str_new2("st_disk_offset"), INT2NUM(bdb_stat->st_disk_offset)); #if BDB_VERSION < 40100 rb_hash_aset(res, rb_tainted_str_new2("st_flushcommit"), INT2NUM(bdb_stat->st_flushcommit)); #endif rb_hash_aset(res, rb_tainted_str_new2("st_maxcommitperflush"), INT2NUM(bdb_stat->st_maxcommitperflush)); rb_hash_aset(res, rb_tainted_str_new2("st_mincommitperflush"), INT2NUM(bdb_stat->st_mincommitperflush)); #endif free(bdb_stat); return res; } #if BDB_VERSION < 40000 static VALUE bdb_env_log_get(VALUE obj, VALUE a) { bdb_ENV *envst; DBT data; struct dblsnst *lsnst; VALUE res, lsn; int ret, flag; GetEnvDB(obj, envst); flag = NUM2INT(a); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flag)); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flag)); #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); return rb_assoc_new(res, lsn); } #endif #if BDB_VERSION >= 40000 static VALUE bdb_log_cursor _((VALUE)); #endif #define BDB_LOG_INIT 0 #define BDB_LOG_SET 1 #define BDB_LOG_NEXT 2 static VALUE bdb_i_each_log_get(VALUE obj, int flag) { #if BDB_VERSION < 40000 bdb_ENV *envst; #endif struct dblsnst *lsnst, *lsnst1; DBT data; VALUE lsn, res, lsn1; int ret, init, flags; init = BDB_LOG_INIT; #if BDB_VERSION < 40000 GetEnvDB(obj, envst); #else lsn = obj; Data_Get_Struct(obj, struct dblsnst, lsnst); flag = lsnst->flags; if (lsnst->cursor == 0) { DB_LSN *lsn1; init = BDB_LOG_SET; lsn1 = lsnst->lsn; lsn = bdb_makelsn(lsnst->env); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, lsn1, DB_LSN, 1); bdb_log_cursor(lsn); } #endif do { #if BDB_VERSION < 40000 lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); #endif MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; switch (init) { case BDB_LOG_INIT: flags = (flag == DB_NEXT)?DB_FIRST:DB_LAST; break; case BDB_LOG_SET: flags = DB_SET; break; default: flags = flag; break; } init = BDB_LOG_NEXT; #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flags)); #else #if BDB_VERSION >= 40000 ret = bdb_test_error(lsnst->cursor->get(lsnst->cursor, lsnst->lsn, &data, flags)); lsn1 = bdb_makelsn(lsnst->env); Data_Get_Struct(lsn1, struct dblsnst, lsnst1); MEMCPY(lsnst1->lsn, lsnst->lsn, DB_LSN, 1); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flags)); lsn1 = lsn; #endif #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); rb_yield(rb_assoc_new(res, lsn)); } while (1); return Qnil; } #if BDB_VERSION < 40000 static VALUE bdb_env_log_each(VALUE obj) { return bdb_i_each_log_get(obj, DB_NEXT); } static VALUE bdb_env_log_hcae(VALUE obj) { return bdb_i_each_log_get(obj, DB_PREV); } #else static VALUE log_cursor_close(VALUE obj) { struct dblsnst *lsnst; Data_Get_Struct(obj, struct dblsnst, lsnst); if (lsnst->cursor) { bdb_test_error(lsnst->cursor->close(lsnst->cursor, 0)); lsnst->cursor = 0; } return Qnil; } static VALUE bdb_log_cursor_close(VALUE obj) { struct dblsnst *lsnst; Data_Get_Struct(obj, struct dblsnst, lsnst); bdb_clean_env(lsnst->env, obj); return log_cursor_close(obj); } static VALUE bdb_log_cursor(VALUE lsn) { bdb_ENV *envst; struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); if (!lsnst->cursor) { GetEnvDB(lsnst->env, envst); bdb_test_error(envst->envp->log_cursor(envst->envp, &lsnst->cursor, 0)); bdb_ary_push(&envst->db_ary, lsn); } return lsn; } static VALUE bdb_env_log_cursor(VALUE obj) { return bdb_log_cursor(bdb_makelsn(obj)); } static VALUE bdb_env_i_get(VALUE obj) { bdb_ENV *envst; struct dblsnst *lsnst; log_cursor_close(obj); Data_Get_Struct(obj, struct dblsnst, lsnst); GetEnvDB(lsnst->env, envst); bdb_test_error(envst->envp->log_cursor(envst->envp, &lsnst->cursor, 0)); return bdb_i_each_log_get(obj, lsnst->flags); } static VALUE bdb_env_log_each(VALUE obj) { VALUE lsn; struct dblsnst *lsnst; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_NEXT; return rb_ensure(bdb_env_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_env_log_hcae(VALUE obj) { VALUE lsn; struct dblsnst *lsnst; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_PREV; return rb_ensure(bdb_env_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_log_i_get(VALUE obj) { struct dblsnst *lsnst; log_cursor_close(obj); Data_Get_Struct(obj, struct dblsnst, lsnst); return bdb_i_each_log_get(obj, lsnst->flags); } static VALUE bdb_log_each(VALUE lsn) { struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_NEXT; return rb_ensure(bdb_log_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_log_hcae(VALUE lsn) { struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_PREV; return rb_ensure(bdb_log_i_get, lsn, bdb_log_cursor_close, lsn); } #endif static VALUE bdb_env_log_archive(int argc, VALUE *argv, VALUE obj) { char **list, **file; bdb_ENV *envst; int flag; VALUE res; GetEnvDB(obj, envst); flag = 0; list = NULL; if (rb_scan_args(argc, argv, "01", &res)) { flag = NUM2INT(res); } #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_archive(envst->envp->lg_info, &list, flag, NULL)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_archive(envst->envp, &list, flag)); #else #if BDB_VERSION < 30300 bdb_test_error(log_archive(envst->envp, &list, flag, NULL)); #else bdb_test_error(log_archive(envst->envp, &list, flag)); #endif #endif #endif res = rb_ary_new(); for (file = list; file != NULL && *file != NULL; file++) { rb_ary_push(res, rb_tainted_str_new2(*file)); } if (list != NULL) free(list); return res; } #define GetLsn(obj, lsnst, envst) \ { \ Data_Get_Struct(obj, struct dblsnst, lsnst); \ GetEnvDB(lsnst->env, envst); \ } static VALUE bdb_lsn_env(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; GetLsn(obj, lsnst, envst); return lsnst->env; } static VALUE bdb_lsn_log_file(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; char name[2048]; GetLsn(obj, lsnst, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_file(envst->envp->lg_info, lsnst->lsn, name, 2048)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_file(envst->envp, lsnst->lsn, name, 2048)); #else bdb_test_error(log_file(envst->envp, lsnst->lsn, name, 2048)); #endif #endif return rb_tainted_str_new2(name); } static VALUE bdb_lsn_log_flush(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; GetLsn(obj, lsnst, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_flush(envst->envp->lg_info, lsnst->lsn)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_flush(envst->envp, lsnst->lsn)); #else bdb_test_error(log_flush(envst->envp, lsnst->lsn)); #endif #endif return obj; } static VALUE bdb_lsn_log_compare(VALUE obj, VALUE a) { struct dblsnst *lsnst1, *lsnst2; bdb_ENV *envst1, *envst2; if (!rb_obj_is_kind_of(a, bdb_cLsn)) { rb_raise(bdb_eFatal, "invalid argument for <=>"); } GetLsn(obj, lsnst1, envst1); GetLsn(a, lsnst2, envst2); return INT2NUM(log_compare(lsnst1->lsn, lsnst2->lsn)); } static VALUE bdb_lsn_log_get(int argc, VALUE *argv, VALUE obj) { struct dblsnst *lsnst; DBT data; VALUE res, a; int ret, flags; bdb_ENV *envst; #if BDB_VERSION >= 40000 DB_LOGC *cursor; #endif flags = DB_SET; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } GetLsn(obj, lsnst, envst); #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_cursor(envst->envp, &cursor, 0)); #endif MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flags)); #else #if BDB_VERSION >= 40000 ret = cursor->get(cursor, lsnst->lsn, &data, flags); cursor->close(cursor, 0); ret = bdb_test_error(ret); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flags)); #endif #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); return res; } static VALUE bdb_log_register(VALUE obj, VALUE a) { #if BDB_VERSION >= 40100 rb_warn("log_register is obsolete"); return Qnil; #else bdb_DB *dbst; bdb_ENV *envst; if (TYPE(a) != T_STRING) { rb_raise(bdb_eFatal, "Need a filename"); } if (bdb_env_p(obj) == Qfalse) { rb_raise(bdb_eFatal, "Database must be open in an Env"); } Data_Get_Struct(obj, bdb_DB, dbst); Data_Get_Struct(dbst->env, bdb_ENV, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_register(envst->envp->lg_info, dbst->dbp, StringValuePtr(a), dbst->type, &envst->fidp)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_register(envst->envp, dbst->dbp, StringValuePtr(a))); #else #if BDB_VERSION <= 30105 bdb_test_error(log_register(envst->envp, dbst->dbp, StringValuePtr(a), &envst->fidp)); #else bdb_test_error(log_register(envst->envp, dbst->dbp, StringValuePtr(a))); #endif #endif #endif return obj; #endif } static VALUE bdb_log_unregister(VALUE obj) { #if BDB_VERSION >= 40100 rb_warn("log_unregister is obsolete"); return Qnil; #else bdb_DB *dbst; bdb_ENV *envst; if (bdb_env_p(obj) == Qfalse) { rb_raise(bdb_eFatal, "Database must be open in an Env"); } Data_Get_Struct(obj, bdb_DB, dbst); Data_Get_Struct(dbst->env, bdb_ENV, envst); #if BDB_VERSION < 30000 if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_unregister(envst->envp->lg_info, envst->fidp)); #else #if BDB_VERSION >= 40000 bdb_test_error(envst->envp->log_unregister(envst->envp, dbst->dbp)); #else #if BDB_VERSION <= 30105 bdb_test_error(log_unregister(envst->envp, envst->fidp)); #else bdb_test_error(log_unregister(envst->envp, dbst->dbp)); #endif #endif #endif return obj; #endif } void bdb_init_log() { rb_define_method(bdb_cEnv, "log_put", bdb_s_log_put, -1); rb_define_method(bdb_cEnv, "log_curlsn", bdb_s_log_curlsn, 0); rb_define_method(bdb_cEnv, "log_checkpoint", bdb_s_log_checkpoint, 1); rb_define_method(bdb_cEnv, "log_flush", bdb_s_log_flush, -1); rb_define_method(bdb_cEnv, "log_stat", bdb_env_log_stat, -1); rb_define_method(bdb_cEnv, "log_archive", bdb_env_log_archive, -1); #if BDB_VERSION < 40000 rb_define_method(bdb_cEnv, "log_get", bdb_env_log_get, 1); #else rb_define_method(bdb_cEnv, "log_cursor", bdb_env_log_cursor, 0); #endif rb_define_method(bdb_cEnv, "log_each", bdb_env_log_each, 0); rb_define_method(bdb_cEnv, "log_reverse_each", bdb_env_log_hcae, 0); rb_define_method(bdb_cCommon, "log_register", bdb_log_register, 1); rb_define_method(bdb_cCommon, "log_unregister", bdb_log_unregister, 0); bdb_cLsn = rb_define_class_under(bdb_mDb, "Lsn", rb_cObject); rb_include_module(bdb_cLsn, rb_mComparable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cLsn); #else rb_undef_method(CLASS_OF(bdb_cLsn), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cLsn), "new"); rb_define_method(bdb_cLsn, "env", bdb_lsn_env, 0); #if BDB_VERSION >= 40000 rb_define_method(bdb_cLsn, "log_cursor", bdb_log_cursor, 0); rb_define_method(bdb_cLsn, "cursor", bdb_log_cursor, 0); rb_define_method(bdb_cLsn, "log_close", bdb_log_cursor_close, 0); rb_define_method(bdb_cLsn, "close", bdb_log_cursor_close, 0); rb_define_method(bdb_cLsn, "log_each", bdb_log_each, 0); rb_define_method(bdb_cLsn, "each", bdb_log_each, 0); rb_define_method(bdb_cLsn, "log_reverse_each", bdb_log_hcae, 0); rb_define_method(bdb_cLsn, "reverse_each", bdb_log_hcae, 0); #endif rb_define_method(bdb_cLsn, "log_get", bdb_lsn_log_get, -1); rb_define_method(bdb_cLsn, "get", bdb_lsn_log_get, -1); rb_define_method(bdb_cLsn, "log_compare", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "compare", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "<=>", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "log_file", bdb_lsn_log_file, 0); rb_define_method(bdb_cLsn, "file", bdb_lsn_log_file, 0); rb_define_method(bdb_cLsn, "log_flush", bdb_lsn_log_flush, 0); rb_define_method(bdb_cLsn, "flush", bdb_lsn_log_flush, 0); }