[asterisk-commits] akshayb: branch akshayb/ao2_containers r273880 - /team/akshayb/ao2_containers...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Jul 4 09:25:33 CDT 2010
Author: akshayb
Date: Sun Jul 4 09:25:28 2010
New Revision: 273880
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=273880
Log:
Beta befor submission
Modified:
team/akshayb/ao2_containers/main/astobj2.c
team/akshayb/ao2_containers/main/astobj2_btree.c
team/akshayb/ao2_containers/main/astobj2_hash.c
team/akshayb/ao2_containers/main/btree.c
Modified: team/akshayb/ao2_containers/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/akshayb/ao2_containers/main/astobj2.c?view=diff&rev=273880&r1=273879&r2=273880
==============================================================================
--- team/akshayb/ao2_containers/main/astobj2.c (original)
+++ team/akshayb/ao2_containers/main/astobj2.c Sun Jul 4 09:25:28 2010
@@ -458,7 +458,7 @@
/* XXX maybe consistency check on arguments ? */
/* compute the container size */
const unsigned int num_buckets = hash_fn ? n_buckets : 1;
- size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
+ size_t container_size = get_container_size(num_buckets)
struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn, link_fn, unlink_fn);
@@ -671,7 +671,7 @@
*/
if (ret && (multi_container != NULL)) {
//__ao2_link(multi_container, ret);
- multi_container.ao2_link(multi_container, ret);
+ multi_container.link_fn(multi_container, ret);
ret = NULL;
}
Modified: team/akshayb/ao2_containers/main/astobj2_btree.c
URL: http://svnview.digium.com/svn/asterisk/team/akshayb/ao2_containers/main/astobj2_btree.c?view=diff&rev=273880&r1=273879&r2=273880
==============================================================================
--- team/akshayb/ao2_containers/main/astobj2_btree.c (original)
+++ team/akshayb/ao2_containers/main/astobj2_btree.c Sun Jul 4 09:25:28 2010
@@ -5,12 +5,34 @@
struct ao2_container_var {
ao2_link_fn *link_fn;
ao2_unlink_fn * unlink_fn;
- struct btree btree;
+ struct btree * btree;
+ int order;
};
-void internal_ao2_container_var_alloc(struct ao2_container *c,struct btree btree, ao2_link_fn *link_fn, ao2_unlink_fn *unlink_fn)
-{
- c->var.btree = btree;
+
+
+// Writing Code for ao2_container allocation
+
+
+struct ao2_container *__ao2_container_alloc_debug(ao2_callback_fn *cmp_fn, int order, char*tag, char *file, int line, const char *funcname, int ref_debug)
+{
+ size_t container_size = sizeof(struct ao2_container);
+ struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
+ return internal_ao2_container_alloc(c, cmp_fn, link_fn, unlink_fn, order);
+}
+
+struct ao2_container *__ao2_container_alloc(ao2_callback_fn *cmp_fn, int order)
+{
+ size_t container_size = sizeof(struct ao2_container);
+ struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
+ return internal_ao2_container_alloc(c, cmp_fn, link_fn, unlink_fn, order);
+}
+
+void internal_ao2_container_var_alloc(struct ao2_container *c, ao2_link_fn *link_fn, ao2_unlink_fn *unlink_fn, int order)
+{
+ // We need to get order. Have to check where we do that.
+ c->var.order = order;
+ c->var.btree = btree_create(order)
c->var.link_fn = link_fn;
c->var.unlink_fn = unlink_fn;
}
@@ -20,7 +42,7 @@
size_t get_container_size (const unsigned int num_buckets)
{
- return (sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket));
+ return (sizeof(struct ao2_container));
}
static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
@@ -29,6 +51,8 @@
/* create a new list entry */
struct bucket_entry *p;
struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct bt_key_val * key_val;
+
if (obj == NULL)
return NULL;
@@ -40,13 +64,18 @@
if (!p)
return NULL;
- i = abs(c->var.hash_fn(user_data, OBJ_POINTER));
ao2_lock(c);
- i %= c->n_buckets;
p->astobj = obj;
p->version = ast_atomic_fetchadd_int(&c->version, 1);
- AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
+// AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
+// Here we add our code to insert element into btree.
+
+ key_val = (struct bt_key_val *) malloc(sizeof(struct bt_key_val));
+ key_val->val = INTERNAL_OBJ(user_data);
+ key_val->key = NULL
+ // I have to insert key? I don't know how, but I will add it here.
+ btree_insert_key(c, key_val);
ast_atomic_fetchadd_int(&c->elements, 1);
/* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
@@ -107,3 +136,271 @@
return NULL;
}
+
+
+/*!
+ * Browse the container using different stategies accoding the flags.
+ * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
+ * specified.
+ * Luckily, for debug purposes, the added args (tag, file, line, funcname)
+ * aren't an excessive load to the system, as the callback should not be
+ * called as often as, say, the ao2_ref func is called.
+ */
+
+
+struct void *interanl_ao2_callback(struct ao2_container *c,
+ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
+ char *tag, char *file, int line, const char *funcname)
+{
+ //No requirement for search boundaries.
+ void *ret = NULL;
+ ao2_callback_fn *cb_default = NULL;
+ ao2_callback_data_fn *cb_withdata = NULL;
+ struct ao2_container *multi_container = NULL;
+ struct ao2_iterator *multi_iterator = NULL;
+
+ /*Safety check*/
+ if (INTERNAL_OBJ(c) = NULL)
+ return NULL;
+ if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
+ if (!(multi_container = __ao2_container_alloc(1, NULL, NULL)))
+ {
+ return NULL;
+ }
+ if (!multi_iterator = ast_calloc(1, sizeof(*multi_iterator))) {
+ ao2_ref(multi_container, -1);
+ return NULL;
+ }
+ }
+
+
+ /* override the match function if necessary */
+ if (cb_fn == NULL) { /* if NULL, match everything */
+ if (type == WITH_DATA) {
+ cb_withdata = cb_true_data;
+ } else {
+ cb_default = cb_true;
+ }
+ } else {
+ /* We do this here to avoid the per object casting penalty (even though
+ that is probably optimized away anyway). */
+ if (type == WITH_DATA) {
+ cb_withdata = cb_fn;
+ } else {
+ cb_default = cb_fn;
+ }
+ }
+
+static void *internal_ao2_callback(struct ao2_container *c,
+ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
+ char *tag, char *file, int line, const char *funcname)
+{
+ int i, start, last; /* search boundaries */
+ void *ret = NULL;
+ ao2_callback_fn *cb_default = NULL;
+ ao2_callback_data_fn *cb_withdata = NULL;
+ struct ao2_container *multi_container = NULL;
+ struct ao2_iterator *multi_iterator = NULL;
+
+ if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
+ return NULL;
+
+ /*
+ * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
+ * turned off. This if statement checks for the special condition
+ * where multiple items may need to be returned.
+ */
+ if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
+ /* we need to return an ao2_iterator with the results,
+ * as there could be more than one. the iterator will
+ * hold the only reference to a container that has all the
+ * matching objects linked into it, so when the iterator
+ * is destroyed, the container will be automatically
+ * destroyed as well.
+ */
+ if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) {
+ return NULL;
+ }
+// This part dosen't needs to be corrected as, it will be automatically corrected once we correct the ao2_iterator.
+ if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
+ ao2_ref(multi_container, -1);
+ return NULL;
+ }
+ }
+
+ /* override the match function if necessary */
+ if (cb_fn == NULL) { /* if NULL, match everything */
+ if (type == WITH_DATA) {
+ cb_withdata = cb_true_data;
+ } else {
+ cb_default = cb_true;
+ }
+ } else {
+ /* We do this here to avoid the per object casting penalty (even though
+ that is probably optimized away anyway). */
+ if (type == WITH_DATA) {
+ cb_withdata = cb_fn;
+ } else {
+ cb_default = cb_fn;
+ }
+ }
+
+ /*
+ * XXX this can be optimized.
+ * If we have a hash function and lookup by pointer,
+ * run the hash function. Otherwise, scan the whole container
+ * (this only for the time being. We need to optimize this.)
+ */
+ if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
+ start = i = c->var.hash_fn(arg, flags & OBJ_POINTER) % c->var.n_buckets;
+ else /* don't know, let's scan all buckets */
+ start = i = -1; /* XXX this must be fixed later. */
+
+ /* determine the search boundaries: i..last-1 */
+ if (i < 0) {
+ start = i = 0;
+ last = c->var.n_buckets; // This get changed
+ } else if ((flags & OBJ_CONTINUE)) {
+ last = c->n_buckets;
+ } else {
+ last = i + 1;
+ }
+
+ ao2_lock(c); /* avoid modifications to the content */
+
+ for (; i < last ; i++) {
+ /* scan the list with prev-cur pointers */
+ struct bucket_entry *cur;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&c->var.buckets[i], cur, entry) {
+ int match = (CMP_MATCH | CMP_STOP);
+
+ if (type == WITH_DATA) {
+ match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
+ } else {
+ match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
+ }
+
+ /* we found the object, performing operations according flags */
+ if (match == 0) { /* no match, no stop, continue */
+ continue;
+ } else if (match == CMP_STOP) { /* no match but stop, we are done */
+ i = last;
+ break;
+ }
+
+ /* we have a match (CMP_MATCH) here */
+ if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */
+ /* it is important to handle this case before the unlink */
+ ret = EXTERNAL_OBJ(cur->astobj);
+ if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
+ if (tag)
+ __ao2_ref_debug(ret, 1, tag, file, line, funcname);
+ else
+ __ao2_ref(ret, 1);
+ }
+ }
+
+ /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off,
+ * link the object into the container that will hold the results.
+ */
+ if (ret && (multi_container != NULL)) {
+ //__ao2_link(multi_container, ret);
+ multi_container.link_fn(multi_container, ret);
+ ret = NULL;
+ }
+
+ if (flags & OBJ_UNLINK) { /* must unlink */
+ /* we are going to modify the container, so update version */
+ ast_atomic_fetchadd_int(&c->version, 1);
+ AST_LIST_REMOVE_CURRENT(entry);
+ /* update number of elements */
+ ast_atomic_fetchadd_int(&c->elements, -1);
+
+ /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
+ * must be decremented.
+ * - When unlinking with OBJ_MULTIPLE the ref from the original container
+ * must be decremented regardless if OBJ_NODATA is used. This is because the result is
+ * returned in a new container that already holds its own ref for the object. If the ref
+ * from the original container is not accounted for here a memory leak occurs. */
+ if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
+ if (tag)
+ __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
+ else
+ __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
+ }
+ ast_free(cur); /* free the link record */
+ }
+
+ if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
+ /* We found our only (or last) match, so force an exit from
+ the outside loop. */
+ i = last;
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ if (ret) {
+ break;
+ }
+
+ if (i == c->var.n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
+ /* Move to the beginning to ensure we check every bucket */
+ i = -1;
+ last = start;
+ }
+ }
+ ao2_unlock(c);
+
+ /* if multi_container was created, we are returning multiple objects */
+ if (multi_container != NULL) {
+ *multi_iterator = ao2_iterator_init(multi_container,
+ AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
+ ao2_ref(multi_container, -1);
+ return multi_iterator;
+ } else {
+ return ret;
+ }
+}
+
+void *__ao2_callback_debug(struct ao2_container *c,
+ const enum search_flags flags,
+ ao2_callback_fn *cb_fn, void *arg,
+ char *tag, char *file, int line, const char *funcname)
+{
+ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
+}
+
+void *__ao2_callback(struct ao2_container *c, const enum search_flags flags,
+ ao2_callback_fn *cb_fn, void *arg)
+{
+ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
+}
+
+void *__ao2_callback_data_debug(struct ao2_container *c,
+ const enum search_flags flags,
+ ao2_callback_data_fn *cb_fn, void *arg, void *data,
+ char *tag, char *file, int line, const char *funcname)
+{
+ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
+}
+
+void *__ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
+ ao2_callback_data_fn *cb_fn, void *arg, void *data)
+{
+ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
+}
+
+/*!
+ * the find function just invokes the default callback with some reasonable flags.
+ */
+void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
+{
+ return __ao2_callback_debug(c, flags, c->core.cmp_fn, arg, tag, file, line, funcname);
+}
+
+void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
+{
+ return __ao2_callback(c, flags, c->core.cmp_fn, arg);
+}
Modified: team/akshayb/ao2_containers/main/astobj2_hash.c
URL: http://svnview.digium.com/svn/asterisk/team/akshayb/ao2_containers/main/astobj2_hash.c?view=diff&rev=273880&r1=273879&r2=273880
==============================================================================
--- team/akshayb/ao2_containers/main/astobj2_hash.c (original)
+++ team/akshayb/ao2_containers/main/astobj2_hash.c Sun Jul 4 09:25:28 2010
@@ -4,7 +4,7 @@
struct ao2_container_var {
ao2_link_fn *link_fn;
ao2_unlink_fn *unlink_fn;
- sturct btree btree;
+ sturct btree *btree;
};
void internal_ao2_container_var_alloc(ao2_hash_fn *hash_fn, const unsigned int n_buckets)
Modified: team/akshayb/ao2_containers/main/btree.c
URL: http://svnview.digium.com/svn/asterisk/team/akshayb/ao2_containers/main/btree.c?view=diff&rev=273880&r1=273879&r2=273880
==============================================================================
--- team/akshayb/ao2_containers/main/btree.c (original)
+++ team/akshayb/ao2_containers/main/btree.c Sun Jul 4 09:25:28 2010
@@ -7,20 +7,20 @@
unsigned int index;
};
-static void print_single_node(btree *btree, bt_node * node);
-static sturct bt_node * allocate_btree_node (unsigned int order);
-static int free_btree_node (bt_node * node);
-
-static struct node_pos get_btree_node(btree * btree,void * key);
-
-static int delete_key_from_node(btree * btree, node_pos * node_pos);
-static struct bt_node * merge_nodes(btree * btree, bt_node * n1, bt_key_val * kv ,bt_node * n2);
-static void move_key(btree * btree, bt_node * node, unsigned int index, position_t pos);
-static struct node_pos get_max_key_pos(btree * btree, bt_node * subtree);
-static struct node_pos get_min_key_pos(btree * btree, bt_node * subtree);
-static struct bt_node * merge_siblings(btree * btree, bt_node * parent,unsigned int index,
- position_t pos);
-static void copy_key_val(btree * btree,bt_key_val * src, bt_key_val * dst);
+static void print_single_node(struct btree *btree, struct bt_node * node);
+static struct bt_node * allocate_btree_node (unsigned int order);
+static int free_btree_node (struct bt_node * node);
+
+static struct node_pos get_btree_node(struct btree * btree,void * key);
+
+static int delete_key_from_node(struct btree * btree, struct node_pos * node_pos);
+static struct bt_node * merge_nodes(struct btree * btree, struct bt_node * n1, struct bt_key_val * kv ,struct bt_node * n2);
+static void move_key(struct btree * btree, struct bt_node * node, unsigned int index, struct position_t pos);
+static struct node_pos get_max_key_pos(struct btree * btree, struct bt_node * subtree);
+static struct node_pos get_min_key_pos(struct btree * btree, struct bt_node * subtree);
+static struct bt_node * merge_siblings(struct btree * btree, struct bt_node * parent,unsigned int index,
+ struct position_t pos);
+static void copy_key_val(struct btree * btree,struct bt_key_val * src, struct bt_key_val * dst);
/**
* Used to create a btree with just the root node
@@ -29,7 +29,7 @@
*/
struct btree * btree_create(unsigned int order) {
struct btree * btree;
- btree = mem_alloc(sizeof(*btree));
+ btree = mem_alloc(sizeof(struct btree));
btree->order = order;
btree->root = allocate_btree_node(order);
btree->root->leaf = true;
@@ -187,12 +187,11 @@
* @param compare Function used to compare the two nodes of the tree
* @return success or failure
*/
-int btree_insert_key(struct btree * btree, struct bt_key_val * key_val) {
- bt_node * rnode;
-
- rnode = btree->root;
+int btree_insert_key(struct ao2_container *c, struct bt_key_val * key_val) {
+ struct btree * btree = c->ao2_container_var.btree;
+ struct bt_node * rnode = btree->root;
if(rnode->nr_active == (2*btree->order - 1)) {
- bt_node * new_root;
+ struct bt_node * new_root;
new_root = allocate_btree_node(btree->order);
new_root->level = btree->root->level + 1;
btree->root = new_root;
@@ -649,10 +648,10 @@
* @param key The the key to be searched
* @return The node and position of the key within the node
*/
-node_pos get_btree_node(btree * btree,void * key) {
- node_pos kp;
+struct node_pos get_btree_node(struct btree * btree,void * key) {
+ struct node_pos kp;
unsigned int key_val = btree->value(key);
- bt_node * node;
+ struct bt_node * node;
unsigned int i = 0;
node = btree->root;
More information about the asterisk-commits
mailing list