Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
A
asterisk
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Voice
asterisk
Commits
0ad0e89b
Commit
0ad0e89b
authored
6 years ago
by
George Joseph
Committed by
Gerrit Code Review
6 years ago
Browse files
Options
Downloads
Plain Diff
Merge "astobj2: Create function to copy weak proxied objects from container." into 16
parents
450ca982
0d2b3906
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
include/asterisk/astobj2.h
+22
-0
22 additions, 0 deletions
include/asterisk/astobj2.h
main/astobj2_container.c
+53
-0
53 additions, 0 deletions
main/astobj2_container.c
tests/test_astobj2_weaken.c
+158
-0
158 additions, 0 deletions
tests/test_astobj2_weaken.c
with
233 additions
and
0 deletions
include/asterisk/astobj2.h
+
22
−
0
View file @
0ad0e89b
...
...
@@ -1422,6 +1422,28 @@ int ao2_container_count(struct ao2_container *c);
*/
int
ao2_container_dup
(
struct
ao2_container
*
dest
,
struct
ao2_container
*
src
,
enum
search_flags
flags
);
/*!
* \brief Copy object references associated with src container weakproxies into the dest container.
*
* \param dest Container to copy src strong object references into.
* \param src Container to copy all weak object references from.
* \param flags OBJ_NOLOCK if a lock is already held on both containers.
* Otherwise, the src container is locked first.
*
* \pre The dest container must be empty. If the duplication fails, the
* dest container will be returned empty.
*
* \note This can potentially be expensive because a malloc is
* needed for every object in the src container.
*
* \note Every object inside the container is locked by \ref ao2_weakproxy_get_object.
* Any weakproxy in \ref src with no associated object is ignored.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int
ao2_container_dup_weakproxy_objs
(
struct
ao2_container
*
dest
,
struct
ao2_container
*
src
,
enum
search_flags
flags
);
/*!
* \brief Create a clone/copy of the given container.
* \since 11.0
...
...
This diff is collapsed.
Click to expand it.
main/astobj2_container.c
+
53
−
0
View file @
0ad0e89b
...
...
@@ -697,6 +697,59 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
return
res
;
}
/*!
* \brief Copy obj associated with a weakproxy into the arg container.
*
* \param proxy pointer to the weakproxy.
* \param arg callback argument from ao2_callback()
* \param flags flags from ao2_callback()
*
* \retval 0 on success.
* \retval CMP_STOP|CMP_MATCH on error.
*/
static
int
dup_weakproxy_cb
(
void
*
proxy
,
void
*
arg
,
int
flags
)
{
void
*
obj
=
ao2_weakproxy_get_object
(
proxy
,
0
);
struct
ao2_container
*
dest
=
arg
;
int
ret
;
if
(
!
obj
)
{
return
0
;
}
ret
=
ao2_t_link_flags
(
dest
,
obj
,
OBJ_NOLOCK
,
NULL
)
?
0
:
(
CMP_MATCH
|
CMP_STOP
);
ao2_ref
(
obj
,
-
1
);
return
ret
;
}
int
ao2_container_dup_weakproxy_objs
(
struct
ao2_container
*
dest
,
struct
ao2_container
*
src
,
enum
search_flags
flags
)
{
void
*
obj
;
int
res
=
0
;
if
(
!
(
flags
&
OBJ_NOLOCK
))
{
ao2_rdlock
(
src
);
ao2_wrlock
(
dest
);
}
obj
=
ao2_callback
(
src
,
OBJ_NOLOCK
,
dup_weakproxy_cb
,
dest
);
if
(
obj
)
{
/* Failed to put this obj into the dest container. */
ao2_t_ref
(
obj
,
-
1
,
"Failed to put this object into the dest container."
);
/* Remove all items from the dest container. */
ao2_t_callback
(
dest
,
OBJ_NOLOCK
|
OBJ_UNLINK
|
OBJ_NODATA
|
OBJ_MULTIPLE
,
NULL
,
NULL
,
NULL
);
res
=
-
1
;
}
if
(
!
(
flags
&
OBJ_NOLOCK
))
{
ao2_unlock
(
dest
);
ao2_unlock
(
src
);
}
return
res
;
}
struct
ao2_container
*
__ao2_container_clone
(
struct
ao2_container
*
orig
,
enum
search_flags
flags
,
const
char
*
tag
,
const
char
*
file
,
int
line
,
const
char
*
func
)
{
struct
ao2_container
*
clone
;
...
...
This diff is collapsed.
Click to expand it.
tests/test_astobj2_weaken.c
+
158
−
0
View file @
0ad0e89b
...
...
@@ -262,9 +262,166 @@ fail_cleanup:
return
AST_TEST_FAIL
;
}
struct
strong_str
{
char
*
value
;
};
struct
weakproxy_str
{
AO2_WEAKPROXY
();
char
value
[
0
];
};
static
struct
strong_str
*
alloc_str
(
struct
ao2_container
*
weakcontainer
,
const
char
*
value
)
{
struct
strong_str
*
strong
=
ao2_t_alloc
(
sizeof
(
*
strong
),
NULL
,
value
);
struct
weakproxy_str
*
weak
=
ao2_weakproxy_alloc
(
sizeof
(
*
weak
)
+
strlen
(
value
)
+
1
,
NULL
);
if
(
!
weak
||
!
strong
)
{
goto
error_return
;
}
strcpy
(
weak
->
value
,
value
);
/*SAFE*/
strong
->
value
=
weak
->
value
;
if
(
ao2_weakproxy_set_object
(
weak
,
strong
,
0
))
{
goto
error_return
;
}
if
(
!
ao2_link
(
weakcontainer
,
weak
))
{
goto
error_return
;
}
ao2_ref
(
weak
,
-
1
);
return
strong
;
error_return:
ao2_cleanup
(
weak
);
ao2_cleanup
(
strong
);
return
NULL
;
}
AO2_STRING_FIELD_HASH_FN
(
weakproxy_str
,
value
);
AO2_STRING_FIELD_CMP_FN
(
weakproxy_str
,
value
);
AO2_STRING_FIELD_SORT_FN
(
strong_str
,
value
);
#define ITERATOR_CHECK_NEXT(iter, var, expected) \
do { \
var = ao2_iterator_next(iter); \
ast_test_validate_cleanup(test, var == expected, ret, cleanup); \
ao2_cleanup(var); \
} while (0)
#define WEAKFIND_CHECK(c, key, var, expected) \
do { \
var = ao2_weakproxy_find(c, key, OBJ_SEARCH_KEY, ""); \
ast_test_validate_cleanup(test, var == expected, ret, cleanup); \
ao2_cleanup(var); \
} while (0)
AST_TEST_DEFINE
(
astobj2_weak_container
)
{
int
ret
=
AST_TEST_FAIL
;
struct
strong_str
*
strong1
=
NULL
;
struct
strong_str
*
strong2
=
NULL
;
struct
strong_str
*
strong3
=
NULL
;
struct
strong_str
*
strong
=
NULL
;
struct
ao2_container
*
weakcontainer
=
NULL
;
struct
ao2_container
*
dupcontainer
=
NULL
;
struct
ao2_iterator
iter
;
switch
(
cmd
)
{
case
TEST_INIT
:
info
->
name
=
"astobj2_weak_container"
;
info
->
category
=
"/main/astobj2/"
;
info
->
summary
=
"Test ao2 weak containers"
;
info
->
description
=
"Test ao2 weak containers."
;
return
AST_TEST_NOT_RUN
;
case
TEST_EXECUTE
:
break
;
}
weakcontainer
=
ao2_container_alloc_hash
(
AO2_ALLOC_OPT_LOCK_MUTEX
,
0
,
7
,
weakproxy_str_hash_fn
,
NULL
,
weakproxy_str_cmp_fn
);
dupcontainer
=
ao2_container_alloc_list
(
AO2_ALLOC_OPT_LOCK_MUTEX
,
0
,
strong_str_sort_fn
,
NULL
);
if
(
!
weakcontainer
||
!
dupcontainer
)
{
goto
cleanup
;
}
strong1
=
alloc_str
(
weakcontainer
,
"obj1"
);
strong2
=
alloc_str
(
weakcontainer
,
"obj2"
);
strong3
=
alloc_str
(
weakcontainer
,
"obj3"
);
if
(
!
strong1
||
!
strong2
||
!
strong3
)
{
goto
cleanup
;
}
if
(
ao2_container_dup_weakproxy_objs
(
dupcontainer
,
weakcontainer
,
0
))
{
goto
cleanup
;
}
iter
=
ao2_iterator_init
(
dupcontainer
,
0
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
strong1
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
strong2
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
strong3
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
NULL
);
ao2_iterator_cleanup
(
&
iter
);
ao2_callback
(
dupcontainer
,
OBJ_NODATA
|
OBJ_UNLINK
|
OBJ_MULTIPLE
,
NULL
,
NULL
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj1"
,
strong
,
strong1
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj2"
,
strong
,
strong2
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj3"
,
strong
,
strong3
);
WEAKFIND_CHECK
(
weakcontainer
,
"unknown"
,
strong
,
NULL
);
/* This will orphan "obj2" in weakcontainer. */
ao2_replace
(
strong2
,
NULL
);
if
(
ao2_container_dup_weakproxy_objs
(
dupcontainer
,
weakcontainer
,
0
))
{
goto
cleanup
;
}
ast_test_validate_cleanup
(
test
,
ao2_container_count
(
weakcontainer
)
==
ao2_container_count
(
dupcontainer
)
+
1
,
ret
,
cleanup
);
iter
=
ao2_iterator_init
(
dupcontainer
,
0
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
strong1
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
strong3
);
ITERATOR_CHECK_NEXT
(
&
iter
,
strong
,
NULL
);
ao2_iterator_cleanup
(
&
iter
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj1"
,
strong
,
strong1
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj2"
,
strong
,
NULL
);
WEAKFIND_CHECK
(
weakcontainer
,
"obj3"
,
strong
,
strong3
);
WEAKFIND_CHECK
(
weakcontainer
,
"unknown"
,
strong
,
NULL
);
ret
=
AST_TEST_PASS
;
cleanup:
ao2_cleanup
(
strong1
);
ao2_cleanup
(
strong2
);
ao2_cleanup
(
strong3
);
ao2_cleanup
(
weakcontainer
);
ao2_cleanup
(
dupcontainer
);
ao2_cleanup
(
strong
);
return
ret
;
}
static
int
unload_module
(
void
)
{
AST_TEST_UNREGISTER
(
astobj2_weak1
);
AST_TEST_UNREGISTER
(
astobj2_weak_container
);
return
0
;
}
...
...
@@ -272,6 +429,7 @@ static int unload_module(void)
static
int
load_module
(
void
)
{
AST_TEST_REGISTER
(
astobj2_weak1
);
AST_TEST_REGISTER
(
astobj2_weak_container
);
return
AST_MODULE_LOAD_SUCCESS
;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment