Sat Jul 12 2014 17:18:26

Asterisk developer's documentation


astobj2.c
Go to the documentation of this file.
00001 /*
00002  * astobj2 - replacement containers for asterisk data structures.
00003  *
00004  * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*
00018  * Function implementing astobj2 objects.
00019  */
00020 
00021 /*** MODULEINFO
00022    <support_level>core</support_level>
00023  ***/
00024 
00025 #include "asterisk.h"
00026 
00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 417505 $")
00028 
00029 #include "asterisk/_private.h"
00030 #include "asterisk/astobj2.h"
00031 #include "asterisk/linkedlists.h"
00032 #include "asterisk/utils.h"
00033 #include "asterisk/cli.h"
00034 #include "asterisk/paths.h"
00035 
00036 #if defined(TEST_FRAMEWORK)
00037 /* We are building with the test framework enabled so enable AO2 debug tests as well. */
00038 #define AO2_DEBUG 1
00039 #endif   /* defined(TEST_FRAMEWORK) */
00040 
00041 static FILE *ref_log;
00042 
00043 /*!
00044  * astobj2 objects are always preceded by this data structure,
00045  * which contains a reference counter,
00046  * option flags and a pointer to a destructor.
00047  * The refcount is used to decide when it is time to
00048  * invoke the destructor.
00049  * The magic number is used for consistency check.
00050  */
00051 struct __priv_data {
00052    int ref_counter;
00053    ao2_destructor_fn destructor_fn;
00054    /*! User data size for stats */
00055    size_t data_size;
00056    /*! The ao2 object option flags */
00057    uint32_t options;
00058    /*! magic number.  This is used to verify that a pointer passed in is a
00059     *  valid astobj2 */
00060    uint32_t magic;
00061 };
00062 
00063 #define  AO2_MAGIC   0xa570b123
00064 
00065 /*!
00066  * What an astobj2 object looks like: fixed-size private data
00067  * followed by variable-size user data.
00068  */
00069 struct astobj2 {
00070    struct __priv_data priv_data;
00071    void *user_data[0];
00072 };
00073 
00074 struct ao2_lock_priv {
00075    ast_mutex_t lock;
00076 };
00077 
00078 /* AstObj2 with recursive lock. */
00079 struct astobj2_lock {
00080    struct ao2_lock_priv mutex;
00081    struct __priv_data priv_data;
00082    void *user_data[0];
00083 };
00084 
00085 struct ao2_rwlock_priv {
00086    ast_rwlock_t lock;
00087    /*! Count of the number of threads holding a lock on this object. -1 if it is the write lock. */
00088    int num_lockers;
00089 };
00090 
00091 /* AstObj2 with RW lock. */
00092 struct astobj2_rwlock {
00093    struct ao2_rwlock_priv rwlock;
00094    struct __priv_data priv_data;
00095    void *user_data[0];
00096 };
00097 
00098 #ifdef AO2_DEBUG
00099 struct ao2_stats {
00100    volatile int total_objects;
00101    volatile int total_mem;
00102    volatile int total_containers;
00103    volatile int total_refs;
00104    volatile int total_locked;
00105 };
00106 
00107 static struct ao2_stats ao2;
00108 #endif
00109 
00110 #ifndef HAVE_BKTR /* backtrace support */
00111 void ao2_bt(void) {}
00112 #else
00113 #include <execinfo.h>    /* for backtrace */
00114 
00115 void ao2_bt(void)
00116 {
00117    int c, i;
00118 #define N1  20
00119    void *addresses[N1];
00120    char **strings;
00121 
00122    c = backtrace(addresses, N1);
00123    strings = ast_bt_get_symbols(addresses,c);
00124    ast_verbose("backtrace returned: %d\n", c);
00125    for(i = 0; i < c; i++) {
00126       ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
00127    }
00128    ast_std_free(strings);
00129 }
00130 #endif
00131 
00132 #define INTERNAL_OBJ_MUTEX(user_data) \
00133    ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
00134 
00135 #define INTERNAL_OBJ_RWLOCK(user_data) \
00136    ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
00137 
00138 /*!
00139  * \brief convert from a pointer _p to a user-defined object
00140  *
00141  * \return the pointer to the astobj2 structure
00142  */
00143 static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
00144 {
00145    struct astobj2 *p;
00146 
00147    if (!user_data) {
00148       ast_log(LOG_ERROR, "user_data is NULL\n");
00149       return NULL;
00150    }
00151 
00152    p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
00153    if (AO2_MAGIC != p->priv_data.magic) {
00154       if (p->priv_data.magic) {
00155          ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
00156             p->priv_data.magic, user_data);
00157       } else {
00158          ast_log(LOG_ERROR,
00159             "bad magic number for object %p. Object is likely destroyed.\n",
00160             user_data);
00161       }
00162       ast_assert(0);
00163       return NULL;
00164    }
00165 
00166    return p;
00167 }
00168 
00169 enum ao2_callback_type {
00170    DEFAULT,
00171    WITH_DATA,
00172 };
00173 
00174 /*!
00175  * \brief convert from a pointer _p to an astobj2 object
00176  *
00177  * \return the pointer to the user-defined portion.
00178  */
00179 #define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
00180 
00181 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
00182 {
00183    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00184    struct astobj2_lock *obj_mutex;
00185    struct astobj2_rwlock *obj_rwlock;
00186    int res = 0;
00187 
00188    if (obj == NULL) {
00189       return -1;
00190    }
00191 
00192    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00193    case AO2_ALLOC_OPT_LOCK_MUTEX:
00194       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00195       res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
00196 #ifdef AO2_DEBUG
00197       if (!res) {
00198          ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00199       }
00200 #endif
00201       break;
00202    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00203       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00204       switch (lock_how) {
00205       case AO2_LOCK_REQ_MUTEX:
00206       case AO2_LOCK_REQ_WRLOCK:
00207          res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00208          if (!res) {
00209             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
00210 #ifdef AO2_DEBUG
00211             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00212 #endif
00213          }
00214          break;
00215       case AO2_LOCK_REQ_RDLOCK:
00216          res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00217          if (!res) {
00218             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
00219 #ifdef AO2_DEBUG
00220             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00221 #endif
00222          }
00223          break;
00224       }
00225       break;
00226    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00227       /* The ao2 object has no lock. */
00228       break;
00229    default:
00230       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00231          user_data);
00232       return -1;
00233    }
00234 
00235    return res;
00236 }
00237 
00238 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
00239 {
00240    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00241    struct astobj2_lock *obj_mutex;
00242    struct astobj2_rwlock *obj_rwlock;
00243    int res = 0;
00244    int current_value;
00245 
00246    if (obj == NULL) {
00247       return -1;
00248    }
00249 
00250    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00251    case AO2_ALLOC_OPT_LOCK_MUTEX:
00252       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00253       res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
00254 #ifdef AO2_DEBUG
00255       if (!res) {
00256          ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00257       }
00258 #endif
00259       break;
00260    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00261       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00262 
00263       current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
00264       if (current_value < 0) {
00265          /* It was a WRLOCK that we are unlocking.  Fix the count. */
00266          ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
00267       }
00268       res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00269 #ifdef AO2_DEBUG
00270       if (!res) {
00271          ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00272       }
00273 #endif
00274       break;
00275    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00276       /* The ao2 object has no lock. */
00277       break;
00278    default:
00279       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00280          user_data);
00281       res = -1;
00282       break;
00283    }
00284    return res;
00285 }
00286 
00287 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
00288 {
00289    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00290    struct astobj2_lock *obj_mutex;
00291    struct astobj2_rwlock *obj_rwlock;
00292    int res = 0;
00293 
00294    if (obj == NULL) {
00295       return -1;
00296    }
00297 
00298    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00299    case AO2_ALLOC_OPT_LOCK_MUTEX:
00300       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00301       res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
00302 #ifdef AO2_DEBUG
00303       if (!res) {
00304          ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00305       }
00306 #endif
00307       break;
00308    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00309       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00310       switch (lock_how) {
00311       case AO2_LOCK_REQ_MUTEX:
00312       case AO2_LOCK_REQ_WRLOCK:
00313          res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00314          if (!res) {
00315             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
00316 #ifdef AO2_DEBUG
00317             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00318 #endif
00319          }
00320          break;
00321       case AO2_LOCK_REQ_RDLOCK:
00322          res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00323          if (!res) {
00324             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
00325 #ifdef AO2_DEBUG
00326             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00327 #endif
00328          }
00329          break;
00330       }
00331       break;
00332    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00333       /* The ao2 object has no lock. */
00334       return 0;
00335    default:
00336       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00337          user_data);
00338       return -1;
00339    }
00340 
00341 
00342    return res;
00343 }
00344 
00345 /*!
00346  * \internal
00347  * \brief Adjust an object's lock to the requested level.
00348  *
00349  * \param user_data An ao2 object to adjust lock level.
00350  * \param lock_how What level to adjust lock.
00351  * \param keep_stronger TRUE if keep original lock level if it is stronger.
00352  *
00353  * \pre The ao2 object is already locked.
00354  *
00355  * \details
00356  * An ao2 object with a RWLOCK will have its lock level adjusted
00357  * to the specified level if it is not already there.  An ao2
00358  * object with a different type of lock is not affected.
00359  *
00360  * \return Original lock level.
00361  */
00362 static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
00363 {
00364    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00365    struct astobj2_rwlock *obj_rwlock;
00366    enum ao2_lock_req orig_lock;
00367 
00368    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00369    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00370       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00371       if (obj_rwlock->rwlock.num_lockers < 0) {
00372          orig_lock = AO2_LOCK_REQ_WRLOCK;
00373       } else {
00374          orig_lock = AO2_LOCK_REQ_RDLOCK;
00375       }
00376       switch (lock_how) {
00377       case AO2_LOCK_REQ_MUTEX:
00378          lock_how = AO2_LOCK_REQ_WRLOCK;
00379          /* Fall through */
00380       case AO2_LOCK_REQ_WRLOCK:
00381          if (lock_how != orig_lock) {
00382             /* Switch from read lock to write lock. */
00383             ao2_unlock(user_data);
00384             ao2_wrlock(user_data);
00385          }
00386          break;
00387       case AO2_LOCK_REQ_RDLOCK:
00388          if (!keep_stronger && lock_how != orig_lock) {
00389             /* Switch from write lock to read lock. */
00390             ao2_unlock(user_data);
00391             ao2_rdlock(user_data);
00392          }
00393          break;
00394       }
00395       break;
00396    default:
00397       ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
00398       /* Fall through */
00399    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00400    case AO2_ALLOC_OPT_LOCK_MUTEX:
00401       orig_lock = AO2_LOCK_REQ_MUTEX;
00402       break;
00403    }
00404 
00405    return orig_lock;
00406 }
00407 
00408 void *ao2_object_get_lockaddr(void *user_data)
00409 {
00410    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00411    struct astobj2_lock *obj_mutex;
00412 
00413    if (obj == NULL) {
00414       return NULL;
00415    }
00416 
00417    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00418    case AO2_ALLOC_OPT_LOCK_MUTEX:
00419       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00420       return &obj_mutex->mutex.lock;
00421    default:
00422       break;
00423    }
00424 
00425    return NULL;
00426 }
00427 
00428 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
00429 {
00430    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00431    struct astobj2_lock *obj_mutex;
00432    struct astobj2_rwlock *obj_rwlock;
00433    int current_value;
00434    int ret;
00435 
00436    if (obj == NULL) {
00437       return -1;
00438    }
00439 
00440    /* if delta is 0, just return the refcount */
00441    if (delta == 0) {
00442       return obj->priv_data.ref_counter;
00443    }
00444 
00445    /* we modify with an atomic operation the reference counter */
00446    ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
00447    current_value = ret + delta;
00448 
00449 #ifdef AO2_DEBUG
00450    ast_atomic_fetchadd_int(&ao2.total_refs, delta);
00451 #endif
00452 
00453    if (0 < current_value) {
00454       /* The object still lives. */
00455       return ret;
00456    }
00457 
00458    /* this case must never happen */
00459    if (current_value < 0) {
00460       ast_log(__LOG_ERROR, file, line, func,
00461          "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
00462    }
00463 
00464    /* last reference, destroy the object */
00465    if (obj->priv_data.destructor_fn != NULL) {
00466       obj->priv_data.destructor_fn(user_data);
00467    }
00468 
00469 #ifdef AO2_DEBUG
00470    ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
00471    ast_atomic_fetchadd_int(&ao2.total_objects, -1);
00472 #endif
00473 
00474    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00475    case AO2_ALLOC_OPT_LOCK_MUTEX:
00476       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00477       ast_mutex_destroy(&obj_mutex->mutex.lock);
00478 
00479       /*
00480        * For safety, zero-out the astobj2_lock header and also the
00481        * first word of the user-data, which we make sure is always
00482        * allocated.
00483        */
00484       memset(obj_mutex, '\0', sizeof(*obj_mutex) + sizeof(void *) );
00485       ast_free(obj_mutex);
00486       break;
00487    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00488       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00489       ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
00490 
00491       /*
00492        * For safety, zero-out the astobj2_rwlock header and also the
00493        * first word of the user-data, which we make sure is always
00494        * allocated.
00495        */
00496       memset(obj_rwlock, '\0', sizeof(*obj_rwlock) + sizeof(void *) );
00497       ast_free(obj_rwlock);
00498       break;
00499    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00500       /*
00501        * For safety, zero-out the astobj2 header and also the first
00502        * word of the user-data, which we make sure is always
00503        * allocated.
00504        */
00505       memset(obj, '\0', sizeof(*obj) + sizeof(void *) );
00506       ast_free(obj);
00507       break;
00508    default:
00509       ast_log(__LOG_ERROR, file, line, func,
00510          "Invalid lock option on ao2 object %p\n", user_data);
00511       break;
00512    }
00513 
00514    return ret;
00515 }
00516 
00517 int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
00518 {
00519    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00520 
00521    if (ref_log && user_data) {
00522       if (obj && obj->priv_data.ref_counter + delta == 0) {
00523          fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n", user_data, delta, ast_get_tid(), file, line, func, tag);
00524          fflush(ref_log);
00525       } else if (delta != 0) {
00526          fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
00527             delta, ast_get_tid(), file, line, func, obj ? obj->priv_data.ref_counter : -1, tag);
00528          fflush(ref_log);
00529       }
00530    }
00531 
00532    if (obj == NULL) {
00533       return -1;
00534    }
00535 
00536    return internal_ao2_ref(user_data, delta, file, line, func);
00537 }
00538 
00539 int __ao2_ref(void *user_data, int delta)
00540 {
00541    return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
00542 }
00543 
00544 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)
00545 {
00546    /* allocation */
00547    struct astobj2 *obj;
00548    struct astobj2_lock *obj_mutex;
00549    struct astobj2_rwlock *obj_rwlock;
00550 
00551    if (data_size < sizeof(void *)) {
00552       /*
00553        * We always alloc at least the size of a void *,
00554        * for debugging purposes.
00555        */
00556       data_size = sizeof(void *);
00557    }
00558 
00559    switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
00560    case AO2_ALLOC_OPT_LOCK_MUTEX:
00561 #if defined(__AST_DEBUG_MALLOC)
00562       obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
00563 #else
00564       obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
00565 #endif
00566       if (obj_mutex == NULL) {
00567          return NULL;
00568       }
00569 
00570       ast_mutex_init(&obj_mutex->mutex.lock);
00571       obj = (struct astobj2 *) &obj_mutex->priv_data;
00572       break;
00573    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00574 #if defined(__AST_DEBUG_MALLOC)
00575       obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
00576 #else
00577       obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
00578 #endif
00579       if (obj_rwlock == NULL) {
00580          return NULL;
00581       }
00582 
00583       ast_rwlock_init(&obj_rwlock->rwlock.lock);
00584       obj = (struct astobj2 *) &obj_rwlock->priv_data;
00585       break;
00586    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00587 #if defined(__AST_DEBUG_MALLOC)
00588       obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
00589 #else
00590       obj = ast_calloc(1, sizeof(*obj) + data_size);
00591 #endif
00592       if (obj == NULL) {
00593          return NULL;
00594       }
00595       break;
00596    default:
00597       /* Invalid option value. */
00598       ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
00599       return NULL;
00600    }
00601 
00602    /* Initialize common ao2 values. */
00603    obj->priv_data.ref_counter = 1;
00604    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00605    obj->priv_data.data_size = data_size;
00606    obj->priv_data.options = options;
00607    obj->priv_data.magic = AO2_MAGIC;
00608 
00609 #ifdef AO2_DEBUG
00610    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00611    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00612    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00613 #endif
00614 
00615    /* return a pointer to the user data */
00616    return EXTERNAL_OBJ(obj);
00617 }
00618 
00619 void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
00620    const char *file, int line, const char *func, int ref_debug)
00621 {
00622    /* allocation */
00623    void *obj;
00624 
00625    if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
00626       return NULL;
00627    }
00628 
00629    if (ref_log) {
00630       fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, func, tag);
00631       fflush(ref_log);
00632    }
00633 
00634    /* return a pointer to the user data */
00635    return obj;
00636 }
00637 
00638 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
00639 {
00640    return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
00641 }
00642 
00643 
00644 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
00645 {
00646    if (!holder) {
00647       /* For sanity */
00648       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00649       return;
00650    }
00651    if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
00652       /* Could not get the write lock. */
00653       return;
00654    }
00655 
00656    /* Release the held ao2 object. */
00657    if (holder->obj) {
00658       if (tag) {
00659          __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
00660       } else {
00661          __ao2_ref(holder->obj, -1);
00662       }
00663       holder->obj = NULL;
00664    }
00665 
00666    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00667 }
00668 
00669 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)
00670 {
00671    void *obj_old;
00672 
00673    if (!holder) {
00674       /* For sanity */
00675       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00676       return NULL;
00677    }
00678    if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
00679       /* Could not get the write lock. */
00680       return NULL;
00681    }
00682 
00683    if (obj) {
00684       if (tag) {
00685          __ao2_ref_debug(obj, +1, tag, file, line, func);
00686       } else {
00687          __ao2_ref(obj, +1);
00688       }
00689    }
00690    obj_old = holder->obj;
00691    holder->obj = obj;
00692 
00693    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00694 
00695    return obj_old;
00696 }
00697 
00698 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)
00699 {
00700    void *obj_old;
00701 
00702    obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
00703    if (obj_old) {
00704       if (tag) {
00705          __ao2_ref_debug(obj_old, -1, tag, file, line, func);
00706       } else {
00707          __ao2_ref(obj_old, -1);
00708       }
00709       return 1;
00710    }
00711    return 0;
00712 }
00713 
00714 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
00715 {
00716    void *obj;
00717 
00718    if (!holder) {
00719       /* For sanity */
00720       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00721       return NULL;
00722    }
00723 
00724    if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
00725       /* Could not get the read lock. */
00726       return NULL;
00727    }
00728 
00729    obj = holder->obj;
00730    if (obj) {
00731       if (tag) {
00732          __ao2_ref_debug(obj, +1, tag, file, line, func);
00733       } else {
00734          __ao2_ref(obj, +1);
00735       }
00736    }
00737 
00738    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00739 
00740    return obj;
00741 }
00742 
00743 /* internal callback to destroy a container. */
00744 static void container_destruct(void *c);
00745 
00746 /* internal callback to destroy a container. */
00747 static void container_destruct_debug(void *c);
00748 
00749 /*!
00750  * A structure to create a linked list of entries,
00751  * used within a bucket.
00752  * XXX \todo this should be private to the container code
00753  */
00754 struct bucket_entry {
00755    AST_LIST_ENTRY(bucket_entry) entry;
00756    int version;
00757    struct astobj2 *astobj;/* pointer to internal data */
00758 };
00759 
00760 /* each bucket in the container is a tailq. */
00761 AST_LIST_HEAD_NOLOCK(bucket, bucket_entry);
00762 
00763 /*!
00764  * A container; stores the hash and callback functions, information on
00765  * the size, the hash bucket heads, and a version number, starting at 0
00766  * (for a newly created, empty container)
00767  * and incremented every time an object is inserted or deleted.
00768  * The assumption is that an object is never moved in a container,
00769  * but removed and readded with the new number.
00770  * The version number is especially useful when implementing iterators.
00771  * In fact, we can associate a unique, monotonically increasing number to
00772  * each object, which means that, within an iterator, we can store the
00773  * version number of the current object, and easily look for the next one,
00774  * which is the next one in the list with a higher number.
00775  * Since all objects have a version >0, we can use 0 as a marker for
00776  * 'we need the first object in the bucket'.
00777  *
00778  * \todo Linking and unlink objects is typically expensive, as it
00779  * involves a malloc() of a small object which is very inefficient.
00780  * To optimize this, we allocate larger arrays of bucket_entry's
00781  * when we run out of them, and then manage our own freelist.
00782  * This will be more efficient as we can do the freelist management while
00783  * we hold the lock (that we need anyways).
00784  */
00785 struct ao2_container {
00786    ao2_hash_fn *hash_fn;
00787    ao2_callback_fn *cmp_fn;
00788    int n_buckets;
00789    /*! Number of elements in the container */
00790    int elements;
00791    /*! described above */
00792    int version;
00793    /*! variable size */
00794    struct bucket buckets[0];
00795 };
00796 
00797 /*!
00798  * \brief always zero hash function
00799  *
00800  * it is convenient to have a hash function that always returns 0.
00801  * This is basically used when we want to have a container that is
00802  * a simple linked list.
00803  *
00804  * \returns 0
00805  */
00806 static int hash_zero(const void *user_obj, const int flags)
00807 {
00808    return 0;
00809 }
00810 
00811 /*
00812  * A container is just an object, after all!
00813  */
00814 static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c,
00815    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
00816 {
00817    /* XXX maybe consistency check on arguments ? */
00818    /* compute the container size */
00819 
00820    if (!c) {
00821       return NULL;
00822    }
00823 
00824    c->version = 1;   /* 0 is a reserved value here */
00825    c->n_buckets = hash_fn ? n_buckets : 1;
00826    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00827    c->cmp_fn = cmp_fn;
00828 
00829 #ifdef AO2_DEBUG
00830    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00831 #endif
00832 
00833    return c;
00834 }
00835 
00836 struct ao2_container *__ao2_container_alloc_debug(unsigned int options,
00837    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
00838    const char *tag, const char *file, int line, const char *func, int ref_debug)
00839 {
00840    /* XXX maybe consistency check on arguments ? */
00841    /* compute the container size */
00842    unsigned int num_buckets = hash_fn ? n_buckets : 1;
00843    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00844    struct ao2_container *c = __ao2_alloc_debug(container_size, ref_debug ? container_destruct_debug : container_destruct, options, tag, file, line, func, ref_debug);
00845 
00846    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00847 }
00848 
00849 struct ao2_container *__ao2_container_alloc(unsigned int options,
00850    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
00851 {
00852    /* XXX maybe consistency check on arguments ? */
00853    /* compute the container size */
00854    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00855    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00856    struct ao2_container *c = __ao2_alloc(container_size, container_destruct, options);
00857 
00858    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00859 }
00860 
00861 /*!
00862  * return the number of elements in the container
00863  */
00864 int ao2_container_count(struct ao2_container *c)
00865 {
00866    return c->elements;
00867 }
00868 
00869 /*
00870  * link an object to a container
00871  */
00872 static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func)
00873 {
00874    int i;
00875    enum ao2_lock_req orig_lock;
00876    /* create a new list entry */
00877    struct bucket_entry *p;
00878    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00879 
00880    if (obj == NULL) {
00881       return NULL;
00882    }
00883 
00884    if (INTERNAL_OBJ(c) == NULL) {
00885       return NULL;
00886    }
00887 
00888    p = ast_calloc(1, sizeof(*p));
00889    if (!p) {
00890       return NULL;
00891    }
00892 
00893    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00894 
00895    if (flags & OBJ_NOLOCK) {
00896       orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
00897    } else {
00898       ao2_wrlock(c);
00899       orig_lock = AO2_LOCK_REQ_MUTEX;
00900    }
00901 
00902    i %= c->n_buckets;
00903    p->astobj = obj;
00904    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00905    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00906    ast_atomic_fetchadd_int(&c->elements, 1);
00907 
00908    if (tag) {
00909       __ao2_ref_debug(user_data, +1, tag, file, line, func);
00910    } else {
00911       __ao2_ref(user_data, +1);
00912    }
00913 
00914    if (flags & OBJ_NOLOCK) {
00915       adjust_lock(c, orig_lock, 0);
00916    } else {
00917       ao2_unlock(c);
00918    }
00919 
00920    return p;
00921 }
00922 
00923 void *__ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
00924 {
00925    return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
00926 }
00927 
00928 void *__ao2_link(struct ao2_container *c, void *obj_new, int flags)
00929 {
00930    return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00931 }
00932 
00933 /*!
00934  * \brief another convenience function is a callback that matches on address
00935  */
00936 int ao2_match_by_addr(void *user_data, void *arg, int flags)
00937 {
00938    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00939 }
00940 
00941 /*
00942  * Unlink an object from the container
00943  * and destroy the associated * bucket_entry structure.
00944  */
00945 void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
00946    const char *tag, const char *file, int line, const char *func)
00947 {
00948    if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
00949       return NULL;
00950    }
00951 
00952    flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
00953    __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
00954 
00955    return NULL;
00956 }
00957 
00958 void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
00959 {
00960    if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
00961       return NULL;
00962    }
00963 
00964    flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
00965    __ao2_callback(c, flags, ao2_match_by_addr, user_data);
00966 
00967    return NULL;
00968 }
00969 
00970 /*!
00971  * \brief special callback that matches all
00972  */
00973 static int cb_true(void *user_data, void *arg, int flags)
00974 {
00975    return CMP_MATCH;
00976 }
00977 
00978 /*!
00979  * \brief similar to cb_true, but is an ao2_callback_data_fn instead
00980  */
00981 static int cb_true_data(void *user_data, void *arg, void *data, int flags)
00982 {
00983    return CMP_MATCH;
00984 }
00985 
00986 /*!
00987  * Browse the container using different stategies accoding the flags.
00988  * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
00989  * specified.
00990  * Luckily, for debug purposes, the added args (tag, file, line, func)
00991  * aren't an excessive load to the system, as the callback should not be
00992  * called as often as, say, the ao2_ref func is called.
00993  */
00994 static void *internal_ao2_callback(struct ao2_container *c, enum search_flags flags,
00995    void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag,
00996    const char *file, int line, const char *func)
00997 {
00998    int i, start, last;  /* search boundaries */
00999    enum ao2_lock_req orig_lock;
01000    void *ret = NULL;
01001    ao2_callback_fn *cb_default = NULL;
01002    ao2_callback_data_fn *cb_withdata = NULL;
01003    struct ao2_container *multi_container = NULL;
01004    struct ao2_iterator *multi_iterator = NULL;
01005 
01006    if (INTERNAL_OBJ(c) == NULL) {   /* safety check on the argument */
01007       return NULL;
01008    }
01009 
01010    /*
01011     * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
01012     * turned off.  This if statement checks for the special condition
01013     * where multiple items may need to be returned.
01014     */
01015    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
01016       /* we need to return an ao2_iterator with the results,
01017        * as there could be more than one. the iterator will
01018        * hold the only reference to a container that has all the
01019        * matching objects linked into it, so when the iterator
01020        * is destroyed, the container will be automatically
01021        * destroyed as well.
01022        */
01023       multi_container = __ao2_container_alloc(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
01024       if (!multi_container) {
01025          return NULL;
01026       }
01027       if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
01028          ao2_ref(multi_container, -1);
01029          return NULL;
01030       }
01031    }
01032 
01033    /* override the match function if necessary */
01034    if (cb_fn == NULL) { /* if NULL, match everything */
01035       if (type == WITH_DATA) {
01036          cb_withdata = cb_true_data;
01037       } else {
01038          cb_default = cb_true;
01039       }
01040    } else {
01041       /* We do this here to avoid the per object casting penalty (even though
01042          that is probably optimized away anyway). */
01043       if (type == WITH_DATA) {
01044          cb_withdata = cb_fn;
01045       } else {
01046          cb_default = cb_fn;
01047       }
01048    }
01049 
01050    /*
01051     * XXX this can be optimized.
01052     * If we have a hash function and lookup by pointer,
01053     * run the hash function. Otherwise, scan the whole container
01054     * (this only for the time being. We need to optimize this.)
01055     */
01056    if ((flags & (OBJ_POINTER | OBJ_KEY))) {
01057       /* we know hash can handle this case */
01058       start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
01059    } else {
01060       /* don't know, let's scan all buckets */
01061       start = i = -1;      /* XXX this must be fixed later. */
01062    }
01063 
01064    /* determine the search boundaries: i..last-1 */
01065    if (i < 0) {
01066       start = i = 0;
01067       last = c->n_buckets;
01068    } else if ((flags & OBJ_CONTINUE)) {
01069       last = c->n_buckets;
01070    } else {
01071       last = i + 1;
01072    }
01073 
01074    /* avoid modifications to the content */
01075    if (flags & OBJ_NOLOCK) {
01076       if (flags & OBJ_UNLINK) {
01077          orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
01078       } else {
01079          orig_lock = adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
01080       }
01081    } else {
01082       orig_lock = AO2_LOCK_REQ_MUTEX;
01083       if (flags & OBJ_UNLINK) {
01084          ao2_wrlock(c);
01085       } else {
01086          ao2_rdlock(c);
01087       }
01088    }
01089 
01090    for (; i < last ; i++) {
01091       /* scan the list with prev-cur pointers */
01092       struct bucket_entry *cur;
01093 
01094       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
01095          int match = (CMP_MATCH | CMP_STOP);
01096 
01097          if (type == WITH_DATA) {
01098             match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
01099          } else {
01100             match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
01101          }
01102 
01103          /* we found the object, performing operations according flags */
01104          if (match == 0) { /* no match, no stop, continue */
01105             continue;
01106          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
01107             i = last;
01108             break;
01109          }
01110 
01111          /* we have a match (CMP_MATCH) here */
01112          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
01113             /* it is important to handle this case before the unlink */
01114             ret = EXTERNAL_OBJ(cur->astobj);
01115             if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
01116                if (tag) {
01117                   __ao2_ref_debug(ret, 1, tag, file, line, func);
01118                } else {
01119                   __ao2_ref(ret, 1);
01120                }
01121             }
01122          }
01123 
01124          /* If we are in OBJ_MULTIPLE mode and OBJ_NODATA is off,
01125           * link the object into the container that will hold the results.
01126           */
01127          if (ret && (multi_container != NULL)) {
01128             if (tag) {
01129                __ao2_link_debug(multi_container, ret, flags, tag, file, line, func);
01130             } else {
01131                __ao2_link(multi_container, ret, flags);
01132             }
01133             ret = NULL;
01134          }
01135 
01136          if (flags & OBJ_UNLINK) {  /* must unlink */
01137             /* we are going to modify the container, so update version */
01138             ast_atomic_fetchadd_int(&c->version, 1);
01139             AST_LIST_REMOVE_CURRENT(entry);
01140             /* update number of elements */
01141             ast_atomic_fetchadd_int(&c->elements, -1);
01142 
01143             /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
01144              * must be decremented.
01145              * - When unlinking with OBJ_MULTIPLE the ref from the original container
01146              * must be decremented regardless if OBJ_NODATA is used. This is because the result is
01147              * returned in a new container that already holds its own ref for the object. If the ref
01148              * from the original container is not accounted for here a memory leak occurs. */
01149             if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
01150                if (tag)
01151                   __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, func);
01152                else
01153                   __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
01154             }
01155             ast_free(cur); /* free the link record */
01156          }
01157 
01158          if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
01159             /* We found our only (or last) match, so force an exit from
01160                the outside loop. */
01161             i = last;
01162             break;
01163          }
01164       }
01165       AST_LIST_TRAVERSE_SAFE_END;
01166 
01167       if (ret) {
01168          break;
01169       }
01170 
01171       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
01172          /* Move to the beginning to ensure we check every bucket */
01173          i = -1;
01174          last = start;
01175       }
01176    }
01177 
01178    if (flags & OBJ_NOLOCK) {
01179       adjust_lock(c, orig_lock, 0);
01180    } else {
01181       ao2_unlock(c);
01182    }
01183 
01184    /* if multi_container was created, we are returning multiple objects */
01185    if (multi_container != NULL) {
01186       *multi_iterator = ao2_iterator_init(multi_container,
01187          AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
01188       ao2_ref(multi_container, -1);
01189       return multi_iterator;
01190    } else {
01191       return ret;
01192    }
01193 }
01194 
01195 void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
01196    ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
01197    const char *func)
01198 {
01199    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
01200 }
01201 
01202 void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
01203    ao2_callback_fn *cb_fn, void *arg)
01204 {
01205    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
01206 }
01207 
01208 void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
01209    ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
01210    int line, const char *func)
01211 {
01212    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
01213 }
01214 
01215 void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
01216    ao2_callback_data_fn *cb_fn, void *arg, void *data)
01217 {
01218    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
01219 }
01220 
01221 /*!
01222  * the find function just invokes the default callback with some reasonable flags.
01223  */
01224 void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
01225    const char *tag, const char *file, int line, const char *func)
01226 {
01227    void *arged = (void *) arg;/* Done to avoid compiler const warning */
01228 
01229    return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
01230 }
01231 
01232 void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
01233 {
01234    void *arged = (void *) arg;/* Done to avoid compiler const warning */
01235 
01236    return __ao2_callback(c, flags, c->cmp_fn, arged);
01237 }
01238 
01239 /*!
01240  * initialize an iterator so we start from the first object
01241  */
01242 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
01243 {
01244    struct ao2_iterator a = {
01245       .c = c,
01246       .flags = flags
01247    };
01248 
01249    ao2_ref(c, +1);
01250 
01251    return a;
01252 }
01253 
01254 /*!
01255  * destroy an iterator
01256  */
01257 void ao2_iterator_destroy(struct ao2_iterator *iter)
01258 {
01259    ao2_ref(iter->c, -1);
01260    if (iter->flags & AO2_ITERATOR_MALLOCD) {
01261       ast_free(iter);
01262    } else {
01263       iter->c = NULL;
01264    }
01265 }
01266 
01267 /*
01268  * move to the next element in the container.
01269  */
01270 static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
01271 {
01272    int lim;
01273    enum ao2_lock_req orig_lock;
01274    struct bucket_entry *p = NULL;
01275    void *ret;
01276 
01277    if (INTERNAL_OBJ(iter->c) == NULL) {
01278       return NULL;
01279    }
01280 
01281    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
01282       if (iter->flags & AO2_ITERATOR_UNLINK) {
01283          orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
01284       } else {
01285          orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
01286       }
01287    } else {
01288       orig_lock = AO2_LOCK_REQ_MUTEX;
01289       if (iter->flags & AO2_ITERATOR_UNLINK) {
01290          ao2_wrlock(iter->c);
01291       } else {
01292          ao2_rdlock(iter->c);
01293       }
01294    }
01295 
01296    /* optimization. If the container is unchanged and
01297     * we have a pointer, try follow it
01298     */
01299    if (iter->c->version == iter->c_version && (p = iter->obj)) {
01300       if ((p = AST_LIST_NEXT(p, entry))) {
01301          goto found;
01302       }
01303       /* nope, start from the next bucket */
01304       iter->bucket++;
01305       iter->version = 0;
01306       iter->obj = NULL;
01307    }
01308 
01309    lim = iter->c->n_buckets;
01310 
01311    /* Browse the buckets array, moving to the next
01312     * buckets if we don't find the entry in the current one.
01313     * Stop when we find an element with version number greater
01314     * than the current one (we reset the version to 0 when we
01315     * switch buckets).
01316     */
01317    for (; iter->bucket < lim; iter->bucket++, iter->version = 0) {
01318       /* scan the current bucket */
01319       AST_LIST_TRAVERSE(&iter->c->buckets[iter->bucket], p, entry) {
01320          if (p->version > iter->version) {
01321             goto found;
01322          }
01323       }
01324    }
01325 
01326 found:
01327    if (p) {
01328       ret = EXTERNAL_OBJ(p->astobj);
01329       if (iter->flags & AO2_ITERATOR_UNLINK) {
01330          /* we are going to modify the container, so update version */
01331          ast_atomic_fetchadd_int(&iter->c->version, 1);
01332          AST_LIST_REMOVE(&iter->c->buckets[iter->bucket], p, entry);
01333          /* update number of elements */
01334          ast_atomic_fetchadd_int(&iter->c->elements, -1);
01335          iter->version = 0;
01336          iter->obj = NULL;
01337          iter->c_version = iter->c->version;
01338          ast_free(p);
01339       } else {
01340          iter->version = p->version;
01341          iter->obj = p;
01342          iter->c_version = iter->c->version;
01343 
01344          /* inc refcount of returned object */
01345          if (tag) {
01346             __ao2_ref_debug(ret, 1, tag, file, line, func);
01347          } else {
01348             __ao2_ref(ret, 1);
01349          }
01350       }
01351    } else {
01352       ret = NULL;
01353    }
01354 
01355    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
01356       adjust_lock(iter->c, orig_lock, 0);
01357    } else {
01358       ao2_unlock(iter->c);
01359    }
01360 
01361    return ret;
01362 }
01363 
01364 void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
01365 {
01366    return internal_ao2_iterator_next(iter, tag, file, line, func);
01367 }
01368 
01369 void *__ao2_iterator_next(struct ao2_iterator *iter)
01370 {
01371    return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
01372 }
01373 
01374 /* callback for destroying container.
01375  * we can make it simple as we know what it does
01376  */
01377 static int cd_cb(void *obj, void *arg, int flag)
01378 {
01379    __ao2_ref(obj, -1);
01380    return 0;
01381 }
01382 
01383 static int cd_cb_debug(void *obj, void *arg, int flag)
01384 {
01385    __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
01386    return 0;
01387 }
01388 
01389 static void container_destruct(void *_c)
01390 {
01391    struct ao2_container *c = _c;
01392    int i;
01393 
01394    __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
01395 
01396    for (i = 0; i < c->n_buckets; i++) {
01397       struct bucket_entry *current;
01398 
01399       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
01400          ast_free(current);
01401       }
01402    }
01403 
01404 #ifdef AO2_DEBUG
01405    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
01406 #endif
01407 }
01408 
01409 static void container_destruct_debug(void *_c)
01410 {
01411    struct ao2_container *c = _c;
01412    int i;
01413 
01414    __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
01415 
01416    for (i = 0; i < c->n_buckets; i++) {
01417       struct bucket_entry *current;
01418 
01419       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
01420          ast_free(current);
01421       }
01422    }
01423 
01424 #ifdef AO2_DEBUG
01425    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
01426 #endif
01427 }
01428 
01429 /*!
01430  * \internal
01431  * \brief Put obj into the arg container.
01432  * \since 11.0
01433  *
01434  * \param obj  pointer to the (user-defined part) of an object.
01435  * \param arg callback argument from ao2_callback()
01436  * \param flags flags from ao2_callback()
01437  *
01438  * \retval 0 on success.
01439  * \retval CMP_STOP|CMP_MATCH on error.
01440  */
01441 static int dup_obj_cb(void *obj, void *arg, int flags)
01442 {
01443    struct ao2_container *dest = arg;
01444 
01445    return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
01446 }
01447 
01448 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
01449 {
01450    void *obj;
01451    int res = 0;
01452 
01453    if (!(flags & OBJ_NOLOCK)) {
01454       ao2_rdlock(src);
01455       ao2_wrlock(dest);
01456    }
01457    obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
01458    if (obj) {
01459       /* Failed to put this obj into the dest container. */
01460       __ao2_ref(obj, -1);
01461 
01462       /* Remove all items from the dest container. */
01463       __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
01464          NULL);
01465       res = -1;
01466    }
01467    if (!(flags & OBJ_NOLOCK)) {
01468       ao2_unlock(dest);
01469       ao2_unlock(src);
01470    }
01471 
01472    return res;
01473 }
01474 
01475 struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
01476 {
01477    struct ao2_container *clone;
01478    struct astobj2 *orig_obj;
01479    unsigned int options;
01480    int failed;
01481 
01482    orig_obj = INTERNAL_OBJ(orig);
01483    if (!orig_obj) {
01484       return NULL;
01485    }
01486    options = orig_obj->priv_data.options;
01487 
01488    /* Create the clone container with the same properties as the original. */
01489    clone = __ao2_container_alloc(options, orig->n_buckets, orig->hash_fn, orig->cmp_fn);
01490    if (!clone) {
01491       return NULL;
01492    }
01493 
01494    if (flags & OBJ_NOLOCK) {
01495       ao2_wrlock(clone);
01496    }
01497    failed = ao2_container_dup(clone, orig, flags);
01498    if (flags & OBJ_NOLOCK) {
01499       ao2_unlock(clone);
01500    }
01501    if (failed) {
01502       /* Object copy into the clone container failed. */
01503       __ao2_ref(clone, -1);
01504       clone = NULL;
01505    }
01506    return clone;
01507 }
01508 
01509 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)
01510 {
01511    struct ao2_container *clone;
01512    struct astobj2 *orig_obj;
01513    unsigned int options;
01514    int failed;
01515 
01516    orig_obj = INTERNAL_OBJ(orig);
01517    if (!orig_obj) {
01518       return NULL;
01519    }
01520    options = orig_obj->priv_data.options;
01521 
01522    /* Create the clone container with the same properties as the original. */
01523    clone = __ao2_container_alloc_debug(options, orig->n_buckets, orig->hash_fn,
01524       orig->cmp_fn, tag, file, line, func, ref_debug);
01525    if (!clone) {
01526       return NULL;
01527    }
01528 
01529    if (flags & OBJ_NOLOCK) {
01530       ao2_wrlock(clone);
01531    }
01532    failed = ao2_container_dup(clone, orig, flags);
01533    if (flags & OBJ_NOLOCK) {
01534       ao2_unlock(clone);
01535    }
01536    if (failed) {
01537       /* Object copy into the clone container failed. */
01538       if (ref_debug) {
01539          __ao2_ref_debug(clone, -1, tag, file, line, func);
01540       } else {
01541          __ao2_ref(clone, -1);
01542       }
01543       clone = NULL;
01544    }
01545    return clone;
01546 }
01547 
01548 void __ao2_cleanup_debug(void *obj, const char *file, int line, const char *function)
01549 {
01550    if (obj) {
01551       __ao2_ref_debug(obj, -1, "ao2_cleanup", file, line, function);
01552    }
01553 }
01554 
01555 void __ao2_cleanup(void *obj)
01556 {
01557    if (obj) {
01558       ao2_ref(obj, -1);
01559    }
01560 }
01561 
01562 void ao2_iterator_cleanup(struct ao2_iterator *iter)
01563 {
01564    if (iter) {
01565       ao2_iterator_destroy(iter);
01566    }
01567 }
01568 
01569 #ifdef AO2_DEBUG
01570 static int print_cb(void *obj, void *arg, int flag)
01571 {
01572    struct ast_cli_args *a = (struct ast_cli_args *) arg;
01573    char *s = (char *)obj;
01574 
01575    ast_cli(a->fd, "string <%s>\n", s);
01576    return 0;
01577 }
01578 
01579 /*
01580  * Print stats
01581  */
01582 static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01583 {
01584    switch (cmd) {
01585    case CLI_INIT:
01586       e->command = "astobj2 show stats";
01587       e->usage = "Usage: astobj2 show stats\n"
01588             "       Show astobj2 show stats\n";
01589       return NULL;
01590    case CLI_GENERATE:
01591       return NULL;
01592    }
01593    ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
01594    ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
01595    ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
01596    ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
01597    ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
01598    return CLI_SUCCESS;
01599 }
01600 
01601 /*
01602  * This is testing code for astobj
01603  */
01604 static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01605 {
01606    struct ao2_container *c1;
01607    struct ao2_container *c2;
01608    int i, lim;
01609    char *obj;
01610    static int prof_id = -1;
01611    struct ast_cli_args fake_args = { a->fd, 0, NULL };
01612 
01613    switch (cmd) {
01614    case CLI_INIT:
01615       e->command = "astobj2 test";
01616       e->usage = "Usage: astobj2 test <num>\n"
01617             "       Runs astobj2 test. Creates 'num' objects,\n"
01618             "       and test iterators, callbacks and may be other stuff\n";
01619       return NULL;
01620    case CLI_GENERATE:
01621       return NULL;
01622    }
01623 
01624    if (a->argc != 3) {
01625       return CLI_SHOWUSAGE;
01626    }
01627 
01628    if (prof_id == -1)
01629       prof_id = ast_add_profile("ao2_alloc", 0);
01630 
01631    ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
01632    lim = atoi(a->argv[2]);
01633    ast_cli(a->fd, "called astobj_test\n");
01634 
01635    handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
01636    /*
01637     * allocate a container with no default callback, and no hash function.
01638     * No hash means everything goes in the same bucket.
01639     */
01640    c1 = ao2_t_container_alloc(100, NULL /* no callback */, NULL /* no hash */,"test");
01641    ast_cli(a->fd, "container allocated as %p\n", c1);
01642 
01643    /*
01644     * fill the container with objects.
01645     * ao2_alloc() gives us a reference which we pass to the
01646     * container when we do the insert.
01647     */
01648    for (i = 0; i < lim; i++) {
01649       ast_mark(prof_id, 1 /* start */);
01650       obj = ao2_t_alloc(80, NULL,"test");
01651       ast_mark(prof_id, 0 /* stop */);
01652       ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
01653       sprintf(obj, "-- this is obj %d --", i);
01654       ao2_link(c1, obj);
01655       /* At this point, the refcount on obj is 2 due to the allocation
01656        * and linking. We can go ahead and reduce the refcount by 1
01657        * right here so that when the container is unreffed later, the
01658        * objects will be freed
01659        */
01660       ao2_t_ref(obj, -1, "test");
01661    }
01662 
01663    ast_cli(a->fd, "testing callbacks\n");
01664    ao2_t_callback(c1, 0, print_cb, a, "test callback");
01665 
01666    ast_cli(a->fd, "testing container cloning\n");
01667    c2 = ao2_container_clone(c1, 0);
01668    if (ao2_container_count(c1) != ao2_container_count(c2)) {
01669       ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
01670    }
01671    ao2_t_callback(c2, 0, print_cb, a, "test callback");
01672 
01673    ast_cli(a->fd, "testing iterators, remove every second object\n");
01674    {
01675       struct ao2_iterator ai;
01676       int x = 0;
01677 
01678       ai = ao2_iterator_init(c1, 0);
01679       while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
01680          ast_cli(a->fd, "iterator on <%s>\n", obj);
01681          if (x++ & 1)
01682             ao2_t_unlink(c1, obj,"test");
01683          ao2_t_ref(obj, -1,"test");
01684       }
01685       ao2_iterator_destroy(&ai);
01686       ast_cli(a->fd, "testing iterators again\n");
01687       ai = ao2_iterator_init(c1, 0);
01688       while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
01689          ast_cli(a->fd, "iterator on <%s>\n", obj);
01690          ao2_t_ref(obj, -1,"test");
01691       }
01692       ao2_iterator_destroy(&ai);
01693    }
01694 
01695    ast_cli(a->fd, "testing callbacks again\n");
01696    ao2_t_callback(c1, 0, print_cb, a, "test callback");
01697 
01698    ast_verbose("now you should see an error message:\n");
01699    ao2_t_ref(&i, -1, "");  /* i is not a valid object so we print an error here */
01700 
01701    ast_cli(a->fd, "destroy container\n");
01702    ao2_t_ref(c1, -1, "");  /* destroy container */
01703    ao2_t_ref(c2, -1, "");  /* destroy container */
01704    handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
01705    return CLI_SUCCESS;
01706 }
01707 
01708 static struct ast_cli_entry cli_astobj2[] = {
01709    AST_CLI_DEFINE(handle_astobj2_stats, "Print astobj2 statistics"),
01710    AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
01711 };
01712 #endif /* AO2_DEBUG */
01713 
01714 static void astobj2_cleanup(void)
01715 {
01716 #ifdef AO2_DEBUG
01717    ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01718 #endif
01719 
01720 #ifdef REF_DEBUG
01721    fclose(ref_log);
01722    ref_log = NULL;
01723 #endif
01724 }
01725 
01726 int astobj2_init(void)
01727 {
01728 #ifdef REF_DEBUG
01729    char ref_filename[1024];
01730 #endif
01731 
01732 #ifdef REF_DEBUG
01733    snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
01734    ref_log = fopen(ref_filename, "w");
01735    if (!ref_log) {
01736       ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
01737    }
01738 #endif
01739 
01740 #ifdef AO2_DEBUG
01741    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01742 #endif
01743 
01744    ast_register_atexit(astobj2_cleanup);
01745 
01746    return 0;
01747 }