[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