Prevent CDR backends from unregistering while billing data is in flight

This patch makes it so that CDR backends cannot be unregistered while active
CDR records exist. This helps to prevent billing data from being lost during
restarts and shutdowns.

Review: https://reviewboard.asterisk.org/r/2880/
........

Merged revisions 402081 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402082 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Matthew Jordan 12 years ago
parent 2e24dfe4d1
commit 3713fa5c9f

@ -384,9 +384,11 @@ static int my_unload_module(int reload)
} }
dbport = 0; dbport = 0;
ast_cdr_unregister(name); if (reload) {
return ast_cdr_backend_suspend(name);
return 0; } else {
return ast_cdr_unregister(name);
}
} }
static int my_load_config_string(struct ast_config *cfg, const char *category, const char *variable, struct ast_str **field, const char *def) static int my_load_config_string(struct ast_config *cfg, const char *category, const char *variable, struct ast_str **field, const char *def)
@ -660,7 +662,11 @@ static int my_load_module(int reload)
return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_FAILURE;
} }
res = ast_cdr_register(name, desc, mysql_log); if (!reload) {
res = ast_cdr_register(name, desc, mysql_log);
} else {
res = ast_cdr_backend_unsuspend(name);
}
if (res) { if (res) {
ast_log(LOG_ERROR, "Unable to register MySQL CDR handling\n"); ast_log(LOG_ERROR, "Unable to register MySQL CDR handling\n");
} else { } else {

@ -767,7 +767,10 @@ early_release:
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (AST_RWLIST_WRLOCK(&odbc_tables)) { if (AST_RWLIST_WRLOCK(&odbc_tables)) {
ast_cdr_register(name, ast_module_info->description, odbc_log); ast_cdr_register(name, ast_module_info->description, odbc_log);
ast_log(LOG_ERROR, "Unable to lock column list. Unload failed.\n"); ast_log(LOG_ERROR, "Unable to lock column list. Unload failed.\n");

@ -315,7 +315,10 @@ static int csv_log(struct ast_cdr *cdr)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
loaded = 0; loaded = 0;
return 0; return 0;
} }

@ -184,7 +184,9 @@ static int custom_log(struct ast_cdr *cdr)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (AST_RWLIST_WRLOCK(&sinks)) { if (AST_RWLIST_WRLOCK(&sinks)) {
ast_cdr_register(name, ast_module_info->description, custom_log); ast_cdr_register(name, ast_module_info->description, custom_log);

@ -86,8 +86,9 @@ static int load_config(int reload)
if (!cfg) { if (!cfg) {
/* Standard configuration */ /* Standard configuration */
ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n"); ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
if (enablecdr) if (enablecdr) {
ast_cdr_unregister(name); ast_cdr_backend_suspend(name);
}
enablecdr = 0; enablecdr = 0;
return -1; return -1;
} }
@ -135,10 +136,11 @@ static int load_config(int reload)
ast_config_destroy(cfg); ast_config_destroy(cfg);
if (enablecdr && !newenablecdr) if (!newenablecdr) {
ast_cdr_unregister(name); ast_cdr_backend_suspend(name);
else if (!enablecdr && newenablecdr) } else if (newenablecdr) {
ast_cdr_register(name, "Asterisk Manager Interface CDR Backend", manager_log); ast_cdr_backend_unsuspend(name);
}
enablecdr = newenablecdr; enablecdr = newenablecdr;
return 0; return 0;
@ -210,7 +212,10 @@ static int manager_log(struct ast_cdr *cdr)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (customfields) if (customfields)
ast_free(customfields); ast_free(customfields);
@ -219,7 +224,12 @@ static int unload_module(void)
static int load_module(void) static int load_module(void)
{ {
if (ast_cdr_register(name, "Asterisk Manager Interface CDR Backend", manager_log)) {
return AST_MODULE_LOAD_DECLINE;
}
if (load_config(0)) { if (load_config(0)) {
ast_cdr_unregister(name);
return AST_MODULE_LOAD_DECLINE; return AST_MODULE_LOAD_DECLINE;
} }

@ -266,8 +266,10 @@ static int odbc_load_module(int reload)
} while (0); } while (0);
if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) { if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) {
ast_cdr_unregister(name); ast_cdr_backend_suspend(name);
ast_clear_flag(&config, CONFIG_REGISTERED); ast_clear_flag(&config, CONFIG_REGISTERED);
} else {
ast_cdr_backend_unsuspend(name);
} }
if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) { if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) {
@ -283,7 +285,9 @@ static int load_module(void)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (dsn) { if (dsn) {
ast_verb(11, "cdr_odbc: free dsn\n"); ast_verb(11, "cdr_odbc: free dsn\n");

@ -436,7 +436,10 @@ static void empty_columns(void)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
ast_cli_unregister_multiple(cdr_pgsql_status_cli, ARRAY_LEN(cdr_pgsql_status_cli)); ast_cli_unregister_multiple(cdr_pgsql_status_cli, ARRAY_LEN(cdr_pgsql_status_cli));
PQfinish(conn); PQfinish(conn);

@ -230,7 +230,10 @@ return_cleanup:
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (rh) { if (rh) {
rc_destroy(rh); rc_destroy(rh);
rh = NULL; rh = NULL;

@ -191,7 +191,10 @@ static int sqlite_log(struct ast_cdr *cdr)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (db) { if (db) {
sqlite_close(db); sqlite_close(db);
} }

@ -289,7 +289,9 @@ static int write_cdr(struct ast_cdr *cdr)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
free_config(0); free_config(0);

@ -235,7 +235,9 @@ static int load_config(int reload)
static int unload_module(void) static int unload_module(void)
{ {
ast_cdr_unregister(name); if (ast_cdr_unregister(name)) {
return -1;
}
if (AST_RWLIST_WRLOCK(&sinks)) { if (AST_RWLIST_WRLOCK(&sinks)) {
ast_cdr_register(name, ast_module_info->description, syslog_log); ast_cdr_register(name, ast_module_info->description, syslog_log);

@ -443,6 +443,10 @@ failed:
static int tds_unload_module(void) static int tds_unload_module(void)
{ {
if (ast_cdr_unregister(name)) {
return -1;
}
if (settings) { if (settings) {
ast_mutex_lock(&tds_lock); ast_mutex_lock(&tds_lock);
mssql_disconnect(); mssql_disconnect();
@ -452,8 +456,6 @@ static int tds_unload_module(void)
ast_free(settings); ast_free(settings);
} }
ast_cdr_unregister(name);
dbexit(); dbexit();
return 0; return 0;

@ -503,8 +503,27 @@ int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be);
* \brief Unregister a CDR handling engine * \brief Unregister a CDR handling engine
* \param name name of CDR handler to unregister * \param name name of CDR handler to unregister
* Unregisters a CDR by it's name * Unregisters a CDR by it's name
*
* \retval 0 The backend unregistered successfully
* \retval -1 The backend could not be unregistered at this time
*/
int ast_cdr_unregister(const char *name);
/*!
* \brief Suspend a CDR backend temporarily
*
* \retval 0 The backend is suspdended
* \retval -1 The backend could not be suspended
*/
int ast_cdr_backend_suspend(const char *name);
/*!
* \brief Unsuspend a CDR backend
*
* \retval 0 The backend was unsuspended
* \retval -1 The back could not be unsuspended
*/ */
void ast_cdr_unregister(const char *name); int ast_cdr_backend_unsuspend(const char *name);
/*! /*!
* \brief Disposition to a string * \brief Disposition to a string

@ -294,6 +294,7 @@ struct cdr_beitem {
char desc[80]; char desc[80];
ast_cdrbe be; ast_cdrbe be;
AST_RWLIST_ENTRY(cdr_beitem) list; AST_RWLIST_ENTRY(cdr_beitem) list;
int suspended:1;
}; };
/*! \brief List of registered backends */ /*! \brief List of registered backends */
@ -2581,6 +2582,42 @@ int ast_cdr_is_enabled(void)
return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED); return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
} }
int ast_cdr_backend_suspend(const char *name)
{
int success = -1;
struct cdr_beitem *i = NULL;
AST_RWLIST_WRLOCK(&be_list);
AST_RWLIST_TRAVERSE(&be_list, i, list) {
if (!strcasecmp(name, i->name)) {
ast_debug(3, "Suspending CDR backend %s\n", i->name);
i->suspended = 1;
success = 0;
}
}
AST_RWLIST_UNLOCK(&be_list);
return success;
}
int ast_cdr_backend_unsuspend(const char *name)
{
int success = -1;
struct cdr_beitem *i = NULL;
AST_RWLIST_WRLOCK(&be_list);
AST_RWLIST_TRAVERSE(&be_list, i, list) {
if (!strcasecmp(name, i->name)) {
ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
i->suspended = 0;
success = 0;
}
}
AST_RWLIST_UNLOCK(&be_list);
return success;
}
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be) int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
{ {
struct cdr_beitem *i = NULL; struct cdr_beitem *i = NULL;
@ -2615,24 +2652,39 @@ int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
return 0; return 0;
} }
void ast_cdr_unregister(const char *name) int ast_cdr_unregister(const char *name)
{ {
struct cdr_beitem *i = NULL; struct cdr_beitem *match = NULL;
int active_count;
AST_RWLIST_WRLOCK(&be_list); AST_RWLIST_WRLOCK(&be_list);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { AST_RWLIST_TRAVERSE(&be_list, match, list) {
if (!strcasecmp(name, i->name)) { if (!strcasecmp(name, match->name)) {
AST_RWLIST_REMOVE_CURRENT(list);
break; break;
} }
} }
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&be_list);
if (i) { if (!match) {
ast_verb(2, "Unregistered '%s' CDR backend\n", name); AST_RWLIST_UNLOCK(&be_list);
ast_free(i); return 0;
}
active_count = ao2_container_count(active_cdrs_by_channel);
if (!match->suspended && active_count != 0) {
AST_RWLIST_UNLOCK(&be_list);
ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
name, active_count);
return -1;
} }
AST_RWLIST_REMOVE(&be_list, match, list);
AST_RWLIST_UNLOCK(&be_list);
ast_verb(2, "Unregistered '%s' CDR backend\n", name);
ast_free(match);
return 0;
} }
struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr) struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
@ -3159,7 +3211,9 @@ static void post_cdr(struct ast_cdr *cdr)
} }
AST_RWLIST_RDLOCK(&be_list); AST_RWLIST_RDLOCK(&be_list);
AST_RWLIST_TRAVERSE(&be_list, i, list) { AST_RWLIST_TRAVERSE(&be_list, i, list) {
i->be(cdr); if (!i->suspended) {
i->be(cdr);
}
} }
AST_RWLIST_UNLOCK(&be_list); AST_RWLIST_UNLOCK(&be_list);
} }
@ -3772,7 +3826,7 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, " (none)\n"); ast_cli(a->fd, " (none)\n");
} else { } else {
AST_RWLIST_TRAVERSE(&be_list, beitem, list) { AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
ast_cli(a->fd, " %s\n", beitem->name); ast_cli(a->fd, " %s%s\n", beitem->name, beitem->suspended ? " (suspended) " : "");
} }
} }
AST_RWLIST_UNLOCK(&be_list); AST_RWLIST_UNLOCK(&be_list);

Loading…
Cancel
Save