[asterisk-commits] russell: branch russell/indications r174539 - in /team/russell/indications: i...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Feb 10 07:54:46 CST 2009
Author: russell
Date: Tue Feb 10 07:54:46 2009
New Revision: 174539
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=174539
Log:
knock off a couple todo items
Modified:
team/russell/indications/include/asterisk/indications.h
team/russell/indications/main/indications.c
Modified: team/russell/indications/include/asterisk/indications.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/include/asterisk/indications.h?view=diff&rev=174539&r1=174538&r2=174539
==============================================================================
--- team/russell/indications/include/asterisk/indications.h (original)
+++ team/russell/indications/include/asterisk/indications.h Tue Feb 10 07:54:46 2009
@@ -41,6 +41,12 @@
const char *name; /*!< Identifying name */
const char *data; /*!< Actual zone description */
AST_LIST_ENTRY(ast_tone_zone_sound) entry;
+ union {
+ uint32_t __padding;
+ struct {
+ unsigned int killme:1;
+ };
+ };
};
struct ast_tone_zone {
@@ -49,6 +55,12 @@
int nrringcadence; /*!< # registered ringcadence elements */
int *ringcadence; /*!< Ring cadence */
AST_LIST_HEAD_NOLOCK(, ast_tone_zone_sound) tones; /*!< The known tones for this zone */
+ union {
+ uint32_t __padding;
+ struct {
+ unsigned int killme:1;
+ };
+ };
};
/*!
Modified: team/russell/indications/main/indications.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/main/indications.c?view=diff&rev=174539&r1=174538&r2=174539
==============================================================================
--- team/russell/indications/main/indications.c (original)
+++ team/russell/indications/main/indications.c Tue Feb 10 07:54:46 2009
@@ -26,8 +26,6 @@
/*
* XXX TODO
* - API documentation
- * - finish re-write of config parsing
- * - re-use an object for a country if it already exists when loading config
* - fix users of the API to account for ref count (only chan_unistim left)
* - Integrate work to pull out tone parsing into an API
* - change the code such that tone definitions are only parsed once
@@ -853,21 +851,30 @@
static int handle_stopplaytones(struct ast_channel *chan, void *data)
{
ast_playtones_stop(chan);
+
return 0;
}
static int is_valid_tone_zone(struct ast_tone_zone *zone)
{
- return (!ast_strlen_zero(zone->description) && !AST_LIST_EMPTY(&zone->tones));
-}
-
+ int res;
+
+ ast_tone_zone_lock(zone);
+ res = (!ast_strlen_zero(zone->description) && !AST_LIST_EMPTY(&zone->tones));
+ ast_tone_zone_unlock(zone);
+
+ return res;
+}
+
+/*!
+ * \note This is called with the tone zone locked.
+ */
static void store_tone_zone_ring_cadence(struct ast_tone_zone *zone, const char *val)
{
- char *ring, *c;
char buf[1024];
+ char *ring, *c = buf;
ast_copy_string(buf, val, sizeof(buf));
- c = buf;
while ((ring = strsep(&c, ","))) {
int *tmp, val;
@@ -889,25 +896,23 @@
}
}
+/*!
+ * \note This is called with the tone zone locked.
+ */
static void store_tone_zone_sound(struct ast_tone_zone *zone, const char *name,
const char *val)
{
struct ast_tone_zone_sound *ts;
- int ignore = 0;
-
- /* add tone to country */
- AST_LIST_TRAVERSE(&zone->tones, ts, entry) {
+
+ /* Remove the tone if it already existed, we'll redo it with new values */
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, ts, entry) {
if (!strcasecmp(name, ts->name)) {
- /* already there */
- ast_log(LOG_NOTICE, "Duplicate entry '%s' skipped.\n", name);
- ignore = 1;
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_tone_zone_sound_destroy(ts);
break;
}
}
-
- if (ignore) {
- return;
- }
+ AST_LIST_TRAVERSE_SAFE_END
/* not there, add it to the back */
if (!(ts = ast_calloc(1, sizeof(*ts)))) {
@@ -941,31 +946,105 @@
CV_END;
}
+static void reset_tone_zone(struct ast_tone_zone *zone)
+{
+ ast_tone_zone_lock(zone);
+
+ zone->killme = 0;
+
+ if (zone->nrringcadence) {
+ zone->nrringcadence = 0;
+ ast_free(zone->ringcadence);
+ zone->ringcadence = NULL;
+ }
+
+ ast_tone_zone_unlock(zone);
+}
+
static int parse_tone_zone(struct ast_config *cfg, const char *country)
{
struct ast_variable *v;
struct ast_tone_zone *zone;
-
- if (!(zone = ast_tone_zone_alloc())) {
+ struct ast_tone_zone tmp_zone = {
+ .nrringcadence = 0,
+ };
+ int allocd = 0;
+
+ ast_copy_string(tmp_zone.country, country, sizeof(tmp_zone.country));
+
+ if ((zone = ao2_find(ast_tone_zones, &tmp_zone, OBJ_POINTER))) {
+ reset_tone_zone(zone);
+ } else if ((zone = ast_tone_zone_alloc())) {
+ allocd = 1;
+ ast_copy_string(zone->country, country, sizeof(zone->country));
+ } else {
return -1;
}
- ast_copy_string(zone->country, country, sizeof(zone->country));
-
+ ast_tone_zone_lock(zone);
for (v = ast_variable_browse(cfg, country); v; v = v->next) {
store_config_tone_zone(zone, v->name, v->value);
}
-
- if (is_valid_tone_zone(zone)) {
- if (ast_register_indication_country(zone)) {
- ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
- zone = ast_tone_zone_unref(zone);
- }
- } else {
- zone = ast_tone_zone_unref(zone);
- }
+ ast_tone_zone_unlock(zone);
+
+ if (allocd) {
+ if (!is_valid_tone_zone(zone)) {
+ ast_log(LOG_WARNING, "Indication country '%s' is invalid\n", country);
+ } else if (ast_register_indication_country(zone)) {
+ ast_log(LOG_WARNING, "Unable to register indication country '%s'.\n",
+ country);
+ }
+ }
+
+ zone = ast_tone_zone_unref(zone);
return 0;
+}
+
+/*!
+ * Mark the zone and its tones before parsing configuration. We will use this
+ * to know what to remove after configuration is parsed.
+ */
+static int tone_zone_mark(void *obj, void *arg, int flags)
+{
+ struct ast_tone_zone *zone = obj;
+ struct ast_tone_zone_sound *s;
+
+ ast_tone_zone_lock(zone);
+
+ zone->killme = 1;
+
+ AST_LIST_TRAVERSE(&zone->tones, s, entry) {
+ s->killme = 1;
+ }
+
+ ast_tone_zone_unlock(zone);
+
+ return 0;
+}
+
+/*!
+ * Prune tones no longer in the configuration, and have the tone zone unlinked
+ * if it is no longer in the configuration at all.
+ */
+static int prune_tone_zone(void *obj, void *arg, int flags)
+{
+ struct ast_tone_zone *zone = obj;
+ struct ast_tone_zone_sound *s;
+
+ ast_tone_zone_lock(zone);
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, s, entry) {
+ if (s->killme) {
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_tone_zone_sound_destroy(s);
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+
+ ast_tone_zone_unlock(zone);
+
+ return zone->killme ? CMP_MATCH : 0;
}
/*! \brief load indications module */
@@ -975,6 +1054,7 @@
const char *cxt = NULL;
const char *country = NULL;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+ int res = -1;
cfg = ast_config_load2(config, NULL, config_flags);
@@ -984,10 +1064,10 @@
return 0;
}
- if (reload) {
- /* Clear indications */
- ast_unregister_indication_country(NULL);
- }
+ /* Lock the container to prevent multiple simultaneous reloads */
+ ao2_lock(ast_tone_zones);
+
+ ao2_callback(ast_tone_zones, OBJ_NODATA, tone_zone_mark, NULL);
/* Use existing config to populate the Indication table */
while ((cxt = ast_category_browse(cfg, cxt))) {
@@ -997,10 +1077,12 @@
}
if (parse_tone_zone(cfg, cxt)) {
- ast_config_destroy(cfg);
- return -1;
- }
- }
+ goto return_cleanup;
+ }
+ }
+
+ ao2_callback(ast_tone_zones, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
+ prune_tone_zone, NULL);
/* determine which country is the default */
country = ast_variable_retrieve(cfg, "general", "country");
@@ -1008,9 +1090,13 @@
ast_log(LOG_WARNING, "Unable to set the default country (for indication tones)\n");
}
+ res = 0;
+
+return_cleanup:
+ ao2_unlock(ast_tone_zones);
ast_config_destroy(cfg);
- return 0;
+ return res;
}
/*! \brief CLI entries for commands provided by this module */
More information about the asterisk-commits
mailing list