From d7659ea8c1f3025bbeaca670aec7b2e584571750 Mon Sep 17 00:00:00 2001 From: Gregory Burd Date: Sun, 4 Dec 2011 14:45:30 -0500 Subject: [PATCH] Add BDB failchk support which requires thread_id and is_alive (implement thread_id_string while we're at it). --- c_src/bdberl_drv.c | 26 ++++++++++++++++++++++++- c_src/bdberl_tpool.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index aa16871..721f3e2 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -263,6 +263,9 @@ DRIVER_INIT(bdberl_drv) DB_RECOVER | /* Enable support for recovering from failures */ DB_CREATE | /* Create files as necessary */ DB_REGISTER | /* Run recovery if needed */ + DB_FAILCHK | /* Release any database reads locks held by the + thread of control that exited and, if needed, + abort unresolved transaction. */ DB_USE_ENVIRON | /* Use DB_HOME environment variable */ DB_THREAD; /* Make the environment free-threaded */ @@ -285,9 +288,30 @@ DRIVER_INIT(bdberl_drv) } else { + // DB should use the safe allocation routines provided by the Erlang VM + DBG("G_DB_ENV->set_alloc(%p, ...)", &G_DB_ENV); G_DB_ENV_ERROR = G_DB_ENV->set_alloc(G_DB_ENV, driver_alloc, driver_realloc, driver_free); - DBG(" = %d", G_DB_ENV_ERROR); + DBG(" = %d\n", G_DB_ENV_ERROR); + // Inform DB of the number of threads that will be operating on the DB Environment + unsigned int nthreads = G_NUM_GENERAL_THREADS + G_NUM_TXN_THREADS; + DBG("G_DB_ENV->set_thread_count(%p, %d, ...)", &G_DB_ENV, nthreads); + G_DB_ENV_ERROR = G_DB_ENV->set_thread_count(G_DB_ENV, nthreads); + DBG(" = %d\n", G_DB_ENV_ERROR); + + DBG("G_DB_ENV->set_thread_id(%p, ...)", &G_DB_ENV); + G_DB_ENV_ERROR = G_DB_ENV->set_thread_id(G_DB_ENV, &bdberl_tpool_thread_id); + DBG(" = %d\n", G_DB_ENV_ERROR); + + DBG("G_DB_ENV->set_thread_id_string(%p, ...)", &G_DB_ENV); + G_DB_ENV_ERROR = G_DB_ENV->set_thread_id_string(G_DB_ENV, &bdberl_tpool_thread_id_string); + DBG(" = %d\n", G_DB_ENV_ERROR); + + DBG("G_DB_ENV->set_is_alive(%p, ...)", &G_DB_ENV); + G_DB_ENV_ERROR = G_DB_ENV->set_isalive(G_DB_ENV, &bdberl_tpool_thread_is_alive); + DBG(" = %d\n", G_DB_ENV_ERROR); + + // Open the DB Environment DBG("G_DB_ENV->open(%p, 0, %08X, 0)", &G_DB_ENV, flags); G_DB_ENV_ERROR = G_DB_ENV->open(G_DB_ENV, 0, flags, 0); DBG(" = %d\n", G_DB_ENV_ERROR); diff --git a/c_src/bdberl_tpool.c b/c_src/bdberl_tpool.c index 42129e7..e0210c7 100644 --- a/c_src/bdberl_tpool.c +++ b/c_src/bdberl_tpool.c @@ -25,11 +25,19 @@ * THE SOFTWARE. * * ------------------------------------------------------------------- */ + +#include +#include "bdberl_drv.h" #include "bdberl_tpool.h" #include #include #include +#include +#include +#include +#include +#include static void* bdberl_tpool_main(void* tpool); static TPoolJob* next_job(TPool* tpool); @@ -356,3 +364,41 @@ void bdberl_tpool_job_count(TPool* tpool, unsigned int *pending_count_ptr, *active_count_ptr = tpool->active_job_count; UNLOCK(tpool); } + +// Returns a unique identifier pair for the current thread of control +void bdberl_tpool_thread_id(DB_ENV *env, pid_t *pid, db_threadid_t *tid) +{ + if (pid) + *pid = getpid(); + if (tid) + *tid = (db_threadid_t)pthread_self(); +} + +char *bdberl_tpool_thread_id_string(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, char *buf) +{ + snprintf(buf, DB_THREADID_STRLEN, "[pid:%08X/tid:%08X]", (unsigned int)pid, (unsigned int)tid); + return buf; +} + +// Returns non-zero if the thread of control, identified by the pid and tid arguments, +// is still running. +// If DB_MUTEX_PROCESS_ONLY is set in flags then return only if the process (pid) is +// alive, ignore the thread ID. +int bdberl_tpool_thread_is_alive(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, u_int32_t flags) +{ + static char path[200]; + static struct stat sb; + int alive = 0; + + snprintf(path, 200, "/dev/%d/status", pid); + if (stat(path, &sb)) + { + if (flags & DB_MUTEX_PROCESS_ONLY) + alive = 1; + else + if (pthread_kill(tid, 0) != ESRCH) + alive = 1; + } + DBG("bdberl_tpool_thread_is_alive(%08X, %08X, %d) = %d\n", pid, tid, flags, alive); + return alive; +}