Adding support for registering a logger port/pid to capture BDB messages

This commit is contained in:
Dave Smith 2009-04-16 07:08:22 -06:00
parent d6374488eb
commit 22f33e0b0d
2 changed files with 85 additions and 1 deletions

View file

@ -50,6 +50,9 @@ static void* deadlock_check(void* arg);
static void* trickle_write(void* arg);
static void* txn_checkpoint(void* arg);
static void bdb_errcall(const DB_ENV* dbenv, const char* errpfx, const char* msg);
static void bdb_msgcall(const DB_ENV* dbenv, const char* msg);
/**
* Global instance of DB_ENV; only a single one exists per O/S process.
*/
@ -117,6 +120,15 @@ static unsigned int G_CHECKPOINT_INTERVAL = 60 * 60; /* Seconds between checkpoi
*/
static int G_BDBERL_PIPE[2] = {-1, -1};
/**
* Lock, port and pid reference for relaying BDB output into the SASL logger. READ lock
* is required to log data. WRITE lock is used when replacing the pid/port reference. If
* no pid/port is available, no callback is registered with BDB.
*/
static ErlDrvRWLock* G_LOG_RWLOCK = 0;
static ErlDrvTermData G_LOG_PID;
static ErlDrvPort G_LOG_PORT;
/**
*
*/
@ -277,6 +289,11 @@ DRIVER_INIT(bdberl_drv)
// TODO: Make configurable/adjustable
G_TPOOL_GENERAL = bdberl_tpool_start(10);
G_TPOOL_TXNS = bdberl_tpool_start(10);
// Initialize logging lock and refs
G_LOG_RWLOCK = erl_drv_rwlock_create("bdberl_drv: G_LOG_RWLOCK");
G_LOG_PORT = 0;
G_LOG_PID = 0;
}
return &bdberl_drv_entry;
@ -358,6 +375,24 @@ static void bdberl_drv_stop(ErlDrvData handle)
close_database(d->dbrefs->dbref, 0, d);
}
// If this port was registered as the endpoint for logging, go ahead and
// remove it. Note that we don't need to lock to check this since we only
// unregister if it's already initialized to this port.
if (G_LOG_PORT == d->port)
{
WRITE_LOCK(G_LOG_RWLOCK);
// Remove the references
G_LOG_PORT = 0;
G_LOG_PID = 0;
// Unregister with BDB -- MUST DO THIS WITH WRITE LOCK HELD!
G_DB_ENV->set_msgcall(G_DB_ENV, 0);
G_DB_ENV->set_errcall(G_DB_ENV, 0);
WRITE_UNLOCK(G_LOG_RWLOCK);
}
DBG("Stopped port: %p\r\n", d->port);
// Release the port instance data
@ -400,6 +435,9 @@ static void bdberl_drv_finish()
erl_drv_rwlock_destroy(G_DATABASES_RWLOCK);
hive_hash_destroy(G_DATABASES_NAMES);
// Release the logging rwlock
erl_drv_rwlock_destroy(G_LOG_RWLOCK);
DBG("DRIVER_FINISH\n");
}
@ -693,6 +731,25 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd,
RETURN_INT(ERROR_INVALID_DBREF, outbuf);
}
}
case CMD_REGISTER_LOGGER:
{
// If this port is not the current logger, make it so. Only one logger can be registered
// at a time.
if (G_LOG_PORT != d->port)
{
// Grab the write lock and update the global vars; also make sure to update BDB callbacks
// within the write lock to avoid race conditions.
WRITE_LOCK(G_LOG_RWLOCK);
G_LOG_PORT = d->port;
G_LOG_PID = driver_connected(d->port);
G_DB_ENV->set_msgcall(G_DB_ENV, &bdb_msgcall);
G_DB_ENV->set_errcall(G_DB_ENV, &bdb_errcall);
WRITE_UNLOCK(G_LOG_RWLOCK);
}
}
}
*outbuf = 0;
return 0;
@ -1532,3 +1589,30 @@ static void* txn_checkpoint(void* arg)
DBG("Checkpointer exiting.\r\n");
return 0;
}
static void bdb_errcall(const DB_ENV* dbenv, const char* errpfx, const char* msg)
{
READ_LOCK(G_LOG_RWLOCK);
if (G_LOG_PORT)
{
ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("bdb_error_log"),
ERL_DRV_STRING, (ErlDrvTermData)msg, (ErlDrvUInt)strlen(msg),
ERL_DRV_TUPLE, 2};
driver_send_term(G_LOG_PORT, G_LOG_PID, response, sizeof(response) / sizeof(response[0]));
}
READ_UNLOCK(G_LOG_RWLOCK);
}
static void bdb_msgcall(const DB_ENV* dbenv, const char* msg)
{
printf("msgcall: %s\n", msg);
READ_LOCK(G_LOG_RWLOCK);
if (G_LOG_PORT)
{
ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("bdb_info_log"),
ERL_DRV_STRING, (ErlDrvTermData)msg, (ErlDrvUInt)strlen(msg),
ERL_DRV_TUPLE, 2};
driver_send_term(G_LOG_PORT, G_LOG_PID, response, sizeof(response) / sizeof(response[0]));
}
READ_UNLOCK(G_LOG_RWLOCK);
}

View file

@ -45,7 +45,7 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd,
#define CMD_PUT_COMMIT 14
#define CMD_REMOVE_DB 15
#define CMD_TRUNCATE 16
#define CMD_REGISTER_LOGGER 17
/**
* Command status values