[asterisk-commits] rmudgett: branch rmudgett/parking r329894 - /team/rmudgett/parking/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 27 19:25:01 CDT 2011


Author: rmudgett
Date: Wed Jul 27 19:24:58 2011
New Revision: 329894

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=329894
Log:
Work in progress.

Modified:
    team/rmudgett/parking/main/features.c

Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=329894&r1=329893&r2=329894
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Wed Jul 27 19:24:58 2011
@@ -466,7 +466,6 @@
 
 	/*! Add parking hints automatically */
 	unsigned int parkaddhints:1;
-/* BUGBUG need to make use is_invalid to prevent use of parking lot. */
 	/*! TRUE if configuration is invalid and the parking lot should not be used. */
 	unsigned int is_invalid:1;
 };
@@ -480,7 +479,6 @@
 
 	/*! That which bears the_mark shall be deleted if parking lot empty! (Used during reloads.) */
 	unsigned int the_mark:1;
-/* BUGBUG need to make use disabled flag to prevent new calls going into the parking lot. */
 	/*! TRUE if the parking lot is disabled. */
 	unsigned int disabled:1;
 
@@ -494,13 +492,16 @@
 /*!
  * \brief Default parking lot.
  * \note Holds a parkinglot reference.
- * \note Will not be NULL while running. (BUGBUG can I guarantee this? The code already expects it.)
+ * \note Will not be NULL while running.
  */
 static struct ast_parkinglot *default_parkinglot;
 
-static char courtesytone[256];                             /*!< Courtesy tone */
+/*! Force a config reload to reload regardless of config file timestamp. */
+static int force_reload_load;
+
 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
 static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
+static char courtesytone[256];                             /*!< Courtesy tone */
 static char xfersound[256];                                /*!< Call transfer sound */
 static char xferfailsound[256];                            /*!< Call transfer failure sound */
 static char pickupsound[256];                              /*!< Pickup sound */
@@ -646,6 +647,7 @@
 static struct ast_parkinglot *find_parkinglot(const char *name);
 static struct ast_parkinglot *create_parkinglot(const char *name);
 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
+static int parkinglot_activate(struct ast_parkinglot *parkinglot);
 
 int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
 {
@@ -951,6 +953,10 @@
 		}
 		if (!ast_strlen_zero(parkinglotname)) {
 			parkinglot = find_parkinglot(parkinglotname);
+		} else {
+			/* Parking lot is not specified.  Fallback to default lot. */
+			ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
+			parkinglot = parkinglot_addref(default_parkinglot);
 		}
 	}
 
@@ -972,8 +978,12 @@
 
 		if (!ast_strlen_zero(parkinglotname_copy)) {
 			parkinglot_copy = find_parkinglot(parkinglotname_copy);
-			if (parkinglot_copy && parkinglot_copy->cfg.is_invalid) {
-				ast_debug(1, "Requested parking lot has invalid config.\n");
+			if (!parkinglot_copy) {
+				ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
+					parkinglotname_copy);
+			} else if (parkinglot_copy->cfg.is_invalid) {
+				ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
+					parkinglotname_copy);
 				parkinglot_unref(parkinglot_copy);
 				parkinglot_copy = NULL;
 			}
@@ -1007,17 +1017,23 @@
 					parkinglot->cfg.parking_stop = dyn_end;
 				}
 			}
-/* BUGBUG need to create the dynamic parking lot context and park extension if they do not already exist! */
+			parkinglot_activate(parkinglot);
 			ao2_link(parkinglots, parkinglot);
 		}
 	}
 
 	if (!parkinglot) {
-		/* We'll just have to use the default parking lot. */
-		parkinglot = parkinglot_addref(default_parkinglot);
-	}
-
-	ast_debug(1, "Parkinglot: %s\n", parkinglot->name);
+		ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", chan->name);
+		return NULL;
+	}
+
+	ast_debug(1, "Parking lot: %s\n", parkinglot->name);
+	if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
+		ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
+			parkinglot->name);
+		parkinglot_unref(parkinglot);
+		return NULL;
+	}
 
 	/* Allocate memory for parking data */
 	if (!(pu = ast_calloc(1, sizeof(*pu)))) {
@@ -1039,8 +1055,7 @@
 		 * arbitrary non-numeric extensions.
 		 */
 		if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
-			ast_log(LOG_WARNING,
-				"PARKINGEXTEN does not indicate a valid parking space: '%s'.\n",
+			ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
 				parkingexten);
 			AST_LIST_UNLOCK(&parkinglot->parkings);
 			parkinglot_unref(parkinglot);
@@ -1055,8 +1070,7 @@
 			 * outside of lot.  (Things like dialplan hints don't exist for
 			 * outside lot space.)
 			 */
-			ast_log(LOG_WARNING,
-				"PARKINGEXTEN requested parking space %d is not in %s (%d-%d).\n",
+			ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
 				parking_space, parkinglot->name, parkinglot->cfg.parking_start,
 				parkinglot->cfg.parking_stop);
 			AST_LIST_UNLOCK(&parkinglot->parkings);
@@ -1068,8 +1082,7 @@
 		/* Check if requested parking space is in use. */
 		AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
 			if (cur->parkingnum == parking_space) {
-				ast_log(LOG_WARNING,
-					"PARKINGEXTEN requested parking space %d is in use in %s\n",
+				ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
 					parking_space, parkinglot->name);
 				AST_LIST_UNLOCK(&parkinglot->parkings);
 				parkinglot_unref(parkinglot);
@@ -4264,6 +4277,8 @@
 					}
 				}
 
+/* BUGBUG need to check collision of recall call and parking pickup scenario. */
+/* BUGBUG need to protect cfg.parking_con_dial context from the config reload routine. */
 				con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->cfg.parking_con_dial, registrar);
 				if (!con) {
 					ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->cfg.parking_con_dial);
@@ -4480,7 +4495,7 @@
 
 	parkinglot = ao2_find(parkinglots, (void *) name, 0);
 	if (parkinglot) {
-		ast_debug(1, "Found Parkinglot: %s\n", parkinglot->name);
+		ast_debug(1, "Found Parking lot: %s\n", parkinglot->name);
 	}
 
 	return parkinglot;
@@ -4857,12 +4872,12 @@
 }
 
 /*! 
- * \brief Add parking hints for all defined parking lots 
- * \param context
- * \param start starting parkinglot number
- * \param stop ending parkinglot number
+ * \brief Add parking hints for all defined parking spaces.
+ * \param context Dialplan context to add the hints.
+ * \param start Starting space in parkinglot.
+ * \param stop Ending space in parkinglot.
  */
-static void park_add_hints(char *context, int start, int stop)
+static void park_add_hints(const char *context, int start, int stop)
 {
 	int numext;
 	char device[AST_MAX_EXTENSION];
@@ -4895,37 +4910,58 @@
 
 /*!
  * \internal
+ * \brief Set parking lot feature flag configuration value.
+ *
+ * \param pl_name Parking lot name for diagnostic messages.
+ * \param param Parameter value to set.
+ * \param var Current configuration variable item.
+ *
+ * \return Nothing
+ */
+static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
+{
+	ast_debug(1, "Setting parking lot %s %s to %s\n", pl_name, var->name, var->value);
+	if (!strcasecmp(var->value, "both")) {
+		*param = AST_FEATURE_FLAG_BYBOTH;
+	} else if (!strcasecmp(var->value, "caller")) {
+		*param = AST_FEATURE_FLAG_BYCALLER;
+	} else if (!strcasecmp(var->value, "callee")) {
+		*param = AST_FEATURE_FLAG_BYCALLEE;
+	}
+}
+
+/*!
+ * \internal
  * \brief Read parking lot configuration.
  *
- * \param parkinglot Parking lot to read user config into.
- * \param cfg_defaults Parking lot default values to start with.
+ * \param pl_name Parking lot name for diagnostic messages.
+ * \param cfg Parking lot config to update that is already initialized with defaults.
  * \param var Config variable list.
  *
  * \retval 0 on success.
- * \retval 1 on error.
+ * \retval -1 on error.
  */
-static int parkinglot_config_read(struct ast_parkinglot *parkinglot, const struct parkinglot_cfg *cfg_defaults, struct ast_variable *var)
+static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
 {
 	int error = 0;
 
-	parkinglot->cfg = *cfg_defaults;
 	while (var) {
 		if (!strcasecmp(var->name, "context")) {
-			ast_copy_string(parkinglot->cfg.parking_con, var->value, sizeof(parkinglot->cfg.parking_con));
+			ast_copy_string(cfg->parking_con, var->value, sizeof(cfg->parking_con));
 		} else if (!strcasecmp(var->name, "parkext")) {
-			ast_copy_string(parkinglot->cfg.parkext, var->value, sizeof(parkinglot->cfg.parkext));
+			ast_copy_string(cfg->parkext, var->value, sizeof(cfg->parkext));
 		} else if (!strcasecmp(var->name, "parkinghints")) {
-			parkinglot->cfg.parkaddhints = ast_true(var->value);
+			cfg->parkaddhints = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "parkedmusicclass")) {
-			ast_copy_string(parkinglot->cfg.mohclass, var->value, sizeof(parkinglot->cfg.mohclass));
+			ast_copy_string(cfg->mohclass, var->value, sizeof(cfg->mohclass));
 		} else if (!strcasecmp(var->name, "parkingtime")) {
 			int parkingtime = 0;
 
 			if ((sscanf(var->value, "%30d", &parkingtime) != 1) || parkingtime < 1) {
 				ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
-				error = 1;
+				error = -1;
 			} else {
-				parkinglot->cfg.parkingtime = parkingtime * 1000;
+				cfg->parkingtime = parkingtime * 1000;
 			}
 		} else if (!strcasecmp(var->name, "parkpos")) {
 			int start = 0;
@@ -4935,152 +4971,161 @@
 				ast_log(LOG_WARNING,
 					"Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
 					var->lineno, var->file);
-				error = 1;
+				error = -1;
 			} else if (end < start || start <= 0 || end <= 0) {
 				ast_log(LOG_WARNING, "Parking range is invalid. Must be a <= b, at line %d of %s\n",
 					var->lineno, var->file);
-				error = 1;
+				error = -1;
 			} else {
-				parkinglot->cfg.parking_start = start;
-				parkinglot->cfg.parking_stop = end;
+				cfg->parking_start = start;
+				cfg->parking_stop = end;
 			}
 		} else if (!strcasecmp(var->name, "parkedcalltransfers")) {
-			ast_debug(1, "Setting parking lot %s %s to %s\n",
-				parkinglot->name, var->name, var->value);
-			if (!strcasecmp(var->value, "both")) {
-				parkinglot->cfg.parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
-			} else if (!strcasecmp(var->value, "caller")) {
-				parkinglot->cfg.parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
-			} else if (!strcasecmp(var->value, "callee")) {
-				parkinglot->cfg.parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
-			}
+			parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcalltransfers, var);
 		} else if (!strcasecmp(var->name, "parkedcallreparking")) {
-			ast_debug(1, "Setting parking lot %s %s to %s\n",
-				parkinglot->name, var->name, var->value);
-			if (!strcasecmp(var->value, "both")) {
-				parkinglot->cfg.parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
-			} else if (!strcasecmp(var->value, "caller")) {
-				parkinglot->cfg.parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
-			} else if (!strcasecmp(var->value, "callee")) {
-				parkinglot->cfg.parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
-			}
+			parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallreparking, var);
 		} else if (!strcasecmp(var->name, "parkedcallhangup")) {
-			ast_debug(1, "Setting parking lot %s %s to %s\n",
-				parkinglot->name, var->name, var->value);
-			if (!strcasecmp(var->value, "both")) {
-				parkinglot->cfg.parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
-			} else if (!strcasecmp(var->value, "caller")) {
-				parkinglot->cfg.parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
-			} else if (!strcasecmp(var->value, "callee")) {
-				parkinglot->cfg.parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
-			}
+			parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
 		} else if (!strcasecmp(var->name, "parkedcallrecording")) {
-			ast_debug(1, "Setting parking lot %s %s to %s\n",
-				parkinglot->name, var->name, var->value);
-			if (!strcasecmp(var->value, "both")) {
-				parkinglot->cfg.parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
-			} else if (!strcasecmp(var->value, "caller")) {
-				parkinglot->cfg.parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
-			} else if (!strcasecmp(var->value, "callee")) {
-				parkinglot->cfg.parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
-			}
+			parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
 		}
 		var = var->next;
 	}
 
 	/* Check for configuration errors */
-	if (ast_strlen_zero(parkinglot->cfg.parking_con)) {
-		ast_log(LOG_WARNING, "Parking lot %s needs context\n", parkinglot->name);
-		error = 1;
-	}
-	if (ast_strlen_zero(parkinglot->cfg.parkext)) {
-		ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", parkinglot->name);
-		error = 1;
-	}
-	if (!parkinglot->cfg.parking_start) {
-		ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", parkinglot->name);
-		error = 1;
+	if (ast_strlen_zero(cfg->parking_con)) {
+		ast_log(LOG_WARNING, "Parking lot %s needs context\n", pl_name);
+		error = -1;
+	}
+	if (ast_strlen_zero(cfg->parkext)) {
+		ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", pl_name);
+		error = -1;
+	}
+	if (!cfg->parking_start) {
+		ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
+		error = -1;
 	}
 	if (error) {
-		parkinglot->cfg.is_invalid = 1;
+		cfg->is_invalid = 1;
 	}
 
 	return error;
 }
 
+/*!
+ * \internal
+ * \brief Activate the given parkinglot.
+ *
+ * \param parkinglot Parking lot to activate.
+ *
+ * \details
+ * Insert into the dialplan the context, parking lot access
+ * extension, and optional dialplan hints.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int parkinglot_activate(struct ast_parkinglot *parkinglot)
+{
+	int disabled = 0;
+	struct ast_context *con;
+
+	/* Create context */
+	con = ast_context_find_or_create(NULL, NULL, parkinglot->cfg.parking_con, registrar);
+	if (!con) {
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n",
+			parkinglot->cfg.parking_con);
+		disabled = 1;
+
+	/* Add a parking extension into the context */
+	} else if (ast_add_extension2(con, 1, parkinglot->cfg.parkext, 1, NULL, NULL,
+		parkcall, ast_strdup(""), ast_free_ptr, registrar)) {
+		ast_log(LOG_ERROR, "Could not create parking lot %s access exten %s@%s\n",
+			parkinglot->name, parkinglot->cfg.parkext, parkinglot->cfg.parking_con);
+		disabled = 1;
+	} else {
+		/* Add parking hints */
+		if (parkinglot->cfg.parkaddhints) {
+			park_add_hints(parkinglot->cfg.parking_con, parkinglot->cfg.parking_start,
+				parkinglot->cfg.parking_stop);
+		}
+
+		/*
+		 * XXX Not sure why we should need to notify the metermaids for
+		 * this exten.  It was originally done for the default parking
+		 * lot entry exten only.
+		 */
+		/* Notify metermaids about parking lot entry exten state. */
+		notify_metermaids(parkinglot->cfg.parkext, parkinglot->cfg.parking_con,
+			AST_DEVICE_INUSE); 
+	}
+
+	parkinglot->disabled = disabled;
+	return disabled ? -1 : 0;
+}
+
 /*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
-static struct ast_parkinglot *build_parkinglot(const char *name, struct ast_variable *var)
+static struct ast_parkinglot *build_parkinglot(const char *pl_name, struct ast_variable *var)
 {
 	struct ast_parkinglot *parkinglot;
-	struct ast_context *con = NULL;
-	struct parkinglot_cfg orig_cfg;
 	const struct parkinglot_cfg *cfg_defaults;
-	int error;
+	struct parkinglot_cfg new_cfg;
+	int cfg_error;
 	int oldparkinglot = 0;
 
-	parkinglot = find_parkinglot(name);
+	parkinglot = find_parkinglot(pl_name);
 	if (parkinglot) {
 		oldparkinglot = 1;
 	} else {
-		parkinglot = create_parkinglot(name);
+		parkinglot = create_parkinglot(pl_name);
 		if (!parkinglot) {
 			return NULL;
 		}
 	}
-	if (!strcmp(name, DEFAULT_PARKINGLOT)) {
+	if (!strcmp(parkinglot->name, DEFAULT_PARKINGLOT)) {
 		cfg_defaults = &parkinglot_cfg_default_default;
 	} else {
 		cfg_defaults = &parkinglot_cfg_default;
 	}
+	new_cfg = *cfg_defaults;
+
+	ast_debug(1, "Building parking lot %s\n", parkinglot->name);
+
+	ao2_lock(parkinglot);
+
+	/* Do some config stuff */
+	cfg_error = parkinglot_config_read(parkinglot->name, &new_cfg, var);
 	if (oldparkinglot) {
-		orig_cfg = parkinglot->cfg;
-	} else {
-		orig_cfg = *cfg_defaults;
-	}
-
-	ao2_lock(parkinglot);
-
-	ast_debug(1, "Building parking lot %s\n", name);
-
-	/* Do some config stuff */
-	error = parkinglot_config_read(parkinglot, cfg_defaults, var);
-	if (oldparkinglot) {
-		if (error) {
-			/* Bad configuration read so restoring original config. */
-			parkinglot->cfg = orig_cfg;
-			error = 0;
+		if (cfg_error) {
+			/* Bad configuration read.  Keep using the original config. */
+			ast_debug(1, "Changes to parking lot %s are discarded.\n", parkinglot->name);
+			cfg_error = 0;
 		} else if (!AST_LIST_EMPTY(&parkinglot->parkings)
-			&& !memcmp(&parkinglot->cfg, &orig_cfg, sizeof(orig_cfg))) {
+			&& memcmp(&new_cfg, &parkinglot->cfg, sizeof(parkinglot->cfg))) {
 			/* Try reloading later when parking lot is empty. */
 			ast_log(LOG_WARNING,
-				"Parking lot %s has parked calls.  Parking lot changes ignored.\n",
+				"Parking lot %s has parked calls.  Parking lot changes discarded.\n",
 				parkinglot->name);
-			parkinglot->cfg = orig_cfg;
-		}
+			force_reload_load = 1;
+		} else {
+			/* Accept the new config */
+			parkinglot->cfg = new_cfg;
+		}
+	} else {
+		/* Load the initial parking lot config. */
+		parkinglot->cfg = new_cfg;
 	}
 	parkinglot->the_mark = 0;
 
-	/* Create context */
-	if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->cfg.parking_con, registrar))) {
-		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->cfg.parking_con);
-		error = 1;
-	}
-
-	/* Add a parking extension into the context */
-	if (!error && !oldparkinglot) {
-		if (ast_add_extension2(con, 1, parkinglot->cfg.parkext, 1, NULL, NULL, parkcall, ast_strdup(""), ast_free_ptr, registrar) == -1) {
-			error = 1;
-		}
-	}
-
-	/* Add parking hints */
-	if (parkinglot->cfg.parkaddhints) {
-		park_add_hints(parkinglot->cfg.parking_con, parkinglot->cfg.parking_start, parkinglot->cfg.parking_stop);
-	}
-
-	if (error) {
-		ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", name);
-		parkinglot->disabled = 1;
+	if (cfg_error || parkinglot_activate(parkinglot)) {
+		ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", parkinglot->name);
+		if (oldparkinglot) {
+			/*
+			 * The old parking lot failed to activate most likely because of
+			 * changes.  Allow reloading later to see if that fixes it.
+			 */
+			force_reload_load = 1;
+		}
 		ao2_unlock(parkinglot);
 		parkinglot_unref(parkinglot);
 		return NULL;
@@ -5088,7 +5133,7 @@
 	ao2_unlock(parkinglot);
 
 	ast_debug(1, "Parking lot %s now open for business. (parkpos %d-%d)\n",
-		name, parkinglot->cfg.parking_start, parkinglot->cfg.parking_stop);
+		parkinglot->name, parkinglot->cfg.parking_start, parkinglot->cfg.parking_stop);
 
 	/* Move it into the list, if it wasn't already there */
 	if (!oldparkinglot) {
@@ -5115,20 +5160,6 @@
 		"applicationmap"
 	};
 
-#if 0	//BUGBUG
-/* BUGBUG this defeats the mark and sweep of a reload. (Done for ASTERISK-17397 because the dialplan contexts were not cleaned up.) */
-	/* Clear the existing parkinglots in the parkinglots container. */
-	{
-		struct ast_parkinglot *p;
-		struct ao2_iterator iter = ao2_iterator_init(parkinglots, 0);
-		while ((p = ao2_iterator_next(&iter))) {
-			ao2_unlink(parkinglots, p);
-			ao2_ref(p,-1);
-		}
-		ao2_iterator_destroy(&iter);
-	}
-#endif
-	
 	/* Reset to defaults */
 	strcpy(pickup_ext, "*8");
 	courtesytone[0] = '\0';
@@ -5372,20 +5403,6 @@
 
 	AST_RWLIST_UNLOCK(&feature_groups);
 
-#if 0	//BUGBUG should no longer need this code after redesign.
-	if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->cfg.parking_con, registrar))) {
-		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->cfg.parking_con);
-		return -1;
-	}
-	res = ast_add_extension2(con, 1, default_parkinglot->cfg.parkext, 1, NULL, NULL, parkcall, ast_strdup(""), ast_free_ptr, registrar);
-	if (default_parkinglot->cfg.parkaddhints)
-		park_add_hints(default_parkinglot->cfg.parking_con, default_parkinglot->cfg.parking_start, default_parkinglot->cfg.parking_stop);
-	if (!res)
-#endif
-
-/* BUGBUG why is this code needed?  If it is needed then the other parkinglot->cfg.parkext need to be notified as inuse. */
-	notify_metermaids(default_parkinglot->cfg.parkext, default_parkinglot->cfg.parking_con, AST_DEVICE_INUSE); 
-
 	return 0;
 }
 
@@ -5409,6 +5426,8 @@
 		ast_log(LOG_WARNING,
 			"Parking lot %s has parked calls.  Could not remove.\n",
 			parkinglot->name);
+		parkinglot->disabled = 1;
+		force_reload_load = 1;
 	}
 
 	return 0;
@@ -5417,20 +5436,24 @@
 static int load_config(int reload)
 {
 #ifdef BUGBUG
-	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+	struct ast_flags config_flags = {
+		reload && !force_reload_load ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 #else
 	struct ast_flags config_flags = { 0 };
 #endif
 	struct ast_config *cfg;
 
+	/* We are reloading now and have already determined if we will force the reload. */
+	force_reload_load = 0;
+
 	if (!default_parkinglot) {
-		/* Must create the default parking lot */
+		/* Must create the default default parking lot */
 		default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
 		if (!default_parkinglot) {
-			ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
+			ast_log(LOG_ERROR, "Configuration of default default parking lot failed.\n");
 			return -1;
 		}
-		ast_debug(1, "Configuration of default default parkinglot done.\n");
+		ast_debug(1, "Configuration of default default parking lot done.\n");
 		parkinglot_addref(default_parkinglot);
 	}
 
@@ -5449,11 +5472,11 @@
 /* BUGBUG build old contexts and extens usage list. */
 
 	ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_markall_cb, NULL,
-		"callback to mark all parkinglots");
+		"callback to mark all parking lots");
 	process_config(cfg);
 	ast_config_destroy(cfg);
 	ao2_t_callback(parkinglots, OBJ_NODATA | OBJ_UNLINK, parkinglot_is_marked_cb, NULL,
-		"callback to remove marked parkinglots");
+		"callback to remove marked parking lots");
 
 /* BUGBUG build new contexts and extens usage list. */
 /* BUGBUG Remove dead contexts and extens */
@@ -5554,6 +5577,8 @@
 
 int ast_features_reload(void)
 {
+/* BUGBUG Should always destroy cfg.parking_con_dial context and protect it from the manage_parkinglot() thread. */
+/* Destroying it removes buildup of recalled extensions in the context. */
 	return load_config(1);
 }
 




More information about the asterisk-commits mailing list