[svn-commits] akshayb: branch akshayb/ao2_containers r273880 - /team/akshayb/ao2_containers...

SVN commits to the Digium repositories svn-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 svn-commits mailing list