[svn-commits] murf: branch murf/bug11210 r89317 - /team/murf/bug11210/channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Nov 15 18:18:24 CST 2007


Author: murf
Date: Thu Nov 15 18:18:23 2007
New Revision: 89317

URL: http://svn.digium.com/view/asterisk?view=rev&rev=89317
Log:
about halfway on updating chan_sip. Don't expect this to compile

Modified:
    team/murf/bug11210/channels/chan_sip.c

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=89317&r1=89316&r2=89317
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Thu Nov 15 18:18:23 2007
@@ -130,7 +130,7 @@
 #include "asterisk/causes.h"
 #include "asterisk/utils.h"
 #include "asterisk/file.h"
-#include "asterisk/astobj.h"
+#include "asterisk/astobj2.h"
 #include "asterisk/dnsmgr.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/linkedlists.h"
@@ -1198,7 +1198,7 @@
 /*! \brief Structure for SIP user data. User's place calls to us */
 struct sip_user {
 	/* Users who can access various contexts */
-	ASTOBJ_COMPONENTS(struct sip_user);
+	char name[80];
 	char secret[80];		/*!< Password */
 	char md5secret[80];		/*!< Password in md5 */
 	char context[AST_MAX_CONTEXT];	/*!< Default context for incoming calls */
@@ -1248,8 +1248,7 @@
 /*! \brief Structure for SIP peer data, we place calls to peers if registered  or fixed IP address (host) */
 /* XXX field 'name' must be first otherwise sip_addrcmp() will fail */
 struct sip_peer {
-	ASTOBJ_COMPONENTS(struct sip_peer);	/*!< name, refcount, objflags,  object pointers */
-					/*!< peer->name is the unique name of this object */
+	char name[80];			/*!< peer->name is the unique name of this object */
 	char secret[80];		/*!< Password */
 	char md5secret[80];		/*!< Password in MD5 */
 	struct sip_auth *auth;		/*!< Realm authentication list */
@@ -1333,7 +1332,6 @@
  * as the dialoglist is also manipulated by other threads.
  */
 struct sip_registry {
-	ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(callid);	/*!< Global Call-ID */
 		AST_STRING_FIELD(realm);	/*!< Authorization realm */
@@ -1365,23 +1363,91 @@
 	char lastmsg[256];		/*!< Last Message sent/received */
 };
 
-/* --- Linked lists of various objects --------*/
+/* --- Hash tables of various objects --------*/
+
+#ifdef LOW_MEMORY
+#define MAX_PEER_BUCKETS 17
+#else
+#define MAX_PEER_BUCKETS 563
+#endif
+
+#define MAX_USER_BUCKETS MAX_PEER_BUCKETS
 
 /*! \brief  The user list: Users and friends */
 static struct ast_user_list {
-	ASTOBJ_CONTAINER_COMPONENTS(struct sip_user);
+	struct ao2_container *users;
 } userl;
 
 /*! \brief  The peer list: Peers and Friends */
 static struct ast_peer_list {
-	ASTOBJ_CONTAINER_COMPONENTS(struct sip_peer);
+	struct ao2_container *peers;
 } peerl;
 
 /*! \brief  The register list: Other SIP proxies we register with and place calls to */
 static struct ast_register_list {
-	ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
+	struct ao2_container *registry;
 	int recheck;
 } regl;
+
+/*!
+ * \note The only member of the peer passed here guaranteed to be set is the name field
+ */
+static int peer_hash_cb(const void *obj, const int flags)
+{
+	const struct sip_peer *peer = obj;
+
+	return ast_str_hash(peer->name);
+}
+
+/*!
+ * \note The only member of the peer passed here guaranteed to be set is the name field
+ */
+static int peer_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct sip_peer *peer = obj, *peer2 = arg;
+
+	return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
+}
+
+/*!
+ * \note The only member of the user passed here guaranteed to be set is the name field
+ */
+static int user_hash_cb(const void *obj, const int flags)
+{
+	const struct sip_user *user = obj;
+
+	return ast_str_hash(user->name);
+}
+
+/*!
+ * \note The only member of the user passed here guaranteed to be set is the name field
+ */
+static int user_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct sip_user *user = obj, *user2 = arg;
+
+	return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
+}
+
+/*!
+ * \note The only member of the user passed here guaranteed to be set is the name field
+ */
+static int reg_hash_cb(const void *obj, const int flags)
+{
+	const struct sip_registry *reg = obj;
+
+	return ast_str_hash(reg->name);
+}
+
+/*!
+ * \note The only member of the user passed here guaranteed to be set is the name field
+ */
+static int reg_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct sip_registry *reg = obj, *reg2 = arg;
+
+	return !strcasecmp(reg->name, reg2->name) ? CMP_MATCH : 0;
+}
 
 static int temp_pvt_init(void *);
 static void temp_pvt_cleanup(void *);
@@ -1881,26 +1947,28 @@
  */
 static void unref_peer(struct sip_peer *peer)
 {
-	ASTOBJ_UNREF(peer, sip_destroy_peer);
+	ao2_unref(peer);
 }
 
 static void unref_user(struct sip_user *user)
 {
-	ASTOBJ_UNREF(user, sip_destroy_user);
+	ao2_unref(user);
 }
 
 static void *registry_unref(struct sip_registry *reg)
 {
-	ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1);
-	ASTOBJ_UNREF(reg, sip_registry_destroy);
+	/* ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1); */
+	/* AO2 DOES'NT SUPPLY A FUNC TO GET THE OBJECT ACCESS COUNT */
+	ao2_unref(reg);
 	return NULL;
 }
 
 /*! \brief Add object reference to SIP registry */
 static struct sip_registry *registry_addref(struct sip_registry *reg)
 {
-	ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1);
-	return ASTOBJ_REF(reg);	/* Add pointer to registry in packet */
+	/* ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1); */
+	ao2_ref(reg,1);
+	return reg;	/* Add pointer to registry in packet */
 }
 
 /*! \brief Interface structure with callbacks used to connect to UDPTL module*/
@@ -3160,7 +3228,7 @@
 			peer->expire = ast_sched_replace(peer->expire, sched, 
 				global_rtautoclear * 1000, expire_register, (void *) peer);
 		}
-		ASTOBJ_CONTAINER_LINK(&peerl,peer);
+		ao2_link(peerl->peers, peer);
 	} else {
 		peer->is_realtime = 1;
 	}
@@ -3190,10 +3258,13 @@
 static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
 {
 	struct sip_peer *p = NULL;
-
+	struct sip_peer tmp_peer;
+	
+	ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
+	
 	if (peer)
-		p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
-	else
+		p = ao2_find(peerl->peers, &tmp_peer, OBJ_POINTER);
+	else /* search by addr? */
 		p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp);
 
 	if (!p && realtime)
@@ -3250,7 +3321,7 @@
 	if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 		ast_set_flag(&user->flags[1], SIP_PAGE2_RTCACHEFRIENDS);
 		suserobjs++;
-		ASTOBJ_CONTAINER_LINK(&userl,user);
+		ao2_link(userl->users, user);
 	} else {
 		/* Move counter from s to r... */
 		suserobjs--;
@@ -3267,7 +3338,12 @@
  * realtime storage (defined in extconfig.conf) */
 static struct sip_user *find_user(const char *name, int realtime)
 {
-	struct sip_user *u = ASTOBJ_CONTAINER_FIND(&userl, name);
+	struct sip_user tmp;
+	struct sip_user *u;
+
+	ast_copy_string(tmp.name, name, sizeof(tmp.name));
+	u = ao2_find(userl->users, &tmp_user, OBJ_POINTER);
+
 	if (!u && realtime)
 		u = realtime_user(name);
 	return u;
@@ -5291,7 +5367,7 @@
 			return -1;
 		}
 	}
-	if (!(reg = ast_calloc(1, sizeof(*reg)))) {
+	if (!(reg = ao2_alloc(sizeof(*reg), sip_registry_destroy))) {
 		ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
 		return -1;
 	}
@@ -5303,7 +5379,6 @@
 	}
 
 	regobjs++;
-	ASTOBJ_INIT(reg);
 	ast_string_field_set(reg, callback, callback);
 	if (!ast_strlen_zero(username))
 		ast_string_field_set(reg, username, username);
@@ -5320,8 +5395,8 @@
 	reg->portno = portnum;
 	reg->callid_valid = FALSE;
 	reg->ocseq = INITIAL_CSEQ;
-	ASTOBJ_CONTAINER_LINK(&regl, reg);	/* Add the new registry entry to the list */
-	registry_unref(reg);	/* release the reference given by ASTOBJ_INIT. The container has another reference */
+	ao2_link(regl->registry, reg);/* Add the new registry entry to the list */
+	registry_unref(reg);	/* release the reference. The container has another reference */
 	return 0;
 }
 
@@ -8597,7 +8672,7 @@
 
 	if (peer->selfdestruct ||
 	    ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
-		peer = ASTOBJ_CONTAINER_UNLINK(&peerl, peer);	/* Remove from peer list */
+		peer = ao2_find(peerl->peers, peer, OBJ_POINTER|OBJ_UNLINK);	/* Remove from peer list */
 		unref_peer(peer);		/* Remove from memory */
 	}
 
@@ -9176,9 +9251,9 @@
 {
 	struct sip_peer *peer = userdata;
 
-	ASTOBJ_RDLOCK(peer);
+	ao2_lock(peer);
 	sip_send_mwi_to_peer(peer, event, 0);
-	ASTOBJ_UNLOCK(peer);
+	ao2_unlock(peer);
 }
 
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
@@ -9352,7 +9427,7 @@
 		/* Create peer if we have autocreate mode enabled */
 		peer = temp_peer(name);
 		if (peer) {
-			ASTOBJ_CONTAINER_LINK(&peerl, peer);
+			ao2_link(peerl->peers, peer);
 			sip_cancel_destroy(p);
 			switch (parse_register_contact(p, peer, req)) {
 			case PARSE_REGISTER_FAILED:
@@ -10287,7 +10362,8 @@
 		/* copy channel vars */
 		p->chanvars = copy_vars(peer->chanvars);
 		if (authpeer) {
-			(*authpeer) = ASTOBJ_REF(peer);	/* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */
+			ao2_ref(peer,1);
+			(*authpeer) = peer;	/* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */
 		}
 
 		if (!ast_strlen_zero(peer->username)) {
@@ -10545,7 +10621,10 @@
 	char ilimits[40];
 	char iused[40];
 	int showall = FALSE;
-
+	struct ao2_iterator i;
+	struct sip_user *user;
+	struct sip_peer *peer;
+	
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "sip show inuse";
@@ -10565,31 +10644,32 @@
 		showall = TRUE;
 	
 	ast_cli(a->fd, FORMAT, "* User name", "In use", "Limit");
-	ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
-		ASTOBJ_RDLOCK(iterator);
-		if (iterator->call_limit)
-			snprintf(ilimits, sizeof(ilimits), "%d", iterator->call_limit);
+	
+	i = ao2_iterator_init(userl->users, 0);
+	
+	while ((user = ao2_iterator_init(&i))) {
+		if (user->call_limit)
+			snprintf(ilimits, sizeof(ilimits), "%d", user->call_limit);
 		else 
 			ast_copy_string(ilimits, "N/A", sizeof(ilimits));
-		snprintf(iused, sizeof(iused), "%d", iterator->inUse);
-		if (showall || iterator->call_limit)
-			ast_cli(a->fd, FORMAT2, iterator->name, iused, ilimits);
-		ASTOBJ_UNLOCK(iterator);
-	} while (0) );
+		snprintf(iused, sizeof(iused), "%d", user->inUse);
+		if (showall || user->call_limit)
+			ast_cli(a->fd, FORMAT2, user->name, iused, ilimits);
+	}
 
 	ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit");
 
-	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
-		ASTOBJ_RDLOCK(iterator);
-		if (iterator->call_limit)
-			snprintf(ilimits, sizeof(ilimits), "%d", iterator->call_limit);
+	i = ao2_iterator_init(peerl->peers, 0);
+
+	while ((peer = ao2_iterator_next(&i))) {
+		if (peer->call_limit)
+			snprintf(ilimits, sizeof(ilimits), "%d", peer->call_limit);
 		else 
 			ast_copy_string(ilimits, "N/A", sizeof(ilimits));
-		snprintf(iused, sizeof(iused), "%d/%d/%d", iterator->inUse, iterator->inRinging, iterator->onHold);
-		if (showall || iterator->call_limit)
-			ast_cli(a->fd, FORMAT2, iterator->name, iused, ilimits);
-		ASTOBJ_UNLOCK(iterator);
-	} while (0) );
+		snprintf(iused, sizeof(iused), "%d/%d/%d", peer->inUse, peer->inRinging, peer->onHold);
+		if (showall || peer->call_limit)
+			ast_cli(a->fd, FORMAT2, peer->name, iused, ilimits);
+	}
 
 	return CLI_SUCCESS;
 #undef FORMAT
@@ -10661,7 +10741,9 @@
 {
 	regex_t regexbuf;
 	int havepattern = FALSE;
-
+	struct sip_user *user;
+	struct ao2_iterator i;
+	
 #define FORMAT  "%-25.25s  %-15.15s  %-15.15s  %-15.15s  %-5.5s%-10.10s\n"
 
 	switch (cmd) {
@@ -10691,11 +10773,13 @@
 	}
 
 	ast_cli(a->fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT");
-	ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
-		ASTOBJ_RDLOCK(iterator);
+
+	i = ao2_iterator_init(userl->users, 0);
+
+	while ((user = ao2_iterator_next(&i))) {
 
 		if (havepattern && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
-			ASTOBJ_UNLOCK(iterator);
+			ao2_unlock(iterator);
 			continue;
 		}
 
@@ -10705,9 +10789,7 @@
 			iterator->context,
 			cli_yesno(iterator->ha != NULL),
 			nat2str(ast_test_flag(&iterator->flags[0], SIP_NAT)));
-		ASTOBJ_UNLOCK(iterator);
-	} while (0)
-	);
+	}
 
 	if (havepattern)
 		regfree(&regexbuf);
@@ -10771,7 +10853,9 @@
 {
 	regex_t regexbuf;
 	int havepattern = FALSE;
-
+	struct sip_peer *peer;
+	struct ao2_iterator i;
+	
 /* the last argument is left-aligned, so we don't need a size anyways */
 #define FORMAT2 "%-25.25s  %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n"
 #define FORMAT  "%-25.25s  %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n"
@@ -10811,52 +10895,51 @@
 	if (!s) /* Normal list */
 		ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : ""));
 	
-	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
+	i = ao2_iterator_init(peerl->peers, 0);
+	while ((peer = ao2_iterator_next(&i))) {	
 		char status[20] = "";
 		char srch[2000];
 		char pstatus;
 		
-		ASTOBJ_RDLOCK(iterator);
-
-		if (havepattern && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
-			ASTOBJ_UNLOCK(iterator);
+		if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0)) {
+			ao2_unlock(peer);
 			continue;
 		}
 
-		if (!ast_strlen_zero(iterator->username) && !s)
-			snprintf(name, sizeof(name), "%s/%s", iterator->name, iterator->username);
+		if (!ast_strlen_zero(peer->username) && !s)
+			snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
 		else
-			ast_copy_string(name, iterator->name, sizeof(name));
+			ast_copy_string(name, peer->name, sizeof(name));
 		
-		pstatus = peer_status(iterator, status, sizeof(status));
+		pstatus = peer_status(peer, status, sizeof(status));
 		if (pstatus == 1)
 			peers_mon_online++;
 		else if (pstatus == 0)
 			peers_mon_offline++;
 		else {
-			if (iterator->addr.sin_port == 0)
+			if (peer->addr.sin_port == 0)
 				peers_unmon_offline++;
 			else
 				peers_unmon_online++;
 		}
 
 		snprintf(srch, sizeof(srch), FORMAT, name,
-			iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "(Unspecified)",
-			iterator->host_dynamic ? " D " : "   ", 	/* Dynamic or not? */
-			ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
-			iterator->ha ? " A " : "   ", 	/* permit/deny */
-			ntohs(iterator->addr.sin_port), status,
-			realtimepeers ? (iterator->is_realtime ? "Cached RT":"") : "");
+			peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
+			peer->host_dynamic ? " D " : "   ", 	/* Dynamic or not? */
+			ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
+			peer->ha ? " A " : "   ", 	/* permit/deny */
+			ntohs(peer->addr.sin_port), status,
+			realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
 
 		if (!s)  {/* Normal CLI list */
 			ast_cli(fd, FORMAT, name, 
-			iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "(Unspecified)",
-			iterator->host_dynamic ? " D " : "   ", 	/* Dynamic or not? */
-			ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
-			iterator->ha ? " A " : "   ",       /* permit/deny */
+			peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
+			peer->host_dynamic ? " D " : "   ", 	/* Dynamic or not? */
+			ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
+			peer->ha ? " A " : "   ",       /* permit/deny */
 			
-			ntohs(iterator->addr.sin_port), status,
-			realtimepeers ? (iterator->is_realtime ? "Cached RT":"") : "");
+			ntohs(peer->addr.sin_port), status,
+			realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
 		} else {	/* Manager format */
 			/* The names here need to be the same as other channels */
 			astman_append(s, 
@@ -10874,22 +10957,20 @@
 			"Status: %s\r\n"
 			"RealtimeDevice: %s\r\n\r\n", 
 			idtext,
-			iterator->name, 
-			iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "-none-",
-			ntohs(iterator->addr.sin_port), 
-			iterator->host_dynamic ? "yes" : "no", 	/* Dynamic or not? */
-			ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? "yes" : "no",	/* NAT=yes? */
-			ast_test_flag(&iterator->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no",	/* VIDEOSUPPORT=yes? */
-			ast_test_flag(&iterator->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no",	/* TEXTSUPPORT=yes? */
-			iterator->ha ? "yes" : "no",       /* permit/deny */
+			peer->name, 
+			peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-",
+			ntohs(peer->addr.sin_port), 
+			peer->host_dynamic ? "yes" : "no", 	/* Dynamic or not? */
+			ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? "yes" : "no",	/* NAT=yes? */
+			ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no",	/* VIDEOSUPPORT=yes? */
+			ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no",	/* TEXTSUPPORT=yes? */
+			peer->ha ? "yes" : "no",       /* permit/deny */
 			status,
-			realtimepeers ? (iterator->is_realtime ? "yes":"no") : "no");
-		}
-
-		ASTOBJ_UNLOCK(iterator);
+			realtimepeers ? (peer->is_realtime ? "yes":"no") : "no");
+		}
 
 		total_peers++;
-	} while(0) );
+	}
 	
 	if (!s)
 		ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
@@ -11004,14 +11085,15 @@
 /*! \brief Remove temporary realtime objects from memory (CLI) */
 static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct sip_peer *peer;
-	struct sip_user *user;
+	struct sip_peer *peer, *pi;
+	struct sip_user *user, *ui;
 	int pruneuser = FALSE;
 	int prunepeer = FALSE;
 	int multi = FALSE;
 	char *name = NULL;
 	regex_t regexbuf;
-
+	struct ao2_iterator i;
+	
 	if (cmd == CLI_INIT) {
 		e->command = "sip prune realtime [peer|user|all] [all|like]";
 		e->usage =
@@ -11086,42 +11168,38 @@
 	if (multi) {
 		if (prunepeer) {
 			int pruned = 0;
-
-			ASTOBJ_CONTAINER_WRLOCK(&peerl);
-			ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
-				ASTOBJ_RDLOCK(iterator);
+			
+			ao2_lock(peerl->peers); /* was WRLOCK */
+			i = ao2_iterator_init(peerl->peers, 0);
+			while ((pi = ao2_iterator_next(&i))) {
+				if (name && regexec(&regexbuf, pi->name, 0, NULL, 0)) {
+					continue;
+				};
+				if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
+					ASTOBJ_MARK(pi);
+					pruned++;
+				}
+			}
+			if (pruned) {
+				ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, sip_destroy_peer);
+				ast_cli(a->fd, "%d peers pruned.\n", pruned);
+			} else
+				ast_cli(a->fd, "No peers found to prune.\n");
+			ASTOBJ_CONTAINER_UNLOCK(&peerl);
+		}
+		if (pruneuser) {
+			int pruned = 0;
+
+			ao2_lock(userl->users); /* was WRLOCK */
+			i = ao2_iterator_init(userl->users, 0);
+			while ((ui = ao2_iterator_next(&i))) {
 				if (name && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
-					ASTOBJ_UNLOCK(iterator);
 					continue;
 				};
 				if (ast_test_flag(&iterator->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 					ASTOBJ_MARK(iterator);
 					pruned++;
 				}
-				ASTOBJ_UNLOCK(iterator);
-			} while (0) );
-			if (pruned) {
-				ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, sip_destroy_peer);
-				ast_cli(a->fd, "%d peers pruned.\n", pruned);
-			} else
-				ast_cli(a->fd, "No peers found to prune.\n");
-			ASTOBJ_CONTAINER_UNLOCK(&peerl);
-		}
-		if (pruneuser) {
-			int pruned = 0;
-
-			ASTOBJ_CONTAINER_WRLOCK(&userl);
-			ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
-				ASTOBJ_RDLOCK(iterator);
-				if (name && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
-					ASTOBJ_UNLOCK(iterator);
-					continue;
-				};
-				if (ast_test_flag(&iterator->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
-					ASTOBJ_MARK(iterator);
-					pruned++;
-				}
-				ASTOBJ_UNLOCK(iterator);
 			} while (0) );
 			if (pruned) {
 				ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, sip_destroy_user);
@@ -11132,10 +11210,12 @@
 		}
 	} else {
 		if (prunepeer) {
-			if ((peer = ASTOBJ_CONTAINER_FIND_UNLINK(&peerl, name))) {
+			struct sip_peer tmp;
+			ast_copy_string(tmp.name, name, sizeof(tmp.name));
+			if ((peer = ao2_find(peerl->peers, &tmp, OBJ_POINTER|OBJ_UNLINK))) {
 				if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 					ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name);
-					ASTOBJ_CONTAINER_LINK(&peerl, peer);
+					ao2_link(peerl->peers, peer);
 				} else
 					ast_cli(a->fd, "Peer '%s' pruned.\n", name);
 				unref_peer(peer);
@@ -11143,10 +11223,12 @@
 				ast_cli(a->fd, "Peer '%s' not found.\n", name);
 		}
 		if (pruneuser) {
-			if ((user = ASTOBJ_CONTAINER_FIND_UNLINK(&userl, name))) {
+			struct sip_user tmp;
+			ast_copy_string(tmp.name, name, sizeof(tmp.name));
+			if ((user = ao2_find(userl->users, &tmp, OBJ_POINTER|OBJ_UNLINK))) {
 				if (!ast_test_flag(&user->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 					ast_cli(a->fd, "User '%s' is not a Realtime user, cannot be pruned.\n", name);
-					ASTOBJ_CONTAINER_LINK(&userl, user);
+					ao2_link(userl->users, user);
 				} else
 					ast_cli(a->fd, "User '%s' pruned.\n", name);
 				unref_user(user);
@@ -11597,7 +11679,7 @@
 		return CLI_SHOWUSAGE;
 	ast_cli(a->fd, FORMAT2, "Host", "Username", "Refresh", "State", "Reg.Time");
 	ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
-		ASTOBJ_RDLOCK(iterator);
+		ASTOBJ_RDLOCK(iterator); /* was RDLOCK */
 		snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
 		if (iterator->regtime.tv_sec) {
 			ast_localtime(&iterator->regtime, &tm, NULL);
@@ -11605,7 +11687,7 @@
 		} else 
 			tmpdat[0] = '\0';
 		ast_cli(a->fd, FORMAT, host, iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat);
-		ASTOBJ_UNLOCK(iterator);
+		ao2_unlock(iterator);
 		counter++;
 	} while(0));
 	ast_cli(a->fd, "%d SIP registrations.\n", counter);
@@ -12005,12 +12087,12 @@
        int which = 0;
 
        ASTOBJ_CONTAINER_TRAVERSE(&peerl, !result, do {
-               ASTOBJ_WRLOCK(iterator);
+               ASTOBJ_WRLOCK(iterator); /* was WRLOCK */
                if (!strncasecmp(word, iterator->name, wordlen) &&
                                (!flags2 || ast_test_flag(&iterator->flags[1], flags2)) &&
                                ++which > state && iterator->expire > 0)
                        result = ast_strdup(iterator->name);
-               ASTOBJ_UNLOCK(iterator);
+               ao2_unlock(iterator);
        } while(0) );
        return result;
 }
@@ -16067,9 +16149,9 @@
 		if (p->subscribed == MWI_NOTIFICATION) {
 			transmit_response(p, "200 OK", req);
 			if (p->relatedpeer) {	/* Send first notification */
-				ASTOBJ_WRLOCK(p->relatedpeer);
+				ASTOBJ_WRLOCK(p->relatedpeer); /* was WRLOCK */
 				sip_send_mwi_to_peer(p->relatedpeer, NULL, 0);
-				ASTOBJ_UNLOCK(p->relatedpeer);
+				ao2_unlock(p->relatedpeer);
 			}
 		} else {
 			struct sip_pvt *p_old;
@@ -17348,11 +17430,10 @@
 	struct ast_flags mask[2] = {{(0)}};
 
 
-	if (!(user = ast_calloc(1, sizeof(*user))))
+	if (!(user = ao2_alloc(sizeof(*user), sip_destroy_user)))
 		return NULL;
 		
 	suserobjs++;
-	ASTOBJ_INIT(user);
 	ast_copy_string(user->name, name, sizeof(user->name));
 	oldha = user->ha;
 	user->ha = NULL;
@@ -17498,11 +17579,10 @@
 {
 	struct sip_peer *peer;
 
-	if (!(peer = ast_calloc(1, sizeof(*peer))))
+	if (!(peer = ao2_alloc(sizeof(*peer), sip_destroy_peer)))
 		return NULL;
 
 	apeerobjs++;
-	ASTOBJ_INIT(peer);
 	set_peer_defaults(peer);
 
 	ast_copy_string(peer->name, name, sizeof(peer->name));
@@ -17566,7 +17646,7 @@
 		if (!(peer->objflags & ASTOBJ_FLAG_MARKED))
 			firstpass = 0;
  	} else {
-		if (!(peer = ast_calloc(1, sizeof(*peer))))
+		if (!(peer = ao2_alloc(sizeof(*peer),sip_destroy_peer)))
 			return NULL;
 
 		if (realtime) {
@@ -17574,7 +17654,6 @@
 			ast_debug(3,"-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs);
 		} else
 			speerobjs++;
-		ASTOBJ_INIT(peer);
 	}
 	/* Note that our peer HAS had its reference count incrased */
 	if (firstpass) {
@@ -17870,20 +17949,20 @@
 		/* First, destroy all outstanding registry calls */
 		/* This is needed, since otherwise active registry entries will not be destroyed */
 		ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
-			ASTOBJ_RDLOCK(iterator);
+			ASTOBJ_RDLOCK(iterator); /* was RDLOCK */
 			if (iterator->call) {
 				ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
 				/* This will also remove references to the registry */
 				iterator->call = sip_destroy(iterator->call);
 			}
-			ASTOBJ_UNLOCK(iterator);
+			ao2_unlock(iterator);
 
 		} while(0));
 
 		/* Then, actually destroy users and registry */
-		ASTOBJ_CONTAINER_DESTROYALL(&userl, sip_destroy_user);
+		ao2_ref(userl->users, -1);
 		ast_debug(4, "--------------- Done destroying user list\n");
-		ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
+		ao2_ref(regl->registry, -1);
 		ast_debug(4, "--------------- Done destroying registry list\n");
 		ASTOBJ_CONTAINER_MARKALL(&peerl);
 	}
@@ -18284,7 +18363,7 @@
 					peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
 					if (peer) {
 						ast_device_state_changed("SIP/%s", peer->name);
-						ASTOBJ_CONTAINER_LINK(&peerl,peer);
+						ao2_link(peerl->peers, peer);
 						unref_peer(peer);
 						peer_count++;
 					}
@@ -18344,7 +18423,7 @@
 			if (is_user) {
 				user = build_user(cat, ast_variable_browse(cfg, cat), 0);
 				if (user) {
-					ASTOBJ_CONTAINER_LINK(&userl,user);
+					ao2_link(userl->users, user);
 					unref_user(user);
 					user_count++;
 				}
@@ -18352,7 +18431,7 @@
 			if (is_peer) {
 				peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
 				if (peer) {
-					ASTOBJ_CONTAINER_LINK(&peerl,peer);
+					ao2_link(peerl->peers, peer);
 					unref_peer(peer);
 					peer_count++;
 				}
@@ -18911,11 +18990,11 @@
 		return;
 
 	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
-		ASTOBJ_WRLOCK(iterator);
+		ASTOBJ_WRLOCK(iterator); /* was WRLOCK */
 		ms += 100;
 		iterator->pokeexpire = ast_sched_replace(iterator->pokeexpire, 
 			sched, ms, sip_poke_peer_s, iterator);
-		ASTOBJ_UNLOCK(iterator);
+		ao2_unlock(iterator);
 	} while (0)
 	);
 }
@@ -18932,11 +19011,11 @@
 		regspacing = 100;
 	ms = regspacing;
 	ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
-		ASTOBJ_WRLOCK(iterator);
+		ASTOBJ_WRLOCK(iterator); /* was WRLOCK */
 		ms += regspacing;
 		iterator->expire = ast_sched_replace(iterator->expire, 
 			sched, ms, sip_reregister, iterator);
-		ASTOBJ_UNLOCK(iterator);
+		ao2_unlock(iterator);
 	} while (0)
 	);
 }
@@ -19024,9 +19103,11 @@
 static int load_module(void)
 {
 	ast_verbose("SIP channel loading...\n");
-	ASTOBJ_CONTAINER_INIT(&userl);	/* User object list */
-	ASTOBJ_CONTAINER_INIT(&peerl);	/* Peer object list */
-	ASTOBJ_CONTAINER_INIT(&regl);	/* Registry object list */
+	/* the fact that ao2_containers can't resize automatically is a major worry! */
+    /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
+	userl->users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
+	userl->peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
+	regl->registry = ao2_container_alloc(MAX_REG_BUCKETS, reg_hash_cb, reg_cmp_cb); /* if we never search for a particular element in the registry, why on earth are they being tracked? */
 
 	if (!(sched = sched_context_create())) {
 		ast_log(LOG_ERROR, "Unable to create scheduler context\n");




More information about the svn-commits mailing list