Add ability to clone ao2 containers.

Occasionally there is a need to put all objects in one container also into
another container.

Some reasons you might need to do this:

1) You need to reconfigure a container.  You would do this by creating a
new container with the new configuration and ao2_container_dup the old
container into it.  Then replace the old container with the new.  Then
destroy the old container.

2) You need the contents of a container to remain stable while operating
on all of the objects.  You would do this by creating a cloned container
of the original with ao2_container_clone.  The cloned container is a
snapshot of the objects at the time of the cloning.  When done, just
destroy the cloned container.

Review: https://reviewboard.asterisk.org/r/1746/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@357145 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2012-02-28 00:42:38 +00:00
parent ae07610d73
commit 50c8557f03
3 changed files with 215 additions and 0 deletions

View File

@@ -109,9 +109,11 @@ static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, stru
{
struct ao2_container *c1;
struct ao2_container *c2;
struct ao2_container *c3 = NULL;
struct ao2_iterator it;
struct ao2_iterator *mult_it;
struct test_obj *obj;
struct test_obj *obj2;
struct test_obj tmp_obj;
int bucket_size;
int increment = 0;
@@ -154,6 +156,44 @@ static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, stru
ast_test_status_update(test, "Container created: random bucket size %d: number of items: %d\n", bucket_size, lim);
/* Testing ao2_container_clone */
c3 = ao2_container_clone(c1, 0);
if (!c3) {
ast_test_status_update(test, "ao2_container_clone failed.\n");
res = AST_TEST_FAIL;
goto cleanup;
}
if (ao2_container_count(c1) != ao2_container_count(c3)) {
ast_test_status_update(test, "Cloned container does not have the same number of objects.\n");
res = AST_TEST_FAIL;
} else {
it = ao2_iterator_init(c1, 0);
for (; (obj = ao2_t_iterator_next(&it, "test orig")); ao2_t_ref(obj, -1, "test orig")) {
/*
* Unlink the matching object from the cloned container to make
* the next search faster. This is a big speed optimization!
* It reduces the container with 100000 objects test time from
* 18 seconds to 200 ms.
*/
obj2 = ao2_t_callback(c3, OBJ_POINTER | OBJ_UNLINK, ao2_match_by_addr, obj,
"test clone");
if (obj2) {
ao2_t_ref(obj2, -1, "test clone");
continue;
}
ast_test_status_update(test,
"Orig container has an object %p not in the clone container.\n", obj);
res = AST_TEST_FAIL;
}
ao2_iterator_destroy(&it);
if (ao2_container_count(c3)) {
ast_test_status_update(test, "Cloned container still has objects.\n");
res = AST_TEST_FAIL;
}
}
ao2_t_ref(c3, -1, "bye c3");
c3 = NULL;
/* Testing ao2_find with no flags */
num = 100;
for (; num; num--) {
@@ -336,6 +376,9 @@ cleanup:
if (c2) {
ao2_t_ref(c2, -1, "bye c2");
}
if (c3) {
ao2_t_ref(c3, -1, "bye c3");
}
if (destructor_count > 0) {
ast_test_status_update(test, "all destructors were not called, destructor count is %d\n", destructor_count);