
Property changes on: .
___________________________________________________________________
Added: automerge
   + *
Added: svnmerge-integrated
   + /branches/12:1-414967
Added: automerge-email
   + mjordan@digium.com

Index: apps/app_queue.c
===================================================================
--- apps/app_queue.c	(revision 414971)
+++ apps/app_queue.c	(working copy)
@@ -3506,9 +3506,7 @@
 				     "Queue", q->name,
 				     "Position", qe->pos,
 				     "Count", q->count);
-		ast_channel_lock(qe->chan);
-		ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob);
-		ast_channel_unlock(qe->chan);
+		ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob);
 		ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
 	}
 	ao2_unlock(q);
@@ -3787,9 +3785,7 @@
 					     "Queue", q->name,
 					     "Position", qe->pos,
 					     "Count", q->count);
-			ast_channel_lock(qe->chan);
-			ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob);
-			ast_channel_unlock(qe->chan);
+			ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob);
 			ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
 			/* Take us out of the queue */
 			if (prev) {
@@ -4391,9 +4387,7 @@
 	qe->parent->callsabandoned++;
 	ao2_unlock(qe->parent);
 
-	ast_channel_lock(qe->chan);
-	ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob);
-	ast_channel_unlock(qe->chan);
+	ast_channel_publish_cached_blob(qe->chan, queue_caller_abandon_type(), blob);
 }
 
 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
Index: apps/app_agent_pool.c
===================================================================
--- apps/app_agent_pool.c	(revision 414971)
+++ apps/app_agent_pool.c	(working copy)
@@ -1442,7 +1442,7 @@
 		return;
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_agent_login_type(), blob);
+	ast_channel_publish_cached_blob(chan, ast_channel_agent_login_type(), blob);
 }
 
 static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
@@ -1458,7 +1458,7 @@
 		return;
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_agent_logoff_type(), blob);
+	ast_channel_publish_cached_blob(chan, ast_channel_agent_logoff_type(), blob);
 }
 
 /*!
Index: apps/app_meetme.c
===================================================================
--- apps/app_meetme.c	(revision 414971)
+++ apps/app_meetme.c	(working copy)
@@ -1379,9 +1379,7 @@
 		}
 	}
 
-	ast_channel_lock(chan);
-	msg = ast_channel_blob_create(chan, message_type, json_object);
-	ast_channel_unlock(chan);
+	msg = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), message_type, json_object);
 
 	if (!msg) {
 		return;
Index: include/asterisk/stasis_channels.h
===================================================================
--- include/asterisk/stasis_channels.h	(revision 414971)
+++ include/asterisk/stasis_channels.h	(working copy)
@@ -39,17 +39,16 @@
 struct ast_channel_snapshot {
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(name);             /*!< ASCII unique channel name */
-		AST_STRING_FIELD(type);             /*!< Type of channel technology */
-		AST_STRING_FIELD(accountcode);      /*!< Account code for billing */
-		AST_STRING_FIELD(peeraccount);      /*!< Peer account code for billing */
-		AST_STRING_FIELD(userfield);        /*!< Userfield for CEL billing */
 		AST_STRING_FIELD(uniqueid);         /*!< Unique Channel Identifier */
 		AST_STRING_FIELD(linkedid);         /*!< Linked Channel Identifier -- gets propagated by linkage */
-		AST_STRING_FIELD(hangupsource);     /*!< Who is responsible for hanging up this channel */
 		AST_STRING_FIELD(appl);             /*!< Current application */
 		AST_STRING_FIELD(data);             /*!< Data passed to current application */
 		AST_STRING_FIELD(context);          /*!< Dialplan: Current extension context */
 		AST_STRING_FIELD(exten);            /*!< Dialplan: Current extension number */
+		AST_STRING_FIELD(accountcode);      /*!< Account code for billing */
+		AST_STRING_FIELD(peeraccount);      /*!< Peer account code for billing */
+		AST_STRING_FIELD(userfield);        /*!< Userfield for CEL billing */
+		AST_STRING_FIELD(hangupsource);     /*!< Who is responsible for hanging up this channel */
 		AST_STRING_FIELD(caller_name);      /*!< Caller ID Name */
 		AST_STRING_FIELD(caller_number);    /*!< Caller ID Number */
 		AST_STRING_FIELD(caller_dnid);      /*!< Dialed ID Number */
@@ -59,31 +58,20 @@
 		AST_STRING_FIELD(dialed_subaddr);   /*!< Dialed subaddress */
 		AST_STRING_FIELD(connected_name);   /*!< Connected Line Name */
 		AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
-		AST_STRING_FIELD(effective_name);   /*!< Effective Connected Line Name */
-		AST_STRING_FIELD(effective_number); /*!< Effective Connected Line Number */
 		AST_STRING_FIELD(language);         /*!< The default spoken language for the channel */
 		AST_STRING_FIELD(bridgeid);         /*!< Unique Bridge Identifier */
-		AST_STRING_FIELD(nativeformats);    /*!< Native formats on the channel */
-		AST_STRING_FIELD(readformat);       /*!< The current read format */
-		AST_STRING_FIELD(writeformat);      /*!< The current write format */
-		AST_STRING_FIELD(writetrans);       /*!< The current write translation path */
-		AST_STRING_FIELD(readtrans);        /*!< The current read translation path */
+		AST_STRING_FIELD(type);             /*!< Type of channel technology */
 	);
 
-	char callid[AST_CALLID_BUFFER_LENGTH];  /*!< Callid for the channel */
 	struct timeval creationtime;            /*!< The time of channel creation */
-	struct timeval hanguptime;              /*!< When the channel should hang up */
 	enum ast_channel_state state;           /*!< State of line */
 	int priority;                           /*!< Dialplan: Current extension priority */
 	int amaflags;                           /*!< AMA flags for billing */
 	int hangupcause;                        /*!< Why is the channel hanged up. See causes.h */
 	int caller_pres;                        /*!< Caller ID presentation. */
 	struct ast_flags flags;                 /*!< channel flags of AST_FLAG_ type */
-	ast_group_t callgroup;                  /*!< Call group */
-	ast_group_t pickupgroup;                /*!< Pickup group */
 	struct ast_flags softhangup_flags;      /*!< softhangup channel flags */
 	struct varshead *manager_vars;          /*!< Variables to be appended to manager events */
-	struct varshead *channel_vars;          /*!< Variables set on the channel */
 	int tech_properties;                    /*!< Properties of the channel's technology */
 };
 
@@ -321,6 +309,23 @@
 	struct ast_json *blob);
 
 /*!
+ * \brief Publish a channel blob message using the latest snapshot from the cache
+ * \since 12.4.0
+ *
+ * \param chan Channel publishing the blob.
+ * \param type Type of stasis message.
+ * \param blob The blob being published. (NULL if no blob)
+ *
+ * \note As this only accesses the uniqueid and topic of the channel - neither of
+ * which should ever be changed on a channel anyhow - a channel does not have to
+ * be locked when calling this function.
+ *
+ * \return Nothing
+ */
+void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type,
+	struct ast_json *blob);
+
+/*!
  * \since 12
  * \brief Set flag to indicate channel snapshot is being staged.
  *
Index: include/asterisk/channel.h
===================================================================
--- include/asterisk/channel.h	(revision 414971)
+++ include/asterisk/channel.h	(working copy)
@@ -4190,6 +4190,15 @@
 struct ast_flags *ast_channel_flags(struct ast_channel *chan);
 
 /*!
+ * \since 12.4.0
+ * \brief Return whether or not any manager variables have been set
+ *
+ * \retval 0 if no manager variables are expected
+ * \retval 1 if manager variables are expected
+ */
+int ast_channel_has_manager_vars(void);
+
+/*!
  * \since 12
  * \brief Sets the variables to be stored in the \a manager_vars field of all
  * snapshots.
Index: main/stasis_channels.c
===================================================================
--- main/stasis_channels.c	(revision 414971)
+++ main/stasis_channels.c	(working copy)
@@ -195,18 +195,12 @@
 
 	ast_string_field_free_memory(snapshot);
 	ao2_cleanup(snapshot->manager_vars);
-	ao2_cleanup(snapshot->channel_vars);
 }
 
 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
 {
 	struct ast_channel_snapshot *snapshot;
 	struct ast_bridge *bridge;
-	char nativeformats[256];
-	struct ast_str *write_transpath = ast_str_alloca(256);
-	struct ast_str *read_transpath = ast_str_alloca(256);
-	struct ast_party_id effective_connected_id;
-	struct ast_callid *callid;
 
 	/* no snapshots for dummy channels */
 	if (!ast_channel_tech(chan)) {
@@ -263,38 +257,16 @@
 		ao2_cleanup(bridge);
 	}
 
-	ast_string_field_set(snapshot, nativeformats, ast_getformatname_multiple(nativeformats, sizeof(nativeformats),
-		ast_channel_nativeformats(chan)));
-	ast_string_field_set(snapshot, readformat, ast_getformatname(ast_channel_readformat(chan)));
-	ast_string_field_set(snapshot, writeformat, ast_getformatname(ast_channel_writeformat(chan)));
-	ast_string_field_set(snapshot, writetrans, ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath));
-	ast_string_field_set(snapshot, readtrans, ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath));
-
-	effective_connected_id = ast_channel_connected_effective_id(chan);
-	ast_string_field_set(snapshot, effective_name,
-		S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, ""));
-	ast_string_field_set(snapshot, effective_number,
-		S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, ""));
-
-	if ((callid = ast_channel_callid(chan))) {
-		ast_callid_strnprint(snapshot->callid, sizeof(snapshot->callid), callid);
-		ast_callid_unref(callid);
-	}
-
 	snapshot->creationtime = ast_channel_creationtime(chan);
-	snapshot->hanguptime = *(ast_channel_whentohangup(chan));
 	snapshot->state = ast_channel_state(chan);
 	snapshot->priority = ast_channel_priority(chan);
 	snapshot->amaflags = ast_channel_amaflags(chan);
 	snapshot->hangupcause = ast_channel_hangupcause(chan);
 	ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
 	snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
-	snapshot->callgroup = ast_channel_callgroup(chan);
-	snapshot->pickupgroup = ast_channel_pickupgroup(chan);
 	ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));
 
 	snapshot->manager_vars = ast_channel_get_manager_vars(chan);
-	snapshot->channel_vars = ast_channel_get_vars(chan);
 	snapshot->tech_properties = ast_channel_tech(chan)->properties;
 
 	return snapshot;
@@ -347,7 +319,11 @@
 
 	if (caller) {
 		ast_channel_lock(caller);
-		caller_snapshot = ast_channel_snapshot_create(caller);
+		if (ast_strlen_zero(dialstatus)) {
+			caller_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(caller));
+		} else {
+			caller_snapshot = ast_channel_snapshot_create(caller);
+		}
 		ast_channel_unlock(caller);
 		if (!caller_snapshot) {
 			return;
@@ -356,7 +332,11 @@
 	}
 
 	ast_channel_lock(peer);
-	peer_snapshot = ast_channel_snapshot_create(peer);
+	if (ast_strlen_zero(dialstatus)) {
+		peer_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(peer));
+	} else {
+		peer_snapshot = ast_channel_snapshot_create(peer);
+	}
 	ast_channel_unlock(peer);
 	if (!peer_snapshot) {
 		return;
@@ -682,9 +662,24 @@
 	stasis_publish(ast_channel_topic(chan), message);
 }
 
+void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
+{
+	struct stasis_message *message;
+
+	if (!blob) {
+		blob = ast_json_null();
+	}
+
+	message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), type, blob);
+	if (message) {
+		stasis_publish(ast_channel_topic(chan), message);
+	}
+	ao2_cleanup(message);
+}
+
 void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
 {
-	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	struct stasis_message *message;
 
 	if (!blob) {
 		blob = ast_json_null();
@@ -694,11 +689,12 @@
 	if (message) {
 		stasis_publish(ast_channel_topic(chan), message);
 	}
+	ao2_cleanup(message);
 }
 
 void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
 {
-	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+	struct ast_json *blob;
 
 	ast_assert(name != NULL);
 	ast_assert(value != NULL);
@@ -711,7 +707,15 @@
 		return;
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_varset_type(), blob);
+	if (chan && !ast_channel_has_manager_vars()) {
+		ast_channel_publish_cached_blob(chan, ast_channel_varset_type(), blob);
+	} else {
+		/* This function is NULL safe. If there are manager variables,
+		 * we have to produce the full snapshot.
+		 */
+		ast_channel_publish_blob(chan, ast_channel_varset_type(), blob);
+	}
+	ast_json_unref(blob);
 }
 
 static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg)
@@ -1179,3 +1183,4 @@
 
 	return res;
 }
+
Index: main/pbx.c
===================================================================
--- main/pbx.c	(revision 414971)
+++ main/pbx.c	(working copy)
@@ -8326,8 +8326,7 @@
 /*! \brief CLI support for listing chanvar's variables in a parseable way */
 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
-	struct ast_channel_snapshot *snapshot;
+	struct ast_channel *chan;
 	struct ast_var_t *var;
 
 	switch (cmd) {
@@ -8341,19 +8340,23 @@
 		return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
 	}
 
-	if (a->argc != e->args + 1)
+	if (a->argc != e->args + 1) {
 		return CLI_SHOWUSAGE;
+	}
 
-	if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), a->argv[3]))) {
+	chan = ast_channel_get_by_name(a->argv[e->args]);
+	if (!chan) {
 		ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
 		return CLI_FAILURE;
 	}
-	snapshot = stasis_message_data(msg);
 
-	AST_LIST_TRAVERSE(snapshot->channel_vars, var, entries) {
+	ast_channel_lock(chan);
+	AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
 		ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
 	}
+	ast_channel_unlock(chan);
 
+	ast_channel_unref(chan);
 	return CLI_SUCCESS;
 }
 
@@ -10146,7 +10149,7 @@
 		struct ast_app *app = pbx_findapp(outgoing->app);
 
 		if (app) {
-			ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, outgoing->appdata,
+			ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
 				ast_channel_name(ast_dial_answered(outgoing->dial)));
 			pbx_exec(ast_dial_answered(outgoing->dial), app, outgoing->appdata);
 		} else {
@@ -11403,14 +11406,11 @@
 	AST_LIST_TRAVERSE_SAFE_END;
 
 	if (value && (newvariable = ast_var_assign(name, value))) {
-		if (headp == &globals)
+		if (headp == &globals) {
 			ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
+		}
 		AST_LIST_INSERT_HEAD(headp, newvariable, entries);
 		ast_channel_publish_varset(chan, name, value);
-
-		if (headp != &globals) {
-			ast_channel_publish_snapshot(chan);
-		}
 	}
 
 	if (chan)
Index: main/pickup.c
===================================================================
--- main/pickup.c	(revision 414971)
+++ main/pickup.c	(working copy)
@@ -361,9 +361,7 @@
 		goto pickup_failed;
 	}
 
-	ast_channel_lock(target);
-	target_snapshot = ast_channel_snapshot_create(target);
-	ast_channel_unlock(target);
+	target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target));
 	if (!target_snapshot) {
 		goto pickup_failed;
 	}
Index: main/core_local.c
===================================================================
--- main/core_local.c	(revision 414971)
+++ main/core_local.c	(working copy)
@@ -328,12 +328,12 @@
 	RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
 
-	local_one_snapshot = ast_channel_snapshot_create(p->base.owner);
+	local_one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.owner));
 	if (!local_one_snapshot) {
 		return NULL;
 	}
 
-	local_two_snapshot = ast_channel_snapshot_create(p->base.chan);
+	local_two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.chan));
 	if (!local_two_snapshot) {
 		return NULL;
 	}
@@ -371,7 +371,7 @@
 
 	if (source) {
 		RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
-		source_snapshot = ast_channel_snapshot_create(source);
+		source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source));
 		if (!source_snapshot) {
 			return;
 		}
@@ -516,12 +516,12 @@
 		goto end;
 	}
 
-	one_snapshot = ast_channel_snapshot_create(owner);
+	one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner));
 	if (!one_snapshot) {
 		goto end;
 	}
 
-	two_snapshot = ast_channel_snapshot_create(chan);
+	two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
 	if (!two_snapshot) {
 		goto end;
 	}
Index: main/aoc.c
===================================================================
--- main/aoc.c	(revision 414971)
+++ main/aoc.c	(working copy)
@@ -1871,7 +1871,7 @@
 		return 0;
 	}
 
-	ast_channel_publish_blob(chan, msg_type, blob);
+	ast_channel_publish_cached_blob(chan, msg_type, blob);
 	return 0;
 }
 
Index: main/bridge_channel.c
===================================================================
--- main/bridge_channel.c	(revision 414971)
+++ main/bridge_channel.c	(working copy)
@@ -838,18 +838,16 @@
 		datalen = 0;
 	}
 
-	ast_channel_lock(bridge_channel->chan);
-	ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
-	ast_channel_unlock(bridge_channel->chan);
+	ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
+
 	return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
 		moh_class, datalen);
 }
 
 int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
 {
-	ast_channel_lock(bridge_channel->chan);
-	ast_channel_publish_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
-	ast_channel_unlock(bridge_channel->chan);
+	ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
+
 	return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
 }
 
Index: main/stasis_bridges.c
===================================================================
--- main/stasis_bridges.c	(revision 414971)
+++ main/stasis_bridges.c	(working copy)
@@ -407,9 +407,7 @@
 	}
 
 	if (chan) {
-		ast_channel_lock(chan);
-		obj->channel = ast_channel_snapshot_create(chan);
-		ast_channel_unlock(chan);
+		obj->channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
 		if (obj->channel == NULL) {
 			return NULL;
 		}
@@ -593,9 +591,7 @@
 		}
 	}
 
-	ast_channel_lock(pair->channel);
-	snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel);
-	ast_channel_unlock(pair->channel);
+	snapshot_pair->channel_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(pair->channel));
 	if (!snapshot_pair->channel_snapshot) {
 		return -1;
 	}
@@ -1072,9 +1068,7 @@
 
 	transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
 	for (i = 0; i < 2; ++i) {
-		ast_channel_lock(locals[i]);
-		transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]);
-		ast_channel_unlock(locals[i]);
+		transfer_msg->dest.links[i] = ast_channel_snapshot_get_latest(ast_channel_uniqueid(locals[i]));
 		if (!transfer_msg->dest.links[i]) {
 			return;
 		}
Index: main/channel.c
===================================================================
--- main/channel.c	(revision 414971)
+++ main/channel.c	(working copy)
@@ -1270,7 +1270,6 @@
 	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD };
 	int res;
 
-	ast_channel_lock(chan);
 	if (!ast_strlen_zero(musicclass)) {
 		f.data.ptr = (void *) musicclass;
 		f.datalen = strlen(musicclass) + 1;
@@ -1279,10 +1278,10 @@
 				     "musicclass", musicclass);
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_hold_type(), blob);
+	ast_channel_publish_cached_blob(chan, ast_channel_hold_type(), blob);
 
 	res = ast_queue_frame(chan, &f);
-	ast_channel_unlock(chan);
+
 	return res;
 }
 
@@ -1291,11 +1290,10 @@
 	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD };
 	int res;
 
-	ast_channel_lock(chan);
-	ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL);
+	ast_channel_publish_cached_blob(chan, ast_channel_unhold_type(), NULL);
 
 	res = ast_queue_frame(chan, &f);
-	ast_channel_unlock(chan);
+
 	return res;
 }
 
@@ -3639,7 +3637,7 @@
 		return;
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_dtmf_begin_type(), blob);
+	ast_channel_publish_cached_blob(chan, ast_channel_dtmf_begin_type(), blob);
 }
 
 static void send_dtmf_end_event(struct ast_channel *chan,
@@ -3656,7 +3654,7 @@
 		return;
 	}
 
-	ast_channel_publish_blob(chan, ast_channel_dtmf_end_type(), blob);
+	ast_channel_publish_cached_blob(chan, ast_channel_dtmf_end_type(), blob);
 }
 
 static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f)
@@ -3988,7 +3986,6 @@
 					ast_frfree(f);
 					f = &ast_null_frame;
 				} else {
-					/* Answer the CDR */
 					ast_setstate(chan, AST_STATE_UP);
 				}
 			} else if (f->subclass.integer == AST_CONTROL_READ_ACTION) {
@@ -5337,10 +5334,6 @@
 			generator_write_format_change(chan);
 		}
 
-		ast_channel_lock(chan);
-		ast_channel_publish_snapshot(chan);
-		ast_channel_unlock(chan);
-
 		return 0;
 	}
 
@@ -5420,10 +5413,6 @@
 		generator_write_format_change(chan);
 	}
 
-	ast_channel_lock(chan);
-	ast_channel_publish_snapshot(chan);
-	ast_channel_unlock(chan);
-
 	return res;
 }
 
@@ -7419,6 +7408,17 @@
 	AST_RWLIST_UNLOCK(&channelvars);
 }
 
+int ast_channel_has_manager_vars(void)
+{
+	int vars_present;
+
+	AST_RWLIST_RDLOCK(&channelvars);
+	vars_present = !AST_LIST_EMPTY(&channelvars);
+	AST_RWLIST_UNLOCK(&channelvars);
+
+	return vars_present;
+}
+
 void ast_channel_set_manager_vars(size_t varc, char **vars)
 {
 	size_t i;
@@ -7649,12 +7649,9 @@
 {
 	struct ast_variable *cur;
 
-	ast_channel_stage_snapshot(chan);
-
-	for (cur = vars; cur; cur = cur->next)
+	for (cur = vars; cur; cur = cur->next) {
 		pbx_builtin_setvar_helper(chan, cur->name, cur->value);
-
-	ast_channel_stage_snapshot_done(chan);
+	}
 }
 
 static void *silence_generator_alloc(struct ast_channel *chan, void *data)
Index: main/stasis_cache.c
===================================================================
--- main/stasis_cache.c	(revision 414971)
+++ main/stasis_cache.c	(working copy)
@@ -127,9 +127,17 @@
 	return NULL;
 }
 
+/*!
+ * \brief The key for an entry in the cache
+ * \note The items in this struct must be immutable for the item in the cache
+ */
 struct cache_entry_key {
+	/*! The message type of the item stored in the cache */
 	struct stasis_message_type *type;
+	/*! The unique ID of the item stored in the cache */
 	const char *id;
+	/*! The hash, computed from \c type and \c id */
+	unsigned int hash;
 };
 
 struct stasis_cache_entry {
@@ -166,6 +174,12 @@
 	AST_VECTOR_FREE(&entry->remote);
 }
 
+static void cache_entry_compute_hash(struct cache_entry_key *key)
+{
+	key->hash = ast_hashtab_hash_string(stasis_message_type_name(key->type));
+	key->hash += ast_hashtab_hash_string(key->id);
+}
+
 static struct stasis_cache_entry *cache_entry_create(struct stasis_message_type *type, const char *id, struct stasis_message *snapshot)
 {
 	struct stasis_cache_entry *entry;
@@ -187,6 +201,7 @@
 		return NULL;
 	}
 	entry->key.type = ao2_bump(type);
+	cache_entry_compute_hash(&entry->key);
 
 	is_remote = ast_eid_cmp(&ast_eid_default, stasis_message_eid(snapshot)) ? 1 : 0;
 	if (AST_VECTOR_INIT(&entry->remote, is_remote)) {
@@ -211,7 +226,6 @@
 {
 	const struct stasis_cache_entry *object;
 	const struct cache_entry_key *key;
-	int hash = 0;
 
 	switch (flags & OBJ_SEARCH_MASK) {
 	case OBJ_SEARCH_KEY:
@@ -227,9 +241,7 @@
 		return 0;
 	}
 
-	hash += ast_hashtab_hash_string(stasis_message_type_name(key->type));
-	hash += ast_hashtab_hash_string(key->id);
-	return hash;
+	return (int)key->hash;
 }
 
 static int cache_entry_cmp(void *obj, void *arg, int flags)
@@ -347,6 +359,7 @@
 
 	search_key.type = type;
 	search_key.id = id;
+	cache_entry_compute_hash(&search_key);
 	entry = ao2_find(entries, &search_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
 
 	/* Ensure that what we looked for is what we found. */
Index: main/cli.c
===================================================================
--- main/cli.c	(revision 414971)
+++ main/cli.c	(working copy)
@@ -1513,8 +1513,7 @@
 
 static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
-	struct ast_channel_snapshot *snapshot;
+	struct ast_channel *chan;
 	struct timeval now;
 	char cdrtime[256];
 	struct ast_str *obuf;/*!< Buffer for CDR variables. */
@@ -1522,6 +1521,12 @@
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
 	struct ast_var_t *var;
+	char nativeformats[256];
+	struct ast_str *write_transpath = ast_str_alloca(256);
+	struct ast_str *read_transpath = ast_str_alloca(256);
+	struct ast_bridge *bridge;
+	struct ast_callid *callid;
+	char callid_buf[32];
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -1538,25 +1543,27 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	now = ast_tvnow();
-
-	if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), a->argv[3]))) {
-		ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
-		return CLI_SUCCESS;
-	}
-	snapshot = stasis_message_data(msg);
-
 	obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
 	if (!obuf) {
 		return CLI_FAILURE;
 	}
+
 	output = ast_str_create(8192);
 	if (!output) {
 		return CLI_FAILURE;
 	}
 
-	if (!ast_tvzero(snapshot->creationtime)) {
-		elapsed_seconds = now.tv_sec - snapshot->creationtime.tv_sec;
+	chan = ast_channel_get_by_name(a->argv[3]);
+	if (!chan) {
+		ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
+		return CLI_SUCCESS;
+	}
+
+	now = ast_tvnow();
+	ast_channel_lock(chan);
+
+	if (!ast_tvzero(ast_channel_creationtime(chan))) {
+		elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
 		hour = elapsed_seconds / 3600;
 		min = (elapsed_seconds % 3600) / 60;
 		sec = elapsed_seconds % 60;
@@ -1565,6 +1572,16 @@
 		strcpy(cdrtime, "N/A");
 	}
 
+	ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
+	ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
+
+	bridge = ast_channel_get_bridge(chan);
+	callid = ast_channel_callid(chan);
+	if (callid) {
+		ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
+		ast_callid_unref(callid);
+	}
+
 	ast_str_append(&output, 0,
 		" -- General --\n"
 		"           Name: %s\n"
@@ -1597,51 +1614,63 @@
 		"    Application: %s\n"
 		"           Data: %s\n"
 		" Call Identifer: %s\n",
-		snapshot->name,
-		snapshot->type,
-		snapshot->uniqueid,
-		snapshot->linkedid,
-		S_OR(snapshot->caller_number, "(N/A)"),
-		S_OR(snapshot->caller_name, "(N/A)"),
-		S_OR(snapshot->connected_number, "(N/A)"),
-		S_OR(snapshot->connected_name, "(N/A)"),
-		S_OR(snapshot->effective_number, "(N/A)"),
-		S_OR(snapshot->effective_name, "(N/A)"),
-		S_OR(snapshot->caller_dnid, "(N/A)"),
-		snapshot->language,
-		ast_state2str(snapshot->state),
-		snapshot->state,
-		snapshot->nativeformats,
-		snapshot->writeformat,
-		snapshot->readformat,
-		!ast_strlen_zero(snapshot->writetrans) ? "Yes" : "No",
-		snapshot->writetrans,
-		!ast_strlen_zero(snapshot->readtrans) ? "Yes" : "No",
-		snapshot->readtrans,
-		(long) snapshot->hanguptime.tv_sec,
+		ast_channel_name(chan),
+		ast_channel_tech(chan)->type,
+		ast_channel_uniqueid(chan),
+		ast_channel_linkedid(chan),
+		S_COR(ast_channel_caller(chan)->id.number.valid,
+		      ast_channel_caller(chan)->id.number.str, "(N/A)"),
+		S_COR(ast_channel_caller(chan)->id.name.valid,
+		      ast_channel_caller(chan)->id.name.str, "(N/A)"),
+		S_COR(ast_channel_connected(chan)->id.number.valid,
+		      ast_channel_connected(chan)->id.number.str, "(N/A)"),
+		S_COR(ast_channel_connected(chan)->id.name.valid,
+		      ast_channel_connected(chan)->id.name.str, "(N/A)"),
+		S_COR(ast_channel_connected_effective_id(chan).number.valid,
+		      ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
+		S_COR(ast_channel_connected_effective_id(chan).name.valid,
+		      ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
+		S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
+		ast_channel_language(chan),
+		ast_state2str(ast_channel_state(chan)),
+		ast_channel_state(chan),
+		ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
+		ast_getformatname(ast_channel_writeformat(chan)),
+		ast_getformatname(ast_channel_readformat(chan)),
+		ast_str_strlen(write_transpath) ? "Yes" : "No",
+		ast_str_buffer(write_transpath),
+		ast_str_strlen(read_transpath) ? "Yes" : "No",
+		ast_str_buffer(read_transpath),
+		ast_channel_whentohangup(chan)->tv_sec,
 		cdrtime,
-		S_OR(snapshot->bridgeid, "(Not bridged)"),
-		snapshot->context,
-		snapshot->exten,
-		snapshot->priority,
-		snapshot->callgroup,
-		snapshot->pickupgroup,
-		S_OR(snapshot->appl, "(N/A)"),
-		S_OR(snapshot->data, "(Empty)"),
-		S_OR(snapshot->callid, "(None)"));
-
+		bridge ? bridge->uniqueid : "(Not bridged)",
+		ast_channel_context(chan),
+		ast_channel_exten(chan),
+		ast_channel_priority(chan),
+		ast_channel_callgroup(chan),
+		ast_channel_pickupgroup(chan),
+		S_OR(ast_channel_appl(chan), "(N/A)"),
+		S_OR(ast_channel_data(chan), "(Empty)"),
+		S_OR(callid_buf, "(None)")
+		);
 	ast_str_append(&output, 0, "      Variables:\n");
 
-	AST_LIST_TRAVERSE(snapshot->channel_vars, var, entries) {
+	AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
 		ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
 	}
 
-	if (ast_cdr_serialize_variables(snapshot->name, &obuf, '=', '\n')) {
+	if (ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
 		ast_str_append(&output, 0, "  CDR Variables:\n%s\n", ast_str_buffer(obuf));
 	}
 
+	ast_channel_unlock(chan);
+
 	ast_cli(a->fd, "%s", ast_str_buffer(output));
 	ast_free(output);
+
+	ao2_cleanup(bridge);
+	ast_channel_unref(chan);
+
 	return CLI_SUCCESS;
 }
 
Index: main/dial.c
===================================================================
--- main/dial.c	(revision 414971)
+++ main/dial.c	(working copy)
@@ -306,7 +306,7 @@
 
 	ast_channel_appl_set(channel->owner, "AppDial2");
 	ast_channel_data_set(channel->owner, "(Outgoing Line)");
-	ast_publish_channel_state(channel->owner);
+
 	memset(ast_channel_whentohangup(channel->owner), 0, sizeof(*ast_channel_whentohangup(channel->owner)));
 
 	/* Inherit everything from he who spawned this dial */
Index: main/channel_internal_api.c
===================================================================
--- main/channel_internal_api.c	(revision 414971)
+++ main/channel_internal_api.c	(working copy)
@@ -943,9 +943,8 @@
 		ast_channel_name(chan),
 		call_identifier_to,
 		call_identifier_from);
-
-	ast_channel_publish_snapshot(chan);
 }
+
 void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state value)
 {
 	chan->state = value;
@@ -1073,7 +1072,6 @@
 void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value)
 {
 	chan->whentohangup = *value;
-	ast_channel_publish_snapshot(chan);
 }
 void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value)
 {
@@ -1131,7 +1129,6 @@
 void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
 {
 	chan->callgroup = value;
-	ast_channel_publish_snapshot(chan);
 }
 ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
 {
@@ -1140,7 +1137,6 @@
 void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
 {
 	chan->pickupgroup = value;
-	ast_channel_publish_snapshot(chan);
 }
 struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan)
 {
Index: main/cel.c
===================================================================
--- main/cel.c	(revision 414971)
+++ main/cel.c	(working copy)
@@ -1791,9 +1791,7 @@
 		"event_type", event_type,
 		"event_details", blob);
 
-	ast_channel_lock(chan);
-	message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob);
-	ast_channel_unlock(chan);
+	message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), cel_generic_type(), cel_blob);
 	if (message) {
 		stasis_publish(ast_cel_topic(), message);
 	}
Index: main/manager.c
===================================================================
--- main/manager.c	(revision 414971)
+++ main/manager.c	(working copy)
@@ -99,6 +99,7 @@
 #include "asterisk/bridge.h"
 #include "asterisk/features_config.h"
 #include "asterisk/rtp_engine.h"
+#include "asterisk/translate.h"
 
 /*** DOCUMENTATION
 	<manager name="Ping" language="en_US">
@@ -3845,95 +3846,110 @@
 static int action_status(struct mansession *s, const struct message *m)
 {
 	const char *name = astman_get_header(m, "Channel");
-	const char *cvariables = astman_get_header(m, "Variables");
-	char *variables = ast_strdupa(S_OR(cvariables, ""));
-	RAII_VAR(struct ao2_container *, cached_channels, NULL, ao2_cleanup);
-	struct stasis_message *msg;
+	const char *chan_variables = astman_get_header(m, "Variables");
+	const char *id = astman_get_header(m, "ActionID");
+	char *variables = ast_strdupa(S_OR(chan_variables, ""));
+	struct ast_str *variable_str = ast_str_create(1024);
+	struct ast_str *write_transpath = ast_str_alloca(256);
+	struct ast_str *read_transpath = ast_str_alloca(256);
+	struct ast_channel *chan;
+	char nativeformats[256];
 	int channels = 0;
 	int all = ast_strlen_zero(name); /* set if we want all channels */
-	const char *id = astman_get_header(m, "ActionID");
-	char idText[256];
+	char id_text[256];
+	struct ast_channel_iterator *it_chans = NULL;
 	AST_DECLARE_APP_ARGS(vars,
 		AST_APP_ARG(name)[100];
 	);
-	struct ast_str *str = ast_str_create(1000);
-	struct ao2_iterator it_chans;
-	struct timeval now = ast_tvnow();
 
-	if (!ast_strlen_zero(id)) {
-		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-	} else {
-		idText[0] = '\0';
+	if (!variable_str) {
+		astman_send_error(s, m, "Memory Allocation Failure");
+		return 1;
 	}
 
 	if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) {
+		ast_free(variable_str);
 		astman_send_error(s, m, "Status Access Forbidden: Variables");
 		return 0;
 	}
 
 	if (all) {
-		if (!(cached_channels = stasis_cache_dump(ast_channel_cache_by_name(), ast_channel_snapshot_type()))) {
-			ast_free(str);
+		if (!(it_chans = ast_channel_iterator_all_new())) {
+			ast_free(variable_str);
 			astman_send_error(s, m, "Memory Allocation Failure");
 			return 1;
 		}
-		it_chans = ao2_iterator_init(cached_channels, 0);
-		msg = ao2_iterator_next(&it_chans);
+		chan = ast_channel_iterator_next(it_chans);
 	} else {
-		if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), name))) {
+		chan = ast_channel_get_by_name(name);
+		if (!chan) {
 			astman_send_error(s, m, "No such channel");
-			ast_free(str);
+			ast_free(variable_str);
 			return 0;
 		}
 	}
 
 	astman_send_ack(s, m, "Channel status will follow");
 
-	if (!ast_strlen_zero(cvariables)) {
+	if (!ast_strlen_zero(id)) {
+		snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
+	} else {
+		id_text[0] = '\0';
+	}
+
+	if (!ast_strlen_zero(chan_variables)) {
 		AST_STANDARD_APP_ARGS(vars, variables);
 	}
 
 	/* if we look by name, we break after the first iteration */
-	for (; msg; ao2_ref(msg, -1), msg = all ? ao2_iterator_next(&it_chans) : NULL) {
-		struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
-		struct ast_channel *c;
-		struct ast_str *built = ast_manager_build_channel_state_string_prefix(snapshot, "");
-		long elapsed_seconds = 0;
+	for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) {
+		struct timeval now;
+		long elapsed_seconds;
+		struct ast_bridge *bridge;
 
-		if (!built) {
-			continue;
-		}
+		ast_channel_lock(chan);
 
-		if (!ast_strlen_zero(cvariables) && (c = ast_channel_get_by_name(snapshot->name))) {
+		now = ast_tvnow();
+		elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan));
+
+		if (!ast_strlen_zero(chan_variables)) {
 			int i;
-			ast_str_reset(str);
+			ast_str_reset(variable_str);
 			for (i = 0; i < vars.argc; i++) {
 				char valbuf[512], *ret = NULL;
 
 				if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
-					if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
+					if (ast_func_read(chan, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
 						valbuf[0] = '\0';
 					}
 					ret = valbuf;
 				} else {
-					pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
+					pbx_retrieve_variable(chan, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
 				}
 
-				ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
+				ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
 			}
-			ast_channel_unref(c);
 		}
 
 		channels++;
 
+		bridge = ast_channel_get_bridge(chan);
 
-		if (!ast_tvzero(snapshot->creationtime)) {
-			elapsed_seconds = now.tv_sec - snapshot->creationtime.tv_sec;
-		}
-
 		astman_append(s,
 			"Event: Status\r\n"
 			"Privilege: Call\r\n"
+			"Channel: %s\r\n"
+			"ChannelState: %u\r\n"
+			"ChannelStateDesc: %s\r\n"
+			"CallerIDNum: %s\r\n"
+			"CallerIDName: %s\r\n"
+			"ConnectedLineNum: %s\r\n"
+			"ConnectedLineName: %s\r\n"
+			"Accountcode: %s\r\n"
+			"Context: %s\r\n"
+			"Exten: %s\r\n"
+			"Priority: %d\r\n"
+			"Uniqueid: %s\r\n"
 			"Type: %s\r\n"
 			"DNID: %s\r\n"
 			"EffectiveConnectedLineNum: %s\r\n"
@@ -3953,43 +3969,56 @@
 			"Seconds: %ld\r\n"
 			"%s"
 			"%s"
-			"%s"
 			"\r\n",
-			snapshot->type,
-			snapshot->caller_dnid,
-			S_OR(snapshot->effective_number, "<unknown>"),
-			S_OR(snapshot->effective_name, "<unknown>"),
-			snapshot->hanguptime.tv_sec,
-			snapshot->bridgeid,
-			snapshot->linkedid,
-			snapshot->appl,
-			snapshot->data,
-			snapshot->nativeformats,
-			snapshot->readformat,
-			snapshot->readtrans,
-			snapshot->writeformat,
-			snapshot->writetrans,
-			snapshot->callgroup,
-			snapshot->pickupgroup,
-			(long) elapsed_seconds,
-			ast_str_buffer(built),
-			ast_str_buffer(str),
-			idText);
+			ast_channel_name(chan),
+			ast_channel_state(chan),
+			ast_state2str(ast_channel_state(chan)),
+			S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
+			S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>"),
+			S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "<unknown>"),
+			S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "<unknown>"),
+			ast_channel_accountcode(chan),
+			ast_channel_context(chan),
+			ast_channel_exten(chan),
+			ast_channel_priority(chan),
+			ast_channel_uniqueid(chan),
+			ast_channel_tech(chan)->type,
+			S_OR(ast_channel_dialed(chan)->number.str, ""),
+			S_COR(ast_channel_connected_effective_id(chan).number.valid, ast_channel_connected_effective_id(chan).number.str, "<unknown>"),
+			S_COR(ast_channel_connected_effective_id(chan).name.valid, ast_channel_connected_effective_id(chan).name.str, "<unknown>"),
+			ast_channel_whentohangup(chan)->tv_sec,
+			bridge ? bridge->uniqueid : "",
+			ast_channel_linkedid(chan),
+			ast_channel_appl(chan),
+			ast_channel_data(chan),
+			ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
+			ast_getformatname(ast_channel_readformat(chan)),
+			ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
+			ast_getformatname(ast_channel_writeformat(chan)),
+			ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
+			ast_channel_callgroup(chan),
+			ast_channel_pickupgroup(chan),
+			(long)elapsed_seconds,
+			ast_str_buffer(variable_str),
+			id_text);
 
-		ast_free(built);
+		ao2_cleanup(bridge);
+
+		ast_channel_unlock(chan);
+		chan = ast_channel_unref(chan);
 	}
 
-	if (all) {
-		ao2_iterator_destroy(&it_chans);
+	if (it_chans) {
+		ast_channel_iterator_destroy(it_chans);
 	}
 
 	astman_append(s,
 		"Event: StatusComplete\r\n"
 		"%s"
 		"Items: %d\r\n"
-		"\r\n", idText, channels);
+		"\r\n", id_text, channels);
 
-	ast_free(str);
+	ast_free(variable_str);
 
 	return 0;
 }
Index: main/endpoints.c
===================================================================
--- main/endpoints.c	(revision 414971)
+++ main/endpoints.c	(working copy)
@@ -203,9 +203,6 @@
 	ast_str_container_add(endpoint->channel_ids, ast_channel_uniqueid(chan));
 	ao2_unlock(endpoint);
 
-	ast_channel_lock(chan);
-	ast_publish_channel_state(chan);
-	ast_channel_unlock(chan);
 	endpoint_publish_snapshot(endpoint);
 
 	return 0;
Index: res/res_pjsip/pjsip_configuration.c
===================================================================
--- res/res_pjsip/pjsip_configuration.c	(revision 414971)
+++ res/res_pjsip/pjsip_configuration.c	(working copy)
@@ -1398,8 +1398,8 @@
 		indent = CLI_INDENT_TO_SPACES(context->indent_level);
 		filler = CLI_LAST_TABSTOP - indent - 38;
 		ast_str_append(&context->output_buffer, 0,
-			"%*s:  <Codec>  Exten: <DialedExten%*.*s>  CLCID: <ConnectedLineCID.......>\n",
-			indent, "Codec", filler, filler, CLI_HEADER_FILLER);
+			"%*s: <DialedExten%*.*s>  CLCID: <ConnectedLineCID.......>\n",
+			indent, "Exten", filler, filler, CLI_HEADER_FILLER);
 		context->indent_level--;
 	}
 
@@ -1443,9 +1443,8 @@
 		flexwidth = CLI_LAST_TABSTOP - indent - 25;
 
 		ast_str_append(&context->output_buffer, 0,
-			"%*s:  %-7s  Exten: %-*.*s  CLCID: \"%s\" <%s>\n",
-			indent, "Codec",
-			snapshot->nativeformats,
+			"%*s: %-*.*s  CLCID: \"%s\" <%s>\n",
+			indent, "Exten",
 			flexwidth, flexwidth,
 			snapshot->exten,
 			snapshot->connected_name,
Index: res/res_agi.c
===================================================================
--- res/res_agi.c	(revision 414971)
+++ res/res_agi.c	(working copy)
@@ -1481,9 +1481,10 @@
 	   to execute based on the setup info */
 	ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
 	startblob = ast_json_pack("{s: s}", "Env", ami_buffer);
-	ast_channel_lock(chan);
-	ast_channel_publish_blob(chan, agi_async_start_type(), startblob);
 
+	ast_channel_publish_cached_blob(chan, agi_async_start_type(), startblob);
+
+	ast_channel_lock(chan);
 	hungup = ast_check_hangup(chan);
 	ast_channel_unlock(chan);
 	for (;;) {
@@ -1529,9 +1530,7 @@
 			if (execblob && !ast_strlen_zero(cmd->cmd_id)) {
 				ast_json_object_set(execblob, "CommandId", ast_json_string_create(cmd->cmd_id));
 			}
-			ast_channel_lock(chan);
-			ast_channel_publish_blob(chan, agi_async_exec_type(), execblob);
-			ast_channel_unlock(chan);
+			ast_channel_publish_cached_blob(chan, agi_async_exec_type(), execblob);
 
 			free_agi_cmd(cmd);
 
@@ -1591,9 +1590,7 @@
 		ast_speech_destroy(async_agi.speech);
 	}
 	/* notify manager users this channel cannot be controlled anymore by Async AGI */
-	ast_channel_lock(chan);
-	ast_channel_publish_blob(chan, agi_async_end_type(), NULL);
-	ast_channel_unlock(chan);
+	ast_channel_publish_cached_blob(chan, agi_async_end_type(), NULL);
 
 async_agi_abort:
 	/* close the pipe */
@@ -3665,9 +3662,7 @@
 			     "Command", command,
 			     "ResultCode", result_code,
 			     "Result", result);
-	ast_channel_lock(chan);
-	ast_channel_publish_blob(chan, agi_exec_end_type(), blob);
-	ast_channel_unlock(chan);
+	ast_channel_publish_cached_blob(chan, agi_exec_end_type(), blob);
 }
 
 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
@@ -3685,9 +3680,7 @@
 	startblob = ast_json_pack("{s: i, s: s}",
 			     "CommandId", command_id,
 			     "Command", ami_cmd);
-	ast_channel_lock(chan);
-	ast_channel_publish_blob(chan, agi_exec_start_type(), startblob);
-	ast_channel_unlock(chan);
+	ast_channel_publish_cached_blob(chan, agi_exec_start_type(), startblob);
 
 	parse_args(buf, &argc, argv);
 	c = find_command(argv, 0);
Index: res/ari/resource_channels.c
===================================================================
--- res/ari/resource_channels.c	(revision 414971)
+++ res/ari/resource_channels.c	(working copy)
@@ -859,7 +859,7 @@
 		return;
 	}
 
-	snapshot = ast_channel_snapshot_create(chan);
+	snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
 	ast_channel_unlock(chan);
 
 	if (!ast_strlen_zero(args_app)) {
@@ -1086,7 +1086,7 @@
 		return;
 	}
 
-	snapshot = ast_channel_snapshot_create(snoop);
+	snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(snoop));
 	ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
 }
 
