return NULL;
}
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ flags &= ~OBJ_SEARCH_MASK;
+ flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
__ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
return NULL;
return NULL;
}
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ flags &= ~OBJ_SEARCH_MASK;
+ flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
__ao2_callback(c, flags, ao2_match_by_addr, user_data);
return NULL;
return NULL;
}
- i = abs(self->hash_fn(obj_new, OBJ_POINTER));
+ i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT));
i %= self->n_buckets;
if (tag) {
if (options & AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN) {
if (sort_fn) {
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp > 0) {
continue;
}
} else {
if (sort_fn) {
AST_DLLIST_TRAVERSE_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp < 0) {
continue;
}
* If lookup by pointer or search key, run the hash and optional
* sort functions. Otherwise, traverse the whole container.
*/
- if (flags & (OBJ_POINTER | OBJ_KEY)) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ case OBJ_SEARCH_KEY:
/* we know hash can handle this case */
- bucket_cur = abs(self->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)));
+ bucket_cur = abs(self->hash_fn(arg, flags & OBJ_SEARCH_MASK));
bucket_cur %= self->n_buckets;
state->sort_fn = self->common.sort_fn;
- } else {
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ /* scan all buckets for partial key matches */
+ bucket_cur = -1;
+ state->sort_fn = self->common.sort_fn;
+ break;
+ default:
/* don't know, let's scan all buckets */
bucket_cur = -1;
- state->sort_fn = (flags & OBJ_PARTIAL_KEY) ? self->common.sort_fn : NULL;
+ state->sort_fn = NULL;
+ break;
}
if (state->descending) {
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp > 0) {
continue;
}
/* Was this the starting bucket? */
if (bucket_cur == state->bucket_start
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* In case the bucket was empty or none of the nodes matched. */
state->sort_fn = NULL;
}
/* Was this the first container bucket? */
if (bucket_cur == 0
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the end to ensure we check every bucket */
bucket_cur = self->n_buckets;
state->bucket_last = state->bucket_start + 1;
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp < 0) {
continue;
}
/* Was this the starting bucket? */
if (bucket_cur == state->bucket_start
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* In case the bucket was empty or none of the nodes matched. */
state->sort_fn = NULL;
}
/* Was this the last container bucket? */
if (bucket_cur == self->n_buckets - 1
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the beginning to ensure we check every bucket */
bucket_cur = -1;
state->bucket_last = state->bucket_start;
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp > 0) {
continue;
}
/* Was this the first container bucket? */
if (bucket_cur == 0
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the end to ensure we check every bucket */
bucket_cur = self->n_buckets;
state->bucket_last = state->bucket_start + 1;
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp < 0) {
continue;
}
/* Was this the last container bucket? */
if (bucket_cur == self->n_buckets - 1
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the beginning to ensure we check every bucket */
bucket_cur = -1;
state->bucket_last = state->bucket_start;
++count_obj;
/* Check container hash key for expected bucket. */
- bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_POINTER));
+ bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_SEARCH_OBJECT));
bucket_exp %= self->n_buckets;
if (bucket != bucket_exp) {
ast_log(LOG_ERROR, "Bucket %d node hashes to bucket %d!\n",
/* Check sort if configured. */
if (self->common.sort_fn) {
if (obj_last
- && self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+ && self->common.sort_fn(obj_last, node->common.obj, OBJ_SEARCH_OBJECT) > 0) {
ast_log(LOG_ERROR, "Bucket %d nodes out of sorted order!\n",
bucket);
return -1;
* \param sort_fn Sort comparison function for non-empty nodes.
* \param obj_right pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
- * OBJ_POINTER - if set, 'obj_right', is an object.
- * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
- * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
+ * OBJ_SEARCH_OBJECT - if set, 'obj_right', is an object.
+ * OBJ_SEARCH_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_SEARCH_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
* \param bias How to bias search direction for duplicates
*
* \return enum empty_node_direction to proceed.
for (;;) {
if (!cur->common.obj) {
/* Which direction do we go to insert this node? */
- if (rb_find_empty_direction(cur, sort_fn, node->common.obj, OBJ_POINTER, bias)
+ if (rb_find_empty_direction(cur, sort_fn, node->common.obj, OBJ_SEARCH_OBJECT, bias)
== GO_LEFT) {
if (cur->left) {
cur = cur->left;
rb_insert_fixup(self, node);
return AO2_CONTAINER_INSERT_NODE_INSERTED;
}
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp > 0) {
if (cur->left) {
cur = cur->left;
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp) {
/* No more nodes in this container are possible to match. */
break;
* \param self Container to operate upon.
* \param obj_right pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
- * OBJ_POINTER - if set, 'obj_right', is an object.
- * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
- * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
+ * OBJ_SEARCH_OBJECT - if set, 'obj_right', is an object.
+ * OBJ_SEARCH_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_SEARCH_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
* OBJ_CONTINUE - if set, return node right before or right after search key if not a match.
* \param bias How to bias search direction for duplicates
*
struct rbtree_node *next = NULL;
ao2_sort_fn *sort_fn;
- sort_flags = flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY);
+ sort_flags = flags & OBJ_SEARCH_MASK;
sort_fn = self->common.sort_fn;
/* Find node where normal search would find it. */
state->arg = arg;
state->flags = flags;
- if (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ case OBJ_SEARCH_KEY:
+ case OBJ_SEARCH_PARTIAL_KEY:
/* We are asked to do a directed search. */
state->sort_fn = self->common.sort_fn;
- } else {
+ break;
+ default:
/* Don't know, let's visit all nodes */
state->sort_fn = NULL;
+ break;
}
if (!self->root) {
switch (self->common.options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
- if ((flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) != OBJ_PARTIAL_KEY) {
+ if ((flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_PARTIAL_KEY) {
/* There are no duplicates allowed. */
bias = BIAS_EQUAL;
break;
switch (self->common.options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
- if ((flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) != OBJ_PARTIAL_KEY) {
+ if ((flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_PARTIAL_KEY) {
/* There are no duplicates allowed. */
bias = BIAS_EQUAL;
break;
}
if (obj_last) {
- if (self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+ if (self->common.sort_fn(obj_last, node->common.obj, OBJ_SEARCH_OBJECT) > 0) {
ast_log(LOG_ERROR, "Tree nodes are out of sorted order!\n");
return -1;
}
const struct ao2_reg_container *reg_left = obj_left;
int cmp;
- if (flags & OBJ_KEY) {
- const char *name = obj_right;
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ {
+ const struct ao2_reg_container *reg_right = obj_right;
- cmp = strcasecmp(reg_left->name, name);
- } else if (flags & OBJ_PARTIAL_KEY) {
- const struct ao2_reg_partial_key *partial_key = obj_right;
+ cmp = strcasecmp(reg_left->name, reg_right->name);
+ }
+ break;
+ case OBJ_SEARCH_KEY:
+ {
+ const char *name = obj_right;
- cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
- } else {
- const struct ao2_reg_container *reg_right = obj_right;
+ cmp = strcasecmp(reg_left->name, name);
+ }
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ {
+ const struct ao2_reg_partial_key *partial_key = obj_right;
- cmp = strcasecmp(reg_left->name, reg_right->name);
+ cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
+ }
+ break;
+ default:
+ /* Sort can only work on something with a full or partial key. */
+ ast_assert(0);
+ cmp = 0;
+ break;
}
return cmp;
}
void ao2_container_unregister(const char *name)
{
#if defined(AST_DEVMODE)
- ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_KEY,
+ ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_SEARCH_KEY,
"Unregister container");
#endif /* defined(AST_DEVMODE) */
}
partial_key.name = a->word;
which.find_nth = a->n;
which.count = 0;
- reg = ao2_t_callback_data(reg_containers, partial_key.len ? OBJ_PARTIAL_KEY : 0,
+ reg = ao2_t_callback_data(reg_containers, partial_key.len ? OBJ_SEARCH_PARTIAL_KEY : 0,
ao2_complete_reg_cb, &partial_key, &which, "Find partial registered container");
if (reg) {
name = ast_strdup(reg->name);
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ao2_container_dump(reg->registered, 0, name, (void *) &a->fd, cli_output,
reg->prnt_obj);
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ao2_container_stats(reg->registered, 0, name, (void *) &a->fd, cli_output);
ao2_t_ref(reg, -1, "Done with registered container object.");
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ast_cli(a->fd, "Container check of '%s': %s.\n", name,
ao2_container_check(reg->registered, 0) ? "failed" : "OK");