cdr.c: Defer getting ao2_global_obj_ref() until needed.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 6 Oct 2017 18:45:30 +0000 (13:45 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 13 Oct 2017 00:12:07 +0000 (19:12 -0500)
The CDR performance gets worse the further it gets behind in processing
stasis messages.  One of the reasons is we were getting the global config
even if we didn't need it.

* Most uses of the global config were only needed on off nominal code
paths so it makes sense to not get it until absolutely needed.

ASTERISK-27335

Change-Id: I00c63b7ec233e5bfffd5d976f05568613d3c2365

main/cdr.c

index 6a3365e..dc5c947 100644 (file)
@@ -950,6 +950,28 @@ static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
 }
 
 /*!
+ * \internal
+ * \brief Determine if CDR flag is configured.
+ *
+ * \param cdr_flag The configured CDR flag to check.
+ *
+ * \retval 0 if the CDR flag is not configured.
+ * \retval non-zero if the CDR flag is configured.
+ *
+ * \return Nothing
+ */
+static int is_cdr_flag_set(unsigned int cdr_flag)
+{
+       struct module_config *mod_cfg;
+       int flag_set;
+
+       mod_cfg = ao2_global_obj_ref(module_configs);
+       flag_set = mod_cfg && ast_test_flag(&mod_cfg->general->settings, cdr_flag);
+       ao2_cleanup(mod_cfg);
+       return flag_set;
+}
+
+/*!
  * \brief Return whether or not a channel has changed its state in the dialplan, subject
  * to endbeforehexten logic
  *
@@ -962,12 +984,9 @@ static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
        struct ast_channel_snapshot *new_snapshot)
 {
-       RAII_VAR(struct module_config *, mod_cfg,
-               ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        /* If we ignore hangup logic, don't indicate that we're executing anything new */
-       if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
-               && ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
+       if (ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
+               && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN)) {
                return 0;
        }
 
@@ -975,10 +994,11 @@ static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
         * will attempt to clear the application and restore the dummy originate application
         * of "AppDialX". Ignore application changes to AppDialX as a result.
         */
-       if (strcmp(new_snapshot->appl, old_snapshot->appl) && strncasecmp(new_snapshot->appl, "appdial", 7)
+       if (strcmp(new_snapshot->appl, old_snapshot->appl)
+               && strncasecmp(new_snapshot->appl, "appdial", 7)
                && (strcmp(new_snapshot->context, old_snapshot->context)
-               || strcmp(new_snapshot->exten, old_snapshot->exten)
-               || new_snapshot->priority != old_snapshot->priority)) {
+                       || strcmp(new_snapshot->exten, old_snapshot->exten)
+                       || new_snapshot->priority != old_snapshot->priority)) {
                return 1;
        }
 
@@ -1050,15 +1070,15 @@ static long cdr_object_get_duration(struct cdr_object *cdr)
  */
 static long cdr_object_get_billsec(struct cdr_object *cdr)
 {
-       RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
        long int ms;
 
        if (ast_tvzero(cdr->answer)) {
                return 0;
        }
+
        ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
-       if (ast_test_flag(&mod_cfg->general->settings, CDR_INITIATED_SECONDS)
-               && (ms % 1000 >= 500)) {
+       if (ms % 1000 >= 500
+               && is_cdr_flag_set(CDR_INITIATED_SECONDS)) {
                ms = (ms / 1000) + 1;
        } else {
                ms = ms / 1000;
@@ -1219,16 +1239,13 @@ static void cdr_object_dispatch(struct cdr_object *cdr)
  */
 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
 {
-       RAII_VAR(struct module_config *, mod_cfg,
-                       ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        /* Change the disposition based on the hang up cause */
        switch (hangupcause) {
        case AST_CAUSE_BUSY:
                cdr->disposition = AST_CDR_BUSY;
                break;
        case AST_CAUSE_CONGESTION:
-               if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
+               if (!is_cdr_flag_set(CDR_CONGESTION)) {
                        cdr->disposition = AST_CDR_FAILED;
                } else {
                        cdr->disposition = AST_CDR_CONGESTION;
@@ -1295,10 +1312,8 @@ static void cdr_object_finalize(struct cdr_object *cdr)
  */
 static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
 {
-       RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
-
-       if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
-               && ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
+       if (ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
+               && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN)) {
                cdr_object_finalize(cdr);
        }
 
@@ -1361,13 +1376,11 @@ static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
 
 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 {
-       RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
 
        /* Finalize the CDR if we're in hangup logic and we're set to do so */
        if (ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
-               && ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)) {
+               && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN)) {
                cdr_object_finalize(cdr);
                return 0;
        }
@@ -1651,9 +1664,6 @@ static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_chan
  */
 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
 {
-       RAII_VAR(struct module_config *, mod_cfg,
-               ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        if (!strcmp(dial_status, "ANSWER")) {
                return AST_CDR_ANSWERED;
        } else if (!strcmp(dial_status, "BUSY")) {
@@ -1661,7 +1671,7 @@ static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_stat
        } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
                return AST_CDR_NOANSWER;
        } else if (!strcmp(dial_status, "CONGESTION")) {
-               if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
+               if (!is_cdr_flag_set(CDR_CONGESTION)) {
                        return AST_CDR_FAILED;
                } else {
                        return AST_CDR_CONGESTION;
@@ -1871,11 +1881,8 @@ static void finalized_state_init_function(struct cdr_object *cdr)
 
 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 {
-       RAII_VAR(struct module_config *, mod_cfg,
-               ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        if (ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
-                       && ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)) {
+               && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN)) {
                return 0;
        }
 
@@ -2054,13 +2061,10 @@ static int cdr_object_update_party_b(void *obj, void *arg, int flags)
 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
                struct ast_channel_snapshot *new_snapshot)
 {
-       RAII_VAR(struct module_config *, mod_cfg,
-                       ao2_global_obj_ref(module_configs), ao2_cleanup);
-
        /* If we're dead, we don't need a new CDR */
        if (!new_snapshot
                || (ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
-                       && ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN))) {
+                       && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN))) {
                return 0;
        }
 
@@ -2660,8 +2664,7 @@ void ast_cdr_set_config(struct ast_cdr_config *config)
 
 int ast_cdr_is_enabled(void)
 {
-       RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
-       return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
+       return is_cdr_flag_set(CDR_ENABLED);
 }
 
 int ast_cdr_backend_suspend(const char *name)
@@ -3155,13 +3158,9 @@ int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf,
 
        cdr = cdr_object_get_by_name(channel_name);
        if (!cdr) {
-               RAII_VAR(struct module_config *, mod_cfg,
-                        ao2_global_obj_ref(module_configs), ao2_cleanup);
-
-               if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
+               if (is_cdr_flag_set(CDR_ENABLED)) {
                        ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
                }
-
                return 0;
        }