[asterisk-commits] oej: branch oej/multiparking r55373 -
/team/oej/multiparking/res/res_features.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sun Feb 18 13:55:19 MST 2007
Author: oej
Date: Sun Feb 18 14:55:18 2007
New Revision: 55373
URL: http://svn.digium.com/view/asterisk?view=rev&rev=55373
Log:
- Move from AST LIST to AST Objects
- Implement read/write locks for parkinglots and remove some of the old
locks
Modified:
team/oej/multiparking/res/res_features.c
Modified: team/oej/multiparking/res/res_features.c
URL: http://svn.digium.com/view/asterisk/team/oej/multiparking/res/res_features.c?view=diff&rev=55373&r1=55372&r2=55373
==============================================================================
--- team/oej/multiparking/res/res_features.c (original)
+++ team/oej/multiparking/res/res_features.c Sun Feb 18 14:55:18 2007
@@ -58,6 +58,7 @@
#include "asterisk/adsi.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
+#include "asterisk/astobj.h"
#define DEFAULT_PARK_TIME 45000 /*!< Default parking time */
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
@@ -97,7 +98,7 @@
/*! \brief Structure for parking lots in a linked list. */
struct ast_parkinglot {
- char name[AST_MAX_EXTENSION]; /*!< Name for this lot (used in other configs) */
+ ASTOBJ_COMPONENTS(struct ast_parkinglot); /*!< various object stuff, including ->name */
char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
int parking_start; /*!< First available extension for parking */
@@ -106,10 +107,11 @@
int parkfindnext;
int parkingtime; /*!< Default parking time */
struct parkeduser *occupiedlots;
- AST_LIST_ENTRY(ast_parkinglot) list; /*!< List entry */
};
-static AST_LIST_HEAD_STATIC(parkinglots, ast_parkinglot);
+struct ast_parkinglot_list {
+ ASTOBJ_CONTAINER_COMPONENTS(struct ast_parkinglot);
+} parkinglots;
struct ast_parkinglot *default_parkinglot;
static int comebacktoorigin = 1;
@@ -173,6 +175,14 @@
static pthread_t parking_thread;
+/* Forward declarations */
+static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
+static void parkinglot_unref(struct ast_parkinglot *parkinglot);
+static void parkinglot_destroy(struct ast_parkinglot *ruin);
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds);
+int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot);
+struct ast_parkinglot *find_parkinglot(const char *name);
+
char *ast_parking_ext(void)
{
@@ -191,9 +201,6 @@
struct ast_channel *peer;
};
-/* Forward declarations */
-int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot);
-struct ast_parkinglot *find_parkinglot(const char *name);
/*! \brief store context, priority and extension */
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
@@ -369,22 +376,25 @@
if (!parkinglot)
parkinglot = default_parkinglot;
+ parkinglot_addref(parkinglot);
if (option_debug)
ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
/* Allocate memory for parking data */
- if (!(pu = ast_calloc(1, sizeof(*pu))))
+ if (!(pu = ast_calloc(1, sizeof(*pu)))) {
+ parkinglot_unref(parkinglot);
return -1;
-
- /* Lock parking lot */
- ast_mutex_lock(&parking_lock);
+ }
+ ASTOBJ_WRLOCK(parkinglot);
/* Check for channel variable PARKINGEXTEN */
parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
if (!ast_strlen_zero(parkingexten)) {
if (ast_exists_extension(NULL, parkinglot->parking_con, parkingexten, 1, NULL)) {
ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
+ parkinglot_unref(parkinglot);
+ ASTOBJ_UNLOCK(parkinglot);
return 0; /* Continue execution if possible */
}
ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
@@ -407,6 +417,8 @@
ast_log(LOG_WARNING, "No more parking spaces in parking lot \"%s\"\n", parkinglot->name);
free(pu);
ast_mutex_unlock(&parking_lock);
+ parkinglot_unref(parkinglot);
+ ASTOBJ_UNLOCK(parkinglot);
return -1;
}
/* Set pointer for next parking */
@@ -443,6 +455,7 @@
pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
pu->next = parkinglot->occupiedlots;
parkinglot->occupiedlots = pu;
+ ASTOBJ_UNLOCK(parkinglot);
/* If parking a channel directly, don't quiet yet get parking running on it */
if (peer == chan)
@@ -1591,88 +1604,117 @@
);
}
-/*! \brief Take care of parked calls and unpark them if needed */
-static void *do_parking_thread(void *ignore)
-{
- struct ast_parkinglot *curlot;
- char parkingslot[AST_MAX_EXTENSION];
- fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
-
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
-
- for (;;) {
- struct parkeduser *pu, *pl, *pt = NULL;
- int ms = -1; /* select timeout, uninitialized */
- int max = -1; /* max fd, none there yet */
- fd_set nrfds, nefds; /* args for the next select */
- FD_ZERO(&nrfds);
- FD_ZERO(&nefds);
-
- ast_mutex_lock(&parking_lock);
- pl = NULL;
-
- /* We need to do this for every parking lot */
- AST_LIST_TRAVERSE(&parkinglots, curlot, list) {
- pu = curlot->occupiedlots;
+/*! \brief Run management on parkinglots, called once per parkinglot */
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds)
+{
+ int ms = -1; /* select timeout, uninitialized */
+ int max = -1; /* max fd, none there yet */
+ struct parkeduser *pu, *pl = NULL, *pt = NULL;
+ int res = 0;
+
+ parkinglot_addref(curlot);
+ pu = curlot->occupiedlots;
- while(pu) {
- struct ast_channel *chan = pu->chan; /* shorthand */
- int tms; /* timeout for this item */
- int x; /* fd index in channel */
- struct ast_context *con;
-
- if (pu->notquiteyet) { /* Pretend this one isn't here yet */
- pl = pu;
- pu = pu->next;
+ while(pu) {
+ struct ast_channel *chan = pu->chan; /* shorthand */
+ int tms; /* timeout for this item */
+ int x; /* fd index in channel */
+ struct ast_context *con;
+
+ if (pu->notquiteyet) { /* Pretend this one isn't here yet */
+ pl = pu;
+ pu = pu->next;
+ continue;
+ }
+ tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+ if (tms > pu->parkingtime) {
+ /* Stop music on hold */
+ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+ /* Get chan, exten from derived kludge */
+ if (pu->peername[0]) {
+ char *peername = ast_strdupa(pu->peername);
+ char *cp = strrchr(peername, '-');
+
+ if (cp)
+ *cp = 0;
+ con = ast_context_find(pu->parkinglot->parking_con_dial);
+ if (!con)
+ con = ast_context_create(NULL, pu->parkinglot->parking_con_dial, registrar);
+ if (!con)
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
+ if (con) {
+ char returnexten[AST_MAX_EXTENSION];
+
+ snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
+ ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
+ }
+ if (comebacktoorigin)
+ set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername, 1);
+ else {
+ char parkingslot[AST_MAX_EXTENSION];
+ ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
+ snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+ pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+ set_c_e_p(chan, "parkedcallstimeout", peername, 1);
+ }
+
+ } else {
+ /* They've been waiting too long, send them back to where they came. Theoretically they
+ should have their original extensions and such, but we copy to be on the safe side */
+ set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+
+ }
+ post_manager_event("ParkedCallTimeOut", pu);
+
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
+ /* Start up the PBX, or hang them up */
+ if (ast_pbx_start(chan)) {
+ ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
+ ast_hangup(chan);
+ }
+ /* And take them out of the parking lot */
+ if (pl)
+ pl->next = pu->next;
+ else
+ curlot->occupiedlots = pu->next;
+ pt = pu;
+ pu = pu->next;
+ con = ast_context_find(pt->parkinglot->parking_con);
+ if (con) {
+ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+ ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+ else
+ notify_metermaids(pt->parkingexten, curlot->parking_con);
+ } else
+ ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ free(pt);
+ parkinglot_unref(curlot);
+ } else { /* still within parking time, process descriptors */
+ for (x = 0; x < AST_MAX_FDS; x++) {
+ struct ast_frame *f;
+
+ if ((chan->fds[x] == -1) && (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds)))
continue;
- }
- tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
- if (tms > pu->parkingtime) {
- /* Stop music on hold */
- ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
- /* Get chan, exten from derived kludge */
- if (pu->peername[0]) {
- char *peername = ast_strdupa(pu->peername);
- char *cp = strrchr(peername, '-');
-
- if (cp)
- *cp = 0;
- con = ast_context_find(pu->parkinglot->parking_con_dial);
- if (!con)
- con = ast_context_create(NULL, pu->parkinglot->parking_con_dial, registrar);
- if (!con)
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
- if (con) {
- char returnexten[AST_MAX_EXTENSION];
-
- snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
- ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
- }
- if (comebacktoorigin)
- set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername, 1);
- else {
- ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
- snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
- pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
- set_c_e_p(chan, "parkedcallstimeout", peername, 1);
- }
-
- } else {
- /* They've been waiting too long, send them back to where they came. Theoretically they
- should have their original extensions and such, but we copy to be on the safe side */
- set_c_e_p(chan, pu->context, pu->exten, pu->priority);
-
- }
- post_manager_event("ParkedCallTimeOut", pu);
-
+
+ if (FD_ISSET(chan->fds[x], efds))
+ ast_set_flag(chan, AST_FLAG_EXCEPTION);
+ else
+ ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+ chan->fdno = x;
+
+ /* See if they need servicing */
+ f = ast_read(pu->chan);
+ /* Hangup? */
+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
+ if (f)
+ ast_frfree(f);
+ post_manager_event("ParkedCallGiveUp", pu);
+
+ /* There's a problem, hang them up*/
if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
- /* Start up the PBX, or hang them up */
- if (ast_pbx_start(chan)) {
- ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
- ast_hangup(chan);
- }
+ ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
+ ast_hangup(chan);
/* And take them out of the parking lot */
if (pl)
pl->next = pu->next;
@@ -1680,90 +1722,75 @@
curlot->occupiedlots = pu->next;
pt = pu;
pu = pu->next;
- con = ast_context_find(pt->parkinglot->parking_con);
+ con = ast_context_find(curlot->parking_con);
if (con) {
if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+ ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
else
notify_metermaids(pt->parkingexten, curlot->parking_con);
} else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
free(pt);
- } else { /* still within parking time, process descriptors */
- for (x = 0; x < AST_MAX_FDS; x++) {
- struct ast_frame *f;
-
- if ((chan->fds[x] == -1) && (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(pu->chan->fds[x], &efds)))
- continue;
-
- if (FD_ISSET(chan->fds[x], &efds))
- ast_set_flag(chan, AST_FLAG_EXCEPTION);
- else
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- chan->fdno = x;
-
- /* See if they need servicing */
- f = ast_read(pu->chan);
- /* Hangup? */
- if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
- if (f)
- ast_frfree(f);
- post_manager_event("ParkedCallGiveUp", pu);
-
- /* There's a problem, hang them up*/
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
- ast_hangup(chan);
- /* And take them out of the parking lot */
- if (pl)
- pl->next = pu->next;
- else
- curlot->occupiedlots = pu->next;
- pt = pu;
- pu = pu->next;
- con = ast_context_find(curlot->parking_con);
- if (con) {
- if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else
- notify_metermaids(pt->parkingexten, curlot->parking_con);
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
- free(pt);
- break;
- } else {
- /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
- ast_frfree(f);
- if (pu->moh_trys < 3 && !chan->generatordata) {
- if (option_debug)
- ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting on channel %s.\n", chan->name);
- ast_indicate_data(chan, AST_CONTROL_HOLD,
- S_OR(parkmohclass, NULL),
- !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
- pu->moh_trys++;
- }
- goto std; /* XXX Ick: jumping into an else statement??? XXX */
- }
- } /* End for */
- if (x >= AST_MAX_FDS) {
- std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
- if (chan->fds[x] > -1) {
- FD_SET(chan->fds[x], &nrfds);
- FD_SET(chan->fds[x], &nefds);
- if (chan->fds[x] > max)
- max = chan->fds[x];
- }
- }
- /* Keep track of our shortest wait */
- if (tms < ms || ms < 0)
- ms = tms;
- pl = pu;
- pu = pu->next;
+ parkinglot_unref(curlot);
+ break;
+ } else {
+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
+ ast_frfree(f);
+ if (pu->moh_trys < 3 && !chan->generatordata) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting on channel %s.\n", chan->name);
+ ast_indicate_data(chan, AST_CONTROL_HOLD,
+ S_OR(parkmohclass, NULL),
+ !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
+ pu->moh_trys++;
+ }
+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
+ }
+ } /* End for */
+ if (x >= AST_MAX_FDS) {
+std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
+ if (chan->fds[x] > -1) {
+ FD_SET(chan->fds[x], nrfds);
+ FD_SET(chan->fds[x], nefds);
+ if (chan->fds[x] > max)
+ max = chan->fds[x];
}
}
- } /* end while */
- }
- ast_mutex_unlock(&parking_lock);
+ /* Keep track of our shortest wait */
+ if (tms < ms || ms < 0)
+ ms = tms;
+ pl = pu;
+ pu = pu->next;
+ }
+ }
+ }
+ return res;
+}
+
+/*! \brief Take care of parked calls and unpark them if needed */
+static void *do_parking_thread(void *ignore)
+{
+ fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
+ int ms = -1; /* select timeout, uninitialized */
+ int max = -1; /* max fd, none there yet */
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&efds);
+
+ for (;;) {
+ int res = 0;
+
+ fd_set nrfds, nefds; /* args for the next select */
+ FD_ZERO(&nrfds);
+ FD_ZERO(&nefds);
+
+ /* We need to do this for every parking lot */
+ ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
+
+ ASTOBJ_WRLOCK(iterator);
+ res = manage_parkinglot(iterator, &rfds, &efds, &nrfds, &nefds);
+ ASTOBJ_UNLOCK(iterator);
+ } while (0) );
rfds = nrfds;
efds = nefds;
{
@@ -1784,15 +1811,11 @@
if (ast_strlen_zero(name))
return NULL;
- AST_LIST_TRAVERSE(&parkinglots, parkinglot, list) {
- if (!strcasecmp(parkinglot->name, name)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
- return(parkinglot);
- }
- }
-
- /* We did not find a parking lot */
+ parkinglot = ASTOBJ_CONTAINER_FIND(&parkinglots, name);
+
+ if (parkinglot && option_debug)
+ ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
+
return parkinglot;
}
@@ -1863,6 +1886,8 @@
ast_log(LOG_DEBUG, "Using parking lot: %s\n", parkinglotname);
parkinglot = find_parkinglot(parkinglotname);
}
+ ASTOBJ_WRLOCK(parkinglot);
+ ast_mutex_unlock(&parking_lock);
pu = parkinglot->occupiedlots;
while(pu) {
if (pu->parkingnum == park) {
@@ -1875,7 +1900,6 @@
pl = pu;
pu = pu->next;
}
- ast_mutex_unlock(&parking_lock);
if (pu) {
peer = pu->chan;
con = ast_context_find(pu->parkinglot->parking_con);
@@ -1929,6 +1953,7 @@
if (error) {
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_hangup(peer);
+ ASTOBJ_UNLOCK(parkinglot);
return -1;
}
} else
@@ -1937,6 +1962,7 @@
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
+ ASTOBJ_UNLOCK(parkinglot);
ast_hangup(peer);
return -1;
}
@@ -1960,8 +1986,10 @@
ast_cdr_setdestchan(chan->cdr, peer->name);
/* Simulate the PBX hanging up */
- if (res != AST_PBX_NO_HANGUP_PEER)
+ if (res != AST_PBX_NO_HANGUP_PEER) {
+ ASTOBJ_UNLOCK(parkinglot);
ast_hangup(peer);
+ }
return res;
} else {
/*! \todo XXX Play a message XXX */
@@ -1971,6 +1999,7 @@
ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
res = -1;
}
+ ASTOBJ_UNLOCK(parkinglot);
ast_module_user_remove(u);
@@ -1988,7 +2017,6 @@
int fcount;
struct ast_call_feature *feature;
char format[] = "%-25s %-7s %-7s\n";
- struct ast_parkinglot *parkinglot;
ast_cli(fd, format, "Builtin Feature", "Default", "Current");
ast_cli(fd, format, "---------------", "-------", "-------");
@@ -2019,12 +2047,14 @@
ast_cli(fd, "------------\n");
ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
- AST_LIST_TRAVERSE(&parkinglots, parkinglot, list) {
- ast_cli(fd, "%-24s : %s\n", "Parking lot", parkinglot->name);
- ast_cli(fd," %-24s: %s\n", "Parking context", parkinglot->parking_con);
- ast_cli(fd," %-24s: %d-%d\n", "Parked call extensions", parkinglot->parking_start, parkinglot->parking_stop);
-
- }
+ ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
+ ASTOBJ_RDLOCK(iterator);
+ ast_cli(fd, "%-24s : %s\n", "Parking lot", iterator->name);
+ ast_cli(fd," %-24s: %s\n", "Parking context", iterator->parking_con);
+ ast_cli(fd," %-24s: %d-%d\n", "Parked call extensions", iterator->parking_start, iterator->parking_stop);
+ ASTOBJ_UNLOCK(iterator);
+
+ } while (0) );
ast_cli(fd,"\n");
return RESULT_SUCCESS;
@@ -2038,19 +2068,18 @@
{
struct parkeduser *cur;
int numparked = 0;
- struct ast_parkinglot *parkinglot;
-
ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
, "Context", "Extension", "Pri", "Timeout");
ast_mutex_lock(&parking_lock);
- AST_LIST_TRAVERSE(&parkinglots, parkinglot, list) {
+ ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
int lotparked = 0;
- cur = parkinglot->occupiedlots;
+ ASTOBJ_RDLOCK(iterator);
+ cur = iterator->occupiedlots;
if (cur)
- ast_cli(fd, "*** Parking lot: %s\n", parkinglot->name);
+ ast_cli(fd, "*** Parking lot: %s\n", iterator->name);
while(cur) {
ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
,cur->parkingexten, cur->chan->name, cur->context, cur->exten
@@ -2059,9 +2088,10 @@
lotparked++;
}
if (lotparked)
- ast_cli(fd, " %d parked call%s in parking lot %s\n", lotparked, (lotparked != 1) ? "s" : "", parkinglot->name);
+ ast_cli(fd, " %d parked call%s in parking lot %s\n", lotparked, (lotparked != 1) ? "s" : "", iterator->name);
numparked += lotparked;
- }
+ ASTOBJ_UNLOCK(iterator);
+ } while (0) );
ast_cli(fd, "---\n%d parked call%s in total.\n", numparked, (numparked != 1) ? "s" : "");
ast_mutex_unlock(&parking_lock);
return RESULT_SUCCESS;
@@ -2087,7 +2117,6 @@
struct parkeduser *cur;
const char *id = astman_get_header(m, "ActionID");
char idText[256] = "";
- struct ast_parkinglot *parkinglot;
if (id && !ast_strlen_zero(id))
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
@@ -2097,8 +2126,9 @@
/* Do we need to lock all of parking? */
ast_mutex_lock(&parking_lock);
- AST_LIST_TRAVERSE(&parkinglots, parkinglot, list) {
- cur=parkinglot->occupiedlots;
+ ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
+ ASTOBJ_RDLOCK(iterator);
+ cur=iterator->occupiedlots;
while(cur) {
astman_append(s, "Event: ParkedCall\r\n"
"Exten: %d\r\n"
@@ -2111,7 +2141,7 @@
"%s"
"\r\n",
cur->parkingnum, cur->chan->name, cur->peername,
- parkinglot->name,
+ iterator->name,
(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL),
S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
S_OR(cur->chan->cid.cid_name, ""),
@@ -2119,7 +2149,8 @@
cur = cur->next;
}
- }
+ ASTOBJ_UNLOCK(iterator);
+ } while (0) );
astman_append(s,
"Event: ParkedCallsComplete\r\n"
@@ -2228,6 +2259,22 @@
return res;
}
+/*! \brief Unreference parkinglot object. If no more references,
+ then go ahead and delete it */
+static void parkinglot_unref(struct ast_parkinglot *parkinglot)
+{
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, parkinglot->refcount - 1);
+ ASTOBJ_UNREF(parkinglot, parkinglot_destroy);
+}
+
+static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
+{
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, parkinglot->refcount + 1);
+ return ASTOBJ_REF(parkinglot);
+}
+
/*! \brief Allocate parking lot structure */
static struct ast_parkinglot *create_parkinglot(char *name)
{
@@ -2239,18 +2286,21 @@
newlot = ast_calloc(1, sizeof(*newlot));
if (!newlot)
return NULL;
+
+ ASTOBJ_INIT(newlot);
ast_copy_string(newlot->name, name, sizeof(newlot->name));
return newlot;
}
/*! \brief Destroy a parking lot */
-static void destroy_parkinglot(struct ast_parkinglot *ruin)
+static void parkinglot_destroy(struct ast_parkinglot *ruin)
{
struct ast_context *con;
con = ast_context_find(ruin->parking_con);
if (con)
ast_context_destroy(con, registrar);
+ ASTOBJ_CONTAINER_UNLINK(&parkinglots, ruin); /* Remove from parkinglot list */
free(ruin);
}
@@ -2264,11 +2314,17 @@
int error = 0;
int start = 0, end = 0;
- /* Check if parkinglot with this name already exists */
- /* OEJ */
- parkinglot = create_parkinglot(name);
+ parkinglot = find_parkinglot(name);
+ if (parkinglot)
+ ASTOBJ_UNMARK(parkinglot);
+ else
+ parkinglot = create_parkinglot(name);
+
if (!parkinglot)
return NULL;
+
+ ASTOBJ_WRLOCK(parkinglot);
+
if (option_debug)
ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
@@ -2317,16 +2373,20 @@
if (ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), ast_free, registrar) == -1)
error = 1;
+ ASTOBJ_UNLOCK(parkinglot);
+
if (error) {
ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
- destroy_parkinglot(parkinglot);
+ parkinglot_destroy(parkinglot);
return NULL;
}
if (option_debug)
ast_log(LOG_DEBUG, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
+
/* Move it into the list */
- AST_LIST_INSERT_TAIL(&parkinglots, parkinglot, list);
+ ASTOBJ_CONTAINER_LINK(&parkinglots, parkinglot);
+ parkinglot_unref(parkinglot);
return parkinglot;
@@ -2366,6 +2426,7 @@
} else {
default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
if (default_parkinglot) {
+ ASTOBJ_WRLOCK(default_parkinglot);
default_parkinglot->parking_start = 701;
default_parkinglot->parking_stop = 750;
default_parkinglot->parking_offset = 0;
@@ -2518,6 +2579,9 @@
}
}
+ if (default_parkinglot)
+ ASTOBJ_UNLOCK(default_parkinglot);
+
unmap_features();
for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
if (remap_feature(var->name, var->value))
@@ -2650,27 +2714,22 @@
static int reload(void)
{
+ int res;
/* Release parking lot list */
- if (!AST_LIST_EMPTY(&parkinglots) ) {
- struct ast_parkinglot *park;
- AST_LIST_LOCK(&parkinglots);
- while ((park = AST_LIST_REMOVE_HEAD(&parkinglots, list))) {
- destroy_parkinglot(park);
- }
- AST_LIST_UNLOCK(&parkinglots);
- }
+ ASTOBJ_CONTAINER_MARKALL(&parkinglots);
/* Reload configuration */
- return load_config();
+ res = load_config();
+
+ ASTOBJ_CONTAINER_PRUNE_MARKED(&parkinglots, parkinglot_destroy);
+ return res;
}
static int load_module(void)
{
int res;
- AST_LIST_HEAD_INIT(&parkinglots);
-
if ((res = load_config()))
return res;
ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
More information about the asterisk-commits
mailing list