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