Merge "chan_pjsip: Creating Channel Causes Asterisk to Crash When Duplicate AOR ...
authorMatt Jordan <mjordan@digium.com>
Wed, 29 Apr 2015 15:13:03 +0000 (10:13 -0500)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Wed, 29 Apr 2015 15:13:03 +0000 (10:13 -0500)
41 files changed:
CHANGES
Makefile
UPGRADE.txt
apps/app_queue.c
build_tools/cflags.xml
build_tools/make_buildopts_h
cdr/cdr_odbc.c
channels/chan_iax2.c
channels/chan_sip.c
channels/chan_vpb.cc
configs/samples/asterisk.conf.sample
configs/samples/cdr_odbc.conf.sample
contrib/Makefile
contrib/scripts/clang-scan-build [new file with mode: 0755]
contrib/scripts/refcounter.py
doc/.gitignore
include/asterisk/astobj2.h
include/asterisk/channel.h
include/asterisk/format_cache.h
include/asterisk/format_cap.h
include/asterisk/options.h
main/asterisk.c
main/astobj2.c
main/astobj2_container.c
main/astobj2_container_private.h
main/astobj2_hash.c
main/astobj2_private.h
main/astobj2_rbtree.c
main/channel.c
main/channel_internal_api.c
main/format_cache.c
main/format_cap.c
main/loader.c
main/rtp_engine.c
res/res_musiconhold.c
res/res_pjsip/include/res_pjsip_private.h
res/res_pjsip/location.c
res/res_pjsip/pjsip_options.c
res/res_pjsip/presence_xml.c
res/res_pjsip_outbound_registration.c
res/res_rtp_asterisk.c

diff --git a/CHANGES b/CHANGES
index a3fcc1e..fcb4877 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,14 @@ SMS
    providers to not log SMS content.
 
 
+CDRs
+------------------
+cdr_odbc
+------------------
+ * Added a new configuration option, "newcdrcolumns", which enables use of the
+   post-1.8 CDR columns 'peeraccount', 'linkedid', and 'sequence'.
+
+
 Channel Drivers
 ------------------
 
@@ -133,8 +141,8 @@ CEL Backends
 
 cel_pgsql
 ------------------
-* Added a new option, 'usegmtime', which causes timestamps in CEL events
-  to be logged in GMT.
+ * Added a new option, 'usegmtime', which causes timestamps in CEL events
+   to be logged in GMT.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
index 15e21b6..3252f76 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -982,6 +982,7 @@ ifeq ($(PYTHON),:)
        @echo "--------------------------------------------------------------------------"
        @false
 else
+       @$(INSTALL) -d doc/rest-api
        $(PYTHON) rest-api-templates/make_ari_stubs.py \
                rest-api/resources.json .
 endif
index 0696adb..d9d5cec 100644 (file)
@@ -32,6 +32,9 @@ chan_dahdi:
    Caller-ID detection.
 
 Core:
+ - The REF_DEBUG compiler flag is now used to enable refdebug by default.
+   The setting can be overridden in asterisk.conf by setting refdebug in
+   the options category.  No recompile is required to enable/disable it.
 
 AMI:
  - The 'ModuleCheck' Action's Version key will no longer show the module
index 0b8204c..d2c6406 100644 (file)
@@ -1814,49 +1814,26 @@ static void queue_member_follower_removal(struct call_queue *queue, struct membe
        ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
 }
 
-#ifdef REF_DEBUG
 #define queue_ref(q)                           _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define queue_unref(q)                         _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define queue_t_ref(q, tag)                    _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define queue_t_unref(q, tag)          _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define queues_t_link(c, q, tag)       __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define queues_t_unlink(c, q, tag)     __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
-{
-       __ao2_ref_debug(q, 1, tag, file, line, filename);
-       return q;
-}
-
-static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
-{
-       if (q) {
-               __ao2_ref_debug(q, -1, tag, file, line, filename);
-       }
-       return NULL;
-}
-
-#else
-
-#define queue_t_ref(q, tag)                    queue_ref(q)
-#define queue_t_unref(q, tag)          queue_unref(q)
 #define queues_t_link(c, q, tag)       ao2_t_link(c, q, tag)
 #define queues_t_unlink(c, q, tag)     ao2_t_unlink(c, q, tag)
 
-static inline struct call_queue *queue_ref(struct call_queue *q)
+static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
 {
-       ao2_ref(q, 1);
+       __ao2_ref(q, 1, tag, file, line, filename);
        return q;
 }
 
-static inline struct call_queue *queue_unref(struct call_queue *q)
+static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
 {
        if (q) {
-               ao2_ref(q, -1);
+               __ao2_ref(q, -1, tag, file, line, filename);
        }
        return NULL;
 }
-#endif
 
 /*! \brief Set variables of queue */
 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
index 1a2e78f..b91cf5a 100644 (file)
@@ -5,7 +5,7 @@
                <member name="DEBUG_THREADS" displayname="Enable Thread Debugging">
                        <support_level>core</support_level>
                </member>
-               <member name="REF_DEBUG" displayname="Enable reference count debugging">
+               <member name="REF_DEBUG" displayname="Enable reference count debugging by default">
                        <support_level>extended</support_level>
                </member>
                <member name="AO2_DEBUG" displayname="Enable internal Astobj2 debugging">
index 55d08ba..c96e508 100755 (executable)
@@ -10,27 +10,38 @@ cat << END
  */
 
 END
+
+if ${GREP} "AST_DEVMODE" makeopts | ${GREP} -q "yes"
+then
+       echo "#define AST_DEVMODE 1"
+       BUILDOPTS="AST_DEVMODE"
+fi
+
 TMP=`${GREP} -e "^MENUSELECT_CFLAGS" menuselect.makeopts | sed 's/MENUSELECT_CFLAGS\=//g' | sed 's/-D//g'`
 for x in ${TMP}; do
        echo "#define ${x} 1"
+       if test "${x}" = "DONT_OPTIMIZE" \
+                       -o "${x}" = "BETTER_BACKTRACES" \
+                       -o "${x}" = "LOTS_OF_SPANS" \
+                       -o "${x}" = "BUILD_NATIVE" \
+                       -o "${x}" = "REF_DEBUG" \
+                       -o "${x}" = "AO2_DEBUG" \
+                       -o "${x}" = "REBUILD_PARSERS" \
+                       -o "${x}" = "RADIO_RELAX" \
+                       -o "${x}" = "DEBUG_SCHEDULER" \
+                       -o "${x}" = "DETECT_DEADLOCKS" \
+                       -o "${x}" = "DUMP_SCHEDULER" ; then
+               # These aren't ABI affecting options, keep them out of AST_BUILDOPTS
+               continue
+       fi
        if test "x${BUILDOPTS}" != "x" ; then
                BUILDOPTS="${BUILDOPTS}, ${x}"
        else
                BUILDOPTS="${x}"
        fi
 done
-TMP=`${GREP} -e "^MENUSELECT_BUILD_DEPS" menuselect.makeopts | sed 's/MENUSELECT_BUILD_DEPS\=//g'`
-for x in ${TMP}; do
-       x2=`echo ${x} | tr a-z A-Z`
-       echo "#define AST_MODULE_${x2} 1"
-done
-if ${GREP} "AST_DEVMODE" makeopts | ${GREP} -q "yes"
-then
-       echo "#define AST_DEVMODE 1"
-       TMP="${TMP} AST_DEVMODE"
-fi
 
-BUILDSUM=`echo ${TMP} | ${MD5} | cut -c1-32`
+BUILDSUM=`echo ${BUILDOPTS} | ${MD5} | cut -c1-32`
 
 echo "#define AST_BUILDOPT_SUM \"${BUILDSUM}\""
 echo "#define AST_BUILDOPTS \"${BUILDOPTS}\""
index 8f326f9..4d601ef 100644 (file)
@@ -64,6 +64,7 @@ enum {
        CONFIG_DISPOSITIONSTRING = 1 << 2,
        CONFIG_HRTIME =            1 << 3,
        CONFIG_REGISTERED =        1 << 4,
+       CONFIG_NEWCDRCOLUMNS =     1 << 5,
 };
 
 static struct ast_flags config = { 0 };
@@ -72,23 +73,29 @@ static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data)
 {
        struct ast_cdr *cdr = data;
        SQLRETURN ODBC_res;
-       char sqlcmd[2048] = "", timestr[128];
+       char sqlcmd[2048] = "", timestr[128], new_columns[120] = "", new_values[7] = "";
        struct ast_tm tm;
        SQLHSTMT stmt;
+       int i = 0;
 
        ast_localtime(&cdr->start, &tm, ast_test_flag(&config, CONFIG_USEGMTIME) ? "GMT" : NULL);
        ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
 
+       if (ast_test_flag(&config, CONFIG_NEWCDRCOLUMNS)) {
+               snprintf(new_columns, sizeof(new_columns), "%s", ",peeraccount,linkedid,sequence");
+               snprintf(new_values, sizeof(new_values), "%s", ",?,?,?");
+       }
+
        if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
                snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
                "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
-               "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
-               "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
+               "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield%s) "
+               "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?,?,?%s)", table, new_columns, timestr, new_values);
        } else {
                snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
                "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
-               "duration,billsec,disposition,amaflags,accountcode) "
-               "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
+               "duration,billsec,disposition,amaflags,accountcode%s) "
+               "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?%s)", table, new_columns, timestr, new_values);
        }
 
        ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
@@ -134,9 +141,17 @@ static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data)
        SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
        SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
 
+       i = 14;
        if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
                SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
                SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
+               i = 16;
+       }
+
+       if (ast_test_flag(&config, CONFIG_NEWCDRCOLUMNS)) {
+               SQLBindParameter(stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->peeraccount), 0, cdr->peeraccount, 0, NULL);
+               SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->linkedid), 0, cdr->linkedid, 0, NULL);
+               SQLBindParameter(stmt, i + 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->sequence, 0, NULL);
        }
 
        ODBC_res = SQLExecDirect(stmt, (unsigned char *)sqlcmd, SQL_NTS);
@@ -260,6 +275,13 @@ static int odbc_load_module(int reload)
                                ast_set_flag(&config, CONFIG_REGISTERED);
                        }
                }
+               if (((tmp = ast_variable_retrieve(cfg, "global", "newcdrcolumns"))) && ast_true(tmp)) {
+                       ast_set_flag(&config, CONFIG_NEWCDRCOLUMNS);
+                       ast_debug(1, "cdr_odbc: Add new cdr columns\n");
+               } else {
+                       ast_clear_flag(&config, CONFIG_NEWCDRCOLUMNS);
+                       ast_debug(1, "cdr_odbc: Not add new cdr columns\n");
+               }
        } while (0);
 
        if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) {
index 8d3e7f1..253160a 100644 (file)
@@ -435,37 +435,37 @@ struct iax2_context {
 };
 
 
-#define        IAX_HASCALLERID         (uint64_t)(1 << 0)    /*!< CallerID has been specified */
-#define IAX_DELME               (uint64_t)(1 << 1)    /*!< Needs to be deleted */
-#define IAX_TEMPONLY            (uint64_t)(1 << 2)    /*!< Temporary (realtime) */
-#define IAX_TRUNK               (uint64_t)(1 << 3)    /*!< Treat as a trunk */
-#define IAX_NOTRANSFER          (uint64_t)(1 << 4)    /*!< Don't native bridge */
-#define IAX_USEJITTERBUF        (uint64_t)(1 << 5)    /*!< Use jitter buffer */
-#define IAX_DYNAMIC             (uint64_t)(1 << 6)    /*!< dynamic peer */
-#define IAX_SENDANI             (uint64_t)(1 << 7)    /*!< Send ANI along with CallerID */
-#define IAX_RTSAVE_SYSNAME      (uint64_t)(1 << 8)    /*!< Save Systname on Realtime Updates */
-#define IAX_ALREADYGONE         (uint64_t)(1 << 9)    /*!< Already disconnected */
-#define IAX_PROVISION           (uint64_t)(1 << 10)   /*!< This is a provisioning request */
-#define IAX_QUELCH              (uint64_t)(1 << 11)   /*!< Whether or not we quelch audio */
-#define IAX_ENCRYPTED           (uint64_t)(1 << 12)   /*!< Whether we should assume encrypted tx/rx */
-#define IAX_KEYPOPULATED        (uint64_t)(1 << 13)   /*!< Whether we have a key populated */
-#define IAX_CODEC_USER_FIRST    (uint64_t)(1 << 14)   /*!< are we willing to let the other guy choose the codec? */
-#define IAX_CODEC_NOPREFS       (uint64_t)(1 << 15)   /*!< Force old behaviour by turning off prefs */
-#define IAX_CODEC_NOCAP         (uint64_t)(1 << 16)   /*!< only consider requested format and ignore capabilities*/
-#define IAX_RTCACHEFRIENDS      (uint64_t)(1 << 17)   /*!< let realtime stay till your reload */
-#define IAX_RTUPDATE            (uint64_t)(1 << 18)   /*!< Send a realtime update */
-#define IAX_RTAUTOCLEAR         (uint64_t)(1 << 19)   /*!< erase me on expire */
-#define IAX_RTIGNOREREGEXPIRE   (uint64_t)(1 << 21)   /*!< When using realtime, ignore registration expiration */
-#define IAX_TRUNKTIMESTAMPS     (uint64_t)(1 << 22)   /*!< Send trunk timestamps */
-#define IAX_TRANSFERMEDIA       (uint64_t)(1 << 23)   /*!< When doing IAX2 transfers, transfer media only */
-#define IAX_MAXAUTHREQ          (uint64_t)(1 << 24)   /*!< Maximum outstanding AUTHREQ restriction is in place */
-#define IAX_DELAYPBXSTART       (uint64_t)(1 << 25)   /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else */
-#define IAX_ALLOWFWDOWNLOAD     (uint64_t)(1 << 26)   /*!< Allow the FWDOWNL command? */
-#define IAX_IMMEDIATE           (uint64_t)(1 << 27)   /*!< Allow immediate off-hook to extension s */
-#define IAX_SENDCONNECTEDLINE   (uint64_t)(1 << 28)   /*!< Allow sending of connected line updates */
-#define IAX_RECVCONNECTEDLINE   (uint64_t)(1 << 29)   /*!< Allow receiving of connected line updates */
-#define IAX_FORCE_ENCRYPT       (uint64_t)(1 << 30)   /*!< Forces call encryption, if encryption not possible hangup */
-#define IAX_SHRINKCALLERID      (uint64_t)(1 << 31)   /*!< Turn on and off caller id shrinking */
+#define IAX_HASCALLERID         (uint64_t)(1LLU << 0)    /*!< CallerID has been specified */
+#define IAX_DELME               (uint64_t)(1LLU << 1)    /*!< Needs to be deleted */
+#define IAX_TEMPONLY            (uint64_t)(1LLU << 2)    /*!< Temporary (realtime) */
+#define IAX_TRUNK               (uint64_t)(1LLU << 3)    /*!< Treat as a trunk */
+#define IAX_NOTRANSFER          (uint64_t)(1LLU << 4)    /*!< Don't native bridge */
+#define IAX_USEJITTERBUF        (uint64_t)(1LLU << 5)    /*!< Use jitter buffer */
+#define IAX_DYNAMIC             (uint64_t)(1LLU << 6)    /*!< dynamic peer */
+#define IAX_SENDANI             (uint64_t)(1LLU << 7)    /*!< Send ANI along with CallerID */
+#define IAX_RTSAVE_SYSNAME      (uint64_t)(1LLU << 8)    /*!< Save Systname on Realtime Updates */
+#define IAX_ALREADYGONE         (uint64_t)(1LLU << 9)    /*!< Already disconnected */
+#define IAX_PROVISION           (uint64_t)(1LLU << 10)   /*!< This is a provisioning request */
+#define IAX_QUELCH              (uint64_t)(1LLU << 11)   /*!< Whether or not we quelch audio */
+#define IAX_ENCRYPTED           (uint64_t)(1LLU << 12)   /*!< Whether we should assume encrypted tx/rx */
+#define IAX_KEYPOPULATED        (uint64_t)(1LLU << 13)   /*!< Whether we have a key populated */
+#define IAX_CODEC_USER_FIRST    (uint64_t)(1LLU << 14)   /*!< are we willing to let the other guy choose the codec? */
+#define IAX_CODEC_NOPREFS       (uint64_t)(1LLU << 15)   /*!< Force old behaviour by turning off prefs */
+#define IAX_CODEC_NOCAP         (uint64_t)(1LLU << 16)   /*!< only consider requested format and ignore capabilities*/
+#define IAX_RTCACHEFRIENDS      (uint64_t)(1LLU << 17)   /*!< let realtime stay till your reload */
+#define IAX_RTUPDATE            (uint64_t)(1LLU << 18)   /*!< Send a realtime update */
+#define IAX_RTAUTOCLEAR         (uint64_t)(1LLU << 19)   /*!< erase me on expire */
+#define IAX_RTIGNOREREGEXPIRE   (uint64_t)(1LLU << 21)   /*!< When using realtime, ignore registration expiration */
+#define IAX_TRUNKTIMESTAMPS     (uint64_t)(1LLU << 22)   /*!< Send trunk timestamps */
+#define IAX_TRANSFERMEDIA       (uint64_t)(1LLU << 23)   /*!< When doing IAX2 transfers, transfer media only */
+#define IAX_MAXAUTHREQ          (uint64_t)(1LLU << 24)   /*!< Maximum outstanding AUTHREQ restriction is in place */
+#define IAX_DELAYPBXSTART       (uint64_t)(1LLU << 25)   /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else */
+#define IAX_ALLOWFWDOWNLOAD     (uint64_t)(1LLU << 26)   /*!< Allow the FWDOWNL command? */
+#define IAX_IMMEDIATE           (uint64_t)(1LLU << 27)   /*!< Allow immediate off-hook to extension s */
+#define IAX_SENDCONNECTEDLINE   (uint64_t)(1LLU << 28)   /*!< Allow sending of connected line updates */
+#define IAX_RECVCONNECTEDLINE   (uint64_t)(1LLU << 29)   /*!< Allow receiving of connected line updates */
+#define IAX_FORCE_ENCRYPT       (uint64_t)(1LLU << 30)   /*!< Forces call encryption, if encryption not possible hangup */
+#define IAX_SHRINKCALLERID      (uint64_t)(1LLU << 31)   /*!< Turn on and off caller id shrinking */
 static int global_rtautoclear = 120;
 
 static int reload_config(int forced_reload);
index 3ee92da..aa616cd 100644 (file)
@@ -8599,9 +8599,9 @@ struct sip_pvt *__sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
 {
        struct sip_pvt *p;
 
-       p = __ao2_alloc_debug(sizeof(*p), sip_destroy_fn,
+       p = __ao2_alloc(sizeof(*p), sip_destroy_fn,
                AO2_ALLOC_OPT_LOCK_MUTEX, "allocate a dialog(pvt) struct",
-               file, line, func, 1);
+               file, line, func);
        if (!p) {
                return NULL;
        }
@@ -9178,7 +9178,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr
                struct sip_pvt tmp_dialog = {
                        .callid = callid,
                };
-               sip_pvt_ptr = __ao2_find_debug(dialogs, &tmp_dialog, OBJ_POINTER,
+               sip_pvt_ptr = __ao2_find(dialogs, &tmp_dialog, OBJ_POINTER,
                        "find_call in dialogs", file, line, func);
                if (sip_pvt_ptr) {  /* well, if we don't find it-- what IS in there? */
                        /* Found the call */
@@ -9193,7 +9193,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr
                struct sip_pvt *fork_pvt = NULL;
                struct match_req_args args = { 0, };
                int found;
-               struct ao2_iterator *iterator = __ao2_callback_debug(dialogs,
+               struct ao2_iterator *iterator = __ao2_callback(dialogs,
                        OBJ_POINTER | OBJ_MULTIPLE,
                        dialog_find_multiple,
                        &tmp_dialog,
@@ -9243,7 +9243,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr
                                /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
                                * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */
                                transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
-                               __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.",
+                               __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.",
                                        file, line, func);
                                ao2_iterator_destroy(iterator);
                                dialog_unref(fork_pvt, "unref fork_pvt");
@@ -9255,7 +9255,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr
                                /* fall through */
                        case SIP_REQ_NOT_MATCH:
                        default:
-                               __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search",
+                               __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search",
                                        file, line, func);
                                break;
                        }
index 6a9e9a6..16a66b9 100644 (file)
@@ -59,7 +59,7 @@ extern "C" {
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_REGISTER_FILE()
 
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
index e4883ec..818f5c2 100644 (file)
@@ -14,6 +14,7 @@ astsbindir => /usr/sbin
 [options]
 ;verbose = 3
 ;debug = 3
+;refdebug = yes                        ; Enable reference count debug logging.
 ;alwaysfork = yes              ; Same as -F at startup.
 ;nofork = yes                  ; Same as -f at startup.
 ;quiet = yes                   ; Same as -q at startup.
index 93bd6ff..663ce09 100644 (file)
@@ -9,3 +9,4 @@
 ;table=cdr             ;"cdr" is default table name
 ;usegmtime=no             ; set to "yes" to log in GMT
 ;hrtime=yes            ;Enables microsecond accuracy with the billsec and duration fields
+;newcdrcolumns=yes ; Enable logging of post-1.8 CDR columns (peeraccount, linkedid, sequence)
index 2c91b47..37f4df4 100644 (file)
@@ -20,10 +20,8 @@ clean:
 include $(ASTTOPDIR)/Makefile.rules
 
 install:
-       if [ -n "$(findstring REF_DEBUG,$(MENUSELECT_CFLAGS))" ]; then \
-               $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \
-               $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \
-       fi
+       $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \
+       $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \
 
 uninstall:
        rm -f "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"
diff --git a/contrib/scripts/clang-scan-build b/contrib/scripts/clang-scan-build
new file mode 100755 (executable)
index 0000000..c5f93ac
--- /dev/null
@@ -0,0 +1,136 @@
+#!/bin/bash
+#
+# clang-scan-build: configure and compile asterisk using the llvm static analyzer
+
+# Options/Flags:
+# -c|--compiler        : either [clang|gcc]
+# --cflags     : cflags you would like to add to the default set
+# --configure  : configure flags you would like to use instead off the default set
+# --make       : make flags you would like to use instead off the default set
+# --scanbuild  : scanbuild flags you would like to use instead of the default set
+# --outputdir  : directory where scan-build should create the html files
+# -h|--help    : this help
+
+# Usage:
+# contrib/scripts/clang-scan-build
+# This script will use clang if available and no compiler has been specified
+#
+# Example usage:
+#
+#   contrib/scripts/clang-scan-build
+#   contrib/scripts/clang-scan-build -c gcc
+#   contrib/scripts/clang-scan-build --compiler clang --configure "--enable-dev-mode" --outputdir="/tmp/scan-build_output"
+#   contrib/scripts/clang-scan-build --make "-j2"
+#
+# scan-build will generate html files during the make process, which will be stored in the specified outputdir or ./scan-build_output" by default
+
+# Copyright (C) 2015 Diederik de Groot <dddegroot@users.sf.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+# USA
+
+COMPILER=clang
+SCANBUILD="`which scan-build`"
+CFLAGS=""
+CONFIGURE_FLAGS="--enable-coverage --disable-xmldoc"
+MAKE_FLAGS=""
+SCANBUILD_FLAGS="-maxloop 10 -disable-checker deadcode.DeadStores -enable-checker alpha.core.BoolAssignment -enable-checker alpha.core.CallAndMessageUnInitRefArg -enable-checker alpha.core.CastSize -enable-checker alpha.core.CastToStruct -enable-checker alpha.core.IdenticalExpr -enable-checker alpha.core.PointerArithm -enable-checker alpha.core.PointerSub -enable-checker alpha.core.SizeofPtr -enable-checker alpha.core.TestAfterDivZero -enable-checker alpha.security.ArrayBound -enable-checker alpha.security.ArrayBoundV2 -enable-checker alpha.security.MallocOverflow -enable-checker alpha.security.ReturnPtrRange -enable-checker alpha.security.taint.TaintPropagation -enable-checker alpha.unix.MallocWithAnnotations -enable-checker alpha.unix.PthreadLock -enable-checker alpha.unix.SimpleStream -enable-checker alpha.unix.Stream -enable-checker alpha.unix.cstring.BufferOverlap -enable-checker alpha.unix.cstring.NotNullTerminated -enable-checker alpha.unix.cstring.OutOfBounds"
+OUTPUTDIR="scan-build_output"
+
+function print_usage {
+cat << EOF
+$0 Usage:
+
+Options/Flags:
+-c|--compiler  : either [clang|gcc]
+--cflags       : cflags you would like to add to the default set:
+                 "${CFLAGS}"
+
+--configure    : configure flags you would like to use instead off the default set:
+                 "${CONFIGURE_FLAGS}"
+
+--make         : make flags you would like to use instead off the default set:
+                 "${MAKE_FLAGS}"
+
+--scanbuild    : scanbuild flags you would like to use instead of the default set:
+                 "${SCANBUILD_FLAGS}"
+
+--outputdir    : directory where scan-build should create the html files. default:
+                 "`pwd`/${OUTPUTDIR}"
+
+-h|--help      : this help
+EOF
+}
+
+for i in "$@"
+do
+       case $i in
+               -c=*|--compiler=*)
+                       COMPILER="${i#*=}"
+                       shift
+               ;;
+               --cflags=*)
+                       CFLAGS="${i#*=}"
+                       shift
+               ;;
+               --configure=*)
+                       CONFIGURE_FLAGS="${i#*=}"
+                       shift
+               ;;
+               --make=*)
+                       MAKE_FLAGS="${i#*=}"
+                       shift
+               ;;
+               --scanbuild=*)
+                       SCANBUILD_FLAGS="${i#*=}"
+                       shift
+               ;;
+               --outputdir=*)
+                       OUTPUTDIR="${i#*=}"
+                       shift
+               ;;
+               -h|--help)
+                       print_usage
+                       exit
+               ;;
+       esac
+done
+
+if [ "${COMPILER}" == "clang" ] && [ ! -z "`which clang`" ]; then
+       CCC_CC="`which`clang"
+       CCC_CXX="`which clang++`"
+       CFLAGS="-fblocks ${CFLAGS}"
+elif [ "${COMPILER}" == "gcc" ] && [ ! -z "`which gcc`" ]; then
+       CCC_CC="`which gcc`"
+       CCC_CXX="`which g++`"
+       CFLAGS="${CFLAGS}"
+else
+       echo "Unknown compiler: $2, needs to be either clang or gcc"
+       exit
+fi
+
+if [ ! -f config.status ]; then
+       echo "Running ./configure ${CONFIGURE_FLAGS} ..."
+       ${SCANBUILD} ${SCANBUILD_FLAGS} -o ${OUTPUTDIR} ./configure ${CONFIGURE_FLAGS}
+       if [ $? != 0 ]; then
+               echo "Configure error occurred, see output / config.log"
+               exit
+       fi
+       make clean
+fi
+if [ -f config.status ]; then
+       echo "Running scan-build make ${MAKE_FLAGS} ..."
+       ${SCANBUILD} ${SCANBUILD_FLAGS} -o ${OUTPUTDIR} make ${MAKE_FLAGS}
+fi
index 1a97e90..1f4b375 100755 (executable)
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 """Process a ref debug log
 
- This file will process a log file created by the REF_DEBUG
- build option in Asterisk.
+ This file will process a log file created by enabling
+ the refdebug config option in asterisk.conf.
 
  See http://www.asterisk.org for more information about
  the Asterisk project. Please do not directly contact
index 27acdb3..e098ec0 100644 (file)
@@ -1 +1,2 @@
 core-en_US.xml
+rest-api
\ No newline at end of file
index 1c3c2e8..de35bb3 100644 (file)
@@ -141,31 +141,11 @@ list. However there is no ordering among elements.
 /*
 \note DEBUGGING REF COUNTS BIBLE:
 An interface to help debug refcounting is provided
-in this package. It is dependent on the REF_DEBUG macro being
-defined via menuselect and in using variants of the normal ao2_xxxx
-function that are named ao2_t_xxxx instead, with an extra argument,
-a string that will be printed out into the refs log file when the
-refcount for an object is changed.
-
-  these ao2_t_xxx variants are provided:
-
-ao2_t_alloc(arg1, arg2, arg3)
-ao2_t_ref(arg1,arg2,arg3)
-ao2_t_container_alloc(arg1,arg2,arg3,arg4)
-ao2_t_link(arg1, arg2, arg3)
-ao2_t_unlink(arg1, arg2, arg3)
-ao2_t_callback(arg1,arg2,arg3,arg4,arg5)
-ao2_t_find(arg1,arg2,arg3,arg4)
-ao2_t_iterator_next(arg1, arg2)
-
-If you study each argument list, you will see that these functions all have
-one extra argument than their ao2_xxx counterpart. The last argument in
-each case is supposed to be a string pointer, a "tag", that should contain
-enough of an explanation, that you can pair operations that increment the
-ref count, with operations that are meant to decrement the refcount.
-
-Each of these calls will generate at least one line of output in in the refs
-log files. These lines look like this:
+in this package. It is dependent on the refdebug being enabled in
+asterisk.conf.
+
+Each of the reference manipulations will generate one line of output in in the refs
+log file. These lines look like this:
 ...
 0x8756f00,+1,1234,chan_sip.c,22240,load_module,**constructor**,allocate users
 0x86e3408,+1,1234,chan_sip.c,22241,load_module,**constructor**,allocate peers
@@ -210,61 +190,29 @@ follows:
   context for the ref change. Note that any subsequent columns are
   considered to be part of this tag.
 
-Sometimes you have some helper functions to do object ref/unref
+Sometimes you have some helper functions to do object create/ref/unref
 operations. Using these normally hides the place where these
 functions were called. To get the location where these functions
-were called to appear in /refs, you can do this sort of thing:
+were called to appear in refs log, you can do this sort of thing:
 
-#ifdef REF_DEBUG
-#define dialog_ref(arg1,arg2) dialog_ref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define dialog_unref(arg1,arg2) dialog_unref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-static struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
-{
-       if (p) {
-               ao2_ref_debug(p, 1, tag, file, line, func);
-       } else {
-               ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
-       }
-       return p;
-}
+#define my_t_alloc(data,tag)  my_alloc_debug((data), tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define my_alloc(data)        my_t_alloc((data), "")
 
-static struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
-{
-       if (p) {
-               ao2_ref_debug(p, -1, tag, file, line, func);
-       }
-       return NULL;
-}
-#else
-static struct sip_pvt *dialog_ref(struct sip_pvt *p, const char *tag)
+static struct mydata *my_alloc_debug(void *data,
+       const char *tag, const char *file, int line, const char *func)
 {
-       if (p) {
-               ao2_ref(p, 1);
-       } else {
-               ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
-       }
-       return p;
-}
+       struct mydata *p;
 
-static struct sip_pvt *dialog_unref(struct sip_pvt *p, const char *tag)
-{
+       p = __ao2_alloc(sizeof(*p), NULL, AO2_ALLOC_OPT_LOCK_MUTEX, tag, file, line, func);
        if (p) {
-               ao2_ref(p, -1);
+               p->data = data;
        }
-       return NULL;
+       return p;
 }
-#endif
-
-In the above code, note that the "normal" helper funcs call ao2_ref() as
-normal, and the "helper" functions call ao2_ref_debug directly with the
-file, function, and line number info provided. You might find this
-well worth the effort to help track these function calls in the code.
 
 To find out why objects are not destroyed (a common bug), you can
-edit the source file to use the ao2_t_* variants, enable REF_DEBUG
-in menuselect, and add a descriptive tag to each call. Recompile,
-and run Asterisk, exit asterisk with "core stop gracefully", which should
-result in every object being destroyed.
+enable refdebug in asterisk.conf.  Run asterisk, exit with "core stop gracefully".
+This should result in every object being destroyed.
 
 Then, you can "sort -k 1 {AST_LOG_DIR}/refs > x1" to get a sorted list of
 all the objects, or you can use "contrib/script/refcounter.py" to scan
@@ -439,50 +387,23 @@ enum ao2_alloc_opts {
  * - the returned pointer cannot be free()'d or realloc()'ed;
  *   rather, we just call ao2_ref(o, -1);
  *
+ * \note refdebug logging is skipped if debug_msg is NULL
+ *
  * @{
  */
 
-#if defined(REF_DEBUG)
-
 #define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
-       __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+       __ao2_alloc((data_size), (destructor_fn), (options), (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_alloc_options(data_size, destructor_fn, options) \
-       __ao2_alloc_debug((data_size), (destructor_fn), (options), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+       __ao2_alloc((data_size), (destructor_fn), (options), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 #define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
-       __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+       __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_alloc(data_size, destructor_fn) \
-       __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+       __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
-       __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_alloc_options(data_size, destructor_fn, options) \
-       __ao2_alloc_debug((data_size), (destructor_fn), (options), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
-       __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_alloc(data_size, destructor_fn) \
-       __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
-       __ao2_alloc((data_size), (destructor_fn), (options))
-#define ao2_alloc_options(data_size, destructor_fn, options) \
-       __ao2_alloc((data_size), (destructor_fn), (options))
-
-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
-       __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX)
-#define ao2_alloc(data_size, destructor_fn) \
-       __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX)
-
-#endif
-
-void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
-       const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result;
-void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options) attribute_warn_unused_result;
+void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
 /*! @} */
 
@@ -507,20 +428,12 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in
  * can go away is when we release our reference, and it is
  * the last one in existence.
  *
+ * \note refdebug logging is skipped if tag is NULL
  * @{
  */
 
-#ifdef REF_DEBUG
-
-#define ao2_t_ref(o,delta,tag) __ao2_ref_debug((o), (delta), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_ref(o,delta)       __ao2_ref_debug((o), (delta), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
-
-#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta))
-#define ao2_ref(o,delta)       __ao2_ref((o), (delta))
-
-#endif
+#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_ref(o,delta)       __ao2_ref((o), (delta), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Retrieve the ao2 options used to create the object.
@@ -550,8 +463,7 @@ unsigned int ao2_options_get(void *obj);
 #define ao2_bump(obj) \
        ao2_t_bump((obj), "")
 
-int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *func);
-int __ao2_ref(void *o, int delta);
+int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func);
 
 /*!
  * \since 12.4.0
@@ -848,20 +760,11 @@ struct ao2_global_obj {
  *
  * \return Nothing
  */
-#ifdef REF_DEBUG
 #define ao2_t_global_obj_release(holder, tag)  \
        __ao2_global_obj_release(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 #define ao2_global_obj_release(holder) \
        __ao2_global_obj_release(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 
-#else
-
-#define ao2_t_global_obj_release(holder, tag)  \
-       __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_release(holder) \
-       __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
-
 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name);
 
 /*!
@@ -879,20 +782,11 @@ void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, co
  * \retval Reference to previous global ao2 object stored.
  * \retval NULL if no object available.
  */
-#ifdef REF_DEBUG
 #define ao2_t_global_obj_replace(holder, obj, tag)     \
        __ao2_global_obj_replace(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 #define ao2_global_obj_replace(holder, obj)    \
        __ao2_global_obj_replace(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 
-#else
-
-#define ao2_t_global_obj_replace(holder, obj, tag)     \
-       __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_replace(holder, obj)    \
-       __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
-
 void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result;
 
 /*!
@@ -911,20 +805,11 @@ void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const c
  * \retval 0 The global object was previously empty
  * \retval 1 The global object was not previously empty
  */
-#ifdef REF_DEBUG
 #define ao2_t_global_obj_replace_unref(holder, obj, tag)       \
        __ao2_global_obj_replace_unref(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 #define ao2_global_obj_replace_unref(holder, obj)      \
        __ao2_global_obj_replace_unref(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 
-#else
-
-#define ao2_t_global_obj_replace_unref(holder, obj, tag)       \
-       __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_replace_unref(holder, obj)      \
-       __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
-
 int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name);
 
 /*!
@@ -937,20 +822,11 @@ int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, con
  * \retval Reference to current ao2 object stored in the holder.
  * \retval NULL if no object available.
  */
-#ifdef REF_DEBUG
 #define ao2_t_global_obj_ref(holder, tag)      \
        __ao2_global_obj_ref(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 #define ao2_global_obj_ref(holder)     \
        __ao2_global_obj_ref(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
 
-#else
-
-#define ao2_t_global_obj_ref(holder, tag)      \
-       __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_ref(holder)     \
-       __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
-
 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result;
 
 
@@ -1372,36 +1248,15 @@ struct ao2_container;
  * \note Destructor is set implicitly.
  */
 
-#if defined(REF_DEBUG)
-
-#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
-       __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
-       __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
 #define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn))
+       __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
-       __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn))
-
-#endif
+       __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options,
        unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
-       ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result;
-struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
-       unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
        ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result;
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
 /*!
  * \brief Allocate and initialize a list container.
@@ -1418,34 +1273,14 @@ struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
  * \note Implemented as a degenerate hash table.
  */
 
-#if defined(REF_DEBUG)
-
-#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
 #define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
+       __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn))
-#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn))
-
-#endif
+       __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 struct ao2_container *__ao2_container_alloc_list(unsigned int ao2_options,
-       unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result;
-struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options,
        unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result;
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
 /*!
  * \brief Allocate and initialize a red-black tree container.
@@ -1461,34 +1296,14 @@ struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options,
  * \note Destructor is set implicitly.
  */
 
-#if defined(REF_DEBUG)
-
-#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
 #define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
-       __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
+       __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
-       __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
-
-#endif
+       __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options,
-       ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result;
-struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options,
        ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result;
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
 /*! \brief
  * Returns the number of elements in a container.
@@ -1528,24 +1343,13 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
  * \retval Clone container on success.
  * \retval NULL on error.
  */
-struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags) attribute_warn_unused_result;
-struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result;
-#if defined(REF_DEBUG)
-
-#define ao2_t_container_clone(orig, flags, tag)        __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-#define ao2_container_clone(orig, flags)               __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_clone(orig, flags, tag)        __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_clone(orig, flags)               __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_clone(orig, flags, tag)        __ao2_container_clone(orig, flags)
-#define ao2_container_clone(orig, flags)               __ao2_container_clone(orig, flags)
+struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags,
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
-#endif
+#define ao2_t_container_clone(orig, flags, tag) \
+       __ao2_container_clone(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_container_clone(orig, flags) \
+       __ao2_container_clone(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Print output.
@@ -1661,10 +1465,10 @@ void ao2_container_unregister(const char *name);
  * \note This function automatically increases the reference count to account
  *       for the reference that the container now holds to the object.
  */
-#ifdef REF_DEBUG
-
-#define ao2_t_link(container, obj, tag)                                        __ao2_link_debug((container), (obj), 0, (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_link(container, obj)                                               __ao2_link_debug((container), (obj), 0, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_link(container, obj, tag) \
+       __ao2_link((container), (obj), 0, (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_link(container, obj) \
+       __ao2_link((container), (obj), 0, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Add an object to a container.
@@ -1684,21 +1488,13 @@ void ao2_container_unregister(const char *name);
  * \note This function automatically increases the reference count to account
  *       for the reference that the container now holds to the object.
  */
-#define ao2_t_link_flags(container, obj, flags, tag)   __ao2_link_debug((container), (obj), (flags), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_link_flags(container, obj, flags)                  __ao2_link_debug((container), (obj), (flags), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
+#define ao2_t_link_flags(container, obj, flags, tag) \
+       __ao2_link((container), (obj), (flags), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_link_flags(container, obj, flags) \
+       __ao2_link((container), (obj), (flags), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-#define ao2_t_link(container, obj, tag)                                        __ao2_link((container), (obj), 0)
-#define ao2_link(container, obj)                                               __ao2_link((container), (obj), 0)
-
-#define ao2_t_link_flags(container, obj, flags, tag)   __ao2_link((container), (obj), (flags))
-#define ao2_link_flags(container, obj, flags)                  __ao2_link((container), (obj), (flags))
-
-#endif
-
-int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func);
-int __ao2_link(struct ao2_container *c, void *obj_new, int flags);
+int __ao2_link(struct ao2_container *c, void *obj_new, int flags,
+       const char *tag, const char *file, int line, const char *func);
 
 /*!
  * \brief Remove an object from a container
@@ -1717,10 +1513,11 @@ int __ao2_link(struct ao2_container *c, void *obj_new, int flags);
  *       reference to the object will be automatically released. (The
  *       refcount will be decremented).
  */
-#ifdef REF_DEBUG
 
-#define ao2_t_unlink(container, obj, tag)                              __ao2_unlink_debug((container), (obj), 0, (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_unlink(container, obj)                                             __ao2_unlink_debug((container), (obj), 0, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_unlink(container, obj, tag) \
+       __ao2_unlink((container), (obj), 0, (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_unlink(container, obj) \
+       __ao2_unlink((container), (obj), 0, "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Remove an object from a container
@@ -1741,25 +1538,17 @@ int __ao2_link(struct ao2_container *c, void *obj_new, int flags);
  *       refcount will be decremented).
  */
 
-#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink_debug((container), (obj), (flags), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_unlink_flags(container, obj, flags)                        __ao2_unlink_debug((container), (obj), (flags), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
-
-#define ao2_t_unlink(container, obj, tag)                              __ao2_unlink((container), (obj), 0)
-#define ao2_unlink(container, obj)                                             __ao2_unlink((container), (obj), 0)
-
-#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink((container), (obj), (flags))
-#define ao2_unlink_flags(container, obj, flags)                        __ao2_unlink((container), (obj), (flags))
-
-#endif
-
-void *__ao2_unlink_debug(struct ao2_container *c, void *obj, int flags, const char *tag, const char *file, int line, const char *func);
-void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
+#define ao2_t_unlink_flags(container, obj, flags, tag) \
+       __ao2_unlink((container), (obj), (flags), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_unlink_flags(container, obj, flags) \
+       __ao2_unlink((container), (obj), (flags), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
+void *__ao2_unlink(struct ao2_container *c, void *obj, int flags,
+       const char *tag, const char *file, int line, const char *func);
 
 /*@} */
 
+
 /*! \brief
  * ao2_callback() is a generic function that applies cb_fn() to all objects
  * in a container, as described below.
@@ -1842,26 +1631,15 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
  *
  * @{
  */
-#ifdef REF_DEBUG
 
 #define ao2_t_callback(c, flags, cb_fn, arg, tag) \
-       __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ao2_callback((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_callback(c, flags, cb_fn, arg) \
-       __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
+       __ao2_callback((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-#define ao2_t_callback(c, flags, cb_fn, arg, tag) \
-       __ao2_callback((c), (flags), (cb_fn), (arg))
-#define ao2_callback(c, flags, cb_fn, arg) \
-       __ao2_callback((c), (flags), (cb_fn), (arg))
-
-#endif
-
-void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
        ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
        const char *func);
-void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg);
 
 /*! @} */
 
@@ -1880,50 +1658,27 @@ void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callb
  *
  * \see ao2_callback()
  */
-#ifdef REF_DEBUG
-
-#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
-       __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_callback_data(container, flags, cb_fn, arg, data) \
-       __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
 
 #define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
-       __ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
+       __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_callback_data(container, flags, cb_fn, arg, data) \
-       __ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
+       __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-#endif
-
-void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
        ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
        int line, const char *func);
-void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
-       ao2_callback_data_fn *cb_fn, void *arg, void *data);
 
 /*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg)
  * XXX possibly change order of arguments ?
  */
-#ifdef REF_DEBUG
-
-#define ao2_t_find(container, arg, flags, tag) \
-       __ao2_find_debug((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_find(container, arg, flags) \
-       __ao2_find_debug((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
 
 #define ao2_t_find(container, arg, flags, tag) \
-       __ao2_find((container), (arg), (flags))
+       __ao2_find((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_find(container, arg, flags) \
-       __ao2_find((container), (arg), (flags))
-
-#endif
+       __ao2_find((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags,
        const char *tag, const char *file, int line, const char *func);
-void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags);
 
 /*! \brief
  *
@@ -2083,20 +1838,13 @@ void ao2_iterator_destroy(struct ao2_iterator *iter) __attribute__((noinline));
 void ao2_iterator_destroy(struct ao2_iterator *iter);
 #endif /* defined(TEST_FRAMEWORK) */
 
-#ifdef REF_DEBUG
-
-#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next_debug((iter), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_iterator_next(iter)        __ao2_iterator_next_debug((iter), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
-
-#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next((iter))
-#define ao2_iterator_next(iter)        __ao2_iterator_next((iter))
+#define ao2_t_iterator_next(iter, tag) \
+       __ao2_iterator_next((iter), (tag),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_iterator_next(iter) \
+       __ao2_iterator_next((iter), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-#endif
-
-void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
-void *__ao2_iterator_next(struct ao2_iterator *iter) attribute_warn_unused_result;
+void *__ao2_iterator_next(struct ao2_iterator *iter,
+       const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
 
 /*!
  * \brief Restart an iteration.
@@ -2117,13 +1865,8 @@ void ao2_iterator_restart(struct ao2_iterator *iter);
  * down a NULL */
 void __ao2_cleanup(void *obj);
 void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function);
-#ifdef REF_DEBUG
 #define ao2_cleanup(obj) __ao2_cleanup_debug((obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_t_cleanup(obj, tag) __ao2_cleanup_debug((obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ao2_cleanup(obj) __ao2_cleanup(obj)
-#define ao2_t_cleanup(obj, tag) __ao2_cleanup((obj))
-#endif
 void ao2_iterator_cleanup(struct ao2_iterator *iter);
 
 /*!
index 82abe99..aec7f75 100644 (file)
@@ -1186,8 +1186,6 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16)))
        __ast_channel_alloc((needqueue), (state), (cid_num), (cid_name), (acctcode), (exten), (context), (assignedids), (requestor), (amaflag), (endpoint), \
                __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
 
-
-#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
 /*!
  * \brief Create a fake channel structure
  *
@@ -1206,25 +1204,6 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16)))
  */
 #define ast_dummy_channel_alloc()      __ast_dummy_channel_alloc(__FILE__, __LINE__, __PRETTY_FUNCTION__)
 struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function);
-#else
-/*!
- * \brief Create a fake channel structure
- *
- * \retval NULL failure
- * \retval non-NULL successfully allocated channel
- *
- * \note This function should ONLY be used to create a fake channel
- *       that can then be populated with data for use in variable
- *       substitution when a real channel does not exist.
- *
- * \note The created dummy channel should be destroyed by
- * ast_channel_unref().  Using ast_channel_release() needlessly
- * grabs the channel container lock and can cause a deadlock as
- * a result.  Also grabbing the channel container lock reduces
- * system performance.
- */
-struct ast_channel *ast_dummy_channel_alloc(void);
-#endif
 
 /*!
  * \brief Queue one or more frames to a channel's frame queue
index 9f4e06a..64e53b9 100644 (file)
@@ -252,20 +252,13 @@ int ast_format_cache_set(struct ast_format *format);
  * \note The returned format has its reference count incremented. It must be
  * dropped using ao2_ref or ao2_cleanup.
  */
-struct ast_format *__ast_format_cache_get(const char *name);
-struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func);
+struct ast_format *__ast_format_cache_get(const char *name,
+       const char *tag, const char *file, int line, const char *func);
 
-#ifdef REF_DEBUG
 #define ast_format_cache_get(name) \
-       __ast_format_cache_get_debug((name), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_format_cache_get((name), "ast_format_cache_get", __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ast_t_format_cache_get(name, tag) \
-       __ast_format_cache_get_debug((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ast_format_cache_get(name) \
-       __ast_format_cache_get((name))
-#define ast_t_format_cache_get(name, tag) \
-       __ast_format_cache_get((name))
-#endif
+       __ast_format_cache_get((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 
 /*!
index 94e81f8..e422cc6 100644 (file)
@@ -46,20 +46,14 @@ enum ast_format_cap_flags {
  * \retval ast_format_cap object on success.
  * \retval NULL on failure.
  */
-struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags);
-struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func);
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags,
+       const char *tag, const char *file, int line, const char *func);
 
-#ifdef REF_DEBUG
 #define ast_format_cap_alloc(flags) \
-       __ast_format_cap_alloc_debug((flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_format_cap_alloc((flags), "ast_format_cap_alloc", \
+               __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ast_t_format_cap_alloc(flags, tag) \
-       __ast_format_cap_alloc_debug((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ast_format_cap_alloc(flags) \
-       __ast_format_cap_alloc((flags))
-#define ast_t_format_cap_alloc(flags, tag) \
-       __ast_format_cap_alloc((flags))
-#endif
+       __ast_format_cap_alloc((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Set the global framing.
@@ -103,20 +97,15 @@ unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap);
  *
  * \note If framing is specified here it overrides any global framing that has been set.
  */
-int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing);
-int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func);
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing,
+       const char *tag, const char *file, int line, const char *func);
 
-#ifdef REF_DEBUG
-#define ast_format_cap_append(cap, format, framing) \
-       __ast_format_cap_append_debug((cap), (format), (framing), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ast_t_format_cap_append(cap, format, framing, tag) \
-       __ast_format_cap_append_debug((cap), (format), (framing), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
 #define ast_format_cap_append(cap, format, framing) \
-       __ast_format_cap_append((cap), (format), (framing))
+       __ast_format_cap_append((cap), (format), (framing), "ast_format_cap_append", \
+               __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ast_t_format_cap_append(cap, format, framing, tag) \
-       __ast_format_cap_append((cap), (format), (framing))
-#endif
+       __ast_format_cap_append((cap), (format), (framing), (tag), \
+               __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief Add all codecs Asterisk knows about for a specific type to
index 0da5799..a08b863 100644 (file)
@@ -76,6 +76,8 @@ enum ast_option_flags {
        AST_OPT_FLAG_DONT_WARN = (1 << 18),
        /*! End CDRs before the 'h' extension */
        AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),
+       /*! Reference Debugging */
+       AST_OPT_FLAG_REF_DEBUG = (1 << 20),
        /*! Always fork, even if verbose or debug settings are non-zero */
        AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
        /*! Disable log/verbose output to remote consoles */
@@ -131,6 +133,7 @@ enum ast_option_flags {
 #define ast_opt_hide_connect           ast_test_flag(&ast_options, AST_OPT_FLAG_HIDE_CONSOLE_CONNECT)
 #define ast_opt_lock_confdir           ast_test_flag(&ast_options, AST_OPT_FLAG_LOCK_CONFIG_DIR)
 #define ast_opt_generic_plc         ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC)
+#define ast_opt_ref_debug           ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG)
 
 extern struct ast_flags ast_options;
 
index 574451c..86a190b 100644 (file)
@@ -3424,6 +3424,12 @@ static void ast_readconfig(void)
        ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
        ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
 
+#ifdef REF_DEBUG
+       /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
+        * Support for debugging reference counts is always compiled in. */
+       ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
+#endif
+
        ast_set_default_eid(&ast_eid_default);
 
        /* no asterisk.conf? no problem, use buildtime config! */
@@ -3494,6 +3500,8 @@ static void ast_readconfig(void)
                        if (sscanf(v->value, "%30d", &option_debug) != 1) {
                                option_debug = ast_true(v->value);
                        }
+               } else if (!strcasecmp(v->name, "refdebug")) {
+                       ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
 #if HAVE_WORKING_FORK
                /* Disable forking (-f at startup) */
                } else if (!strcasecmp(v->name, "nofork")) {
index edf1e95..c5b5cd9 100644 (file)
@@ -118,52 +118,73 @@ struct ao2_stats ao2;
 #define INTERNAL_OBJ_RWLOCK(user_data) \
        ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
 
+#define INTERNAL_OBJ(user_data) \
+       (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
+
 /*!
  * \brief convert from a pointer _p to a user-defined object
  *
  * \return the pointer to the astobj2 structure
  */
-static struct astobj2 *INTERNAL_OBJ(void *user_data)
+#define __INTERNAL_OBJ_CHECK(user_data, file, line, func) \
+       ({ \
+               struct astobj2 *p ## __LINE__; \
+               if (!user_data \
+                       || !(p ## __LINE__ = INTERNAL_OBJ(user_data)) \
+                       || IS_AO2_MAGIC_BAD(p ## __LINE__)) { \
+                       log_bad_ao2(user_data, file, line, func); \
+                       p ## __LINE__ = NULL; \
+               } \
+               (p ## __LINE__); \
+       })
+
+#define INTERNAL_OBJ_CHECK(user_data) \
+       __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \brief convert from a pointer _p to an astobj2 object
+ *
+ * \return the pointer to the user-defined portion.
+ */
+#define EXTERNAL_OBJ(_p)       ((_p) == NULL ? NULL : (_p)->user_data)
+
+int internal_is_ao2_object(void *user_data)
 {
        struct astobj2 *p;
 
        if (!user_data) {
-               ast_log(LOG_ERROR, "user_data is NULL\n");
-               return NULL;
+               return 0;
        }
 
-       p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
-       if (IS_AO2_MAGIC_BAD(p)) {
-               if (p->priv_data.magic) {
-                       ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
-                               p->priv_data.magic, user_data);
-               } else {
-                       ast_log(LOG_ERROR,
-                               "bad magic number for object %p. Object is likely destroyed.\n",
-                               user_data);
-               }
-               ast_assert(0);
-               return NULL;
-       }
+       p = INTERNAL_OBJ(user_data);
 
-       return p;
+       return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
 }
 
-/*!
- * \brief convert from a pointer _p to an astobj2 object
- *
- * \return the pointer to the user-defined portion.
- */
-#define EXTERNAL_OBJ(_p)       ((_p) == NULL ? NULL : (_p)->user_data)
-
-int is_ao2_object(void *user_data)
+void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
 {
-       return (INTERNAL_OBJ(user_data) != NULL);
+       struct astobj2 *p;
+
+       if (!user_data) {
+               ast_log(__LOG_ERROR, file, line, func, "user_data is NULL\n");
+               return;
+       }
+
+       p = INTERNAL_OBJ(user_data);
+       if (p->priv_data.magic) {
+               ast_log(__LOG_ERROR, file, line, func,
+                       "bad magic number 0x%x for object %p\n",
+                       p->priv_data.magic, user_data);
+       } else {
+               ast_log(__LOG_ERROR, file, line, func,
+                       "bad magic number for object %p. Object is likely destroyed.\n",
+                       user_data);
+       }
 }
 
 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 {
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
+       struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
        struct astobj2_lock *obj_mutex;
        struct astobj2_rwlock *obj_rwlock;
        int res = 0;
@@ -221,7 +242,7 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co
 
 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
 {
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
+       struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
        struct astobj2_lock *obj_mutex;
        struct astobj2_rwlock *obj_rwlock;
        int res = 0;
@@ -271,7 +292,7 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line,
 
 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 {
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
+       struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
        struct astobj2_lock *obj_mutex;
        struct astobj2_rwlock *obj_rwlock;
        int res = 0;
@@ -393,9 +414,11 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int
 
 void *ao2_object_get_lockaddr(void *user_data)
 {
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
+       struct astobj2 *obj;
        struct astobj2_lock *obj_mutex;
 
+       obj = INTERNAL_OBJ_CHECK(user_data);
+
        if (obj == NULL) {
                ast_assert(0);
                return NULL;
@@ -412,9 +435,10 @@ void *ao2_object_get_lockaddr(void *user_data)
        return NULL;
 }
 
-static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
+int __ao2_ref(void *user_data, int delta,
+       const char *tag, const char *file, int line, const char *func)
 {
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
+       struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
        struct astobj2_lock *obj_mutex;
        struct astobj2_rwlock *obj_rwlock;
        int current_value;
@@ -422,6 +446,11 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
        void *weakproxy = NULL;
 
        if (obj == NULL) {
+               if (ref_log && user_data) {
+                       fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
+                               user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
+                       fflush(ref_log);
+               }
                ast_assert(0);
                return -1;
        }
@@ -446,7 +475,9 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
        if (weakproxy) {
                if (current_value == 1) {
                        /* The only remaining reference is the one owned by the weak object */
-                       struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy);
+                       struct astobj2 *internal_weakproxy;
+
+                       internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
 
                        /* Unlink the obj from the weak proxy */
                        internal_weakproxy->priv_data.weakptr = NULL;
@@ -468,6 +499,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
 
        if (0 < current_value) {
                /* The object still lives. */
+               if (ref_log && tag) {
+                       fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
+                               (delta < 0 ? "" : "+"), delta, ast_get_tid(),
+                               file, line, func, ret, tag);
+                       fflush(ref_log);
+               }
                return ret;
        }
 
@@ -475,6 +512,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
        if (current_value < 0) {
                ast_log(__LOG_ERROR, file, line, func,
                        "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
+               if (ref_log) {
+                       /* Log to ref_log invalid even if (tag == NULL) */
+                       fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
+                               user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
+                       fflush(ref_log);
+               }
                ast_assert(0);
                /* stop here even if assert doesn't DO_CRASH */
                return -1;
@@ -515,51 +558,19 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
                break;
        }
 
-       return ret;
-}
-
-int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
-{
-       struct astobj2 *obj = INTERNAL_OBJ(user_data);
-       int old_refcount = -1;
-
-       if (obj) {
-               old_refcount = internal_ao2_ref(user_data, delta, file, line, func);
-       }
-
-       if (ref_log && user_data) {
-               if (!obj) {
-                       /* Invalid object: Bad magic number. */
-                       fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
-                               user_data, delta, ast_get_tid(), file, line, func, tag);
-                       fflush(ref_log);
-               } else if (old_refcount + delta == 0) {
-                       fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
-                               user_data, delta, ast_get_tid(), file, line, func, tag);
-                       fflush(ref_log);
-               } else if (delta != 0) {
-                       fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
-                               delta, ast_get_tid(), file, line, func, old_refcount, tag);
-                       fflush(ref_log);
-               }
-       }
-
-       if (obj == NULL) {
-               ast_assert(0);
+       if (ref_log && tag) {
+               fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
+                       user_data, delta, ast_get_tid(), file, line, func, tag);
+               fflush(ref_log);
        }
 
-       return old_refcount;
-}
-
-int __ao2_ref(void *user_data, int delta)
-{
-       return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
+       return ret;
 }
 
 void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function)
 {
        if (obj) {
-               __ao2_ref_debug(obj, -1, tag, file, line, function);
+               __ao2_ref(obj, -1, tag, file, line, function);
        }
 }
 
@@ -570,7 +581,8 @@ void __ao2_cleanup(void *obj)
        }
 }
 
-static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *func)
+void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
+       const char *tag, const char *file, int line, const char *func)
 {
        /* allocation */
        struct astobj2 *obj;
@@ -633,43 +645,27 @@ static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_f
        ast_atomic_fetchadd_int(&ao2.total_refs, 1);
 #endif
 
+       if (ref_log && tag) {
+               fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n",
+                       EXTERNAL_OBJ(obj), ast_get_tid(), file, line, func, tag);
+               fflush(ref_log);
+       }
+
        /* return a pointer to the user data */
        return EXTERNAL_OBJ(obj);
 }
 
 unsigned int ao2_options_get(void *obj)
 {
-       struct astobj2 *orig_obj = INTERNAL_OBJ(obj);
+       struct astobj2 *orig_obj;
+
+       orig_obj = INTERNAL_OBJ_CHECK(obj);
        if (!orig_obj) {
                return 0;
        }
        return orig_obj->priv_data.options;
 }
 
-void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
-       const char *file, int line, const char *func, int ref_debug)
-{
-       /* allocation */
-       void *obj;
-
-       if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
-               return NULL;
-       }
-
-       if (ref_log) {
-               fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, func, tag);
-               fflush(ref_log);
-       }
-
-       /* return a pointer to the user data */
-       return obj;
-}
-
-void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
-{
-       return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
-}
-
 
 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
 {
@@ -687,11 +683,7 @@ void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, co
 
        /* Release the held ao2 object. */
        if (holder->obj) {
-               if (tag) {
-                       __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
-               } else {
-                       __ao2_ref(holder->obj, -1);
-               }
+               __ao2_ref(holder->obj, -1, tag, file, line, func);
                holder->obj = NULL;
        }
 
@@ -715,11 +707,7 @@ void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const c
        }
 
        if (obj) {
-               if (tag) {
-                       __ao2_ref_debug(obj, +1, tag, file, line, func);
-               } else {
-                       __ao2_ref(obj, +1);
-               }
+               __ao2_ref(obj, +1, tag, file, line, func);
        }
        obj_old = holder->obj;
        holder->obj = obj;
@@ -735,11 +723,7 @@ int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, con
 
        obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
        if (obj_old) {
-               if (tag) {
-                       __ao2_ref_debug(obj_old, -1, tag, file, line, func);
-               } else {
-                       __ao2_ref(obj_old, -1);
-               }
+               __ao2_ref(obj_old, -1, tag, file, line, func);
                return 1;
        }
        return 0;
@@ -764,11 +748,7 @@ void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const
 
        obj = holder->obj;
        if (obj) {
-               if (tag) {
-                       __ao2_ref_debug(obj, +1, tag, file, line, func);
-               } else {
-                       __ao2_ref(obj, +1);
-               }
+               __ao2_ref(obj, +1, tag, file, line, func);
        }
 
        __ast_rwlock_unlock(file, line, func, &holder->lock, name);
@@ -798,12 +778,14 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
                return NULL;
        }
 
-       weakproxy = __ao2_alloc_debug(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
-               tag, file, line, func, 1);
+       weakproxy = __ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
+               tag, file, line, func);
 
        if (weakproxy) {
-               struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
+               struct astobj2 *weakproxy_internal;
 
+               /* Just created weakproxy, no need to check if it's valid. */
+               weakproxy_internal = INTERNAL_OBJ(weakproxy);
                weakproxy_internal->priv_data.magic = AO2_WEAK;
        }
 
@@ -813,8 +795,8 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
 int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
        const char *tag, const char *file, int line, const char *func)
 {
-       struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
-       struct astobj2 *obj_internal = INTERNAL_OBJ(obj);
+       struct astobj2 *weakproxy_internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
+       struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
        int ret = -1;
 
        if (!weakproxy_internal
@@ -833,8 +815,8 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
        }
 
        if (!weakproxy_internal->priv_data.weakptr) {
-               __ao2_ref_debug(obj, +1, tag, file, line, func);
-               __ao2_ref_debug(weakproxy, +1, tag, file, line, func);
+               __ao2_ref(obj, +1, tag, file, line, func);
+               __ao2_ref(weakproxy, +1, tag, file, line, func);
 
                weakproxy_internal->priv_data.weakptr = obj;
                obj_internal->priv_data.weakptr = weakproxy;
@@ -857,7 +839,7 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
 void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
        const char *tag, const char *file, int line, const char *func)
 {
-       struct astobj2 *internal = INTERNAL_OBJ(weakproxy);
+       struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
        void *obj;
 
        if (!internal || internal->priv_data.magic != AO2_WEAK) {
@@ -872,7 +854,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
 
        obj = internal->priv_data.weakptr;
        if (obj) {
-               __ao2_ref_debug(obj, +1, tag, file, line, func);
+               __ao2_ref(obj, +1, tag, file, line, func);
        }
 
        if (!(flags & OBJ_NOLOCK)) {
@@ -884,7 +866,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
 
 void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func)
 {
-       struct astobj2 *obj_internal = INTERNAL_OBJ(obj);
+       struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
 
        if (!obj_internal || obj_internal->priv_data.magic != AO2_MAGIC) {
                /* This method is meant to be run on normal ao2 objects! */
@@ -895,13 +877,13 @@ void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line
                return NULL;
        }
 
-       __ao2_ref_debug(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
+       __ao2_ref(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
        return obj_internal->priv_data.weakptr;
 }
 
 int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
 {
-       struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
+       struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy);
        int ret = -1;
 
        if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) {
@@ -936,7 +918,7 @@ int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, v
 
 int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
 {
-       struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy);
+       struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
        struct ao2_weakproxy *weak;
        struct ao2_weakproxy_notification *sub;
        int ret = 0;
@@ -1123,29 +1105,28 @@ static void astobj2_cleanup(void)
 #if defined(AO2_DEBUG)
        ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
 #endif
-#ifdef REF_DEBUG
-       fclose(ref_log);
-       ref_log = NULL;
-#endif
+
+       if (ast_opt_ref_debug) {
+               fclose(ref_log);
+               ref_log = NULL;
+       }
 }
 
 int astobj2_init(void)
 {
-#ifdef REF_DEBUG
        char ref_filename[1024];
-#endif
 
        if (container_init() != 0) {
                return -1;
        }
 
-#ifdef REF_DEBUG
-       snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
-       ref_log = fopen(ref_filename, "w");
-       if (!ref_log) {
-               ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
+       if (ast_opt_ref_debug) {
+               snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
+               ref_log = fopen(ref_filename, "w");
+               if (!ref_log) {
+                       ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
+               }
        }
-#endif
 
 #if defined(AO2_DEBUG)
        ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
index 07d10b9..c00da9f 100644 (file)
@@ -49,11 +49,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
 
        if ((flags & AO2_UNLINK_NODE_UNLINK_OBJECT)
                && !(flags & AO2_UNLINK_NODE_NOUNREF_OBJECT)) {
-               if (tag) {
-                       __ao2_ref_debug(node->obj, -1, tag, file, line, func);
-               } else {
-                       ao2_t_ref(node->obj, -1, "Remove obj from container");
-               }
+               __ao2_ref(node->obj, -1, tag ?: "Remove obj from container", file, line, func);
        }
 
        node->obj = NULL;
@@ -76,7 +72,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
 
        if (flags & AO2_UNLINK_NODE_UNREF_NODE) {
                /* Remove node from container */
-               __ao2_ref(node, -1);
+               ao2_t_ref(node, -1, NULL);
        }
 
        return 1;
@@ -97,13 +93,15 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
  * \retval 0 on errors.
  * \retval 1 on success.
  */
-static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
+int __ao2_link(struct ao2_container *self, void *obj_new, int flags,
+       const char *tag, const char *file, int line, const char *func)
 {
        int res;
        enum ao2_lock_req orig_lock;
        struct ao2_container_node *node;
 
-       if (!is_ao2_object(obj_new) || !is_ao2_object(self)
+       if (!__is_ao2_object(obj_new, file, line, func)
+               || !__is_ao2_object(self, file, line, func)
                || !self->v_table || !self->v_table->new_node || !self->v_table->insert) {
                /* Sanity checks. */
                ast_assert(0);
@@ -147,7 +145,7 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag
                        res = 1;
                        break;
                case AO2_CONTAINER_INSERT_NODE_REJECTED:
-                       __ao2_ref(node, -1);
+                       ao2_t_ref(node, -1, NULL);
                        break;
                }
        }
@@ -161,16 +159,6 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag
        return res;
 }
 
-int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
-{
-       return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
-}
-
-int __ao2_link(struct ao2_container *c, void *obj_new, int flags)
-{
-       return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
 /*!
  * \brief another convenience function is a callback that matches on address
  */
@@ -183,10 +171,10 @@ int ao2_match_by_addr(void *user_data, void *arg, int flags)
  * Unlink an object from the container
  * and destroy the associated * bucket_entry structure.
  */
-void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
+void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags,
        const char *tag, const char *file, int line, const char *func)
 {
-       if (!is_ao2_object(user_data)) {
+       if (!__is_ao2_object(user_data, file, line, func)) {
                /* Sanity checks. */
                ast_assert(0);
                return NULL;
@@ -194,22 +182,7 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
 
        flags &= ~OBJ_SEARCH_MASK;
        flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
-       __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
-
-       return NULL;
-}
-
-void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
-{
-       if (!is_ao2_object(user_data)) {
-               /* Sanity checks. */
-               ast_assert(0);
-               return NULL;
-       }
-
-       flags &= ~OBJ_SEARCH_MASK;
-       flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
-       __ao2_callback(c, flags, ao2_match_by_addr, user_data);
+       __ao2_callback(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
 
        return NULL;
 }
@@ -268,8 +241,8 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
        struct ao2_container *multi_container = NULL;
        struct ao2_iterator *multi_iterator = NULL;
 
-       if (!is_ao2_object(self) || !self->v_table || !self->v_table->traverse_first
-               || !self->v_table->traverse_next) {
+       if (!__is_ao2_object(self, file, line, func) || !self->v_table
+               || !self->v_table->traverse_first || !self->v_table->traverse_next) {
                /* Sanity checks. */
                ast_assert(0);
                return NULL;
@@ -376,12 +349,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
                                         * Link the object into the container that will hold the
                                         * results.
                                         */
-                                       if (tag) {
-                                               __ao2_link_debug(multi_container, node->obj, flags,
-                                                       tag, file, line, func);
-                                       } else {
-                                               __ao2_link(multi_container, node->obj, flags);
-                                       }
+                                       __ao2_link(multi_container, node->obj, flags, tag, file, line, func);
                                } else {
                                        ret = node->obj;
                                        /* Returning a single object. */
@@ -390,11 +358,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
                                                 * Bump the ref count since we are not going to unlink and
                                                 * transfer the container's object ref to the returned object.
                                                 */
-                                               if (tag) {
-                                                       __ao2_ref_debug(ret, 1, tag, file, line, func);
-                                               } else {
-                                                       ao2_t_ref(ret, 1, "Traversal found object");
-                                               }
+                                               __ao2_ref(ret, 1, tag ?: "Traversal found object", file, line, func);
                                        }
                                }
                        }
@@ -418,7 +382,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
        }
        if (node) {
                /* Unref the node from self->v_table->traverse_first/traverse_next() */
-               __ao2_ref(node, -1);
+               ao2_t_ref(node, -1, NULL);
        }
 
        if (flags & OBJ_NOLOCK) {
@@ -439,36 +403,24 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
        }
 }
 
-void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
        ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
        const char *func)
 {
        return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func);
 }
 
-void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
-       ao2_callback_fn *cb_fn, void *arg)
-{
-       return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, NULL, NULL, 0, NULL);
-}
-
-void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
        ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
        int line, const char *func)
 {
        return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func);
 }
 
-void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
-       ao2_callback_data_fn *cb_fn, void *arg, void *data)
-{
-       return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, NULL, NULL, 0, NULL);
-}
-
 /*!
  * the find function just invokes the default callback with some reasonable flags.
  */
-void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags,
        const char *tag, const char *file, int line, const char *func)
 {
        void *arged = (void *) arg;/* Done to avoid compiler const warning */
@@ -478,19 +430,7 @@ void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_fla
                ast_assert(0);
                return NULL;
        }
-       return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
-}
-
-void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
-{
-       void *arged = (void *) arg;/* Done to avoid compiler const warning */
-
-       if (!c) {
-               /* Sanity checks. */
-               ast_assert(0);
-               return NULL;
-       }
-       return __ao2_callback(c, flags, c->cmp_fn, arged);
+       return __ao2_callback(c, flags, c->cmp_fn, arged, tag, file, line, func);
 }
 
 /*!
@@ -520,6 +460,12 @@ void ao2_iterator_restart(struct ao2_iterator *iter)
        if (iter->last_node) {
                enum ao2_lock_req orig_lock;
 
+               if (!is_ao2_object(iter->c)) {
+                       /* Sanity check. */
+                       ast_assert(0);
+                       return;
+               }
+
                /*
                 * Do a read lock in case the container node unref does not
                 * destroy the node.  If the container node is destroyed then
@@ -532,7 +478,7 @@ void ao2_iterator_restart(struct ao2_iterator *iter)
                        ao2_rdlock(iter->c);
                }
 
-               __ao2_ref(iter->last_node, -1);
+               ao2_t_ref(iter->last_node, -1, NULL);
                iter->last_node = NULL;
 
                if (iter->flags & AO2_ITERATOR_DONTLOCK) {
@@ -568,16 +514,15 @@ void ao2_iterator_cleanup(struct ao2_iterator *iter)
        }
 }
 
-/*
- * move to the next element in the container.
- */
-static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
+void *__ao2_iterator_next(struct ao2_iterator *iter,
+       const char *tag, const char *file, int line, const char *func)
 {
        enum ao2_lock_req orig_lock;
        struct ao2_container_node *node;
        void *ret;
 
-       if (!is_ao2_object(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
+       if (!__is_ao2_object(iter->c, file, line, func)
+               || !iter->c->v_table || !iter->c->v_table->iterator_next) {
                /* Sanity checks. */
                ast_assert(0);
                return NULL;
@@ -614,14 +559,10 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
                        /* Transfer the container's node ref to the iterator. */
                } else {
                        /* Bump ref of returned object */
-                       if (tag) {
-                               __ao2_ref_debug(ret, +1, tag, file, line, func);
-                       } else {
-                               ao2_t_ref(ret, +1, "Next iterator object.");
-                       }
+                       __ao2_ref(ret, +1, tag ?: "Next iterator object.", file, line, func);
 
                        /* Bump the container's node ref for the iterator. */
-                       __ao2_ref(node, +1);
+                       ao2_t_ref(node, +1, NULL);
                }
        } else {
                /* The iteration has completed. */
@@ -631,7 +572,7 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
 
        /* Replace the iterator's node */
        if (iter->last_node) {
-               __ao2_ref(iter->last_node, -1);
+               ao2_t_ref(iter->last_node, -1, NULL);
        }
        iter->last_node = node;
 
@@ -644,16 +585,6 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
        return ret;
 }
 
-void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
-{
-       return internal_ao2_iterator_next(iter, tag, file, line, func);
-}
-
-void *__ao2_iterator_next(struct ao2_iterator *iter)
-{
-       return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
 int ao2_iterator_count(struct ao2_iterator *iter)
 {
        return ao2_container_count(iter->c);
@@ -665,26 +596,8 @@ void container_destruct(void *_c)
 
        /* Unlink any stored objects in the container. */
        c->destroying = 1;
-       __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
-
-       /* Perform any extra container cleanup. */
-       if (c->v_table && c->v_table->destroy) {
-               c->v_table->destroy(c);
-       }
-
-#if defined(AO2_DEBUG)
-       ast_atomic_fetchadd_int(&ao2.total_containers, -1);
-#endif
-}
-
-void container_destruct_debug(void *_c)
-{
-       struct ao2_container *c = _c;
-
-       /* Unlink any stored objects in the container. */
-       c->destroying = 1;
-       __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
-               "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
+       ao2_t_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
+               "container_destruct called");
 
        /* Perform any extra container cleanup. */
        if (c->v_table && c->v_table->destroy) {
@@ -712,7 +625,7 @@ static int dup_obj_cb(void *obj, void *arg, int flags)
 {
        struct ao2_container *dest = arg;
 
-       return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
+       return ao2_t_link_flags(dest, obj, OBJ_NOLOCK, NULL) ? 0 : (CMP_MATCH | CMP_STOP);
 }
 
 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
@@ -724,14 +637,14 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
                ao2_rdlock(src);
                ao2_wrlock(dest);
        }
-       obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
+       obj = ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
        if (obj) {
                /* Failed to put this obj into the dest container. */
                ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
 
                /* Remove all items from the dest container. */
-               __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
-                       NULL);
+               ao2_t_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
+                       NULL, NULL);
                res = -1;
        }
        if (!(flags & OBJ_NOLOCK)) {
@@ -742,18 +655,19 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
        return res;
 }
 
-struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
+struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
 {
        struct ao2_container *clone;
        int failed;
 
        /* Create the clone container with the same properties as the original. */
-       if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
+       if (!__is_ao2_object(orig, file, line, func)
+               || !orig->v_table || !orig->v_table->alloc_empty_clone) {
                /* Sanity checks. */
                ast_assert(0);
                return NULL;
        }
-       clone = orig->v_table->alloc_empty_clone(orig);
+       clone = orig->v_table->alloc_empty_clone(orig, tag, file, line, func);
        if (!clone) {
                return NULL;
        }
@@ -767,42 +681,7 @@ struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum sea
        }
        if (failed) {
                /* Object copy into the clone container failed. */
-               ao2_t_ref(clone, -1, "Clone creation failed.");
-               clone = NULL;
-       }
-       return clone;
-}
-
-struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
-{
-       struct ao2_container *clone;
-       int failed;
-
-       /* Create the clone container with the same properties as the original. */
-       if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
-               /* Sanity checks. */
-               ast_assert(0);
-               return NULL;
-       }
-       clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
-       if (!clone) {
-               return NULL;
-       }
-
-       if (flags & OBJ_NOLOCK) {
-               ao2_wrlock(clone);
-       }
-       failed = ao2_container_dup(clone, orig, flags);
-       if (flags & OBJ_NOLOCK) {
-               ao2_unlock(clone);
-       }
-       if (failed) {
-               /* Object copy into the clone container failed. */
-               if (ref_debug) {
-                       __ao2_ref_debug(clone, -1, tag, file, line, func);
-               } else {
-                       ao2_t_ref(clone, -1, "Clone creation failed.");
-               }
+               __ao2_ref(clone, -1, tag ?: "Clone creation failed", file, line, func);
                clone = NULL;
        }
        return clone;
index 07779a5..3651ca4 100644 (file)
@@ -87,26 +87,15 @@ typedef void (*ao2_container_destroy_fn)(struct ao2_container *self);
  * \brief Create an empty copy of this container.
  *
  * \param self Container to operate upon.
- *
- * \retval empty-container on success.
- * \retval NULL on error.
- */
-typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self);
-
-/*!
- * \brief Create an empty copy of this container. (Debug version)
- *
- * \param self Container to operate upon.
  * \param tag used for debugging.
  * \param file Debug file name invoked from
  * \param line Debug line invoked from
  * \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
  *
  * \retval empty-container on success.
  * \retval NULL on error.
  */
-typedef struct ao2_container *(*ao2_container_alloc_empty_clone_debug_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func, int ref_debug);
+typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func);
 
 /*!
  * \brief Create a new container node.
@@ -250,8 +239,6 @@ struct ao2_container_methods {
        ao2_container_destroy_fn destroy;
        /*! \brief Create an empty copy of this container. */
        ao2_container_alloc_empty_clone_fn alloc_empty_clone;
-       /*! \brief Create an empty copy of this container. (Debug version) */
-       ao2_container_alloc_empty_clone_debug_fn alloc_empty_clone_debug;
        /*! Create a new container node. */
        ao2_container_new_node_fn new_node;
        /*! Insert a node into this container. */
@@ -336,10 +323,9 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
        const char *tag, const char *file, int line, const char *func);
 
 #define __container_unlink_node(node, flags) \
-       __container_unlink_node_debug(node, flags, NULL, NULL, 0, NULL)
+       __container_unlink_node_debug(node, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 void container_destruct(void *_c);
-void container_destruct_debug(void *_c);
 int container_init(void);
 
 #endif /* ASTOBJ2_CONTAINER_PRIVATE_H_ */
index 110dd16..91ad2d2 100644 (file)
@@ -104,47 +104,27 @@ struct hash_traversal_state_check {
 /*!
  * \internal
  * \brief Create an empty copy of this container.
- * \since 12.0.0
- *
- * \param self Container to operate upon.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self)
-{
-       if (!is_ao2_object(self)) {
-               return NULL;
-       }
-
-       return ao2_t_container_alloc_hash(ao2_options_get(self), self->common.options, self->n_buckets,
-               self->hash_fn, self->common.sort_fn, self->common.cmp_fn, "Clone hash container");
-}
-
-/*!
- * \internal
- * \brief Create an empty copy of this container. (Debug version)
- * \since 12.0.0
+ * \since 14.0.0
  *
  * \param self Container to operate upon.
  * \param tag used for debugging.
  * \param file Debug file name invoked from
  * \param line Debug line invoked from
  * \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
  *
  * \retval empty-clone-container on success.
  * \retval NULL on error.
  */
-static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
+static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self,
+       const char *tag, const char *file, int line, const char *func)
 {
-       if (!is_ao2_object(self)) {
+       if (!__is_ao2_object(self, file, line, func)) {
                return NULL;
        }
 
-       return __ao2_container_alloc_hash_debug(ao2_options_get(self), self->common.options,
+       return __ao2_container_alloc_hash(ao2_options_get(self), self->common.options,
                self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
-               tag, file, line, func, ref_debug);
+               tag, file, line, func);
 }
 
 /*!
@@ -230,7 +210,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel
        struct hash_bucket_node *node;
        int i;
 
-       node = __ao2_alloc(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+       node = ao2_t_alloc_options(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL);
        if (!node) {
                return NULL;
        }
@@ -238,11 +218,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel
        i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT));
        i %= self->n_buckets;
 
-       if (tag) {
-               __ao2_ref_debug(obj_new, +1, tag, file, line, func);
-       } else {
-               ao2_t_ref(obj_new, +1, "Container node creation");
-       }
+       __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func);
        node->common.obj = obj_new;
        node->common.my_container = (struct ao2_container *) self;
        node->my_bucket = i;
@@ -440,7 +416,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s
                                }
 
                                /* We have the first traversal node */
-                               __ao2_ref(node, +1);
+                               ao2_t_ref(node, +1, NULL);
                                return node;
                        }
                }
@@ -482,7 +458,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s
                                }
 
                                /* We have the first traversal node */
-                               __ao2_ref(node, +1);
+                               ao2_t_ref(node, +1, NULL);
                                return node;
                        }
                }
@@ -551,7 +527,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se
                                }
 
                                /* We have the next traversal node */
-                               __ao2_ref(node, +1);
+                               ao2_t_ref(node, +1, NULL);
 
                                /*
                                 * Dereferencing the prev node may result in our next node
@@ -559,7 +535,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se
                                 * the container uses RW locks and the container was read
                                 * locked.
                                 */
-                               __ao2_ref(prev, -1);
+                               ao2_t_ref(prev, -1, NULL);
                                if (node->common.obj) {
                                        return node;
                                }
@@ -595,7 +571,7 @@ hash_descending_resume:;
                                }
 
                                /* We have the next traversal node */
-                               __ao2_ref(node, +1);
+                               ao2_t_ref(node, +1, NULL);
 
                                /*
                                 * Dereferencing the prev node may result in our next node
@@ -603,7 +579,7 @@ hash_descending_resume:;
                                 * the container uses RW locks and the container was read
                                 * locked.
                                 */
-                               __ao2_ref(prev, -1);
+                               ao2_t_ref(prev, -1, NULL);
                                if (node->common.obj) {
                                        return node;
                                }
@@ -615,7 +591,7 @@ hash_ascending_resume:;
        }
 
        /* No more nodes in the container left to traverse. */
-       __ao2_ref(prev, -1);
+       ao2_t_ref(prev, -1, NULL);
        return NULL;
 }
 
@@ -1037,8 +1013,6 @@ static int hash_ao2_integrity(struct ao2_container_hash *self)
 /*! Hash container virtual method table. */
 static const struct ao2_container_methods v_table_hash = {
        .alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) hash_ao2_alloc_empty_clone,
-       .alloc_empty_clone_debug =
-               (ao2_container_alloc_empty_clone_debug_fn) hash_ao2_alloc_empty_clone_debug,
        .new_node = (ao2_container_new_node_fn) hash_ao2_new_node,
        .insert = (ao2_container_insert_fn) hash_ao2_insert_node,
        .traverse_first = (ao2_container_find_first_fn) hash_ao2_find_first,
@@ -1104,25 +1078,8 @@ static struct ao2_container *hash_ao2_container_init(
 
 struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options,
        unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
-       ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
-       unsigned int num_buckets;
-       size_t container_size;
-       struct ao2_container_hash *self;
-
-       num_buckets = hash_fn ? n_buckets : 1;
-       container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
-
-       self = ao2_t_alloc_options(container_size, container_destruct, ao2_options,
-               "New hash container");
-       return hash_ao2_container_init(self, container_options, num_buckets,
-               hash_fn, sort_fn, cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
-       unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
        ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug)
+       const char *tag, const char *file, int line, const char *func)
 {
        unsigned int num_buckets;
        size_t container_size;
@@ -1131,25 +1088,17 @@ struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
        num_buckets = hash_fn ? n_buckets : 1;
        container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
 
-       self = __ao2_alloc_debug(container_size,
-               ref_debug ? container_destruct_debug : container_destruct, ao2_options,
-               tag, file, line, func, ref_debug);
+       self = __ao2_alloc(container_size, container_destruct, ao2_options,
+               tag ?: __PRETTY_FUNCTION__, file, line, func);
        return hash_ao2_container_init(self, container_options, num_buckets, hash_fn,
                sort_fn, cmp_fn);
 }
 
 struct ao2_container *__ao2_container_alloc_list(unsigned int ao2_options,
-       unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
-       return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL, sort_fn,
-               cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options,
        unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug)
+       const char *tag, const char *file, int line, const char *func)
 {
-       return __ao2_container_alloc_hash_debug(ao2_options, container_options, 1, NULL,
-               sort_fn, cmp_fn, tag, file, line, func, ref_debug);
+       return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL,
+               sort_fn, cmp_fn, tag, file, line, func);
 }
 
index 0583faf..ef47ed7 100644 (file)
@@ -43,7 +43,24 @@ struct ao2_stats {
 extern struct ao2_stats ao2;
 #endif /* defined(AO2_DEBUG) */
 
-int is_ao2_object(void *user_data);
+void log_bad_ao2(void *user_data, const char *file, int line, const char *func);
+int internal_is_ao2_object(void *user_data);
+
+#define __is_ao2_object(user_data, file, line, func) \
+       ({ \
+               int ret ## __LINE__ = 0; \
+               if (user_data) { \
+                       ret ## __LINE__ = internal_is_ao2_object(user_data); \
+               } \
+               if (!ret ## __LINE__) { \
+                       log_bad_ao2(user_data, file, line, func); \
+               } \
+               (ret ## __LINE__); \
+       })
+
+#define is_ao2_object(user_data) \
+       __is_ao2_object(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
 enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger);
 
 #endif /* ASTOBJ2_PRIVATE_H_ */
index d3a9025..b06813d 100644 (file)
@@ -545,47 +545,27 @@ static void rb_rotate_right(struct ao2_container_rbtree *self, struct rbtree_nod
 
 /*!
  * \internal
- * \brief Create an empty copy of this container.
- * \since 12.0.0
- *
- * \param self Container to operate upon.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self)
-{
-       if (!is_ao2_object(self)) {
-               return NULL;
-       }
-
-       return ao2_t_container_alloc_rbtree(ao2_options_get(self), self->common.options,
-               self->common.sort_fn, self->common.cmp_fn, "Clone rbtree container");
-}
-
-/*!
- * \internal
  * \brief Create an empty copy of this container. (Debug version)
- * \since 12.0.0
+ * \since 14.0.0
  *
  * \param self Container to operate upon.
  * \param tag used for debugging.
  * \param file Debug file name invoked from
  * \param line Debug line invoked from
  * \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
  *
  * \retval empty-clone-container on success.
  * \retval NULL on error.
  */
-static struct ao2_container *rb_ao2_alloc_empty_clone_debug(struct ao2_container_rbtree *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
+static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self,
+       const char *tag, const char *file, int line, const char *func)
 {
-       if (!is_ao2_object(self)) {
+       if (!__is_ao2_object(self, file, line, func)) {
                return NULL;
        }
 
-       return __ao2_container_alloc_rbtree_debug(ao2_options_get(self), self->common.options,
-               self->common.sort_fn, self->common.cmp_fn, tag, file, line, func, ref_debug);
+       return __ao2_container_alloc_rbtree(ao2_options_get(self), self->common.options,
+               self->common.sort_fn, self->common.cmp_fn, tag, file, line, func);
 }
 
 /*!
@@ -925,16 +905,12 @@ static struct rbtree_node *rb_ao2_new_node(struct ao2_container_rbtree *self, vo
 {
        struct rbtree_node *node;
 
-       node = __ao2_alloc(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+       node = ao2_t_alloc_options(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL);
        if (!node) {
                return NULL;
        }
 
-       if (tag) {
-               __ao2_ref_debug(obj_new, +1, tag, file, line, func);
-       } else {
-               ao2_t_ref(obj_new, +1, "Container node creation");
-       }
+       __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func);
        node->common.obj = obj_new;
        node->common.my_container = (struct ao2_container *) self;
 
@@ -1337,7 +1313,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
                }
 
                /* We have the next traversal node */
-               __ao2_ref(node, +1);
+               ao2_t_ref(node, +1, NULL);
 
                /*
                 * Dereferencing the prev node may result in our next node
@@ -1345,7 +1321,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
                 * the container uses RW locks and the container was read
                 * locked.
                 */
-               __ao2_ref(prev, -1);
+               ao2_t_ref(prev, -1, NULL);
                if (node->common.obj) {
                        return node;
                }
@@ -1353,7 +1329,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
        }
 
        /* No more nodes in the container left to traverse. */
-       __ao2_ref(prev, -1);
+       ao2_t_ref(prev, -1, NULL);
        return NULL;
 }
 
@@ -1636,7 +1612,7 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self,
        }
 
        /* We have the first traversal node */
-       __ao2_ref(node, +1);
+       ao2_t_ref(node, +1, NULL);
        return node;
 }
 
@@ -2018,8 +1994,6 @@ static int rb_ao2_integrity(struct ao2_container_rbtree *self)
 /*! rbtree container virtual method table. */
 static const struct ao2_container_methods v_table_rbtree = {
        .alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) rb_ao2_alloc_empty_clone,
-       .alloc_empty_clone_debug =
-               (ao2_container_alloc_empty_clone_debug_fn) rb_ao2_alloc_empty_clone_debug,
        .new_node = (ao2_container_new_node_fn) rb_ao2_new_node,
        .insert = (ao2_container_insert_fn) rb_ao2_insert_node,
        .traverse_first = (ao2_container_find_first_fn) rb_ao2_find_first,
@@ -2063,24 +2037,8 @@ static struct ao2_container *rb_ao2_container_init(struct ao2_container_rbtree *
 }
 
 struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options,
-       ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
-       struct ao2_container_rbtree *self;
-
-       if (!sort_fn) {
-               /* Sanity checks. */
-               ast_log(LOG_ERROR, "Missing sort_fn()!\n");
-               return NULL;
-       }
-
-       self = ao2_t_alloc_options(sizeof(*self), container_destruct, ao2_options,
-               "New rbtree container");
-       return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options,
        ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
-       const char *tag, const char *file, int line, const char *func, int ref_debug)
+       const char *tag, const char *file, int line, const char *func)
 {
        struct ao2_container_rbtree *self;
 
@@ -2090,9 +2048,8 @@ struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_option
                return NULL;
        }
 
-       self = __ao2_alloc_debug(sizeof(*self),
-               ref_debug ? container_destruct_debug : container_destruct, ao2_options,
-               tag, file, line, func, ref_debug);
+       self = __ao2_alloc(sizeof(*self), container_destruct, ao2_options,
+               tag ?: __PRETTY_FUNCTION__, file, line, func);
        return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn);
 }
 
index db126db..fee7763 100644 (file)
@@ -795,7 +795,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
                return NULL;
        }
 
-       if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor))) {
+       tmp = __ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor,
+               file, line, function);
+       if (!tmp) {
                /* Channel structure allocation failure. */
                return NULL;
        }
@@ -987,16 +989,14 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci
 
 /* only do the minimum amount of work needed here to make a channel
  * structure that can be used to expand channel vars */
-#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
 struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function)
-#else
-struct ast_channel *ast_dummy_channel_alloc(void)
-#endif
 {
        struct ast_channel *tmp;
        struct varshead *headp;
 
-       if (!(tmp = ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL))) {
+       tmp = __ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL,
+               file, line, function);
+       if (!tmp) {
                /* Dummy channel structure allocation failure. */
                return NULL;
        }
index 4e85398..0bb3849 100644 (file)
@@ -1439,15 +1439,9 @@ static int pvt_cause_cmp_fn(void *obj, void *vstr, int flags)
 struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *file, int line, const char *function)
 {
        struct ast_channel *tmp;
-#if defined(REF_DEBUG)
-       tmp = __ao2_alloc_debug(sizeof(*tmp), destructor,
-               AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 1);
-#elif defined(__AST_DEBUG_MALLOC)
-       tmp = __ao2_alloc_debug(sizeof(*tmp), destructor,
-               AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 0);
-#else
-       tmp = ao2_alloc(sizeof(*tmp), destructor);
-#endif
+
+       tmp = __ao2_alloc(sizeof(*tmp), destructor,
+               AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function);
 
        if (!tmp) {
                return NULL;
index 3e72976..def795c 100644 (file)
@@ -457,22 +457,14 @@ int ast_format_cache_set(struct ast_format *format)
        return 0;
 }
 
-struct ast_format *__ast_format_cache_get(const char *name)
+struct ast_format *__ast_format_cache_get(const char *name,
+       const char *tag, const char *file, int line, const char *func)
 {
        if (ast_strlen_zero(name)) {
                return NULL;
        }
 
-       return ao2_find(formats, name, OBJ_SEARCH_KEY);
-}
-
-struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
-{
-       if (ast_strlen_zero(name)) {
-               return NULL;
-       }
-
-       return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
+       return __ao2_find(formats, name, OBJ_SEARCH_KEY, tag, file, line, func);
 }
 
 struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
index c9c6c3b..7456a44 100644 (file)
@@ -103,25 +103,13 @@ static inline void format_cap_init(struct ast_format_cap *cap, enum ast_format_c
        cap->framing = UINT_MAX;
 }
 
-struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags)
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags,
+       const char *tag, const char *file, int line, const char *func)
 {
        struct ast_format_cap *cap;
 
-       cap = ao2_alloc_options(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
-       if (!cap) {
-               return NULL;
-       }
-
-       format_cap_init(cap, flags);
-
-       return cap;
-}
-
-struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func)
-{
-       struct ast_format_cap *cap;
-
-       cap = __ao2_alloc_debug(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(tag, "ast_format_cap_alloc"), file, line, func, 1);
+       cap = __ao2_alloc(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK,
+               tag, file, line, func);
        if (!cap) {
                return NULL;
        }
@@ -187,26 +175,7 @@ static int format_in_format_cap(struct ast_format_cap *cap, struct ast_format *f
        return 0;
 }
 
-int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
-{
-       struct format_cap_framed *framed;
-
-       ast_assert(format != NULL);
-
-       if (format_in_format_cap(cap, format)) {
-               return 0;
-       }
-
-       framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
-       if (!framed) {
-               return -1;
-       }
-       framed->format = ao2_bump(format);
-
-       return format_cap_framed_init(framed, cap, format, framing);
-}
-
-int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
 {
        struct format_cap_framed *framed;
 
@@ -221,7 +190,7 @@ int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format
                return -1;
        }
 
-       __ao2_ref_debug(format, +1, S_OR(tag, "ast_format_cap_append"), file, line, func);
+       __ao2_ref(format, +1, tag, file, line, func);
        framed->format = format;
 
        return format_cap_framed_init(framed, cap, format, framing);
index 26d229f..eb959fa 100644 (file)
@@ -122,10 +122,8 @@ static int modules_loaded;
 
 struct ast_module {
        const struct ast_module_info *info;
-#ifdef REF_DEBUG
-       /* Used to get module references into REF_DEBUG logs */
+       /* Used to get module references into refs log */
        void *ref_debug;
-#endif
        void *lib;                                      /* the shared lib, or NULL if embedded */
        int usecount;                                   /* the number of 'users' currently in this module */
        struct module_user_list users;                  /* the list of users in the module */
@@ -199,9 +197,9 @@ void ast_module_register(const struct ast_module_info *info)
        ast_debug(5, "Registering module %s\n", info->name);
 
        mod->info = info;
-#ifdef REF_DEBUG
-       mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
-#endif
+       if (ast_opt_ref_debug) {
+               mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
+       }
        AST_LIST_HEAD_INIT(&mod->users);
 
        /* during startup, before the loader has been initialized,
@@ -248,9 +246,7 @@ void ast_module_unregister(const struct ast_module_info *info)
        if (mod) {
                ast_debug(5, "Unregistering module %s\n", info->name);
                AST_LIST_HEAD_DESTROY(&mod->users);
-#ifdef REF_DEBUG
                ao2_cleanup(mod->ref_debug);
-#endif
                ast_free(mod);
        }
 }
@@ -270,9 +266,9 @@ struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast
        AST_LIST_INSERT_HEAD(&mod->users, u, entry);
        AST_LIST_UNLOCK(&mod->users);
 
-#ifdef REF_DEBUG
-       ao2_ref(mod->ref_debug, +1);
-#endif
+       if (mod->ref_debug) {
+               ao2_ref(mod->ref_debug, +1);
+       }
 
        ast_atomic_fetchadd_int(&mod->usecount, +1);
 
@@ -298,9 +294,9 @@ void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
                return;
        }
 
-#ifdef REF_DEBUG
-       ao2_ref(mod->ref_debug, -1);
-#endif
+       if (mod->ref_debug) {
+               ao2_ref(mod->ref_debug, -1);
+       }
 
        ast_atomic_fetchadd_int(&mod->usecount, -1);
        ast_free(u);
@@ -318,9 +314,9 @@ void __ast_module_user_hangup_all(struct ast_module *mod)
                        ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
                }
 
-#ifdef REF_DEBUG
-               ao2_ref(mod->ref_debug, -1);
-#endif
+               if (mod->ref_debug) {
+                       ao2_ref(mod->ref_debug, -1);
+               }
 
                ast_atomic_fetchadd_int(&mod->usecount, -1);
                ast_free(u);
@@ -641,9 +637,7 @@ void ast_module_shutdown(void)
                                mod->info->unload();
                        }
                        AST_LIST_HEAD_DESTROY(&mod->users);
-#ifdef REF_DEBUG
                        ao2_cleanup(mod->ref_debug);
-#endif
                        ast_free(mod);
                        somethingchanged = 1;
                }
@@ -1477,9 +1471,9 @@ struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, in
                return NULL;
        }
 
-#ifdef REF_DEBUG
-       __ao2_ref_debug(mod->ref_debug, +1, "", file, line, func);
-#endif
+       if (mod->ref_debug) {
+               __ao2_ref(mod->ref_debug, +1, "", file, line, func);
+       }
 
        ast_atomic_fetchadd_int(&mod->usecount, +1);
        ast_update_use_count();
@@ -1503,9 +1497,9 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons
                return;
        }
 
-#ifdef REF_DEBUG
-       __ao2_ref_debug(mod->ref_debug, -1, "", file, line, func);
-#endif
+       if (mod->ref_debug) {
+               __ao2_ref(mod->ref_debug, -1, "", file, line, func);
+       }
 
        ast_atomic_fetchadd_int(&mod->usecount, -1);
        ast_update_use_count();
index 34e6a94..9c9ad4e 100644 (file)
@@ -1659,6 +1659,8 @@ int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name,
 
 void ast_rtp_dtls_cfg_copy(const struct ast_rtp_dtls_cfg *src_cfg, struct ast_rtp_dtls_cfg *dst_cfg)
 {
+       ast_rtp_dtls_cfg_free(dst_cfg);         /* Prevent a double-call leaking memory via ast_strdup */
+
        dst_cfg->enabled = src_cfg->enabled;
        dst_cfg->verify = src_cfg->verify;
        dst_cfg->rekey = src_cfg->rekey;
index 24a3a28..eaf1f4e 100644 (file)
@@ -210,7 +210,7 @@ static int reload(void);
 
 #define mohclass_ref(class,string)   (ao2_t_ref((class), +1, (string)), class)
 
-#ifndef REF_DEBUG
+#ifndef AST_DEVMODE
 #define mohclass_unref(class,string) ({ ao2_t_ref((class), -1, (string)); (struct mohclass *) NULL; })
 #else
 #define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__)
@@ -219,14 +219,14 @@ static struct mohclass *_mohclass_unref(struct mohclass *class, const char *tag,
        struct mohclass *dup = ao2_callback(mohclasses, OBJ_POINTER, ao2_match_by_addr, class);
 
        if (dup) {
-               if (__ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 2) {
+               if (__ao2_ref(dup, -1, tag, file, line, funcname) == 2) {
                        ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n",
                                class, class->name, file, line, funcname);
                } else {
                        ao2_ref(class, -1);
                }
        } else {
-               __ao2_ref_debug(class, -1, (char *) tag, (char *) file, line, funcname);
+               __ao2_ref(class, -1, tag, file, line, funcname);
        }
        return NULL;
 }
@@ -877,12 +877,8 @@ static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, co
 
        ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name));
 
-#ifdef REF_DEBUG
-       moh = __ao2_find_debug(mohclasses, &tmp_class, flags,
+       moh = __ao2_find(mohclasses, &tmp_class, flags,
                "get_mohbyname", file, lineno, funcname);
-#else
-       moh = __ao2_find(mohclasses, &tmp_class, flags);
-#endif
 
        if (!moh && warn) {
                ast_debug(1, "Music on Hold class '%s' not found in memory\n", name);
@@ -1373,17 +1369,9 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char
 {
        struct mohclass *class;
 
-       if ((class =
-#ifdef REF_DEBUG
-                       __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
-                               AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 1)
-#elif defined(__AST_DEBUG_MALLOC)
-                       __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
-                               AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 0)
-#else
-                       ao2_alloc(sizeof(*class), moh_class_destructor)
-#endif
-               )) {
+       class = __ao2_alloc(sizeof(*class), moh_class_destructor, AO2_ALLOC_OPT_LOCK_MUTEX,
+               "Allocating new moh class", file, line, funcname);
+       if (class) {
                class->format = ao2_bump(ast_format_slin);
                class->srcfd = -1;
        }
index a8b9411..5120fc6 100644 (file)
@@ -319,4 +319,9 @@ void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter
  */
 int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj);
 
+/*!
+ * \internal
+ * \brief Finds or creates contact_status for a contact
+ */
+struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact);
 #endif /* RES_PJSIP_PRIVATE_H_ */
index 45370dd..887053b 100644 (file)
@@ -376,6 +376,11 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab
                        return -1;
                }
 
+               if (!ast_res_pjsip_find_or_create_contact_status(contact)) {
+                       ao2_ref(contact, -1);
+                       return -1;
+               }
+
                ast_string_field_set(contact, uri, contact_uri);
                ao2_link(aor->permanent_contacts, contact);
                ao2_ref(contact, -1);
@@ -750,8 +755,8 @@ static int cli_contact_print_body(void *obj, void *arg, int flags)
                "Contact",
                flexwidth, flexwidth,
                wrapper->contact_id,
-               ast_sip_get_contact_short_status_label(status->status),
-               (status->status != UNKNOWN ? ((long long) status->rtt) / 1000.0 : NAN));
+               ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN),
+               (status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN));
 
        return 0;
 }
@@ -874,6 +879,17 @@ static struct ast_cli_entry cli_commands[] = {
 struct ast_sip_cli_formatter_entry *contact_formatter;
 struct ast_sip_cli_formatter_entry *aor_formatter;
 
+/*! \brief Always create a contact_status for each contact */
+static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
+{
+       struct ast_sip_contact_status *status;
+       struct ast_sip_contact *contact = object;
+
+       status = ast_res_pjsip_find_or_create_contact_status(contact);
+
+       return status ? 0 : -1;
+}
+
 /*! \brief Initialize sorcery with location support */
 int ast_sip_initialize_sorcery_location(void)
 {
@@ -881,7 +897,7 @@ int ast_sip_initialize_sorcery_location(void)
        ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
        ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
 
-       if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, NULL) ||
+       if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, contact_apply_handler) ||
                ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL)) {
                return -1;
        }
index 40b6f7b..8ffb88c 100644 (file)
@@ -76,11 +76,10 @@ static void *contact_status_alloc(const char *name)
 }
 
 /*!
- * \internal
  * \brief Retrieve a ast_sip_contact_status object from sorcery creating
  *        one if not found.
  */
-static struct ast_sip_contact_status *find_or_create_contact_status(const struct ast_sip_contact *contact)
+struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
 {
        struct ast_sip_contact_status *status;
 
@@ -98,6 +97,10 @@ static struct ast_sip_contact_status *find_or_create_contact_status(const struct
                return NULL;
        }
 
+       status->status = UNKNOWN;
+       status->rtt_start = ast_tv(0, 0);
+       status->rtt = 0;
+
        if (ast_sorcery_create(ast_sip_get_sorcery(), status)) {
                ast_log(LOG_ERROR, "Unable to persist ast_sip_contact_status for contact %s\n",
                        contact->uri);
@@ -118,7 +121,7 @@ static void update_contact_status(const struct ast_sip_contact *contact,
        struct ast_sip_contact_status *status;
        struct ast_sip_contact_status *update;
 
-       status = find_or_create_contact_status(contact);
+       status = ast_res_pjsip_find_or_create_contact_status(contact);
        if (!status) {
                ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
                        contact->uri);
@@ -143,8 +146,6 @@ static void update_contact_status(const struct ast_sip_contact *contact,
 
        update->rtt_start = ast_tv(0, 0);
 
-
-
        ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
                "Contact: %s\r\n"
                        "Status: %s\r\n"
@@ -172,7 +173,7 @@ static void init_start_time(const struct ast_sip_contact *contact)
        struct ast_sip_contact_status *status;
        struct ast_sip_contact_status *update;
 
-       status = find_or_create_contact_status(contact);
+       status = ast_res_pjsip_find_or_create_contact_status(contact);
        if (!status) {
                ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
                        contact->uri);
index 2fe6bdc..12bfa07 100644 (file)
  * at the top of the source tree.
  */
 
-/*** MODULEINFO
-       <depend>pjproject</depend>
-       <depend>res_pjsip</depend>
-       <depend>res_pjsip_pubsub</depend>
-       <depend>res_pjsip_exten_state</depend>
-       <support_level>core</support_level>
- ***/
-
 #include "asterisk.h"
 
 #include <pjsip.h>
 #include <pjlib.h>
 
 #include "asterisk/module.h"
-#include "asterisk/res_pjsip.h"
-#include "asterisk/res_pjsip_pubsub.h"
+#include "asterisk/pbx.h"
 #include "asterisk/res_pjsip_presence_xml.h"
-#include "asterisk/res_pjsip_body_generator_types.h"
 
 void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
 {
index e30a32e..69e0124 100644 (file)
@@ -479,10 +479,18 @@ static int handle_client_registration(void *data)
 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
 {
        struct sip_outbound_registration_client_state *client_state = entry->user_data;
+       pjsip_regc_info info;
+
+       pjsip_regc_get_info(client_state->client, &info);
+       ast_debug(1, "Attempting scheduled outbound registration attempt to server '%.*s' from client '%.*s'\n",
+                       (int) info.server_uri.slen, info.server_uri.ptr,
+                       (int) info.client_uri.slen, info.client_uri.ptr);
 
        ao2_ref(client_state, +1);
        if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
-               ast_log(LOG_WARNING, "Failed to pass outbound registration to threadpool\n");
+               ast_log(LOG_WARNING, "Scheduled outbound registration to server '%.*s' from client '%.*s' could not be executed\n",
+                               (int) info.server_uri.slen, info.server_uri.ptr,
+                               (int) info.client_uri.slen, info.client_uri.ptr);
                ao2_ref(client_state, -1);
        }
        ao2_ref(client_state, -1);
@@ -494,12 +502,21 @@ static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, stru
 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
 {
        pj_time_val delay = { .sec = seconds, };
+       pjsip_regc_info info;
 
        cancel_registration(client_state);
 
+       pjsip_regc_get_info(client_state->client, &info);
+       ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
+                       (int) info.server_uri.slen, info.server_uri.ptr,
+                       (int) info.client_uri.slen, info.client_uri.ptr,
+                       seconds);
+
        ao2_ref(client_state, +1);
        if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
-               ast_log(LOG_WARNING, "Failed to pass timed registration to scheduler\n");
+               ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
+                               (int) info.server_uri.slen, info.server_uri.ptr,
+                               (int) info.client_uri.slen, info.client_uri.ptr);
                ao2_ref(client_state, -1);
        }
 }
@@ -611,13 +628,18 @@ static int handle_registration_response(void *data)
        pjsip_regc_info info;
        char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
 
+       pjsip_regc_get_info(response->client_state->client, &info);
+       ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
+       ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
+
        if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
+               ast_debug(1, "Not handling registration response from '%s' (transaction %s). Registration already stopped\n",
+                               server_uri, response->tsx ? response->tsx->obj_name : "<none>");
                return 0;
        }
 
-       pjsip_regc_get_info(response->client_state->client, &info);
-       ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
-       ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
+       ast_debug(1, "Processing REGISTER response %d from '%s' (transaction %s)\n",
+                       response->code, server_uri, response->tsx ? response->tsx->obj_name : "<none>");
 
        if (!response->client_state->auth_attempted &&
                        (response->code == 401 || response->code == 407)) {
@@ -626,11 +648,16 @@ static int handle_registration_response(void *data)
                                response->rdata, response->tsx, &tdata)) {
                        ao2_ref(response->client_state, +1);
                        response->client_state->auth_attempted = 1;
+                       ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
+                                       server_uri, client_uri);
                        if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
                                response->client_state->auth_attempted = 0;
                                ao2_cleanup(response->client_state);
                        }
                        return 0;
+               } else {
+                       ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
+                                       server_uri, client_uri);
                }
                /* Otherwise, fall through so the failure is processed appropriately */
        }
@@ -700,6 +727,7 @@ static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *par
 {
        RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
        struct registration_response *response;
+       pjsip_regc_info info;
 
        ast_assert(client_state != NULL);
 
@@ -712,6 +740,12 @@ static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *par
        response->client_state = client_state;
        ao2_ref(response->client_state, +1);
 
+       pjsip_regc_get_info(client_state->client, &info);
+       ast_debug(1, "Received REGISTER response %d(%.*s) from server '%.*s' for client '%.*s\n",
+                       param->code, (int) param->reason.slen, param->reason.ptr,
+                       (int) info.server_uri.slen, info.server_uri.ptr,
+                       (int) info.client_uri.slen, info.client_uri.ptr);
+
        if (param->rdata) {
                struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
 
@@ -731,6 +765,9 @@ static void sip_outbound_registration_state_destroy(void *obj)
 {
        struct sip_outbound_registration_state *state = obj;
 
+       ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
+                       state->registration->server_uri, state->registration->client_uri);
+
        ao2_cleanup(state->registration);
 
        if (!state->client_state) {
@@ -1146,6 +1183,11 @@ static int unregister_task(void *obj)
        RAII_VAR(struct sip_outbound_registration_state*, state, obj, ao2_cleanup);
        struct pjsip_regc *client = state->client_state->client;
        pjsip_tx_data *tdata;
+       pjsip_regc_info info;
+
+       pjsip_regc_get_info(client, &info);
+       ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
+                       state->registration->server_uri, state->registration->client_uri);
 
        cancel_registration(state->client_state);
 
index 0513c11..62601dc 100644 (file)
@@ -1869,6 +1869,7 @@ static int dtls_srtp_setup(struct ast_rtp *rtp, struct ast_srtp *srtp, struct as
        unsigned char *local_key, *local_salt, *remote_key, *remote_salt;
        struct ast_srtp_policy *local_policy, *remote_policy = NULL;
        struct ast_rtp_instance_stats stats = { 0, };
+       int res = -1;
 
        /* If a fingerprint is present in the SDP make sure that the peer certificate matches it */
        if (rtp->dtls_verify & AST_RTP_DTLS_VERIFY_FINGERPRINT) {
@@ -1983,16 +1984,17 @@ static int dtls_srtp_setup(struct ast_rtp *rtp, struct ast_srtp *srtp, struct as
                }
        }
 
-       return 0;
+       res = 0;
 
 error:
+       /* policy->destroy() called even on success to release local reference to these resources */
        res_srtp_policy->destroy(local_policy);
 
        if (remote_policy) {
                res_srtp_policy->destroy(remote_policy);
        }
 
-       return -1;
+       return res;
 }
 #endif