* to unregister that module's calendar type (usually done in module_unload())
*/
-extern struct ast_config *ast_calendar_config;
-
struct ast_calendar;
struct ast_calendar_event;
*/
void ast_calendar_clear_events(struct ast_calendar *cal);
+/*! \brief Grab and lock pointer to the calendar config (read only)
+ *
+ * \note ast_calendar_config_release must be called when finished with the pointer
+ *
+ * \return the parsed calendar config
+ */
+const struct ast_config *ast_calendar_config_acquire(void);
+
+/*! \brief Release the calendar config
+ */
+void ast_calendar_config_release(void);
+
#endif /* _ASTERISK_CALENDAR_H */
static AST_LIST_HEAD_STATIC(techs, ast_calendar_tech);
AST_LIST_HEAD_NOLOCK(eventlist, evententry); /* define the type */
-struct ast_config *ast_calendar_config;
+static struct ast_config *calendar_config;
+AST_RWLOCK_DEFINE_STATIC(config_lock);
+
+const struct ast_config *ast_calendar_config_acquire(void)
+{
+ ast_rwlock_rdlock(&config_lock);
+
+ if (!calendar_config) {
+ ast_rwlock_unlock(&config_lock);
+ return NULL;
+ }
+
+ return calendar_config;
+}
+
+void ast_calendar_config_release(void)
+{
+ ast_rwlock_unlock(&config_lock);
+}
static struct ast_calendar *unref_calendar(struct ast_calendar *cal)
{
const char *cat = NULL;
const char *val;
- if (!ast_calendar_config) {
+ if (!calendar_config) {
ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type);
return -1;
}
- while ((cat = ast_category_browse(ast_calendar_config, cat))) {
+ ast_rwlock_wrlock(&config_lock);
+ while ((cat = ast_category_browse(calendar_config, cat))) {
if (!strcasecmp(cat, "general")) {
continue;
}
- if (!(val = ast_variable_retrieve(ast_calendar_config, cat, "type")) || strcasecmp(val, tech->type)) {
+ if (!(val = ast_variable_retrieve(calendar_config, cat, "type")) || strcasecmp(val, tech->type)) {
continue;
}
/* A serious error occurred loading calendars from this tech and it should be disabled */
- if (!(cal = build_calendar(ast_calendar_config, cat, tech))) {
+ if (!(cal = build_calendar(calendar_config, cat, tech))) {
ast_calendar_unregister(tech);
+ ast_rwlock_unlock(&config_lock);
return -1;
}
cal = unref_calendar(cal);
}
+ ast_rwlock_unlock(&config_lock);
+
return 0;
}
return 0;
}
- if (ast_calendar_config) {
- ast_config_destroy(ast_calendar_config);
+ ast_rwlock_wrlock(&config_lock);
+ if (calendar_config) {
+ ast_config_destroy(calendar_config);
}
- ast_calendar_config = tmpcfg;
+ calendar_config = tmpcfg;
+ ast_rwlock_unlock(&config_lock);
return 0;
}
static void *caldav_load_calendar(void *void_data)
{
struct caldav_pvt *pvt;
+ const struct ast_config *cfg;
struct ast_variable *v;
struct ast_calendar *cal = void_data;
ast_mutex_t refreshlock;
- if (!(cal && ast_calendar_config)) {
+ if (!(cal && (cfg = ast_calendar_config_acquire()))) {
ast_log(LOG_ERROR, "You must enable calendar support for res_caldav to load\n");
return NULL;
}
} else {
ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
}
+ ast_calendar_config_release();
return NULL;
}
if (!(pvt = ao2_alloc(sizeof(*pvt), caldav_destructor))) {
ast_log(LOG_ERROR, "Could not allocate caldav_pvt structure for calendar: %s\n", cal->name);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
- for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
+ for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
if (!strcasecmp(v->name, "url")) {
ast_string_field_set(pvt, url, v->value);
} else if (!strcasecmp(v->name, "user")) {
}
}
+ ast_calendar_config_release();
+
if (ast_strlen_zero(pvt->url)) {
ast_log(LOG_WARNING, "No URL was specified for CalDAV calendar '%s' - skipping.\n", cal->name);
pvt = unref_caldav(pvt);
static void *exchangecal_load_calendar(void *void_data)
{
struct exchangecal_pvt *pvt;
+ const struct ast_config *cfg;
struct ast_variable *v;
struct ast_calendar *cal = void_data;
ast_mutex_t refreshlock;
- if (!(cal && ast_calendar_config)) {
+ if (!(cal && (cfg = ast_calendar_config_acquire()))) {
ast_log(LOG_ERROR, "You must enable calendar support for res_exchangecal to load\n");
return NULL;
}
} else {
ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
}
+ ast_calendar_config_release();
return NULL;
}
if (!(pvt = ao2_alloc(sizeof(*pvt), exchangecal_destructor))) {
ast_log(LOG_ERROR, "Could not allocate exchangecal_pvt structure for calendar: %s\n", cal->name);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
pvt = unref_exchangecal(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
pvt = unref_exchangecal(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
- for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
+ for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
if (!strcasecmp(v->name, "url")) {
ast_string_field_set(pvt, url, v->value);
} else if (!strcasecmp(v->name, "user")) {
}
}
+ ast_calendar_config_release();
+
if (ast_strlen_zero(pvt->url)) {
ast_log(LOG_WARNING, "No URL was specified for Exchange calendar '%s' - skipping.\n", cal->name);
pvt = unref_exchangecal(pvt);
static void *ical_load_calendar(void *void_data)
{
struct icalendar_pvt *pvt;
+ const struct ast_config *cfg;
struct ast_variable *v;
struct ast_calendar *cal = void_data;
ast_mutex_t refreshlock;
- if (!(cal && ast_calendar_config)) {
+ if (!(cal && (cfg = ast_calendar_config_acquire()))) {
ast_log(LOG_ERROR, "You must enable calendar support for res_icalendar to load\n");
return NULL;
}
} else {
ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
}
+ ast_calendar_config_release();
return NULL;
}
if (!(pvt = ao2_alloc(sizeof(*pvt), icalendar_destructor))) {
ast_log(LOG_ERROR, "Could not allocate icalendar_pvt structure for calendar: %s\n", cal->name);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
pvt = unref_icalendar(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
pvt = unref_icalendar(pvt);
ao2_unlock(cal);
+ ast_calendar_config_release();
return NULL;
}
- for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
+ for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
if (!strcasecmp(v->name, "url")) {
ast_string_field_set(pvt, url, v->value);
} else if (!strcasecmp(v->name, "user")) {
}
}
+ ast_calendar_config_release();
+
if (ast_strlen_zero(pvt->url)) {
ast_log(LOG_WARNING, "No URL was specified for iCalendar '%s' - skipping.\n", cal->name);
pvt = unref_icalendar(pvt);