0dd07103c2ac794d15e4dd90f696d662086fcb37
[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 *func)
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, func,
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, func,
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 *func)
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, func, tag, obj->priv_data.ref_counter);
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, func, tag);
525                         fclose(refo);
526                 }
527         }
528         return internal_ao2_ref(user_data, delta, file, line, func);
529 }
530
531 int __ao2_ref(void *user_data, int delta)
532 {
533         return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
534 }
535
536 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)
537 {
538         /* allocation */
539         struct astobj2 *obj;
540         struct astobj2_lock *obj_mutex;
541         struct astobj2_rwlock *obj_rwlock;
542
543         if (data_size < sizeof(void *)) {
544                 /*
545                  * We always alloc at least the size of a void *,
546                  * for debugging purposes.
547                  */
548                 data_size = sizeof(void *);
549         }
550
551         switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
552         case AO2_ALLOC_OPT_LOCK_MUTEX:
553 #if defined(__AST_DEBUG_MALLOC)
554                 obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
555 #else
556                 obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
557 #endif
558                 if (obj_mutex == NULL) {
559                         return NULL;
560                 }
561
562                 ast_mutex_init(&obj_mutex->mutex.lock);
563                 obj = (struct astobj2 *) &obj_mutex->priv_data;
564                 break;
565         case AO2_ALLOC_OPT_LOCK_RWLOCK:
566 #if defined(__AST_DEBUG_MALLOC)
567                 obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
568 #else
569                 obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
570 #endif
571                 if (obj_rwlock == NULL) {
572                         return NULL;
573                 }
574
575                 ast_rwlock_init(&obj_rwlock->rwlock.lock);
576                 obj = (struct astobj2 *) &obj_rwlock->priv_data;
577                 break;
578         case AO2_ALLOC_OPT_LOCK_NOLOCK:
579 #if defined(__AST_DEBUG_MALLOC)
580                 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
581 #else
582                 obj = ast_calloc(1, sizeof(*obj) + data_size);
583 #endif
584                 if (obj == NULL) {
585                         return NULL;
586                 }
587                 break;
588         default:
589                 /* Invalid option value. */
590                 ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
591                 return NULL;
592         }
593
594         /* Initialize common ao2 values. */
595         obj->priv_data.ref_counter = 1;
596         obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
597         obj->priv_data.data_size = data_size;
598         obj->priv_data.options = options;
599         obj->priv_data.magic = AO2_MAGIC;
600
601 #ifdef AO2_DEBUG
602         ast_atomic_fetchadd_int(&ao2.total_objects, 1);
603         ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
604         ast_atomic_fetchadd_int(&ao2.total_refs, 1);
605 #endif
606
607         /* return a pointer to the user data */
608         return EXTERNAL_OBJ(obj);
609 }
610
611 void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
612         const char *file, int line, const char *func, int ref_debug)
613 {
614         /* allocation */
615         void *obj;
616         FILE *refo;
617
618         if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
619                 return NULL;
620         }
621
622         if (ref_debug && (refo = fopen(REF_FILE, "a"))) {
623                 fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, func, tag);
624                 fclose(refo);
625         }
626
627         /* return a pointer to the user data */
628         return obj;
629 }
630
631 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
632 {
633         return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
634 }
635
636
637 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
638 {
639         if (!holder) {
640                 /* For sanity */
641                 return;
642         }
643         if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
644                 /* Could not get the write lock. */
645                 return;
646         }
647
648         /* Release the held ao2 object. */
649         if (holder->obj) {
650                 __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
651                 holder->obj = NULL;
652         }
653
654         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
655 }
656
657 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)
658 {
659         void *obj_old;
660
661         if (!holder) {
662                 /* For sanity */
663                 return NULL;
664         }
665         if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
666                 /* Could not get the write lock. */
667                 return NULL;
668         }
669
670         if (obj) {
671                 __ao2_ref_debug(obj, +1, tag, file, line, func);
672         }
673         obj_old = holder->obj;
674         holder->obj = obj;
675
676         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
677
678         return obj_old;
679 }
680
681 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)
682 {
683         void *obj_old;
684
685         obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
686         if (obj_old) {
687                 __ao2_ref_debug(obj_old, -1, tag, file, line, func);
688                 return 1;
689         }
690         return 0;
691 }
692
693 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
694 {
695         void *obj;
696
697         if (!holder) {
698                 /* For sanity */
699                 return NULL;
700         }
701         if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
702                 /* Could not get the read lock. */
703                 return NULL;
704         }
705
706         obj = holder->obj;
707         if (obj) {
708                 __ao2_ref_debug(obj, +1, tag, file, line, func);
709         }
710
711         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
712
713         return obj;
714 }
715
716
717 /* internal callback to destroy a container. */
718 static void container_destruct(void *c);
719
720 /* internal callback to destroy a container. */
721 static void container_destruct_debug(void *c);
722
723 /*!
724  * A structure to create a linked list of entries,
725  * used within a bucket.
726  * XXX \todo this should be private to the container code
727  */
728 struct bucket_entry {
729         AST_LIST_ENTRY(bucket_entry) entry;
730         int version;
731         struct astobj2 *astobj;/* pointer to internal data */
732 };
733
734 /* each bucket in the container is a tailq. */
735 AST_LIST_HEAD_NOLOCK(bucket, bucket_entry);
736
737 /*!
738  * A container; stores the hash and callback functions, information on
739  * the size, the hash bucket heads, and a version number, starting at 0
740  * (for a newly created, empty container)
741  * and incremented every time an object is inserted or deleted.
742  * The assumption is that an object is never moved in a container,
743  * but removed and readded with the new number.
744  * The version number is especially useful when implementing iterators.
745  * In fact, we can associate a unique, monotonically increasing number to
746  * each object, which means that, within an iterator, we can store the
747  * version number of the current object, and easily look for the next one,
748  * which is the next one in the list with a higher number.
749  * Since all objects have a version >0, we can use 0 as a marker for
750  * 'we need the first object in the bucket'.
751  *
752  * \todo Linking and unlink objects is typically expensive, as it
753  * involves a malloc() of a small object which is very inefficient.
754  * To optimize this, we allocate larger arrays of bucket_entry's
755  * when we run out of them, and then manage our own freelist.
756  * This will be more efficient as we can do the freelist management while
757  * we hold the lock (that we need anyways).
758  */
759 struct ao2_container {
760         ao2_hash_fn *hash_fn;
761         ao2_callback_fn *cmp_fn;
762         int n_buckets;
763         /*! Number of elements in the container */
764         int elements;
765         /*! described above */
766         int version;
767         /*! variable size */
768         struct bucket buckets[0];
769 };
770
771 /*!
772  * \brief always zero hash function
773  *
774  * it is convenient to have a hash function that always returns 0.
775  * This is basically used when we want to have a container that is
776  * a simple linked list.
777  *
778  * \returns 0
779  */
780 static int hash_zero(const void *user_obj, const int flags)
781 {
782         return 0;
783 }
784
785 /*
786  * A container is just an object, after all!
787  */
788 static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c,
789         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
790 {
791         /* XXX maybe consistency check on arguments ? */
792         /* compute the container size */
793
794         if (!c) {
795                 return NULL;
796         }
797
798         c->version = 1; /* 0 is a reserved value here */
799         c->n_buckets = hash_fn ? n_buckets : 1;
800         c->hash_fn = hash_fn ? hash_fn : hash_zero;
801         c->cmp_fn = cmp_fn;
802
803 #ifdef AO2_DEBUG
804         ast_atomic_fetchadd_int(&ao2.total_containers, 1);
805 #endif
806
807         return c;
808 }
809
810 struct ao2_container *__ao2_container_alloc_debug(unsigned int options,
811         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
812         const char *tag, const char *file, int line, const char *func, int ref_debug)
813 {
814         /* XXX maybe consistency check on arguments ? */
815         /* compute the container size */
816         unsigned int num_buckets = hash_fn ? n_buckets : 1;
817         size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
818         struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, options, tag, file, line, func, ref_debug);
819
820         return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
821 }
822
823 struct ao2_container *__ao2_container_alloc(unsigned int options,
824         unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
825 {
826         /* XXX maybe consistency check on arguments ? */
827         /* compute the container size */
828         const unsigned int num_buckets = hash_fn ? n_buckets : 1;
829         size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
830         struct ao2_container *c = __ao2_alloc(container_size, container_destruct, options);
831
832         return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
833 }
834
835 /*!
836  * return the number of elements in the container
837  */
838 int ao2_container_count(struct ao2_container *c)
839 {
840         return c->elements;
841 }
842
843 /*
844  * link an object to a container
845  */
846 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)
847 {
848         int i;
849         enum ao2_lock_req orig_lock;
850         /* create a new list entry */
851         struct bucket_entry *p;
852         struct astobj2 *obj = INTERNAL_OBJ(user_data);
853
854         if (obj == NULL) {
855                 return NULL;
856         }
857
858         if (INTERNAL_OBJ(c) == NULL) {
859                 return NULL;
860         }
861
862         p = ast_calloc(1, sizeof(*p));
863         if (!p) {
864                 return NULL;
865         }
866
867         i = abs(c->hash_fn(user_data, OBJ_POINTER));
868
869         if (flags & OBJ_NOLOCK) {
870                 orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
871         } else {
872                 ao2_wrlock(c);
873                 orig_lock = AO2_LOCK_REQ_MUTEX;
874         }
875
876         i %= c->n_buckets;
877         p->astobj = obj;
878         p->version = ast_atomic_fetchadd_int(&c->version, 1);
879         AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
880         ast_atomic_fetchadd_int(&c->elements, 1);
881
882         if (tag) {
883                 __ao2_ref_debug(user_data, +1, tag, file, line, func);
884         } else {
885                 __ao2_ref(user_data, +1);
886         }
887
888         if (flags & OBJ_NOLOCK) {
889                 adjust_lock(c, orig_lock, 0);
890         } else {
891                 ao2_unlock(c);
892         }
893
894         return p;
895 }
896
897 void *__ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
898 {
899         return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
900 }
901
902 void *__ao2_link(struct ao2_container *c, void *obj_new, int flags)
903 {
904         return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
905 }
906
907 /*!
908  * \brief another convenience function is a callback that matches on address
909  */
910 int ao2_match_by_addr(void *user_data, void *arg, int flags)
911 {
912         return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
913 }
914
915 /*
916  * Unlink an object from the container
917  * and destroy the associated * bucket_entry structure.
918  */
919 void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
920         const char *tag, const char *file, int line, const char *func)
921 {
922         if (INTERNAL_OBJ(user_data) == NULL) {  /* safety check on the argument */
923                 return NULL;
924         }
925
926         flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
927         __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
928
929         return NULL;
930 }
931
932 void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
933 {
934         if (INTERNAL_OBJ(user_data) == NULL) {  /* safety check on the argument */
935                 return NULL;
936         }
937
938         flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
939         __ao2_callback(c, flags, ao2_match_by_addr, user_data);
940
941         return NULL;
942 }
943
944 /*!
945  * \brief special callback that matches all
946  */
947 static int cb_true(void *user_data, void *arg, int flags)
948 {
949         return CMP_MATCH;
950 }
951
952 /*!
953  * \brief similar to cb_true, but is an ao2_callback_data_fn instead
954  */
955 static int cb_true_data(void *user_data, void *arg, void *data, int flags)
956 {
957         return CMP_MATCH;
958 }
959
960 /*!
961  * Browse the container using different stategies accoding the flags.
962  * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
963  * specified.
964  * Luckily, for debug purposes, the added args (tag, file, line, func)
965  * aren't an excessive load to the system, as the callback should not be
966  * called as often as, say, the ao2_ref func is called.
967  */
968 static void *internal_ao2_callback(struct ao2_container *c, enum search_flags flags,
969         void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag,
970         const char *file, int line, const char *func)
971 {
972         int i, start, last;     /* search boundaries */
973         enum ao2_lock_req orig_lock;
974         void *ret = NULL;
975         ao2_callback_fn *cb_default = NULL;
976         ao2_callback_data_fn *cb_withdata = NULL;
977         struct ao2_container *multi_container = NULL;
978         struct ao2_iterator *multi_iterator = NULL;
979
980         if (INTERNAL_OBJ(c) == NULL) {  /* safety check on the argument */
981                 return NULL;
982         }
983
984         /*
985          * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
986          * turned off.  This if statement checks for the special condition
987          * where multiple items may need to be returned.
988          */
989         if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
990                 /* we need to return an ao2_iterator with the results,
991                  * as there could be more than one. the iterator will
992                  * hold the only reference to a container that has all the
993                  * matching objects linked into it, so when the iterator
994                  * is destroyed, the container will be automatically
995                  * destroyed as well.
996                  */
997                 multi_container = __ao2_container_alloc(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
998                 if (!multi_container) {
999                         return NULL;
1000                 }
1001                 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
1002                         ao2_ref(multi_container, -1);
1003                         return NULL;
1004                 }
1005         }
1006
1007         /* override the match function if necessary */
1008         if (cb_fn == NULL) { /* if NULL, match everything */
1009                 if (type == WITH_DATA) {
1010                         cb_withdata = cb_true_data;
1011                 } else {
1012                         cb_default = cb_true;
1013                 }
1014         } else {
1015                 /* We do this here to avoid the per object casting penalty (even though
1016                    that is probably optimized away anyway). */
1017                 if (type == WITH_DATA) {
1018                         cb_withdata = cb_fn;
1019                 } else {
1020                         cb_default = cb_fn;
1021                 }
1022         }
1023
1024         /*
1025          * XXX this can be optimized.
1026          * If we have a hash function and lookup by pointer,
1027          * run the hash function. Otherwise, scan the whole container
1028          * (this only for the time being. We need to optimize this.)
1029          */
1030         if ((flags & (OBJ_POINTER | OBJ_KEY))) {
1031                 /* we know hash can handle this case */
1032                 start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
1033         } else {
1034                 /* don't know, let's scan all buckets */
1035                 start = i = -1;         /* XXX this must be fixed later. */
1036         }
1037
1038         /* determine the search boundaries: i..last-1 */
1039         if (i < 0) {
1040                 start = i = 0;
1041                 last = c->n_buckets;
1042         } else if ((flags & OBJ_CONTINUE)) {
1043                 last = c->n_buckets;
1044         } else {
1045                 last = i + 1;
1046         }
1047
1048         /* avoid modifications to the content */
1049         if (flags & OBJ_NOLOCK) {
1050                 if (flags & OBJ_UNLINK) {
1051                         orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
1052                 } else {
1053                         orig_lock = adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
1054                 }
1055         } else {
1056                 orig_lock = AO2_LOCK_REQ_MUTEX;
1057                 if (flags & OBJ_UNLINK) {
1058                         ao2_wrlock(c);
1059                 } else {
1060                         ao2_rdlock(c);
1061                 }
1062         }
1063
1064         for (; i < last ; i++) {
1065                 /* scan the list with prev-cur pointers */
1066                 struct bucket_entry *cur;
1067
1068                 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
1069                         int match = (CMP_MATCH | CMP_STOP);
1070
1071                         if (type == WITH_DATA) {
1072                                 match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
1073                         } else {
1074                                 match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
1075                         }
1076
1077                         /* we found the object, performing operations according flags */
1078                         if (match == 0) {       /* no match, no stop, continue */
1079                                 continue;
1080                         } else if (match == CMP_STOP) { /* no match but stop, we are done */
1081                                 i = last;
1082                                 break;
1083                         }
1084
1085                         /* we have a match (CMP_MATCH) here */
1086                         if (!(flags & OBJ_NODATA)) {    /* if must return the object, record the value */
1087                                 /* it is important to handle this case before the unlink */
1088                                 ret = EXTERNAL_OBJ(cur->astobj);
1089                                 if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
1090                                         if (tag) {
1091                                                 __ao2_ref_debug(ret, 1, tag, file, line, func);
1092                                         } else {
1093                                                 __ao2_ref(ret, 1);
1094                                         }
1095                                 }
1096                         }
1097
1098                         /* If we are in OBJ_MULTIPLE mode and OBJ_NODATA is off,
1099                          * link the object into the container that will hold the results.
1100                          */
1101                         if (ret && (multi_container != NULL)) {
1102                                 if (tag) {
1103                                         __ao2_link_debug(multi_container, ret, flags, tag, file, line, func);
1104                                 } else {
1105                                         __ao2_link(multi_container, ret, flags);
1106                                 }
1107                                 ret = NULL;
1108                         }
1109
1110                         if (flags & OBJ_UNLINK) {       /* must unlink */
1111                                 /* we are going to modify the container, so update version */
1112                                 ast_atomic_fetchadd_int(&c->version, 1);
1113                                 AST_LIST_REMOVE_CURRENT(entry);
1114                                 /* update number of elements */
1115                                 ast_atomic_fetchadd_int(&c->elements, -1);
1116
1117                                 /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
1118                                  * must be decremented.
1119                                  * - When unlinking with OBJ_MULTIPLE the ref from the original container
1120                                  * must be decremented regardless if OBJ_NODATA is used. This is because the result is
1121                                  * returned in a new container that already holds its own ref for the object. If the ref
1122                                  * from the original container is not accounted for here a memory leak occurs. */
1123                                 if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
1124                                         if (tag)
1125                                                 __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, func);
1126                                         else
1127                                                 __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
1128                                 }
1129                                 ast_free(cur);  /* free the link record */
1130                         }
1131
1132                         if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
1133                                 /* We found our only (or last) match, so force an exit from
1134                                    the outside loop. */
1135                                 i = last;
1136                                 break;
1137                         }
1138                 }
1139                 AST_LIST_TRAVERSE_SAFE_END;
1140
1141                 if (ret) {
1142                         break;
1143                 }
1144
1145                 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
1146                         /* Move to the beginning to ensure we check every bucket */
1147                         i = -1;
1148                         last = start;
1149                 }
1150         }
1151
1152         if (flags & OBJ_NOLOCK) {
1153                 adjust_lock(c, orig_lock, 0);
1154         } else {
1155                 ao2_unlock(c);
1156         }
1157
1158         /* if multi_container was created, we are returning multiple objects */
1159         if (multi_container != NULL) {
1160                 *multi_iterator = ao2_iterator_init(multi_container,
1161                         AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
1162                 ao2_ref(multi_container, -1);
1163                 return multi_iterator;
1164         } else {
1165                 return ret;
1166         }
1167 }
1168
1169 void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
1170         ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
1171         const char *func)
1172 {
1173         return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
1174 }
1175
1176 void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
1177         ao2_callback_fn *cb_fn, void *arg)
1178 {
1179         return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
1180 }
1181
1182 void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
1183         ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
1184         int line, const char *func)
1185 {
1186         return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
1187 }
1188
1189 void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
1190         ao2_callback_data_fn *cb_fn, void *arg, void *data)
1191 {
1192         return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
1193 }
1194
1195 /*!
1196  * the find function just invokes the default callback with some reasonable flags.
1197  */
1198 void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
1199         const char *tag, const char *file, int line, const char *func)
1200 {
1201         void *arged = (void *) arg;/* Done to avoid compiler const warning */
1202
1203         return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
1204 }
1205
1206 void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
1207 {
1208         void *arged = (void *) arg;/* Done to avoid compiler const warning */
1209
1210         return __ao2_callback(c, flags, c->cmp_fn, arged);
1211 }
1212
1213 /*!
1214  * initialize an iterator so we start from the first object
1215  */
1216 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
1217 {
1218         struct ao2_iterator a = {
1219                 .c = c,
1220                 .flags = flags
1221         };
1222
1223         ao2_ref(c, +1);
1224
1225         return a;
1226 }
1227
1228 /*!
1229  * destroy an iterator
1230  */
1231 void ao2_iterator_destroy(struct ao2_iterator *iter)
1232 {
1233         ao2_ref(iter->c, -1);
1234         if (iter->flags & AO2_ITERATOR_MALLOCD) {
1235                 ast_free(iter);
1236         } else {
1237                 iter->c = NULL;
1238         }
1239 }
1240
1241 /*
1242  * move to the next element in the container.
1243  */
1244 static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
1245 {
1246         int lim;
1247         enum ao2_lock_req orig_lock;
1248         struct bucket_entry *p = NULL;
1249         void *ret;
1250
1251         if (INTERNAL_OBJ(iter->c) == NULL) {
1252                 return NULL;
1253         }
1254
1255         if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1256                 if (iter->flags & AO2_ITERATOR_UNLINK) {
1257                         orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
1258                 } else {
1259                         orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
1260                 }
1261         } else {
1262                 orig_lock = AO2_LOCK_REQ_MUTEX;
1263                 if (iter->flags & AO2_ITERATOR_UNLINK) {
1264                         ao2_wrlock(iter->c);
1265                 } else {
1266                         ao2_rdlock(iter->c);
1267                 }
1268         }
1269
1270         /* optimization. If the container is unchanged and
1271          * we have a pointer, try follow it
1272          */
1273         if (iter->c->version == iter->c_version && (p = iter->obj)) {
1274                 if ((p = AST_LIST_NEXT(p, entry))) {
1275                         goto found;
1276                 }
1277                 /* nope, start from the next bucket */
1278                 iter->bucket++;
1279                 iter->version = 0;
1280                 iter->obj = NULL;
1281         }
1282
1283         lim = iter->c->n_buckets;
1284
1285         /* Browse the buckets array, moving to the next
1286          * buckets if we don't find the entry in the current one.
1287          * Stop when we find an element with version number greater
1288          * than the current one (we reset the version to 0 when we
1289          * switch buckets).
1290          */
1291         for (; iter->bucket < lim; iter->bucket++, iter->version = 0) {
1292                 /* scan the current bucket */
1293                 AST_LIST_TRAVERSE(&iter->c->buckets[iter->bucket], p, entry) {
1294                         if (p->version > iter->version) {
1295                                 goto found;
1296                         }
1297                 }
1298         }
1299
1300 found:
1301         if (p) {
1302                 ret = EXTERNAL_OBJ(p->astobj);
1303                 if (iter->flags & AO2_ITERATOR_UNLINK) {
1304                         /* we are going to modify the container, so update version */
1305                         ast_atomic_fetchadd_int(&iter->c->version, 1);
1306                         AST_LIST_REMOVE(&iter->c->buckets[iter->bucket], p, entry);
1307                         /* update number of elements */
1308                         ast_atomic_fetchadd_int(&iter->c->elements, -1);
1309                         iter->version = 0;
1310                         iter->obj = NULL;
1311                         iter->c_version = iter->c->version;
1312                         ast_free(p);
1313                 } else {
1314                         iter->version = p->version;
1315                         iter->obj = p;
1316                         iter->c_version = iter->c->version;
1317
1318                         /* inc refcount of returned object */
1319                         if (tag) {
1320                                 __ao2_ref_debug(ret, 1, tag, file, line, func);
1321                         } else {
1322                                 __ao2_ref(ret, 1);
1323                         }
1324                 }
1325         } else {
1326                 ret = NULL;
1327         }
1328
1329         if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1330                 adjust_lock(iter->c, orig_lock, 0);
1331         } else {
1332                 ao2_unlock(iter->c);
1333         }
1334
1335         return ret;
1336 }
1337
1338 void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
1339 {
1340         return internal_ao2_iterator_next(iter, tag, file, line, func);
1341 }
1342
1343 void *__ao2_iterator_next(struct ao2_iterator *iter)
1344 {
1345         return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
1346 }
1347
1348 /* callback for destroying container.
1349  * we can make it simple as we know what it does
1350  */
1351 static int cd_cb(void *obj, void *arg, int flag)
1352 {
1353         __ao2_ref(obj, -1);
1354         return 0;
1355 }
1356
1357 static int cd_cb_debug(void *obj, void *arg, int flag)
1358 {
1359         __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
1360         return 0;
1361 }
1362
1363 static void container_destruct(void *_c)
1364 {
1365         struct ao2_container *c = _c;
1366         int i;
1367
1368         __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
1369
1370         for (i = 0; i < c->n_buckets; i++) {
1371                 struct bucket_entry *current;
1372
1373                 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
1374                         ast_free(current);
1375                 }
1376         }
1377
1378 #ifdef AO2_DEBUG
1379         ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1380 #endif
1381 }
1382
1383 static void container_destruct_debug(void *_c)
1384 {
1385         struct ao2_container *c = _c;
1386         int i;
1387
1388         __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
1389
1390         for (i = 0; i < c->n_buckets; i++) {
1391                 struct bucket_entry *current;
1392
1393                 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
1394                         ast_free(current);
1395                 }
1396         }
1397
1398 #ifdef AO2_DEBUG
1399         ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1400 #endif
1401 }
1402
1403 /*!
1404  * \internal
1405  * \brief Put obj into the arg container.
1406  * \since 11.0
1407  *
1408  * \param obj  pointer to the (user-defined part) of an object.
1409  * \param arg callback argument from ao2_callback()
1410  * \param flags flags from ao2_callback()
1411  *
1412  * \retval 0 on success.
1413  * \retval CMP_STOP|CMP_MATCH on error.
1414  */
1415 static int dup_obj_cb(void *obj, void *arg, int flags)
1416 {
1417         struct ao2_container *dest = arg;
1418
1419         return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
1420 }
1421
1422 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
1423 {
1424         void *obj;
1425         int res = 0;
1426
1427         if (!(flags & OBJ_NOLOCK)) {
1428                 ao2_rdlock(src);
1429                 ao2_wrlock(dest);
1430         }
1431         obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
1432         if (obj) {
1433                 /* Failed to put this obj into the dest container. */
1434                 __ao2_ref(obj, -1);
1435
1436                 /* Remove all items from the dest container. */
1437                 __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
1438                         NULL);
1439                 res = -1;
1440         }
1441         if (!(flags & OBJ_NOLOCK)) {
1442                 ao2_unlock(dest);
1443                 ao2_unlock(src);
1444         }
1445
1446         return res;
1447 }
1448
1449 struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
1450 {
1451         struct ao2_container *clone;
1452         struct astobj2 *orig_obj;
1453         unsigned int options;
1454         int failed;
1455
1456         orig_obj = INTERNAL_OBJ(orig);
1457         if (!orig_obj) {
1458                 return NULL;
1459         }
1460         options = orig_obj->priv_data.options;
1461
1462         /* Create the clone container with the same properties as the original. */
1463         clone = __ao2_container_alloc(options, orig->n_buckets, orig->hash_fn, orig->cmp_fn);
1464         if (!clone) {
1465                 return NULL;
1466         }
1467
1468         if (flags & OBJ_NOLOCK) {
1469                 ao2_wrlock(clone);
1470         }
1471         failed = ao2_container_dup(clone, orig, flags);
1472         if (flags & OBJ_NOLOCK) {
1473                 ao2_unlock(clone);
1474         }
1475         if (failed) {
1476                 /* Object copy into the clone container failed. */
1477                 __ao2_ref(clone, -1);
1478                 clone = NULL;
1479         }
1480         return clone;
1481 }
1482
1483 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)
1484 {
1485         struct ao2_container *clone;
1486         struct astobj2 *orig_obj;
1487         unsigned int options;
1488         int failed;
1489
1490         orig_obj = INTERNAL_OBJ(orig);
1491         if (!orig_obj) {
1492                 return NULL;
1493         }
1494         options = orig_obj->priv_data.options;
1495
1496         /* Create the clone container with the same properties as the original. */
1497         clone = __ao2_container_alloc_debug(options, orig->n_buckets, orig->hash_fn,
1498                 orig->cmp_fn, tag, file, line, func, ref_debug);
1499         if (!clone) {
1500                 return NULL;
1501         }
1502
1503         if (flags & OBJ_NOLOCK) {
1504                 ao2_wrlock(clone);
1505         }
1506         failed = ao2_container_dup(clone, orig, flags);
1507         if (flags & OBJ_NOLOCK) {
1508                 ao2_unlock(clone);
1509         }
1510         if (failed) {
1511                 /* Object copy into the clone container failed. */
1512                 if (ref_debug) {
1513                         __ao2_ref_debug(clone, -1, tag, file, line, func);
1514                 } else {
1515                         __ao2_ref(clone, -1);
1516                 }
1517                 clone = NULL;
1518         }
1519         return clone;
1520 }
1521
1522 #ifdef AO2_DEBUG
1523 static int print_cb(void *obj, void *arg, int flag)
1524 {
1525         struct ast_cli_args *a = (struct ast_cli_args *) arg;
1526         char *s = (char *)obj;
1527
1528         ast_cli(a->fd, "string <%s>\n", s);
1529         return 0;
1530 }
1531
1532 /*
1533  * Print stats
1534  */
1535 static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1536 {
1537         switch (cmd) {
1538         case CLI_INIT:
1539                 e->command = "astobj2 show stats";
1540                 e->usage = "Usage: astobj2 show stats\n"
1541                            "       Show astobj2 show stats\n";
1542                 return NULL;
1543         case CLI_GENERATE:
1544                 return NULL;
1545         }
1546         ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
1547         ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
1548         ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
1549         ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
1550         ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
1551         return CLI_SUCCESS;
1552 }
1553
1554 /*
1555  * This is testing code for astobj
1556  */
1557 static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1558 {
1559         struct ao2_container *c1;
1560         struct ao2_container *c2;
1561         int i, lim;
1562         char *obj;
1563         static int prof_id = -1;
1564         struct ast_cli_args fake_args = { a->fd, 0, NULL };
1565
1566         switch (cmd) {
1567         case CLI_INIT:
1568                 e->command = "astobj2 test";
1569                 e->usage = "Usage: astobj2 test <num>\n"
1570                            "       Runs astobj2 test. Creates 'num' objects,\n"
1571                            "       and test iterators, callbacks and may be other stuff\n";
1572                 return NULL;
1573         case CLI_GENERATE:
1574                 return NULL;
1575         }
1576
1577         if (a->argc != 3) {
1578                 return CLI_SHOWUSAGE;
1579         }
1580
1581         if (prof_id == -1)
1582                 prof_id = ast_add_profile("ao2_alloc", 0);
1583
1584         ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
1585         lim = atoi(a->argv[2]);
1586         ast_cli(a->fd, "called astobj_test\n");
1587
1588         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1589         /*
1590          * allocate a container with no default callback, and no hash function.
1591          * No hash means everything goes in the same bucket.
1592          */
1593         c1 = ao2_t_container_alloc(100, NULL /* no callback */, NULL /* no hash */,"test");
1594         ast_cli(a->fd, "container allocated as %p\n", c1);
1595
1596         /*
1597          * fill the container with objects.
1598          * ao2_alloc() gives us a reference which we pass to the
1599          * container when we do the insert.
1600          */
1601         for (i = 0; i < lim; i++) {
1602                 ast_mark(prof_id, 1 /* start */);
1603                 obj = ao2_t_alloc(80, NULL,"test");
1604                 ast_mark(prof_id, 0 /* stop */);
1605                 ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
1606                 sprintf(obj, "-- this is obj %d --", i);
1607                 ao2_link(c1, obj);
1608                 /* At this point, the refcount on obj is 2 due to the allocation
1609                  * and linking. We can go ahead and reduce the refcount by 1
1610                  * right here so that when the container is unreffed later, the
1611                  * objects will be freed
1612                  */
1613                 ao2_t_ref(obj, -1, "test");
1614         }
1615
1616         ast_cli(a->fd, "testing callbacks\n");
1617         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1618
1619         ast_cli(a->fd, "testing container cloning\n");
1620         c2 = ao2_container_clone(c1, 0);
1621         if (ao2_container_count(c1) != ao2_container_count(c2)) {
1622                 ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
1623         }
1624         ao2_t_callback(c2, 0, print_cb, a, "test callback");
1625
1626         ast_cli(a->fd, "testing iterators, remove every second object\n");
1627         {
1628                 struct ao2_iterator ai;
1629                 int x = 0;
1630
1631                 ai = ao2_iterator_init(c1, 0);
1632                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1633                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1634                         if (x++ & 1)
1635                                 ao2_t_unlink(c1, obj,"test");
1636                         ao2_t_ref(obj, -1,"test");
1637                 }
1638                 ao2_iterator_destroy(&ai);
1639                 ast_cli(a->fd, "testing iterators again\n");
1640                 ai = ao2_iterator_init(c1, 0);
1641                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1642                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1643                         ao2_t_ref(obj, -1,"test");
1644                 }
1645                 ao2_iterator_destroy(&ai);
1646         }
1647
1648         ast_cli(a->fd, "testing callbacks again\n");
1649         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1650
1651         ast_verbose("now you should see an error message:\n");
1652         ao2_t_ref(&i, -1, "");  /* i is not a valid object so we print an error here */
1653
1654         ast_cli(a->fd, "destroy container\n");
1655         ao2_t_ref(c1, -1, "");  /* destroy container */
1656         ao2_t_ref(c2, -1, "");  /* destroy container */
1657         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1658         return CLI_SUCCESS;
1659 }
1660
1661 static struct ast_cli_entry cli_astobj2[] = {
1662         AST_CLI_DEFINE(handle_astobj2_stats, "Print astobj2 statistics"),
1663         AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
1664 };
1665 #endif /* AO2_DEBUG */
1666
1667 int astobj2_init(void)
1668 {
1669 #ifdef AO2_DEBUG
1670         ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1671 #endif
1672
1673         return 0;
1674 }