diff options
author | Joshua Colp <jcolp@digium.com> | 2017-10-16 05:45:11 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2017-10-16 05:45:11 -0500 |
commit | 975d07248d487173fb4243bf40a3a8a4ab40ca75 (patch) | |
tree | 1b7928abcb617eeb84b63d55cf9ec8c178205455 /main | |
parent | 87123c90b2bba2b1c9eefd0ca295086288555548 (diff) | |
parent | f369be21a81608460cc29d81528e8b267b08ca6a (diff) |
Merge "cdr.c: Eliminated many calls to ao2_global_obj_ref()."
Diffstat (limited to 'main')
-rw-r--r-- | main/cdr.c | 307 |
1 files changed, 184 insertions, 123 deletions
diff --git a/main/cdr.c b/main/cdr.c index dc5c947fd..def3871bc 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -207,9 +207,16 @@ #define DEFAULT_BATCH_SCHEDULER_ONLY "0" #define DEFAULT_BATCH_SAFE_SHUTDOWN "1" -#define CDR_DEBUG(mod_cfg, fmt, ...) \ +#define cdr_set_debug_mode(mod_cfg) \ do { \ - if (ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG)) { \ + cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \ + } while (0) + +static int cdr_debug_enabled; + +#define CDR_DEBUG(fmt, ...) \ + do { \ + if (cdr_debug_enabled) { \ ast_verbose((fmt), ##__VA_ARGS__); \ } \ } while (0) @@ -237,6 +244,7 @@ static struct aco_type general_option = { static void *module_config_alloc(void); static void module_config_destructor(void *obj); +static void module_config_post_apply(void); /*! \brief The file definition */ static struct aco_file module_file_conf = { @@ -247,10 +255,23 @@ static struct aco_file module_file_conf = { CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc, .files = ACO_FILES(&module_file_conf), + .post_apply_config = module_config_post_apply, ); static struct aco_type *general_options[] = ACO_TYPES(&general_option); +static void module_config_post_apply(void) +{ + struct module_config *mod_cfg; + + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return; + } + cdr_set_debug_mode(mod_cfg); + ao2_cleanup(mod_cfg); +} + /*! \brief Dispose of a module config object */ static void module_config_destructor(void *obj) { @@ -764,9 +785,7 @@ static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr */ static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); - - CDR_DEBUG(mod_cfg, "%p - Transitioning CDR for %s from state %s to %s\n", + CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n", cdr, cdr->party_a.snapshot->name, cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name); cdr->fn_table = fn_table; @@ -874,7 +893,6 @@ static void cdr_object_dtor(void *obj) */ static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object *cdr; ast_assert(chan != NULL); @@ -897,7 +915,7 @@ static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan) cdr->party_a.snapshot = chan; ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation"); - CDR_DEBUG(mod_cfg, "%p - Created CDR for channel %s\n", cdr, chan->name); + CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->name); cdr_object_transition_state(cdr, &single_state_fn_table); @@ -1221,13 +1239,11 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr) */ static void cdr_object_dispatch(struct cdr_object *cdr) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); struct ast_cdr *pub_cdr; - CDR_DEBUG(mod_cfg, "%p - Dispatching CDR for Party A %s, Party B %s\n", cdr, - cdr->party_a.snapshot->name, - cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>"); + CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr, + cdr->party_a.snapshot->name, + cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>"); pub_cdr = cdr_object_create_public_records(cdr); cdr_detach(pub_cdr); } @@ -1327,13 +1343,12 @@ static void cdr_object_check_party_a_hangup(struct cdr_object *cdr) * \brief Check to see if a CDR needs to be answered based on its Party A. * Note that this is safe to call as much as you want - we won't answer twice */ -static void cdr_object_check_party_a_answer(struct cdr_object *cdr) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); - +static void cdr_object_check_party_a_answer(struct cdr_object *cdr) +{ if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) { cdr->answer = ast_tvnow(); /* tv_usec is suseconds_t, which could be int or long */ - CDR_DEBUG(mod_cfg, "%p - Set answered time to %ld.%06ld\n", cdr, + CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr, (long)cdr->answer.tv_sec, (long)cdr->answer.tv_usec); } @@ -1489,15 +1504,13 @@ static void single_state_process_party_b(struct cdr_object *cdr, struct ast_chan static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); - if (caller && !strcasecmp(cdr->party_a.snapshot->name, caller->name)) { base_process_party_a(cdr, caller); - CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr, - cdr->party_a.snapshot->name); + CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr, + cdr->party_a.snapshot->name); cdr_object_swap_snapshot(&cdr->party_b, peer); - CDR_DEBUG(mod_cfg, "%p - Updated Party B %s snapshot\n", cdr, - cdr->party_b.snapshot->name); + CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr, + cdr->party_b.snapshot->name); /* If we have two parties, lock the application that caused the * two parties to be associated. This prevents mid-call event @@ -1507,8 +1520,8 @@ static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_ch } else if (!strcasecmp(cdr->party_a.snapshot->name, peer->name)) { /* We're the entity being dialed, i.e., outbound origination */ base_process_party_a(cdr, peer); - CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr, - cdr->party_a.snapshot->name); + CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr, + cdr->party_a.snapshot->name); } cdr_object_transition_state(cdr, &dial_state_fn_table); @@ -1530,7 +1543,6 @@ static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_ch static int single_state_bridge_enter_comparison(struct cdr_object *cdr, struct cdr_object *cand_cdr) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object_snapshot *party_a; /* Don't match on ourselves */ @@ -1541,7 +1553,7 @@ static int single_state_bridge_enter_comparison(struct cdr_object *cdr, /* Try the candidate CDR's Party A first */ party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a); if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) { - CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n", + CDR_DEBUG("%p - Party A %s has new Party B %s\n", cdr, cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name); cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a); if (!cand_cdr->party_b.snapshot) { @@ -1561,7 +1573,7 @@ static int single_state_bridge_enter_comparison(struct cdr_object *cdr, } party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b); if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) { - CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n", + CDR_DEBUG("%p - Party A %s has new Party B %s\n", cdr, cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name); cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b); return 0; @@ -1937,7 +1949,6 @@ static int dial_status_end(const char *dialstatus) */ static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_message *message) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object *cdr; struct ast_multi_channel_blob *payload = stasis_message_data(message); struct ast_channel_snapshot *caller; @@ -1961,12 +1972,12 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str dial_status = ast_json_string_get(dial_status_blob); } - CDR_DEBUG(mod_cfg, "Dial %s message for %s, %s: %u.%08u\n", - ast_strlen_zero(dial_status) ? "Begin" : "End", - caller ? caller->name : "(none)", - peer ? peer->name : "(none)", - (unsigned int)stasis_message_timestamp(message)->tv_sec, - (unsigned int)stasis_message_timestamp(message)->tv_usec); + CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n", + ast_strlen_zero(dial_status) ? "Begin" : "End", + caller ? caller->name : "(none)", + peer ? peer->name : "(none)", + (unsigned int)stasis_message_timestamp(message)->tv_sec, + (unsigned int)stasis_message_timestamp(message)->tv_usec); /* Figure out who is running this show */ if (caller) { @@ -1986,10 +1997,10 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str if (!it_cdr->fn_table->process_dial_begin) { continue; } - CDR_DEBUG(mod_cfg, "%p - Processing Dial Begin message for channel %s, peer %s\n", - it_cdr, - caller ? caller->name : "(none)", - peer ? peer->name : "(none)"); + CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n", + it_cdr, + caller ? caller->name : "(none)", + peer ? peer->name : "(none)"); res &= it_cdr->fn_table->process_dial_begin(it_cdr, caller, peer); @@ -1997,10 +2008,10 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str if (!it_cdr->fn_table->process_dial_end) { continue; } - CDR_DEBUG(mod_cfg, "%p - Processing Dial End message for channel %s, peer %s\n", - it_cdr, - caller ? caller->name : "(none)", - peer ? peer->name : "(none)"); + CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n", + it_cdr, + caller ? caller->name : "(none)", + peer ? peer->name : "(none)"); it_cdr->fn_table->process_dial_end(it_cdr, caller, peer, @@ -2090,7 +2101,6 @@ static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot, static void handle_channel_cache_message(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct cdr_object *cdr; - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); struct stasis_cache_update *update = stasis_message_data(message); struct ast_channel_snapshot *old_snapshot; struct ast_channel_snapshot *new_snapshot; @@ -2148,7 +2158,7 @@ static void handle_channel_cache_message(void *data, struct stasis_subscription } } } else { - CDR_DEBUG(mod_cfg, "%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name); + CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name); for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) { cdr_object_finalize(it_cdr); } @@ -2228,8 +2238,6 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * struct ast_bridge_blob *update = stasis_message_data(message); struct ast_bridge_snapshot *bridge = update->bridge; struct ast_channel_snapshot *channel = update->channel; - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object *cdr; struct cdr_object *it_cdr; struct bridge_leave_data leave_data = { @@ -2246,10 +2254,10 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * return; } - CDR_DEBUG(mod_cfg, "Bridge Leave message for %s: %u.%08u\n", - channel->name, - (unsigned int)stasis_message_timestamp(message)->tv_sec, - (unsigned int)stasis_message_timestamp(message)->tv_usec); + CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n", + channel->name, + (unsigned int)stasis_message_timestamp(message)->tv_sec, + (unsigned int)stasis_message_timestamp(message)->tv_usec); cdr = ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_SEARCH_KEY); if (!cdr) { @@ -2264,8 +2272,8 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * if (!it_cdr->fn_table->process_bridge_leave) { continue; } - CDR_DEBUG(mod_cfg, "%p - Processing Bridge Leave for %s\n", - it_cdr, channel->name); + CDR_DEBUG("%p - Processing Bridge Leave for %s\n", + it_cdr, channel->name); if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) { ast_string_field_set(it_cdr, bridge, ""); left_bridge = 1; @@ -2293,8 +2301,6 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, struct cdr_object_snapshot *party_b) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object *new_cdr; new_cdr = cdr_object_create_and_append(cdr); @@ -2305,7 +2311,7 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, cdr_object_check_party_a_answer(new_cdr); ast_string_field_set(new_cdr, bridge, cdr->bridge); cdr_object_transition_state(new_cdr, &bridge_state_fn_table); - CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n", + CDR_DEBUG("%p - Party A %s has new Party B %s\n", new_cdr, new_cdr->party_a.snapshot->name, party_b->snapshot->name); } @@ -2324,8 +2330,6 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, */ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); struct cdr_object_snapshot *party_a; struct cdr_object *cand_cdr; @@ -2358,7 +2362,7 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b && strcasecmp(cand_cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) { bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a); } else { - CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n", + CDR_DEBUG("%p - Party A %s has new Party B %s\n", cand_cdr, cand_cdr->party_a.snapshot->name, cdr->party_a.snapshot->name); cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a); @@ -2408,8 +2412,6 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); int res = 1; struct cdr_object *it_cdr; struct cdr_object *new_cdr; @@ -2421,8 +2423,8 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr, res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel); } if (it_cdr->fn_table->process_party_a) { - CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr, - channel->name); + CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr, + channel->name); it_cdr->fn_table->process_party_a(it_cdr, channel); } } @@ -2448,8 +2450,6 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); enum process_bridge_enter_results result; struct cdr_object *it_cdr; struct cdr_object *new_cdr; @@ -2459,15 +2459,15 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr, for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) { if (it_cdr->fn_table->process_party_a) { - CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr, - channel->name); + CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr, + channel->name); it_cdr->fn_table->process_party_a(it_cdr, channel); } /* Notify all states that they have entered a bridge */ if (it_cdr->fn_table->process_bridge_enter) { - CDR_DEBUG(mod_cfg, "%p - Processing bridge enter for %s\n", it_cdr, - channel->name); + CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr, + channel->name); result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel); switch (result) { case BRIDGE_ENTER_ONLY_PARTY: @@ -2530,8 +2530,6 @@ static void handle_bridge_enter_message(void *data, struct stasis_subscription * struct ast_bridge_snapshot *bridge = update->bridge; struct ast_channel_snapshot *channel = update->channel; struct cdr_object *cdr; - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); if (filter_bridge_messages(bridge)) { return; @@ -2541,10 +2539,10 @@ static void handle_bridge_enter_message(void *data, struct stasis_subscription * return; } - CDR_DEBUG(mod_cfg, "Bridge Enter message for channel %s: %u.%08u\n", - channel->name, - (unsigned int)stasis_message_timestamp(message)->tv_sec, - (unsigned int)stasis_message_timestamp(message)->tv_usec); + CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n", + channel->name, + (unsigned int)stasis_message_timestamp(message)->tv_sec, + (unsigned int)stasis_message_timestamp(message)->tv_usec); cdr = ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_SEARCH_KEY); if (!cdr) { @@ -2574,8 +2572,6 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s struct ast_parked_call_payload *payload = stasis_message_data(message); struct ast_channel_snapshot *channel = payload->parkee; struct cdr_object *cdr; - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); int unhandled = 1; struct cdr_object *it_cdr; @@ -2593,10 +2589,10 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s return; } - CDR_DEBUG(mod_cfg, "Parked Call message for channel %s: %u.%08u\n", - channel->name, - (unsigned int)stasis_message_timestamp(message)->tv_sec, - (unsigned int)stasis_message_timestamp(message)->tv_usec); + CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n", + channel->name, + (unsigned int)stasis_message_timestamp(message)->tv_sec, + (unsigned int)stasis_message_timestamp(message)->tv_usec); cdr = ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_SEARCH_KEY); if (!cdr) { @@ -2646,20 +2642,37 @@ static void handle_cdr_sync_message(void *data, struct stasis_subscription *sub, struct ast_cdr_config *ast_cdr_get_config(void) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); - ao2_ref(mod_cfg->general, +1); - return mod_cfg->general; + struct ast_cdr_config *general; + struct module_config *mod_cfg; + + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return NULL; + } + general = ao2_bump(mod_cfg->general); + ao2_cleanup(mod_cfg); + return general; } void ast_cdr_set_config(struct ast_cdr_config *config) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; + + if (!config) { + return; + } + + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return; + } - ao2_cleanup(mod_cfg->general); - mod_cfg->general = config; - ao2_ref(mod_cfg->general, +1); + ao2_replace(mod_cfg->general, config); + cdr_set_debug_mode(mod_cfg); cdr_toggle_runtime_options(); + + ao2_cleanup(mod_cfg); } int ast_cdr_is_enabled(void) @@ -3299,15 +3312,20 @@ void ast_cdr_setuserfield(const char *channel_name, const char *userfield) static void post_cdr(struct ast_cdr *cdr) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; struct cdr_beitem *i; + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return; + } + for (; cdr ; cdr = cdr->next) { /* For people, who don't want to see unanswered single-channel events */ if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) { - ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel); + ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel); continue; } @@ -3329,6 +3347,7 @@ static void post_cdr(struct ast_cdr *cdr) } AST_RWLIST_UNLOCK(&be_list); } + ao2_cleanup(mod_cfg); } int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option) @@ -3547,7 +3566,7 @@ static void *do_batch_backend_process(void *data) static void cdr_submit_batch(int do_shutdown) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; struct cdr_batch_item *oldbatchitems = NULL; pthread_t batch_post_thread = AST_PTHREADT_NULL; @@ -3562,9 +3581,13 @@ static void cdr_submit_batch(int do_shutdown) reset_batch(); ast_mutex_unlock(&cdr_batch_lock); + mod_cfg = ao2_global_obj_ref(module_configs); + /* if configured, spawn a new thread to post these CDRs, also try to save as much as possible if we are shutting down safely */ - if (ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) || do_shutdown) { + if (!mod_cfg + || ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) + || do_shutdown) { ast_debug(1, "CDR single-threaded batch processing begins now\n"); do_batch_backend_process(oldbatchitems); } else { @@ -3575,17 +3598,27 @@ static void cdr_submit_batch(int do_shutdown) ast_debug(1, "CDR multi-threaded batch processing begins now\n"); } } + + ao2_cleanup(mod_cfg); } static int submit_scheduled_batch(const void *data) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; + cdr_submit_batch(0); - /* manually reschedule from this point in time */ + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return 0; + } + + /* manually reschedule from this point in time */ ast_mutex_lock(&cdr_sched_lock); cdr_sched = ast_sched_add(sched, mod_cfg->general->batch_settings.time * 1000, submit_scheduled_batch, NULL); ast_mutex_unlock(&cdr_sched_lock); + + ao2_cleanup(mod_cfg); /* returning zero so the scheduler does not automatically reschedule */ return 0; } @@ -3619,7 +3652,7 @@ static void cdr_detach(struct ast_cdr *cdr) } /* maybe they disabled CDR stuff completely, so just drop it */ - if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { + if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { ast_debug(1, "Dropping CDR !\n"); ast_cdr_free(cdr); return; @@ -3697,7 +3730,7 @@ static void *do_cdr(void *data) static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; switch (cmd) { case CLI_INIT: @@ -3715,6 +3748,11 @@ static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a return CLI_SHOWUSAGE; } + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + ast_cli(a->fd, "Could not set CDR debugging mode\n"); + return CLI_SUCCESS; + } if (!strcasecmp(a->argv[3], "on") && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) { ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG); @@ -3724,6 +3762,8 @@ static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a ast_clear_flag(&mod_cfg->general->settings, CDR_DEBUG); ast_cli(a->fd, "CDR debugging disabled\n"); } + cdr_set_debug_mode(mod_cfg); + ao2_cleanup(mod_cfg); return CLI_SUCCESS; } @@ -3910,7 +3950,7 @@ static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_ar static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct cdr_beitem *beitem = NULL; - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; int cnt = 0; long nextbatchtime = 0; @@ -3929,6 +3969,11 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_ return CLI_SHOWUSAGE; } + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return CLI_FAILURE; + } + ast_cli(a->fd, "\n"); ast_cli(a->fd, "Call Detail Record (CDR) settings\n"); ast_cli(a->fd, "----------------------------------\n"); @@ -3965,12 +4010,13 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_ ast_cli(a->fd, "\n"); } + ao2_cleanup(mod_cfg); return CLI_SUCCESS; } static char *handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; switch (cmd) { case CLI_INIT: @@ -3987,18 +4033,20 @@ static char *handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_ return CLI_SHOWUSAGE; } - if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { - ast_cli(a->fd, "Cannot submit CDR batch: CDR engine disabled.\n"); - return CLI_SUCCESS; + mod_cfg = ao2_global_obj_ref(module_configs); + if (!mod_cfg) { + return CLI_FAILURE; } - if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) { + if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { + ast_cli(a->fd, "Cannot submit CDR batch: CDR engine disabled.\n"); + } else if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) { ast_cli(a->fd, "Cannot submit CDR batch: batch mode not enabled.\n"); - return CLI_SUCCESS; + } else { + submit_unscheduled_batch(); + ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); } - - submit_unscheduled_batch(); - ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); + ao2_cleanup(mod_cfg); return CLI_SUCCESS; } @@ -4094,8 +4142,6 @@ static int create_subscriptions(void) static int process_config(int reload) { - RAII_VAR(struct module_config *, mod_cfg, module_config_alloc(), ao2_cleanup); - if (!reload) { if (aco_info_init(&cfg_info)) { return 1; @@ -4114,19 +4160,26 @@ static int process_config(int reload) aco_option_register(&cfg_info, "time", ACO_EXACT, general_options, DEFAULT_BATCH_TIME, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_cdr_config, batch_settings.time), 0, MAX_BATCH_TIME); } - if (aco_process_config(&cfg_info, reload)) { - if (!mod_cfg) { + if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) { + struct module_config *mod_cfg; + + if (reload) { return 1; } + /* If we couldn't process the configuration and this wasn't a reload, * create a default config */ - if (!reload && !(aco_set_defaults(&general_option, "general", mod_cfg->general))) { - ast_log(LOG_NOTICE, "Failed to process CDR configuration; using defaults\n"); - ao2_global_obj_replace_unref(module_configs, mod_cfg); - return 0; + mod_cfg = module_config_alloc(); + if (!mod_cfg + || aco_set_defaults(&general_option, "general", mod_cfg->general)) { + ao2_cleanup(mod_cfg); + return 1; } - return 1; + ast_log(LOG_NOTICE, "Failed to process CDR configuration; using defaults\n"); + ao2_global_obj_replace_unref(module_configs, mod_cfg); + cdr_set_debug_mode(mod_cfg); + ao2_cleanup(mod_cfg); } return 0; @@ -4213,13 +4266,15 @@ static void cdr_container_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt) */ static int cdr_toggle_runtime_options(void) { - RAII_VAR(struct module_config *, mod_cfg, - ao2_global_obj_ref(module_configs), ao2_cleanup); + struct module_config *mod_cfg; - if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { + mod_cfg = ao2_global_obj_ref(module_configs); + if (mod_cfg + && ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { if (create_subscriptions()) { destroy_subscriptions(); ast_log(AST_LOG_ERROR, "Failed to create Stasis subscriptions\n"); + ao2_cleanup(mod_cfg); return -1; } if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) { @@ -4231,8 +4286,9 @@ static int cdr_toggle_runtime_options(void) destroy_subscriptions(); ast_log(LOG_NOTICE, "CDR logging disabled.\n"); } + ao2_cleanup(mod_cfg); - return 0; + return mod_cfg ? 0 : -1; } int ast_cdr_engine_init(void) @@ -4326,22 +4382,27 @@ void ast_cdr_engine_term(void) int ast_cdr_engine_reload(void) { - RAII_VAR(struct module_config *, old_mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup); - RAII_VAR(struct module_config *, mod_cfg, NULL, ao2_cleanup); + struct module_config *old_mod_cfg; + struct module_config *mod_cfg; + + old_mod_cfg = ao2_global_obj_ref(module_configs); if (!old_mod_cfg || process_config(1)) { + ao2_cleanup(old_mod_cfg); return -1; } mod_cfg = ao2_global_obj_ref(module_configs); - - if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) || - !(ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE))) { + if (!mod_cfg + || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) + || !ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) { /* If batch mode used to be enabled, finalize the batch */ if (ast_test_flag(&old_mod_cfg->general->settings, CDR_BATCHMODE)) { finalize_batch_mode(); } } + ao2_cleanup(mod_cfg); + ao2_cleanup(old_mod_cfg); return cdr_toggle_runtime_options(); } |