diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-09-24 22:55:06 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-09-24 22:55:06 +0000 |
commit | 88436ecbd448569b1517d3340c2f8486010ff0ae (patch) | |
tree | 8e42ae9ccb11efe36529d29eb03163aab087c6e5 | |
parent | b916eaad4c9e662e476b63c5bd5ff7367ad47b8e (diff) |
astobj2: Made use OBJ_SEARCH_xxx identifiers as field enum values internally.
* Made ao2_unlink to protect itself from stray OBJ_SEARCH_xxx values
passed in.
........
Merged revisions 399749 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399750 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | main/astobj2.c | 144 |
1 files changed, 85 insertions, 59 deletions
diff --git a/main/astobj2.c b/main/astobj2.c index cc1e2576b..008c803cc 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -1190,7 +1190,8 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags, 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; @@ -1204,7 +1205,8 @@ void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags) 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; @@ -2138,7 +2140,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel 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) { @@ -2178,7 +2180,7 @@ static enum ao2_container_insert hash_ao2_insert_node(struct ao2_container_hash 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; } @@ -2210,7 +2212,7 @@ static enum ao2_container_insert hash_ao2_insert_node(struct ao2_container_hash } 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; } @@ -2310,15 +2312,24 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s * 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) { @@ -2354,8 +2365,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s 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; } @@ -2380,7 +2390,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s /* 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; } @@ -2388,7 +2398,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s /* 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; @@ -2435,8 +2445,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s 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; } @@ -2461,7 +2470,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s /* 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; } @@ -2469,7 +2478,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s /* 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; @@ -2542,8 +2551,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se 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; } @@ -2574,7 +2582,7 @@ hash_descending_resume:; /* 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; @@ -2609,8 +2617,7 @@ hash_descending_resume:; 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; } @@ -2641,7 +2648,7 @@ hash_ascending_resume:; /* 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; @@ -3043,7 +3050,7 @@ static int hash_ao2_integrity(struct ao2_container_hash *self) ++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", @@ -3054,7 +3061,7 @@ static int hash_ao2_integrity(struct ao2_container_hash *self) /* 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; @@ -3510,9 +3517,9 @@ enum empty_node_direction { * \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. @@ -4260,7 +4267,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree 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; @@ -4284,7 +4291,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree 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; @@ -4366,7 +4373,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree /* 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; } @@ -4382,7 +4389,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree /* 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; } @@ -4407,7 +4414,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree /* 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; } @@ -4423,7 +4430,7 @@ static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree /* 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; } @@ -4544,8 +4551,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s 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; @@ -4581,9 +4587,9 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s * \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 * @@ -4598,7 +4604,7 @@ static struct rbtree_node *rb_find_initial(struct ao2_container_rbtree *self, vo 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. */ @@ -4731,12 +4737,17 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self, 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) { @@ -4764,7 +4775,7 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self, 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; @@ -4799,7 +4810,7 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self, 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; @@ -5229,7 +5240,7 @@ static int rb_ao2_integrity(struct ao2_container_rbtree *self) } 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; } @@ -5518,18 +5529,33 @@ static int ao2_reg_sort_cb(const void *obj_left, const void *obj_right, int flag 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; } @@ -5576,7 +5602,7 @@ int ao2_container_register(const char *name, struct ao2_container *self, ao2_prn 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) */ } @@ -5607,7 +5633,7 @@ static char *complete_container_names(struct ast_cli_args *a) 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); @@ -5676,7 +5702,7 @@ static char *handle_cli_astobj2_container_dump(struct ast_cli_entry *e, int cmd, } 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); @@ -5712,7 +5738,7 @@ static char *handle_cli_astobj2_container_stats(struct ast_cli_entry *e, int cmd } 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."); @@ -5747,7 +5773,7 @@ static char *handle_cli_astobj2_container_check(struct ast_cli_entry *e, int cmd } 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"); |