[asterisk-commits] dhubbard: branch group/issue3450 r136606 - /team/group/issue3450/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Aug 7 14:23:34 CDT 2008


Author: dhubbard
Date: Thu Aug  7 14:23:33 2008
New Revision: 136606

URL: http://svn.digium.com/view/asterisk?view=rev&rev=136606
Log:
Added persistent storage of PRI service state for issue 3450.
Service state is tracked in the AstDB for pri channels that are out-of-service (OOS) only.
When a channel is OOS, it will be put into AstDB with syntax <state>:<reason>, where:
  <state> is "O" for 'out-of-service'; and eventually "M" for 'maintenance'
  <reason> is { "0" | "1" | "2" | "3" }, where:
	"0" - no reason, mostly for backwards compatibility
	"1" - near-end is disabled
	"2" - far-end is disabled
	"3" - near-end and far-end is disabled

Modified:
    team/group/issue3450/channels/chan_dahdi.c

Modified: team/group/issue3450/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/group/issue3450/channels/chan_dahdi.c?view=diff&rev=136606&r1=136605&r2=136606
==============================================================================
--- team/group/issue3450/channels/chan_dahdi.c (original)
+++ team/group/issue3450/channels/chan_dahdi.c Thu Aug  7 14:23:33 2008
@@ -166,6 +166,22 @@
 ;
 
 static const char config[] = "chan_dahdi.conf";
+
+#ifdef HAVE_PRI
+/*! \brief Persistent Service State */
+#define SRVST_DBKEY "service-state"
+#define SRVST_TYPE_OOS "O"
+/* the reason for the service state */
+#define SRVST_NOREASON_MMKAY 0
+#define SRVST_NEAREND 1
+#define SRVST_FAREND 2
+#define SRVST_BOTH (SRVST_NEAREND | SRVST_FAREND)
+
+/*! \brief The AstDB family */
+static const char dahdi_db[] = "dahdi/registry";
+#endif
+
+
 
 #define SIG_EM		DAHDI_SIG_EM
 #define SIG_EMWINK 	(0x0100000 | DAHDI_SIG_EM)
@@ -8701,9 +8717,20 @@
 		tmp->sendcalleridafter = conf->chan.sendcalleridafter;
 		if (!here) {
 			tmp->locallyblocked = tmp->remotelyblocked = 0;
-			if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
+			if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) {
 				tmp->inservice = 0;
-			else /* We default to in service on protocols that don't have a reset */
+#ifdef HAVE_PRI
+				if (chan_sig == SIG_PRI) {
+					char db_chan_name[100];
+					char db_answer[20];
+					snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, tmp->channel);
+					if (ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NOREASON_MMKAY);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+					}
+				}
+#endif
+			} else /* We default to in service on protocols that don't have a reset */
 				tmp->inservice = 1;
 		}
 	}
@@ -10592,19 +10619,37 @@
 						ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
 							PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
 					else {
-						ast_verb(3, "B-channel %d/%d restarted on span %d\n",
-								PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						if (pri->pvts[chanpos]->call) {
-							pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
-							pri->pvts[chanpos]->call = NULL;
+						char db_chan_name[100];
+						char db_answer[20];
+						char state;
+						int why;
+						int skipit = 0;
+						
+						snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, e->restart.channel);
+						if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+							sscanf(db_answer, "%c:%d", &state, &why);
+							if (why) {
+								ast_log(LOG_NOTICE, "channel '%d' is ignoring the PRI_EVENT_RESTART request because it is out-of-service (reason: %d)\n", e->restart.channel, why);
+								skipit = 1;
+							} else {
+								ast_db_del(db_chan_name, SRVST_DBKEY);
+							}
 						}
-						/* Force soft hangup if appropriate */
-						if (pri->pvts[chanpos]->realcall) 
-							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-						else if (pri->pvts[chanpos]->owner)
-							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						if (!skipit) {
+							ast_verb(3, "B-channel %d/%d restarted on span %d\n",
+									PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
+							ast_mutex_lock(&pri->pvts[chanpos]->lock);
+							if (pri->pvts[chanpos]->call) {
+								pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
+								pri->pvts[chanpos]->call = NULL;
+							}
+							/* Force soft hangup if appropriate */
+							if (pri->pvts[chanpos]->realcall) 
+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+							else if (pri->pvts[chanpos]->owner)
+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						}
 					}
 				} else {
 					ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
@@ -10684,11 +10729,47 @@
 					ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
 						e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
 				} else {
+					char db_chan_name[100];
+					char db_answer[20];
+					char state;
+					int ch;
+					int why = -1;
+
 					ast_mutex_lock(&pri->pvts[chanpos]->lock);
 					pri->pvts[chanpos]->changestatus = e->service.changestatus;
+					ch = pri->pvts[chanpos]->channel;
 					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					ast_log(LOG_WARNING, "Received service change status %d on channel %d/%d span %d\n",
-						e->service.changestatus, PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span);
+					
+					snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, ch);
+					if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+						sscanf(db_answer, "%c:%d", &state, &why);
+						ast_db_del(db_chan_name, SRVST_DBKEY);
+					}
+					switch (e->service.changestatus) {
+					case 0: /* enable */
+						if (why > -1) {
+							if (why & SRVST_NEAREND) {
+								snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NEAREND);
+								ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+								ast_log(LOG_DEBUG, "channel '%d' is far-end enabled, but the near-end is out-of-service.\n", ch);
+							}
+						} else
+							ast_log(LOG_WARNING, "Huh??  Channel '%s' wasn't listed in the persistent storage database\n", db_chan_name);
+						break;
+					case 2: /* disable */
+						if (why == -1) {
+							why = SRVST_FAREND;
+						} else {
+							why |= SRVST_FAREND;
+						}
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+						break;
+					default:
+						ast_log(LOG_ERROR, "Huh?  changestatus is: %d\n", e->service.changestatus);
+					}
+					ast_log(LOG_WARNING, "Received service change status %d on channel %d/%d span %d (logical: %d)\n",
+						e->service.changestatus, PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch);
 				}
 				break;
 			case PRI_EVENT_SERVICE_ACK:
@@ -11661,6 +11742,11 @@
 	int trunkgroup;
 	struct dahdi_pri *pri=NULL;
 	int fd = a->fd;
+	char db_chan_name[100];
+	char db_answer[20];
+	char state;
+	int why;
+
 	
 	lock = &iflock;
 	start = iflist;
@@ -11707,6 +11793,40 @@
 	tmp = start;
 	while (tmp) {
 		if (tmp->pri && tmp->channel == channel) {
+
+			why = -1;
+			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, channel);
+			if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+				sscanf(db_answer, "%c:%d", &state, &why);
+				ast_db_del(db_chan_name, SRVST_DBKEY);
+			}
+
+			switch(changestatus) {
+			case 0: /* enable */
+				if (why > -1) {
+					if (why & SRVST_FAREND) {
+						why = SRVST_FAREND;
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+						ast_debug(3, "channel '%d' is near-end enabled, but the far-end is out of service.\n", channel);
+					}
+				}
+				break;
+			//case 1: /* loop */
+			case 2: /* disable */
+				if (why == -1) {
+					why = SRVST_NEAREND;
+				} else {
+					why |= SRVST_NEAREND;
+				}
+				snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+				ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+				break;
+			//case 3: /* continuity */
+			//case 4: /* shutdown */
+			default:
+				ast_log(LOG_ERROR, "Unsupported changestatus: '%d'\n", changestatus);
+			}
 			ast_log(LOG_NOTICE, "about to call pri_maintenance_service(span: %d, channel: %d)\n", PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp));
 			pri_maintenance_service(tmp->pri->pri, PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp), changestatus);
 			ast_mutex_unlock(lock);
@@ -11718,6 +11838,24 @@
 
 	ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
 	return CLI_FAILURE;
+}
+
+
+static char *handle_pri_service_clear_states(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:	
+		e->command = "pri service clear states";
+		e->usage = 
+			"Usage: pri service clear states\n"
+			"	debugging astdb CLI operation\n";
+		return NULL;
+	case CLI_GENERATE:	
+		return NULL;
+	}
+	ast_db_deltree(dahdi_db, NULL);
+	return CLI_SUCCESS;
+	
 }
 
 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -12038,6 +12176,7 @@
 	AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
 	AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
 	AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
+	AST_CLI_DEFINE(handle_pri_service_clear_states, "debug for clearing astdb"),
  	AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
  	AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
  	AST_CLI_DEFINE(handle_pri_service_loop_channel, "Put a channel into maintenance loop"),
@@ -13062,6 +13201,12 @@
 	/* Destroy all the interfaces and free their memory */
 	p = iflist;
 	while (p) {
+#ifdef HAVE_PRI
+		char db_chan_name[100];
+		char db_answer[20];
+		char state;
+		int why;
+#endif
 		/* Free any callerid */
 		if (p->cidspill)
 			ast_free(p->cidspill);
@@ -13074,6 +13219,16 @@
 		/* Free associated memory */
 		if (pl)
 			destroy_dahdi_pvt(&pl);
+#ifdef HAVE_PRI
+		/* clear non-persistent state information */	
+		snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, x);
+		if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+			sscanf(db_answer, "%c:%d", &state, &why);
+			if (!why) {
+				ast_db_del(db_chan_name, SRVST_DBKEY);
+			}
+		}
+#endif
 		ast_verb(3, "Unregistered channel %d\n", x);
 	}
 	iflist = NULL;




More information about the asterisk-commits mailing list