Added extra debug/paranoia on bdberl_drv_stop/bdberl_drv_finish while
looking for the coredump on port close discovered on the local storage ops inside coordinator branch.
This commit is contained in:
parent
254e253d81
commit
86f39286b1
1 changed files with 59 additions and 5 deletions
|
@ -75,6 +75,8 @@ static int check_pos_env(char *env, unsigned int *val_ptr);
|
||||||
|
|
||||||
static int open_database(const char* name, DBTYPE type, unsigned int flags, PortData* data, int* dbref_res);
|
static int open_database(const char* name, DBTYPE type, unsigned int flags, PortData* data, int* dbref_res);
|
||||||
static int close_database(int dbref, unsigned flags, PortData* data);
|
static int close_database(int dbref, unsigned flags, PortData* data);
|
||||||
|
static void check_all_databases_closed();
|
||||||
|
|
||||||
static int delete_database(const char* name);
|
static int delete_database(const char* name);
|
||||||
|
|
||||||
static void get_info(int target, void* values, BinHelper* bh);
|
static void get_info(int target, void* values, BinHelper* bh);
|
||||||
|
@ -381,7 +383,7 @@ static void bdberl_drv_stop(ErlDrvData handle)
|
||||||
{
|
{
|
||||||
PortData* d = (PortData*)handle;
|
PortData* d = (PortData*)handle;
|
||||||
|
|
||||||
DBG("Stopping port %p\r\n", d->port);
|
DBG("Stopping port %p - cancelling async jobs\r\n", d->port);
|
||||||
|
|
||||||
// Grab the port lock, in case we have an async job running
|
// Grab the port lock, in case we have an async job running
|
||||||
erl_drv_mutex_lock(d->port_lock);
|
erl_drv_mutex_lock(d->port_lock);
|
||||||
|
@ -407,6 +409,8 @@ static void bdberl_drv_stop(ErlDrvData handle)
|
||||||
erl_drv_mutex_destroy(d->port_lock);
|
erl_drv_mutex_destroy(d->port_lock);
|
||||||
|
|
||||||
// If a cursor is open, close it
|
// If a cursor is open, close it
|
||||||
|
DBG("Stopping port %p - cleaning up cursors and transactions\r\n", d->port);
|
||||||
|
|
||||||
if (d->cursor)
|
if (d->cursor)
|
||||||
{
|
{
|
||||||
d->cursor->close(d->cursor);
|
d->cursor->close(d->cursor);
|
||||||
|
@ -416,9 +420,14 @@ static void bdberl_drv_stop(ErlDrvData handle)
|
||||||
abort_txn(d);
|
abort_txn(d);
|
||||||
|
|
||||||
// Close all the databases we previously opened
|
// Close all the databases we previously opened
|
||||||
|
DBG("Stopping port %p - closing all dbrefs\r\n", d->port);
|
||||||
while (d->dbrefs)
|
while (d->dbrefs)
|
||||||
{
|
{
|
||||||
close_database(d->dbrefs->dbref, 0, d);
|
int dbref = d->dbrefs->dbref;
|
||||||
|
if (ERROR_NONE != close_database(dbref, 0, d))
|
||||||
|
{
|
||||||
|
DBG("Stopping port %p could not close dbref %d\r\n", d->port, dbref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this port was registered as the endpoint for logging, go ahead and
|
// If this port was registered as the endpoint for logging, go ahead and
|
||||||
|
@ -426,6 +435,8 @@ static void bdberl_drv_stop(ErlDrvData handle)
|
||||||
// unregister if it's already initialized to this port.
|
// unregister if it's already initialized to this port.
|
||||||
if (G_LOG_PORT == d->port)
|
if (G_LOG_PORT == d->port)
|
||||||
{
|
{
|
||||||
|
DBG("Stopping port %p - removing logging portr\n", d->port);
|
||||||
|
|
||||||
WRITE_LOCK(G_LOG_RWLOCK);
|
WRITE_LOCK(G_LOG_RWLOCK);
|
||||||
|
|
||||||
// Remove the references
|
// Remove the references
|
||||||
|
@ -495,6 +506,11 @@ static void bdberl_drv_finish()
|
||||||
}
|
}
|
||||||
G_BDBERL_PIPE[0] = -1;
|
G_BDBERL_PIPE[0] = -1;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Add check to make sure all databases are *really* closed before
|
||||||
|
// the environment is closed.
|
||||||
|
check_all_databases_closed();
|
||||||
|
|
||||||
// Cleanup and shut down the BDB environment. Note that we assume
|
// Cleanup and shut down the BDB environment. Note that we assume
|
||||||
// all ports have been released and thuse all databases/txns/etc are also gone.
|
// all ports have been released and thuse all databases/txns/etc are also gone.
|
||||||
if (NULL != G_DB_ENV)
|
if (NULL != G_DB_ENV)
|
||||||
|
@ -1095,16 +1111,17 @@ static int close_database(int dbref, unsigned flags, PortData* data)
|
||||||
assert(G_DATABASES[dbref].ports != 0);
|
assert(G_DATABASES[dbref].ports != 0);
|
||||||
|
|
||||||
// Now disassociate this port from the database's port list
|
// Now disassociate this port from the database's port list
|
||||||
del_portref(dbref, data->port);
|
assert(1 == del_portref(dbref, data->port));
|
||||||
|
|
||||||
// Finally, if there are no other references to the database, close out
|
// Finally, if there are no other references to the database, close out
|
||||||
// the database completely
|
// the database completely
|
||||||
Database* database = &G_DATABASES[dbref];
|
Database* database = &G_DATABASES[dbref];
|
||||||
|
int rc = ERROR_NONE;
|
||||||
if (database->ports == 0)
|
if (database->ports == 0)
|
||||||
{
|
{
|
||||||
// Close out the BDB handle
|
// Close out the BDB handle
|
||||||
DBGCMD(data, "database->db->close(%p, %08x) (for dbref %d)", database->db, flags, dbref);
|
DBGCMD(data, "database->db->close(%p, %08x) (for dbref %d)", database->db, flags, dbref);
|
||||||
int rc = database->db->close(database->db, flags);
|
rc = database->db->close(database->db, flags);
|
||||||
DBGCMDRC(data, rc);
|
DBGCMDRC(data, rc);
|
||||||
|
|
||||||
// Remove the entry from the names map
|
// Remove the entry from the names map
|
||||||
|
@ -1116,7 +1133,7 @@ static int close_database(int dbref, unsigned flags, PortData* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_UNLOCK(G_DATABASES_RWLOCK);
|
WRITE_UNLOCK(G_DATABASES_RWLOCK);
|
||||||
return ERROR_NONE;
|
return rc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1124,6 +1141,38 @@ static int close_database(int dbref, unsigned flags, PortData* data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Called on driver shutdown to ensure all databases are closed.
|
||||||
|
// This should be unnecessary if all the dbref/port code has worked properly,
|
||||||
|
// but it is very important for BDB to shutdown cleanly so a final check can't hurt.
|
||||||
|
static void check_all_databases_closed()
|
||||||
|
{
|
||||||
|
WRITE_LOCK(G_DATABASES_RWLOCK);
|
||||||
|
|
||||||
|
int dbref;
|
||||||
|
int rc;
|
||||||
|
for (dbref = 0; dbref < G_DATABASES_SIZE; dbref++)
|
||||||
|
{
|
||||||
|
Database* database = &G_DATABASES[dbref];
|
||||||
|
if (NULL != database->ports)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "BDBERL: Ports still open on '%s' dbref %d\r\n",
|
||||||
|
database->name ? database->name : "no name", dbref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != database->db)
|
||||||
|
{
|
||||||
|
int flags = 0;
|
||||||
|
DBG("final db->close(%p, %08x) (for dbref %d)", database->db, flags, dbref);
|
||||||
|
rc = database->db->close(database->db, flags);
|
||||||
|
DBG(" = %s (%d)\r\n", rc == 0 ? "ok" : bdberl_rc_to_atom_str(rc), rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_UNLOCK(G_DATABASES_RWLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Abort the transaction and clean up
|
// Abort the transaction and clean up
|
||||||
static void abort_txn(PortData* d)
|
static void abort_txn(PortData* d)
|
||||||
{
|
{
|
||||||
|
@ -1830,6 +1879,7 @@ static void* zalloc(unsigned int size)
|
||||||
|
|
||||||
static int add_portref(int dbref, ErlDrvPort port)
|
static int add_portref(int dbref, ErlDrvPort port)
|
||||||
{
|
{
|
||||||
|
DBG("Adding port %p to dbref %d\r\n", port, dbref);
|
||||||
PortList* current = G_DATABASES[dbref].ports;
|
PortList* current = G_DATABASES[dbref].ports;
|
||||||
if (current)
|
if (current)
|
||||||
{
|
{
|
||||||
|
@ -1864,6 +1914,7 @@ static int add_portref(int dbref, ErlDrvPort port)
|
||||||
|
|
||||||
static int del_portref(int dbref, ErlDrvPort port)
|
static int del_portref(int dbref, ErlDrvPort port)
|
||||||
{
|
{
|
||||||
|
DBG("Deleting port %p from dbref %d\r\n", port, dbref);
|
||||||
PortList* current = G_DATABASES[dbref].ports;
|
PortList* current = G_DATABASES[dbref].ports;
|
||||||
PortList* last = 0;
|
PortList* last = 0;
|
||||||
assert(NULL != current);
|
assert(NULL != current);
|
||||||
|
@ -1899,6 +1950,7 @@ static int del_portref(int dbref, ErlDrvPort port)
|
||||||
*/
|
*/
|
||||||
static int add_dbref(PortData* data, int dbref)
|
static int add_dbref(PortData* data, int dbref)
|
||||||
{
|
{
|
||||||
|
DBG("Adding dbref %d to port %p\r\n", dbref, data->port);
|
||||||
DbRefList* current = data->dbrefs;
|
DbRefList* current = data->dbrefs;
|
||||||
if (current)
|
if (current)
|
||||||
{
|
{
|
||||||
|
@ -1935,6 +1987,8 @@ static int add_dbref(PortData* data, int dbref)
|
||||||
*/
|
*/
|
||||||
static int del_dbref(PortData* data, int dbref)
|
static int del_dbref(PortData* data, int dbref)
|
||||||
{
|
{
|
||||||
|
DBG("Deleting dbref %d from port %p\r\n", dbref, data->port);
|
||||||
|
|
||||||
DbRefList* current = data->dbrefs;
|
DbRefList* current = data->dbrefs;
|
||||||
DbRefList* last = 0;
|
DbRefList* last = 0;
|
||||||
assert(NULL != current);
|
assert(NULL != current);
|
||||||
|
|
Loading…
Reference in a new issue