237d0ca85dc82015d6f09e4b96b6ba2885156887
[asterisk/asterisk.git] / main / astobj2.c
1 /*
2  * astobj2 - replacement containers for asterisk data structures.
3  *
4  * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*
18  * Function implementing astobj2 objects.
19  */
20 #include "asterisk.h"
21
22 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
23
24 #include "asterisk/_private.h"
25 #include "asterisk/astobj2.h"
26 #include "asterisk/utils.h"
27 #include "asterisk/cli.h"
28 #define REF_FILE "/tmp/refs"
29
30 #if defined(TEST_FRAMEWORK)
31 /* We are building with the test framework enabled so enable AO2 debug tests as well. */
32 #define AO2_DEBUG 1
33 #endif  /* defined(TEST_FRAMEWORK) */
34
35 /*!
36  * astobj2 objects are always preceded by this data structure,
37  * which contains a reference counter,
38  * option flags and a pointer to a destructor.
39  * The refcount is used to decide when it is time to
40  * invoke the destructor.
41  * The magic number is used for consistency check.
42  */
43 struct __priv_data {
44         int ref_counter;
45         ao2_destructor_fn destructor_fn;
46         /*! User data size for stats */
47         size_t data_size;
48         /*! The ao2 object option flags */
49         uint32_t options;
50         /*! magic number.  This is used to verify that a pointer passed in is a
51          *  valid astobj2 */
52         uint32_t magic;
53 };
54
55 #define AO2_MAGIC       0xa570b123
56
57 /*!
58  * What an astobj2 object looks like: fixed-size private data
59  * followed by variable-size user data.
60  */
61 struct astobj2 {
62         struct __priv_data priv_data;
63         void *user_data[0];
64 };
65
66 struct ao2_lock_priv {
67         ast_mutex_t lock;
68 };
69
70 /* AstObj2 with recursive lock. */
71 struct astobj2_lock {
72         struct ao2_lock_priv mutex;
73         struct __priv_data priv_data;
74         void *user_data[0];
75 };
76
77 struct ao2_rwlock_priv {
78         ast_rwlock_t lock;
79         /*! Count of the number of threads holding a lock on this object. -1 if it is the write lock. */
80         int num_lockers;
81 };
82
83 /* AstObj2 with RW lock. */
84 struct astobj2_rwlock {
85         struct ao2_rwlock_priv rwlock;
86         struct __priv_data priv_data;
87         void *user_data[0];
88 };
89
90 #ifdef AO2_DEBUG
91 struct ao2_stats {
92         volatile int total_objects;
93         volatile int total_mem;
94         volatile int total_containers;
95         volatile int total_refs;
96         volatile int total_locked;
97 };
98
99 static struct ao2_stats ao2;
100 #endif
101
102 #ifndef HAVE_BKTR       /* backtrace support */
103 void ao2_bt(void) {}
104 #else
105 #include <execinfo.h>    /* for backtrace */
106
107 void ao2_bt(void)
108 {
109         int c, i;
110 #define N1      20
111         void *addresses[N1];
112         char **strings;
113
114         c = backtrace(addresses, N1);
115         strings = ast_bt_get_symbols(addresses,c);
116         ast_verbose("backtrace returned: %d\n", c);
117         for(i = 0; i < c; i++) {
118                 ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
119         }
120         free(strings);
121 }
122 #endif
123
124 #define INTERNAL_OBJ_MUTEX(user_data) \
125         ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
126
127 #define INTERNAL_OBJ_RWLOCK(user_data) \
128         ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
129
130 /*!
131  * \brief convert from a pointer _p to a user-defined object
132  *
133  * \return the pointer to the astobj2 structure
134  */
135 static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
136 {
137         struct astobj2 *p;
138
139         if (!user_data) {
140                 ast_log(LOG_ERROR, "user_data is NULL\n");
141                 return NULL;
142         }
143
144         p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
145         if (AO2_MAGIC != p->priv_data.magic) {
146                 if (p->priv_data.magic) {
147                         ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p);
148                 } else {
149                         ast_log(LOG_ERROR,
150                                 "bad magic number for %p. Object is likely destroyed.\n", p);
151                 }
152                 return NULL;
153         }
154
155         return p;
156 }
157
158 enum ao2_callback_type {
159         DEFAULT,
160         WITH_DATA,
161 };
162
163 /*!
164  * \brief convert from a pointer _p to an astobj2 object
165  *
166  * \return the pointer to the user-defined portion.
167  */
168 #define EXTERNAL_OBJ(_p)        ((_p) == NULL ? NULL : (_p)->user_data)
169
170 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
171 {
172         struct astobj2 *obj = INTERNAL_OBJ(user_data);
173         struct astobj2_lock *obj_mutex;
174         struct astobj2_rwlock *obj_rwlock;
175         int res = 0;
176
177         if (obj == NULL) {
178                 return -1;
179         }
180
181         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
182         case AO2_ALLOC_OPT_LOCK_MUTEX:
183                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
184                 res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
185 #ifdef AO2_DEBUG
186                 if (!res) {
187                         ast_atomic_fetchadd_int(&ao2.total_locked, 1);
188                 }
189 #endif
190                 break;
191         case AO2_ALLOC_OPT_LOCK_RWLOCK:
192                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
193                 switch (lock_how) {
194                 case AO2_LOCK_REQ_MUTEX:
195                 case AO2_LOCK_REQ_WRLOCK:
196                         res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
197                         if (!res) {
198                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
199 #ifdef AO2_DEBUG
200                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
201 #endif
202                         }
203                         break;
204                 case AO2_LOCK_REQ_RDLOCK:
205                         res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
206                         if (!res) {
207                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
208 #ifdef AO2_DEBUG
209                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
210 #endif
211                         }
212                         break;
213                 }
214                 break;
215         case AO2_ALLOC_OPT_LOCK_NOLOCK:
216                 /* The ao2 object has no lock. */
217                 break;
218         default:
219                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
220                         user_data);
221                 return -1;
222         }
223
224         return res;
225 }
226
227 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
228 {
229         struct astobj2 *obj = INTERNAL_OBJ(user_data);
230         struct astobj2_lock *obj_mutex;
231         struct astobj2_rwlock *obj_rwlock;
232         int res = 0;
233         int current_value;
234
235         if (obj == NULL) {
236                 return -1;
237         }
238
239         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
240         case AO2_ALLOC_OPT_LOCK_MUTEX:
241                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
242                 res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
243 #ifdef AO2_DEBUG
244                 if (!res) {
245                         ast_atomic_fetchadd_int(&ao2.total_locked, -1);
246                 }
247 #endif
248                 break;
249         case AO2_ALLOC_OPT_LOCK_RWLOCK:
250                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
251
252                 current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
253                 if (current_value < 0) {
254                         /* It was a WRLOCK that we are unlocking.  Fix the count. */
255                         ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
256                 }
257                 res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
258 #ifdef AO2_DEBUG
259                 if (!res) {
260                         ast_atomic_fetchadd_int(&ao2.total_locked, -1);
261                 }
262 #endif
263                 break;
264         case AO2_ALLOC_OPT_LOCK_NOLOCK:
265                 /* The ao2 object has no lock. */
266                 break;
267         default:
268                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
269                         user_data);
270                 res = -1;
271                 break;
272         }
273         return res;
274 }
275
276 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
277 {
278         struct astobj2 *obj = INTERNAL_OBJ(user_data);
279         struct astobj2_lock *obj_mutex;
280         struct astobj2_rwlock *obj_rwlock;
281         int res = 0;
282
283         if (obj == NULL) {
284                 return -1;
285         }
286
287         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
288         case AO2_ALLOC_OPT_LOCK_MUTEX:
289                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
290                 res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
291 #ifdef AO2_DEBUG
292                 if (!res) {
293                         ast_atomic_fetchadd_int(&ao2.total_locked, 1);
294                 }
295 #endif
296                 break;
297         case AO2_ALLOC_OPT_LOCK_RWLOCK:
298                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
299                 switch (lock_how) {
300                 case AO2_LOCK_REQ_MUTEX:
301                 case AO2_LOCK_REQ_WRLOCK:
302                         res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
303                         if (!res) {
304                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
305 #ifdef AO2_DEBUG
306                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
307 #endif
308                         }
309                         break;
310                 case AO2_LOCK_REQ_RDLOCK:
311                         res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
312                         if (!res) {
313                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
314 #ifdef AO2_DEBUG
315                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
316 #endif
317                         }
318                         break;
319                 }
320                 break;
321         case AO2_ALLOC_OPT_LOCK_NOLOCK:
322                 /* The ao2 object has no lock. */
323                 return 0;
324         default:
325                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
326                         user_data);
327                 return -1;
328         }
329
330
331         return res;
332 }
333
334 /*!
335  * \internal
336  * \brief Adjust an object's lock to the requested level.
337  *
338  * \param user_data An ao2 object to adjust lock level.
339  * \param lock_how What level to adjust lock.
340  * \param keep_stronger TRUE if keep original lock level if it is stronger.
341  *
342  * \pre The ao2 object is already locked.
343  *
344  * \details
345  * An ao2 object with a RWLOCK will have its lock level adjusted
346  * to the specified level if it is not already there.  An ao2
347  * object with a different type of lock is not affected.
348  *
349  * \return Original lock level.
350  */
351 static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
352 {
353         struct astobj2 *obj = INTERNAL_OBJ(user_data);
354         struct astobj2_rwlock *obj_rwlock;
355         enum ao2_lock_req orig_lock;
356
357         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
358         case AO2_ALLOC_OPT_LOCK_RWLOCK:
359                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
360                 if (obj_rwlock->rwlock.num_lockers < 0) {
361                         orig_lock = AO2_LOCK_REQ_WRLOCK;
362                 } else {
363                         orig_lock = AO2_LOCK_REQ_RDLOCK;
364                 }
365                 switch (lock_how) {
366                 case AO2_LOCK_REQ_MUTEX:
367                         lock_how = AO2_LOCK_REQ_WRLOCK;
368                         /* Fall through */
369                 case AO2_LOCK_REQ_WRLOCK:
370                         if (lock_how != orig_lock) {
371                                 /* Switch from read lock to write lock. */
372                                 ao2_unlock(user_data);
373                                 ao2_wrlock(user_data);
374                         }
375                         break;
376                 case AO2_LOCK_REQ_RDLOCK:
377                         if (!keep_stronger && lock_how != orig_lock) {
378                                 /* Switch from write lock to read lock. */
379                                 ao2_unlock(user_data);
380                                 ao2_rdlock(user_data);
381                         }
382                         break;
383                 }
384                 break;
385         default:
386                 ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
387                 /* Fall through */
388         case AO2_ALLOC_OPT_LOCK_NOLOCK:
389         case AO2_ALLOC_OPT_LOCK_MUTEX:
390                 orig_lock = AO2_LOCK_REQ_MUTEX;
391                 break;
392         }
393
394         return orig_lock;
395 }
396
397 void *ao2_object_get_lockaddr(void *user_data)
398 {
399         struct astobj2 *obj = INTERNAL_OBJ(user_data);
400         struct astobj2_lock *obj_mutex;
401
402         if (obj == NULL) {
403                 return NULL;
404         }
405
406         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
407         case AO2_ALLOC_OPT_LOCK_MUTEX:
408                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
409                 return &obj_mutex->mutex.lock;
410         default:
411                 break;
412         }
413
414         return NULL;
415 }
416
417 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *funcname)
418 {
419         struct astobj2 *obj = INTERNAL_OBJ(user_data);
420         struct astobj2_lock *obj_mutex;
421         struct astobj2_rwlock *obj_rwlock;
422         int current_value;
423         int ret;
424
425         if (obj == NULL) {
426                 return -1;
427         }
428
429         /* if delta is 0, just return the refcount */
430         if (delta == 0) {
431                 return obj->priv_data.ref_counter;
432         }
433
434         /* we modify with an atomic operation the reference counter */
435         ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
436         current_value = ret + delta;
437
438 #ifdef AO2_DEBUG
439         ast_atomic_fetchadd_int(&ao2.total_refs, delta);
440 #endif
441
442         if (0 < current_value) {
443                 /* The object still lives. */
444                 return ret;
445         }
446
447         /* this case must never happen */
448         if (current_value < 0) {
449                 ast_log(__LOG_ERROR, file, line, funcname,
450                         "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
451         }
452
453         /* last reference, destroy the object */
454         if (obj->priv_data.destructor_fn != NULL) {
455                 obj->priv_data.destructor_fn(user_data);
456         }
457
458 #ifdef AO2_DEBUG
459         ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
460         ast_atomic_fetchadd_int(&ao2.total_objects, -1);
461 #endif
462
463         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
464         case AO2_ALLOC_OPT_LOCK_MUTEX:
465                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
466                 ast_mutex_destroy(&obj_mutex->mutex.lock);
467
468                 /*
469                  * For safety, zero-out the astobj2_lock header and also the
470                  * first word of the user-data, which we make sure is always
471                  * allocated.
472                  */
473                 memset(obj_mutex, '\0', sizeof(*obj_mutex) + sizeof(void *) );
474                 ast_free(obj_mutex);
475                 break;
476         case AO2_ALLOC_OPT_LOCK_RWLOCK:
477                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
478                 ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
479
480                 /*
481                  * For safety, zero-out the astobj2_rwlock header and also the
482                  * first word of the user-data, which we make sure is always
483                  * allocated.
484                  */
485                 memset(obj_rwlock, '\0', sizeof(*obj_rwlock) + sizeof(void *) );
486                 ast_free(obj_rwlock);
487                 break;
488         case AO2_ALLOC_OPT_LOCK_NOLOCK:
489                 /*
490                  * For safety, zero-out the astobj2 header and also the first
491                  * word of the user-data, which we make sure is always
492                  * allocated.
493                  */
494                 memset(obj, '\0', sizeof(*obj) + sizeof(void *) );
495                 ast_free(obj);
496                 break;
497         default:
498                 ast_log(__LOG_ERROR, file, line, funcname,
499                         "Invalid lock option on ao2 object %p\n", user_data);
500                 break;
501         }
502
503         return ret;
504 }
505
506 int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *funcname)
507 {
508         struct astobj2 *obj = INTERNAL_OBJ(user_data);
509
510         if (obj == NULL)
511                 return -1;
512
513         if (delta != 0) {
514                 FILE *refo = fopen(REF_FILE, "a");
515                 if (refo) {
516                         fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"),
517                                 delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1);
518                         fclose(refo);
519                 }
520         }
521         if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
522                 FILE *refo = fopen(REF_FILE, "a");
523                 if (refo) {
524                         fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
525                         fclose(refo);
526                 }
527         }
528         return internal_ao2_ref(user_data, delta, file, line, funcname);
529 }
530
531 int __ao2_ref(void *user_data, int delta)
532 {
533         struct astobj2 *obj = INTERNAL_OBJ(user_data);
534
535         if (obj == NULL)
536                 return -1;
537
538         return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
539 }
540
541 static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *funcname)
542 {
543         /* allocation */
544         struct astobj2 *obj;
545         struct astobj2_lock *obj_mutex;
546         struct astobj2_rwlock *obj_rwlock;
547
548         if (data_size < sizeof(void *)) {
549                 /*
550                  * We always alloc at least the size of a void *,
551                  * for debugging purposes.
552                  */
553                 data_size = sizeof(void *);
554         }
555
556         switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
557         case AO2_ALLOC_OPT_LOCK_MUTEX:
558 #if defined(__AST_DEBUG_MALLOC)
559                 obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, funcname);
560 #else
561                 obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
562 #endif
563                 if (obj_mutex == NULL) {
564                         return NULL;
565                 }
566
567                 ast_mutex_init(&obj_mutex->mutex.lock);
568                 obj = (struct astobj2 *) &obj_mutex->priv_data;
569                 break;
570         case AO2_ALLOC_OPT_LOCK_RWLOCK:
571 #if defined(__AST_DEBUG_MALLOC)
572                 obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, funcname);
573 #else
574                 obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
575 #endif
576                 if (obj_rwlock == NULL) {
577                         return NULL;
578                 }
579
580                 ast_rwlock_init(&obj_rwlock->rwlock.lock);
581                 obj = (struct astobj2 *) &obj_rwlock->priv_data;
582                 break;
583         case AO2_ALLOC_OPT_LOCK_NOLOCK:
584 #if defined(__AST_DEBUG_MALLOC)
585                 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
586 #else
587                 obj = ast_calloc(1, sizeof(*obj) + data_size);
588 #endif
589                 if (obj == NULL) {
590                         return NULL;
591                 }
592                 break;
593         default:
594                 /* Invalid option value. */
595                 ast_log(__LOG_DEBUG, file, line, funcname, "Invalid lock option requested\n");
596                 return NULL;
597         }
598
599         /* Initialize common ao2 values. */
600         obj->priv_data.ref_counter = 1;
601         obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
602         obj->priv_data.data_size = data_size;
603         obj->priv_data.options = options;
604         obj->priv_data.magic = AO2_MAGIC;
605
606 #ifdef AO2_DEBUG
607         ast_atomic_fetchadd_int(&ao2.total_objects, 1);
608         ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
609         ast_atomic_fetchadd_int(&ao2.total_refs, 1);
610 #endif
611
612         /* return a pointer to the user data */
613         return EXTERNAL_OBJ(obj);
614 }
615
616 void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
617         const char *file, int line, const char *funcname, int ref_debug)
618 {
619         /* allocation */
620         void *obj;
621         FILE *refo;
622
623         if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, funcname)) == NULL) {
624                 return NULL;
625         }
626
627         if (ref_debug && (refo = fopen(REF_FILE, "a"))) {
628                 fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
629                 fclose(refo);
630         }
631
632         /* return a pointer to the user data */
633         return obj;
634 }
635
636 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
637 {
638         return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
639 }
640
641
642 void __ao2_global_obj_release(struct ao2_global_obj *array, const char *tag, const char *file, int line, const char *func, const char *name)
643 {
644         unsigned int idx;
645
646         if (!array) {
647                 /* For sanity */
648                 return;
649         }
650         if (__ast_rwlock_wrlock(file, line, func, &array->lock, name)) {
651                 /* Could not get the write lock. */
652                 return;
653         }
654
655         /* Release all contained ao2 objects. */
656         idx = array->num_elements;
657         while (idx--) {
658                 if (array->obj[idx]) {
659                         __ao2_ref_debug(array->obj[idx], -1, tag, file, line, func);
660                         array->obj[idx] = NULL;
661                 }
662         }
663
664         __ast_rwlock_unlock(file, line, func, &array->lock, name);
665 }
666
667 void *__ao2_global_obj_replace(struct ao2_global_obj *array, unsigned int idx, void *obj, const char *tag, const char *file, int line, const char *func, const char *name)
668 {
669         void *obj_old;
670
671         if (!array || array->num_elements <= idx) {
672                 /* For sanity */
673                 return NULL;
674         }
675         if (__ast_rwlock_wrlock(file, line, func, &array->lock, name)) {
676                 /* Could not get the write lock. */
677                 return NULL;
678         }
679
680         if (obj) {
681                 __ao2_ref_debug(obj, +1, tag, file, line, func);
682         }
683         obj_old = array->obj[idx];
684         array->obj[idx] = obj;
685
686         __ast_rwlock_unlock(file, line, func, &array->lock, name);
687
688         return obj_old;
689 }
690
691 void *__ao2_global_obj_ref(struct ao2_global_obj *array, unsigned int idx, const char *tag, const char *file, int line, const char *func, const char *name)
692 {
693         void *obj;
694
695         if (!array || array->num_elements <= idx) {
696                 /* For sanity */
697                 return NULL;
698         }
699         if (__ast_rwlock_rdlock(file, line, func, &array->lock, name)) {
700                 /* Could not get the read lock. */
701                 return NULL;
702         }
703
704         obj = array->obj[idx];
705         if (obj) {
706                 __ao2_ref_debug(obj, +1, tag, file, line, func);
707         }
708
709         __ast_rwlock_unlock(file, line, func, &array->lock, name);
710
711         return obj;
712 }
713
714
715 /* internal callback to destroy a container. */
716 static void container_destruct(void *c);
717
718 /* internal callback to destroy a container. */
719 static void container_destruct_debug(void *c);
720
721 /*!
722  * A structure to create a linked list of entries,
723  * used within a bucket.
724  * XXX \todo this should be private to the container code
725  */
726 struct bucket_entry {
727         AST_LIST_ENTRY(bucket_entry) entry;
728         int version;
729         struct astobj2 *astobj;/* pointer to internal data */
730 };
731
732 /* each bucket in the container is a tailq. */
733 AST_LIST_HEAD_NOLOCK(bucket, bucket_entry);
734
735 /*!
736  * A container; stores the hash and callback functions, information on
737  * the size, the hash bucket heads, and a version number, starting at 0
738  * (for a newly created, empty container)
739  * and incremented every time an object is inserted or deleted.
740  * The assumption is that an object is never moved in a container,
741  * but removed and readded with the new number.
742  * The version number is especially useful when implementing iterators.
743  * In fact, we can associate a unique, monotonically increasing number to
744  * each object, which means that, within an iterator, we can store the
745  * version number of the current object, and easily look for the next one,
746  * which is the next one in the list with a higher number.
747  * Since all objects have a version >0, we can use 0 as a marker for
748  * 'we need the first object in the bucket'.
749  *
750  * \todo Linking and unlink objects is typically expensive, as it
751  * involves a malloc() of a small object which is very inefficient.
752  * To optimize this, we allocate larger arrays of bucket_entry's
753  * when we run out of them, and then manage our own freelist.
754  * This will be more efficient as we can do the freelist management while
755  * we hold the lock (that we need anyways).
756  */
757 struct ao2_container {
758         ao2_hash_fn *hash_fn;
759         ao2_callback_fn *cmp_fn;
760         int n_buckets;
761         /*! Number of elements in the container */
762         int elements;
763         /*! described above */
764         int version;
765         /*! variable size */
766         struct bucket buckets[0];
767 };
768
769 /*!
770  * \brief always zero hash function
771  *
772  * it is convenient to have a hash function that always returns 0.
773  * This is basically used when we want to have a container that is
774  * a simple linked list.
775  *
776  * \returns 0
777  */
778 static int hash_zero(const void *user_obj, const int flags)
779 {
780         return 0;
781 }
782
783 /*
784  * A container is just an object, after all!
785  */
786 static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c,
787         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
788 {
789         /* XXX maybe consistency check on arguments ? */
790         /* compute the container size */
791
792         if (!c) {
793                 return NULL;
794         }
795
796         c->version = 1; /* 0 is a reserved value here */
797         c->n_buckets = hash_fn ? n_buckets : 1;
798         c->hash_fn = hash_fn ? hash_fn : hash_zero;
799         c->cmp_fn = cmp_fn;
800
801 #ifdef AO2_DEBUG
802         ast_atomic_fetchadd_int(&ao2.total_containers, 1);
803 #endif
804
805         return c;
806 }
807
808 struct ao2_container *__ao2_container_alloc_debug(unsigned int options,
809         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
810         const char *tag, const char *file, int line, const char *funcname, int ref_debug)
811 {
812         /* XXX maybe consistency check on arguments ? */
813         /* compute the container size */
814         unsigned int num_buckets = hash_fn ? n_buckets : 1;
815         size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
816         struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, options, tag, file, line, funcname, ref_debug);
817
818         return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
819 }
820
821 struct ao2_container *__ao2_container_alloc(unsigned int options,
822         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
823 {
824         /* XXX maybe consistency check on arguments ? */
825         /* compute the container size */
826         const unsigned int num_buckets = hash_fn ? n_buckets : 1;
827         size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
828         struct ao2_container *c = __ao2_alloc(container_size, container_destruct, options);
829
830         return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
831 }
832
833 /*!
834  * return the number of elements in the container
835  */
836 int ao2_container_count(struct ao2_container *c)
837 {
838         return c->elements;
839 }
840
841 /*
842  * link an object to a container
843  */
844 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 *funcname)
845 {
846         int i;
847         enum ao2_lock_req orig_lock;
848         /* create a new list entry */
849         struct bucket_entry *p;
850         struct astobj2 *obj = INTERNAL_OBJ(user_data);
851
852         if (obj == NULL) {
853                 return NULL;
854         }
855
856         if (INTERNAL_OBJ(c) == NULL) {
857                 return NULL;
858         }
859
860         p = ast_calloc(1, sizeof(*p));
861         if (!p) {
862                 return NULL;
863         }
864
865         i = abs(c->hash_fn(user_data, OBJ_POINTER));
866
867         if (flags & OBJ_NOLOCK) {
868                 orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
869         } else {
870                 ao2_wrlock(c);
871                 orig_lock = AO2_LOCK_REQ_MUTEX;
872         }
873
874         i %= c->n_buckets;
875         p->astobj = obj;
876         p->version = ast_atomic_fetchadd_int(&c->version, 1);
877         AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
878         ast_atomic_fetchadd_int(&c->elements, 1);
879
880         if (tag) {
881                 __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
882         } else {
883                 __ao2_ref(user_data, +1);
884         }
885
886         if (flags & OBJ_NOLOCK) {
887                 adjust_lock(c, orig_lock, 0);
888         } else {
889                 ao2_unlock(c);
890         }
891
892         return p;
893 }
894
895 void *__ao2_link_debug(struct ao2_container *c, void *new_obj, int flags, const char *tag, const char *file, int line, const char *funcname)
896 {
897         return internal_ao2_link(c, new_obj, flags, tag, file, line, funcname);
898 }
899
900 void *__ao2_link(struct ao2_container *c, void *new_obj, int flags)
901 {
902         return internal_ao2_link(c, new_obj, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
903 }
904
905 /*!
906  * \brief another convenience function is a callback that matches on address
907  */
908 int ao2_match_by_addr(void *user_data, void *arg, int flags)
909 {
910         return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
911 }
912
913 /*
914  * Unlink an object from the container
915  * and destroy the associated * bucket_entry structure.
916  */
917 void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
918         const char *tag, const char *file, int line, const char *funcname)
919 {
920         if (INTERNAL_OBJ(user_data) == NULL) {  /* safety check on the argument */
921                 return NULL;
922         }
923
924         flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
925         __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, funcname);
926
927         return NULL;
928 }
929
930 void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
931 {
932         if (INTERNAL_OBJ(user_data) == NULL) {  /* safety check on the argument */
933                 return NULL;
934         }
935
936         flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
937         __ao2_callback(c, flags, ao2_match_by_addr, user_data);
938
939         return NULL;
940 }
941
942 /*!
943  * \brief special callback that matches all
944  */
945 static int cb_true(void *user_data, void *arg, int flags)
946 {
947         return CMP_MATCH;
948 }
949
950 /*!
951  * \brief similar to cb_true, but is an ao2_callback_data_fn instead
952  */
953 static int cb_true_data(void *user_data, void *arg, void *data, int flags)
954 {
955         return CMP_MATCH;
956 }
957
958 /*!
959  * Browse the container using different stategies accoding the flags.
960  * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
961  * specified.
962  * Luckily, for debug purposes, the added args (tag, file, line, funcname)
963  * aren't an excessive load to the system, as the callback should not be
964  * called as often as, say, the ao2_ref func is called.
965  */
966 static void *internal_ao2_callback(struct ao2_container *c, enum search_flags flags,
967         void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag,
968         const char *file, int line, const char *funcname)
969 {
970         int i, start, last;     /* search boundaries */
971         enum ao2_lock_req orig_lock;
972         void *ret = NULL;
973         ao2_callback_fn *cb_default = NULL;
974         ao2_callback_data_fn *cb_withdata = NULL;
975         struct ao2_container *multi_container = NULL;
976         struct ao2_iterator *multi_iterator = NULL;
977
978         if (INTERNAL_OBJ(c) == NULL) {  /* safety check on the argument */
979                 return NULL;
980         }
981
982         /*
983          * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
984          * turned off.  This if statement checks for the special condition
985          * where multiple items may need to be returned.
986          */
987         if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
988                 /* we need to return an ao2_iterator with the results,
989                  * as there could be more than one. the iterator will
990                  * hold the only reference to a container that has all the
991                  * matching objects linked into it, so when the iterator
992                  * is destroyed, the container will be automatically
993                  * destroyed as well.
994                  */
995                 multi_container = __ao2_container_alloc(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
996                 if (!multi_container) {
997                         return NULL;
998                 }
999                 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
1000                         ao2_ref(multi_container, -1);
1001                         return NULL;
1002                 }
1003         }
1004
1005         /* override the match function if necessary */
1006         if (cb_fn == NULL) { /* if NULL, match everything */
1007                 if (type == WITH_DATA) {
1008                         cb_withdata = cb_true_data;
1009                 } else {
1010                         cb_default = cb_true;
1011                 }
1012         } else {
1013                 /* We do this here to avoid the per object casting penalty (even though
1014                    that is probably optimized away anyway). */
1015                 if (type == WITH_DATA) {
1016                         cb_withdata = cb_fn;
1017                 } else {
1018                         cb_default = cb_fn;
1019                 }
1020         }
1021
1022         /*
1023          * XXX this can be optimized.
1024          * If we have a hash function and lookup by pointer,
1025          * run the hash function. Otherwise, scan the whole container
1026          * (this only for the time being. We need to optimize this.)
1027          */
1028         if ((flags & (OBJ_POINTER | OBJ_KEY))) {
1029                 /* we know hash can handle this case */
1030                 start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
1031         } else {
1032                 /* don't know, let's scan all buckets */
1033                 start = i = -1;         /* XXX this must be fixed later. */
1034         }
1035
1036         /* determine the search boundaries: i..last-1 */
1037         if (i < 0) {
1038                 start = i = 0;
1039                 last = c->n_buckets;
1040         } else if ((flags & OBJ_CONTINUE)) {
1041                 last = c->n_buckets;
1042         } else {
1043                 last = i + 1;
1044         }
1045
1046         /* avoid modifications to the content */
1047         if (flags & OBJ_NOLOCK) {
1048                 if (flags & OBJ_UNLINK) {
1049                         orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
1050                 } else {
1051                         orig_lock = adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
1052                 }
1053         } else {
1054                 orig_lock = AO2_LOCK_REQ_MUTEX;
1055                 if (flags & OBJ_UNLINK) {
1056                         ao2_wrlock(c);
1057                 } else {
1058                         ao2_rdlock(c);
1059                 }
1060         }
1061
1062         for (; i < last ; i++) {
1063                 /* scan the list with prev-cur pointers */
1064                 struct bucket_entry *cur;
1065
1066                 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
1067                         int match = (CMP_MATCH | CMP_STOP);
1068
1069                         if (type == WITH_DATA) {
1070                                 match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
1071                         } else {
1072                                 match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
1073                         }
1074
1075                         /* we found the object, performing operations according flags */
1076                         if (match == 0) {       /* no match, no stop, continue */
1077                                 continue;
1078                         } else if (match == CMP_STOP) { /* no match but stop, we are done */
1079                                 i = last;
1080                                 break;
1081                         }
1082
1083                         /* we have a match (CMP_MATCH) here */
1084                         if (!(flags & OBJ_NODATA)) {    /* if must return the object, record the value */
1085                                 /* it is important to handle this case before the unlink */
1086                                 ret = EXTERNAL_OBJ(cur->astobj);
1087                                 if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
1088                                         if (tag)
1089                                                 __ao2_ref_debug(ret, 1, tag, file, line, funcname);
1090                                         else
1091                                                 __ao2_ref(ret, 1);
1092                                 }
1093                         }
1094
1095                         /* If we are in OBJ_MULTIPLE mode and OBJ_NODATA is off,
1096                          * link the object into the container that will hold the results.
1097                          */
1098                         if (ret && (multi_container != NULL)) {
1099                                 if (tag) {
1100                                         __ao2_link_debug(multi_container, ret, flags, tag, file, line, funcname);
1101                                 } else {
1102                                         __ao2_link(multi_container, ret, flags);
1103                                 }
1104                                 ret = NULL;
1105                         }
1106
1107                         if (flags & OBJ_UNLINK) {       /* must unlink */
1108                                 /* we are going to modify the container, so update version */
1109                                 ast_atomic_fetchadd_int(&c->version, 1);
1110                                 AST_LIST_REMOVE_CURRENT(entry);
1111                                 /* update number of elements */
1112                                 ast_atomic_fetchadd_int(&c->elements, -1);
1113
1114                                 /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
1115                                  * must be decremented.
1116                                  * - When unlinking with OBJ_MULTIPLE the ref from the original container
1117                                  * must be decremented regardless if OBJ_NODATA is used. This is because the result is
1118                                  * returned in a new container that already holds its own ref for the object. If the ref
1119                                  * from the original container is not accounted for here a memory leak occurs. */
1120                                 if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
1121                                         if (tag)
1122                                                 __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
1123                                         else
1124                                                 __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
1125                                 }
1126                                 ast_free(cur);  /* free the link record */
1127                         }
1128
1129                         if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
1130                                 /* We found our only (or last) match, so force an exit from
1131                                    the outside loop. */
1132                                 i = last;
1133                                 break;
1134                         }
1135                 }
1136                 AST_LIST_TRAVERSE_SAFE_END;
1137
1138                 if (ret) {
1139                         break;
1140                 }
1141
1142                 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
1143                         /* Move to the beginning to ensure we check every bucket */
1144                         i = -1;
1145                         last = start;
1146                 }
1147         }
1148
1149         if (flags & OBJ_NOLOCK) {
1150                 adjust_lock(c, orig_lock, 0);
1151         } else {
1152                 ao2_unlock(c);
1153         }
1154
1155         /* if multi_container was created, we are returning multiple objects */
1156         if (multi_container != NULL) {
1157                 *multi_iterator = ao2_iterator_init(multi_container,
1158                         AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
1159                 ao2_ref(multi_container, -1);
1160                 return multi_iterator;
1161         } else {
1162                 return ret;
1163         }
1164 }
1165
1166 void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
1167         ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
1168         const char *funcname)
1169 {
1170         return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
1171 }
1172
1173 void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
1174         ao2_callback_fn *cb_fn, void *arg)
1175 {
1176         return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
1177 }
1178
1179 void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
1180         ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
1181         int line, const char *funcname)
1182 {
1183         return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
1184 }
1185
1186 void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
1187         ao2_callback_data_fn *cb_fn, void *arg, void *data)
1188 {
1189         return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
1190 }
1191
1192 /*!
1193  * the find function just invokes the default callback with some reasonable flags.
1194  */
1195 void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
1196         const char *tag, const char *file, int line, const char *funcname)
1197 {
1198         void *arged = (void *) arg;/* Done to avoid compiler const warning */
1199
1200         return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, funcname);
1201 }
1202
1203 void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
1204 {
1205         void *arged = (void *) arg;/* Done to avoid compiler const warning */
1206
1207         return __ao2_callback(c, flags, c->cmp_fn, arged);
1208 }
1209
1210 /*!
1211  * initialize an iterator so we start from the first object
1212  */
1213 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
1214 {
1215         struct ao2_iterator a = {
1216                 .c = c,
1217                 .flags = flags
1218         };
1219
1220         ao2_ref(c, +1);
1221
1222         return a;
1223 }
1224
1225 /*!
1226  * destroy an iterator
1227  */
1228 void ao2_iterator_destroy(struct ao2_iterator *i)
1229 {
1230         ao2_ref(i->c, -1);
1231         if (i->flags & AO2_ITERATOR_MALLOCD) {
1232                 ast_free(i);
1233         } else {
1234                 i->c = NULL;
1235         }
1236 }
1237
1238 /*
1239  * move to the next element in the container.
1240  */
1241 static void *internal_ao2_iterator_next(struct ao2_iterator *a, const char *tag, const char *file, int line, const char *funcname)
1242 {
1243         int lim;
1244         enum ao2_lock_req orig_lock;
1245         struct bucket_entry *p = NULL;
1246         void *ret;
1247
1248         if (INTERNAL_OBJ(a->c) == NULL) {
1249                 return NULL;
1250         }
1251
1252         if (a->flags & AO2_ITERATOR_DONTLOCK) {
1253                 if (a->flags & AO2_ITERATOR_UNLINK) {
1254                         orig_lock = adjust_lock(a->c, AO2_LOCK_REQ_WRLOCK, 1);
1255                 } else {
1256                         orig_lock = adjust_lock(a->c, AO2_LOCK_REQ_RDLOCK, 1);
1257                 }
1258         } else {
1259                 orig_lock = AO2_LOCK_REQ_MUTEX;
1260                 if (a->flags & AO2_ITERATOR_UNLINK) {
1261                         ao2_wrlock(a->c);
1262                 } else {
1263                         ao2_rdlock(a->c);
1264                 }
1265         }
1266
1267         /* optimization. If the container is unchanged and
1268          * we have a pointer, try follow it
1269          */
1270         if (a->c->version == a->c_version && (p = a->obj)) {
1271                 if ((p = AST_LIST_NEXT(p, entry))) {
1272                         goto found;
1273                 }
1274                 /* nope, start from the next bucket */
1275                 a->bucket++;
1276                 a->version = 0;
1277                 a->obj = NULL;
1278         }
1279
1280         lim = a->c->n_buckets;
1281
1282         /* Browse the buckets array, moving to the next
1283          * buckets if we don't find the entry in the current one.
1284          * Stop when we find an element with version number greater
1285          * than the current one (we reset the version to 0 when we
1286          * switch buckets).
1287          */
1288         for (; a->bucket < lim; a->bucket++, a->version = 0) {
1289                 /* scan the current bucket */
1290                 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
1291                         if (p->version > a->version) {
1292                                 goto found;
1293                         }
1294                 }
1295         }
1296
1297 found:
1298         if (p) {
1299                 ret = EXTERNAL_OBJ(p->astobj);
1300                 if (a->flags & AO2_ITERATOR_UNLINK) {
1301                         /* we are going to modify the container, so update version */
1302                         ast_atomic_fetchadd_int(&a->c->version, 1);
1303                         AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
1304                         /* update number of elements */
1305                         ast_atomic_fetchadd_int(&a->c->elements, -1);
1306                         a->version = 0;
1307                         a->obj = NULL;
1308                         a->c_version = a->c->version;
1309                         ast_free(p);
1310                 } else {
1311                         a->version = p->version;
1312                         a->obj = p;
1313                         a->c_version = a->c->version;
1314
1315                         /* inc refcount of returned object */
1316                         if (tag) {
1317                                 __ao2_ref_debug(ret, 1, tag, file, line, funcname);
1318                         } else {
1319                                 __ao2_ref(ret, 1);
1320                         }
1321                 }
1322         } else {
1323                 ret = NULL;
1324         }
1325
1326         if (a->flags & AO2_ITERATOR_DONTLOCK) {
1327                 adjust_lock(a->c, orig_lock, 0);
1328         } else {
1329                 ao2_unlock(a->c);
1330         }
1331
1332         return ret;
1333 }
1334
1335 void *__ao2_iterator_next_debug(struct ao2_iterator *a, const char *tag, const char *file, int line, const char *funcname)
1336 {
1337         return internal_ao2_iterator_next(a, tag, file, line, funcname);
1338 }
1339
1340 void *__ao2_iterator_next(struct ao2_iterator *a)
1341 {
1342         return internal_ao2_iterator_next(a, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
1343 }
1344
1345 /* callback for destroying container.
1346  * we can make it simple as we know what it does
1347  */
1348 static int cd_cb(void *obj, void *arg, int flag)
1349 {
1350         __ao2_ref(obj, -1);
1351         return 0;
1352 }
1353
1354 static int cd_cb_debug(void *obj, void *arg, int flag)
1355 {
1356         __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
1357         return 0;
1358 }
1359
1360 static void container_destruct(void *_c)
1361 {
1362         struct ao2_container *c = _c;
1363         int i;
1364
1365         __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
1366
1367         for (i = 0; i < c->n_buckets; i++) {
1368                 struct bucket_entry *current;
1369
1370                 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
1371                         ast_free(current);
1372                 }
1373         }
1374
1375 #ifdef AO2_DEBUG
1376         ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1377 #endif
1378 }
1379
1380 static void container_destruct_debug(void *_c)
1381 {
1382         struct ao2_container *c = _c;
1383         int i;
1384
1385         __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
1386
1387         for (i = 0; i < c->n_buckets; i++) {
1388                 struct bucket_entry *current;
1389
1390                 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
1391                         ast_free(current);
1392                 }
1393         }
1394
1395 #ifdef AO2_DEBUG
1396         ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1397 #endif
1398 }
1399
1400 /*!
1401  * \internal
1402  * \brief Put obj into the arg container.
1403  * \since 11.0
1404  *
1405  * \param obj  pointer to the (user-defined part) of an object.
1406  * \param arg callback argument from ao2_callback()
1407  * \param flags flags from ao2_callback()
1408  *
1409  * \retval 0 on success.
1410  * \retval CMP_STOP|CMP_MATCH on error.
1411  */
1412 static int dup_obj_cb(void *obj, void *arg, int flags)
1413 {
1414         struct ao2_container *dest = arg;
1415
1416         return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
1417 }
1418
1419 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
1420 {
1421         void *obj;
1422         int res = 0;
1423
1424         if (!(flags & OBJ_NOLOCK)) {
1425                 ao2_rdlock(src);
1426                 ao2_wrlock(dest);
1427         }
1428         obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
1429         if (obj) {
1430                 /* Failed to put this obj into the dest container. */
1431                 __ao2_ref(obj, -1);
1432
1433                 /* Remove all items from the dest container. */
1434                 __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
1435                         NULL);
1436                 res = -1;
1437         }
1438         if (!(flags & OBJ_NOLOCK)) {
1439                 ao2_unlock(dest);
1440                 ao2_unlock(src);
1441         }
1442
1443         return res;
1444 }
1445
1446 struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
1447 {
1448         struct ao2_container *clone;
1449         struct astobj2 *orig_obj;
1450         unsigned int options;
1451         int failed;
1452
1453         orig_obj = INTERNAL_OBJ(orig);
1454         if (!orig_obj) {
1455                 return NULL;
1456         }
1457         options = orig_obj->priv_data.options;
1458
1459         /* Create the clone container with the same properties as the original. */
1460         clone = __ao2_container_alloc(options, orig->n_buckets, orig->hash_fn, orig->cmp_fn);
1461         if (!clone) {
1462                 return NULL;
1463         }
1464
1465         if (flags & OBJ_NOLOCK) {
1466                 ao2_wrlock(clone);
1467         }
1468         failed = ao2_container_dup(clone, orig, flags);
1469         if (flags & OBJ_NOLOCK) {
1470                 ao2_unlock(clone);
1471         }
1472         if (failed) {
1473                 /* Object copy into the clone container failed. */
1474                 __ao2_ref(clone, -1);
1475                 clone = NULL;
1476         }
1477         return clone;
1478 }
1479
1480 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 *funcname, int ref_debug)
1481 {
1482         struct ao2_container *clone;
1483         struct astobj2 *orig_obj;
1484         unsigned int options;
1485         int failed;
1486
1487         orig_obj = INTERNAL_OBJ(orig);
1488         if (!orig_obj) {
1489                 return NULL;
1490         }
1491         options = orig_obj->priv_data.options;
1492
1493         /* Create the clone container with the same properties as the original. */
1494         clone = __ao2_container_alloc_debug(options, orig->n_buckets, orig->hash_fn,
1495                 orig->cmp_fn, tag, file, line, funcname, ref_debug);
1496         if (!clone) {
1497                 return NULL;
1498         }
1499
1500         if (flags & OBJ_NOLOCK) {
1501                 ao2_wrlock(clone);
1502         }
1503         failed = ao2_container_dup(clone, orig, flags);
1504         if (flags & OBJ_NOLOCK) {
1505                 ao2_unlock(clone);
1506         }
1507         if (failed) {
1508                 /* Object copy into the clone container failed. */
1509                 if (ref_debug) {
1510                         __ao2_ref_debug(clone, -1, tag, file, line, funcname);
1511                 } else {
1512                         __ao2_ref(clone, -1);
1513                 }
1514                 clone = NULL;
1515         }
1516         return clone;
1517 }
1518
1519 #ifdef AO2_DEBUG
1520 static int print_cb(void *obj, void *arg, int flag)
1521 {
1522         struct ast_cli_args *a = (struct ast_cli_args *) arg;
1523         char *s = (char *)obj;
1524
1525         ast_cli(a->fd, "string <%s>\n", s);
1526         return 0;
1527 }
1528
1529 /*
1530  * Print stats
1531  */
1532 static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1533 {
1534         switch (cmd) {
1535         case CLI_INIT:
1536                 e->command = "astobj2 show stats";
1537                 e->usage = "Usage: astobj2 show stats\n"
1538                            "       Show astobj2 show stats\n";
1539                 return NULL;
1540         case CLI_GENERATE:
1541                 return NULL;
1542         }
1543         ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
1544         ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
1545         ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
1546         ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
1547         ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
1548         return CLI_SUCCESS;
1549 }
1550
1551 /*
1552  * This is testing code for astobj
1553  */
1554 static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1555 {
1556         struct ao2_container *c1;
1557         struct ao2_container *c2;
1558         int i, lim;
1559         char *obj;
1560         static int prof_id = -1;
1561         struct ast_cli_args fake_args = { a->fd, 0, NULL };
1562
1563         switch (cmd) {
1564         case CLI_INIT:
1565                 e->command = "astobj2 test";
1566                 e->usage = "Usage: astobj2 test <num>\n"
1567                            "       Runs astobj2 test. Creates 'num' objects,\n"
1568                            "       and test iterators, callbacks and may be other stuff\n";
1569                 return NULL;
1570         case CLI_GENERATE:
1571                 return NULL;
1572         }
1573
1574         if (a->argc != 3) {
1575                 return CLI_SHOWUSAGE;
1576         }
1577
1578         if (prof_id == -1)
1579                 prof_id = ast_add_profile("ao2_alloc", 0);
1580
1581         ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
1582         lim = atoi(a->argv[2]);
1583         ast_cli(a->fd, "called astobj_test\n");
1584
1585         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1586         /*
1587          * allocate a container with no default callback, and no hash function.
1588          * No hash means everything goes in the same bucket.
1589          */
1590         c1 = ao2_t_container_alloc(100, NULL /* no callback */, NULL /* no hash */,"test");
1591         ast_cli(a->fd, "container allocated as %p\n", c1);
1592
1593         /*
1594          * fill the container with objects.
1595          * ao2_alloc() gives us a reference which we pass to the
1596          * container when we do the insert.
1597          */
1598         for (i = 0; i < lim; i++) {
1599                 ast_mark(prof_id, 1 /* start */);
1600                 obj = ao2_t_alloc(80, NULL,"test");
1601                 ast_mark(prof_id, 0 /* stop */);
1602                 ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
1603                 sprintf(obj, "-- this is obj %d --", i);
1604                 ao2_link(c1, obj);
1605                 /* At this point, the refcount on obj is 2 due to the allocation
1606                  * and linking. We can go ahead and reduce the refcount by 1
1607                  * right here so that when the container is unreffed later, the
1608                  * objects will be freed
1609                  */
1610                 ao2_t_ref(obj, -1, "test");
1611         }
1612
1613         ast_cli(a->fd, "testing callbacks\n");
1614         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1615
1616         ast_cli(a->fd, "testing container cloning\n");
1617         c2 = ao2_container_clone(c1, 0);
1618         if (ao2_container_count(c1) != ao2_container_count(c2)) {
1619                 ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
1620         }
1621         ao2_t_callback(c2, 0, print_cb, a, "test callback");
1622
1623         ast_cli(a->fd, "testing iterators, remove every second object\n");
1624         {
1625                 struct ao2_iterator ai;
1626                 int x = 0;
1627
1628                 ai = ao2_iterator_init(c1, 0);
1629                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1630                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1631                         if (x++ & 1)
1632                                 ao2_t_unlink(c1, obj,"test");
1633                         ao2_t_ref(obj, -1,"test");
1634                 }
1635                 ao2_iterator_destroy(&ai);
1636                 ast_cli(a->fd, "testing iterators again\n");
1637                 ai = ao2_iterator_init(c1, 0);
1638                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1639                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1640                         ao2_t_ref(obj, -1,"test");
1641                 }
1642                 ao2_iterator_destroy(&ai);
1643         }
1644
1645         ast_cli(a->fd, "testing callbacks again\n");
1646         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1647
1648         ast_verbose("now you should see an error message:\n");
1649         ao2_t_ref(&i, -1, "");  /* i is not a valid object so we print an error here */
1650
1651         ast_cli(a->fd, "destroy container\n");
1652         ao2_t_ref(c1, -1, "");  /* destroy container */
1653         ao2_t_ref(c2, -1, "");  /* destroy container */
1654         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1655         return CLI_SUCCESS;
1656 }
1657
1658 static struct ast_cli_entry cli_astobj2[] = {
1659         AST_CLI_DEFINE(handle_astobj2_stats, "Print astobj2 statistics"),
1660         AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
1661 };
1662 #endif /* AO2_DEBUG */
1663
1664 int astobj2_init(void)
1665 {
1666 #ifdef AO2_DEBUG
1667         ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1668 #endif
1669
1670         return 0;
1671 }