[asterisk-commits] file: branch file/sorcery r380041 - in /team/file/sorcery: include/asterisk/ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 24 08:24:39 CST 2013


Author: file
Date: Thu Jan 24 08:24:34 2013
New Revision: 380041

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380041
Log:
Incorporate review feedback.

Modified:
    team/file/sorcery/include/asterisk/sorcery.h
    team/file/sorcery/main/sorcery.c
    team/file/sorcery/res/res_sorcery_config.c
    team/file/sorcery/res/res_sorcery_memory.c
    team/file/sorcery/tests/test_sorcery.c

Modified: team/file/sorcery/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/file/sorcery/include/asterisk/sorcery.h?view=diff&rev=380041&r1=380040&r2=380041
==============================================================================
--- team/file/sorcery/include/asterisk/sorcery.h (original)
+++ team/file/sorcery/include/asterisk/sorcery.h Thu Jan 24 08:24:34 2013
@@ -33,55 +33,60 @@
  * Usage of sorcery is accomplished by first opening a sorcery structure. This structure holds
  * all information about the object types, object fields, and object mappings. All API functions
  * require the sorcery structure to operate. When sorcery is no longer needed the structure can
- * be unreferenced using ast_sorcery_unref.
+ * be unreferenced using \ref ast_sorcery_unref
  *
  * Once opened the sorcery structure must have object mappings applied to it. This maps the
  * object types to their respective wizards (object storage modules). If the developer would like
  * to allow the user to configure this using the sorcery.conf configuration file the
- * ast_sorcery_apply_config API call can be used to read in the configuration file and apply the
+ * \ref ast_sorcery_apply_config API call can be used to read in the configuration file and apply the
  * mappings. If the storage of the object types are such that a default wizard can be used this can
- * be applied using the ast_sorcery_apply_default API call. Note that the default mappings will not
+ * be applied using the \ref ast_sorcery_apply_default API call. Note that the default mappings will not
  * override configured mappings. They are only used in the case where no configured mapping exists.
  *
- * Configuring object mappings implicitly create a basic version of an object type. The object type
- * must be fully registered, however, using the ast_sorcery_object_type_register API call before any
+ * Configuring object mappings implicitly creates a basic version of an object type. The object type
+ * must be fully registered, however, using the \ref ast_sorcery_object_type_register API call before any
  * objects of the type can be allocated, created, or retrieved.
  *
  * Once the object type itself has been fully registered the individual fields within the object must
- * be registered using the ast_sorcery_object_field_register API call. Note that not all fields *need*
+ * be registered using the \ref ast_sorcery_object_field_register API call. Note that not all fields *need*
  * be registered. Only fields that should be accessible using the sorcery API have to be registered.
  *
  * \par Creating Objects
  *
  * Before an object can be created within the sorcery API it must first be allocated using the
- * ast_sorcery_alloc API call. This allocates a new instance of the object, sets sorcery specific
+ * \ref ast_sorcery_alloc API call. This allocates a new instance of the object, sets sorcery specific
  * details, and applies default values to the object. A unique identifier can optionally be specified
  * when allocating an object. If it is not provided one will be automatically generated. Allocating
  * an object does not create it within any object storage mechanisms that are configured for the
- * object type. Creation must explicitly be done using the ast_sorcery_create API call. This API call
+ * object type. Creation must explicitly be done using the \ref ast_sorcery_create API call. This API call
  * passes the object to each configured object storage mechanism for the object type until one
  * successfully persists the object.
  *
  * \par Retrieving Objects
  *
- * Object retrieval is accomplished using the ast_sorcery_retrieve API call. Objects themselves can be
- * retrieved using either the unique identifier OR by specifying specific fields within the object and the
- * respective values to look for. If the criteria given could result in multiple objects being returned the
- * AST_RETRIEVE_FLAG_MULTIPLE flag can be enabled which returns all objects in an astobj2 container. Note
- * that the returned object(s) should *NOT* be modified as they may be shared.
+ * To retrieve a single object using its unique identifier the \ref ast_sorcery_retrieve_by_id API call
+ * can be used.
+ *
+ * To retrieve potentially multiple objects using specific fields the \ref ast_sorcery_retrieve_by_fields
+ * API call can be used. The behavior of this API call is controlled using different flags. If the
+ * AST_RETRIEVE_FLAG_MULTIPLE flag is used a container will be returned which contains all matching objects.
+ * To retrieve all objects the AST_RETRIEVE_FLAG_ALL flag can be specified. Note that when specifying this flag
+ * you do not need to pass any fields.
+ *
+ * Both API calls return shared objects. Modification of the object can not occur until it has been copied.
  *
  * \par Updating Objects
  *
  * As retrieved objects may be shared the first step to updating the object with new details is creating a
- * copy using the ast_sorcery_copy API call. This will return a new object which is specific to the caller.
+ * copy using the \ref ast_sorcery_copy API call. This will return a new object which is specific to the caller.
  * Any field within the object may be modified as needed. Once changes are done the changes can be committed
- * using the ast_sorcery_update API call. Note that as the copied object is specific to the caller it must
+ * using the \ref ast_sorcery_update API call. Note that as the copied object is specific to the caller it must
  * be unreferenced after use.
  *
  * \par Deleting Objects
  *
- * To delete an object simply call the ast_sorcery_delete API call with an object retrieved using the
- * ast_sorcery_retrieve API call or a copy returned from ast_sorcery_copy.
+ * To delete an object simply call the \ref ast_sorcery_delete API call with an object retrieved using the
+ * ast_sorcery_retrieve_by_* API calls or a copy returned from \ref ast_sorcery_copy.
  */
 
 #ifndef _ASTERISK_SORCERY_H
@@ -111,20 +116,6 @@
         AST_RETRIEVE_FLAG_ALL = (1 << 1),
 };
 
-/*!
- * \brief Retrieval parameters
- */
-enum ast_sorcery_retrieve_params {
-	/*! \brief Object identifier */
-	AST_RETRIEVE_PARAM_ID = 0,
-
-	/*! \brief Object field */
-	AST_RETRIEVE_PARAM_FIELD,
-
-	/*! \brief End of retrieval parameters */
-	AST_RETRIEVE_PARAM_END,
-};
-
 /*! \brief Forward declaration for the sorcery main structure */
 struct ast_sorcery;
 
@@ -133,13 +124,12 @@
  *
  * \param obj Object to get value from
  * \param args Where the field is
- * \param buf Buffer to place string into
- * \param len Size of the buffer
- *
- * \retval 0 success
- * \retval -1 failure
- */
-typedef int (*sorcery_field_handler)(const void *obj, const intptr_t *args, char *buf, size_t len);
+ * \param buf Pointer to the buffer that the handler has created which contains the field value
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+typedef int (*sorcery_field_handler)(const void *obj, const intptr_t *args, char **buf);
 
 /*!
  * \brief A callback function for performing a transformation on an object set
@@ -402,13 +392,14 @@
  *
  * \param original Original object set
  * \param modified Modified object set
- *
- * \retval non-NULL if any changes are present
- * \retval NULL if no changes exist
+ * \param changes Pointer to hold any changes between the object sets
+ *
+ * \retval 0 success
+ * \retval -1 failure
  *
  * \note The returned ast_variable list must be destroyed using ast_variables_destroy
  */
-struct ast_variable *ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified);
+int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes);
 
 /*!
  * \brief Allocate an object
@@ -439,15 +430,16 @@
  * \param sorcery Pointer to a sorcery structure
  * \param original Original object
  * \param modified Modified object
- *
- * \retval non-NULL differences exist
- * \retval NULL no differences exist
+ * \param changes Pointer which will be populated with changes if any exist
+ *
+ * \retval 0 success
+ * \retval -1 failure
  *
  * \note The returned ast_variable list must be destroyed using ast_variables_destroy
  *
  * \note While the objects must be of the same type they do not have to be the same object
  */
- struct ast_variable *ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified);
+int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes);
 
 /*!
  * \brief Create and potentially persist an object using an available wizard
@@ -461,22 +453,35 @@
 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object);
 
 /*!
- * \brief Retrieve an object or multiple objects
+ * \brief Retrieve an object using its unique identifier
+ *
+ * \param sorcery Pointer to a sorcery structure
+ * \param type Type of object to retrieve
+ * \param id Unique object identifier
+ *
+ * \retval non-NULL if found
+ * \retval NULL if not found
+ */
+void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id);
+
+/*!
+ * \brief Retrieve an object or multiple objects using specific fields
  *
  * \param sorcery Pointer to a sorcery structure
  * \param type Type of object to retrieve
  * \param flags Flags to control behavior
- * \param params Parameters to dictate search
+ * \param fields Optional jbject fields and values to match against
  *
  * \retval non-NULL if found
  * \retval NULL if not found
  *
- * \note The parameters must end with AST_RETRIEVE_PARAM_END
- *
  * \note If the AST_RETRIEVE_FLAG_MULTIPLE flag is specified the returned value will be an
  *       ao2_container that must be unreferenced after use.
- */
-void *ast_sorcery_retrieve(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, ...);
+ *
+ * \note If the AST_RETRIEVE_FLAG_ALL flag is used you may omit fields to retrieve all objects
+ *       of the given type.
+ */
+void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields);
 
 /*!
  * \brief Update an object

Modified: team/file/sorcery/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorcery/main/sorcery.c?view=diff&rev=380041&r1=380040&r2=380041
==============================================================================
--- team/file/sorcery/main/sorcery.c (original)
+++ team/file/sorcery/main/sorcery.c Thu Jan 24 08:24:34 2013
@@ -39,10 +39,10 @@
 #include "asterisk/netsock2.h"
 #include "asterisk/module.h"
 
-/*! \brief Number of buckets for wizards */
+/*! \brief Number of buckets for wizards (should be prime for performance reasons) */
 #define WIZARD_BUCKETS 7
 
-/*! \brief Number of buckets for types */
+/*! \brief Number of buckets for types (should be prime for performance reasons) */
 #define TYPE_BUCKETS 53
 
 /*! \brief Maximum length of an object field name */
@@ -84,7 +84,7 @@
 	sorcery_field_handler handler;
 
 	/*! \brief Position of the field */
-	intptr_t args[0];
+	intptr_t args[];
 };
 
 /*! \brief Structure for a wizard instance which operates on objects */
@@ -120,57 +120,66 @@
 /*! \brief Registered sorcery wizards */
 struct ao2_container *wizards;
 
-static int int_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	int *field = (int *)(obj + args[0]);
-	snprintf(buf, len, "%d", *field);
-	return 0;
-}
-
-static int uint_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	char value[256];
+
+	snprintf(value, sizeof(value), "%d", *field);
+	*buf = ast_strdup(value);
+	return 0;
+}
+
+static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	unsigned int *field = (unsigned int *)(obj + args[0]);
-	snprintf(buf, len, "%u", *field);
-	return 0;
-}
-
-static int double_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	char value[256];
+
+	snprintf(value, sizeof(value), "%u", *field);
+	*buf = ast_strdup(value);
+	return 0;
+}
+
+static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	double *field = (double *)(obj + args[0]);
-	snprintf(buf, len, "%f", *field);
-	return 0;
-}
-
-static int stringfield_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	char value[256];
+
+	snprintf(value, sizeof(value), "%f", *field);
+	*buf = ast_strdup(value);
+	return 0;
+}
+
+static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	ast_string_field *field = (const char **)(obj + args[0]);
-	ast_copy_string(buf, *field, len);
-	return 0;
-}
-
-static int bool_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	*buf = ast_strdup(*field);
+	return 0;
+}
+
+static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	unsigned int *field = (unsigned int *)(obj + args[0]);
-	snprintf(buf, len, *field ? "true" : "false");
-	return 0;
-}
-
-static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	*buf = ast_strdup(*field ? "true" : "false");
+	return 0;
+}
+
+static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
-	snprintf(buf, len, "%s", ast_sockaddr_stringify(field));
-	return 0;
-}
-
-static int noop_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
-{
-	return 0;
-}
-
-static int chararray_handler_fn(const void *obj, const intptr_t *args, char *buf, size_t len)
+	*buf = ast_strdup(ast_sockaddr_stringify(field));
+	return 0;
+}
+
+static int noop_handler_fn(const void *obj, const intptr_t *args, char **buf)
+{
+	return 0;
+}
+
+static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
 {
 	char *field = (char *)(obj + args[0]);
-	ast_copy_string(buf, field, len);
+	*buf = ast_strdup(field);
 	return 0;
 }
 
@@ -213,6 +222,8 @@
 
 int ast_sorcery_init(void)
 {
+	ast_assert(wizards == NULL);
+
 	if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
 		return -1;
 	}
@@ -534,6 +545,8 @@
 	} else if (argc == 3) {
 		__aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, argc,
 				      va_arg(args, size_t), va_arg(args, size_t), va_arg(args, size_t));
+	} else {
+		ast_assert(0); /* The hack... she does us no good for this */
 	}
 	va_end(args);
 
@@ -607,7 +620,7 @@
 	i = ao2_iterator_init(object_type->fields, 0);
 
 	for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
-		char buf[512];
+		RAII_VAR(char *, buf, NULL, ast_free);
 		struct ast_variable *tmp;
 
 		/* Any fields with no handler just get skipped */
@@ -615,8 +628,8 @@
 			continue;
 		}
 
-		if ((res = object_field->handler(object, object_field->args, buf, sizeof(buf))) ||
-		    !(tmp = ast_variable_new(object_field->name, buf, ""))) {
+		if ((res = object_field->handler(object, object_field->args, &buf)) ||
+		    !(tmp = ast_variable_new(object_field->name, S_OR(buf, ""), ""))) {
 			res = -1;
 			ao2_ref(object_field, -1);
 			break;
@@ -682,15 +695,16 @@
 	return NULL;
 }
 
-struct ast_variable *ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified)
+int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
 {
 	const struct ast_variable *field;
-	struct ast_variable *changes = NULL;
 	int res = 0;
+
+	*changes = NULL;
 
 	/* Unless the ast_variable list changes when examined... it can't differ from itself */
 	if (original == modified) {
-		return NULL;
+		return 0;
 	}
 
 	for (field = modified; field; field = field->next) {
@@ -704,18 +718,18 @@
 				break;
 			}
 
-			tmp->next = changes;
-			changes = tmp;
+			tmp->next = *changes;
+			*changes = tmp;
 		}
 	}
 
 	/* If an error occurred do not return a partial changeset */
 	if (res) {
-		ast_variables_destroy(changes);
-		changes = NULL;
-	}
-
-	return changes;
+		ast_variables_destroy(*changes);
+		*changes = NULL;
+	}
+
+	return res;
 }
 
 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
@@ -768,19 +782,21 @@
 	return copy;
 }
 
-struct ast_variable *ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified)
+int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
 {
 	RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
 	RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
 
+	*changes = NULL;
+
 	if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
-		return NULL;
+		return -1;
 	}
 
 	objectset1 = ast_sorcery_objectset_create(sorcery, original);
 	objectset2 = ast_sorcery_objectset_create(sorcery, modified);
 
-	return ast_sorcery_changeset_create(objectset1, objectset2);
+	return ast_sorcery_changeset_create(objectset1, objectset2, changes);
 }
 
 /*! \brief Internal function used to create an object in caching wizards */
@@ -797,47 +813,48 @@
 	return 0;
 }
 
-void *ast_sorcery_retrieve(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, ...)
+void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
 {
 	RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
-	RAII_VAR(struct ast_variable *, fields, NULL, ast_variables_destroy);
-	va_list args;
-	enum ast_sorcery_retrieve_params param;
-	const char *id = NULL;
 	void *object = NULL;
 	struct ao2_iterator i;
 	struct ast_sorcery_object_wizard *wizard;
 	unsigned int cached = 0;
 
+	if (!object_type || ast_strlen_zero(id)) {
+		return NULL;
+	}
+
+	i = ao2_iterator_init(object_type->wizards, 0);
+	for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
+		if (wizard->wizard->retrieve_id &&
+		    !(object = wizard->wizard->retrieve_id(sorcery, wizard->data, object_type->name, id))) {
+			continue;
+		}
+
+		cached = wizard->caching;
+
+		ao2_ref(wizard, -1);
+		break;
+	}
+        ao2_iterator_destroy(&i);
+
+	if (!cached && object) {
+		ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
+	}
+
+	return object;
+}
+
+void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
+{
+	RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+	void *object = NULL;
+	struct ao2_iterator i;
+	struct ast_sorcery_object_wizard *wizard;
+	unsigned int cached = 0;
+
 	if (!object_type) {
-		return NULL;
-	}
-
-	va_start(args, flags);
-	for (param = va_arg(args, enum ast_sorcery_retrieve_params);
-	     param != AST_RETRIEVE_PARAM_END;
-	     param = va_arg(args, enum ast_sorcery_retrieve_params)) {
-		if (param == AST_RETRIEVE_PARAM_ID && !id) {
-			id = va_arg(args, const char *);
-		} else if (param == AST_RETRIEVE_PARAM_FIELD) {
-			const char *name = va_arg(args, const char *), *value = va_arg(args, const char *);
-			struct ast_variable *tmp;
-
-			if (!(tmp = ast_variable_new(name, value, ""))) {
-				return NULL;
-			}
-
-			tmp->next = fields;
-			fields = tmp;
-		} else {
-			/* If they pass an unsupported parameter type this operation *will* fail */
-			return NULL;
-		}
-	}
-	va_end(args);
-
-	/* Uh... if no parameters are there we obviously can't do anything */
-	if (ast_strlen_zero(id) && !fields && (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) || !(flags & AST_RETRIEVE_FLAG_ALL))) {
 		return NULL;
 	}
 
@@ -855,10 +872,6 @@
 			if (wizard->wizard->retrieve_multiple) {
 				wizard->wizard->retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
 			}
-		} else if (!ast_strlen_zero(id)) {
-			if (wizard->wizard->retrieve_id) {
-				object = wizard->wizard->retrieve_id(sorcery, wizard->data, object_type->name, id);
-			}
 		} else if (fields && wizard->wizard->retrieve_fields) {
 			if (wizard->wizard->retrieve_fields) {
 				object = wizard->wizard->retrieve_fields(sorcery, wizard->data, object_type->name, fields);

Modified: team/file/sorcery/res/res_sorcery_config.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorcery/res/res_sorcery_config.c?view=diff&rev=380041&r1=380040&r2=380041
==============================================================================
--- team/file/sorcery/res/res_sorcery_config.c (original)
+++ team/file/sorcery/res/res_sorcery_config.c Thu Jan 24 08:24:34 2013
@@ -127,7 +127,8 @@
 	 */
 	if (params->fields &&
 	    (!(objset = ast_sorcery_objectset_create(params->sorcery, obj)) ||
-	     (diff = ast_sorcery_changeset_create(objset, params->fields)))) {
+	     (ast_sorcery_changeset_create(objset, params->fields, &diff)) ||
+	     diff)) {
 		return 0;
 	}
 
@@ -190,7 +191,7 @@
 {
 	RAII_VAR(struct ast_variable *, diff, NULL, ast_variables_destroy);
 
-	return (!criteria || !(diff = ast_sorcery_changeset_create(objset, criteria))) ? 1 : 0;
+	return (!criteria || (!ast_sorcery_changeset_create(objset, criteria, &diff) && !diff)) ? 1 : 0;
 }
 
 static void sorcery_config_internal_load(void *data, const struct ast_sorcery *sorcery, const char *type, unsigned int reload)
@@ -210,14 +211,12 @@
 	} else if (cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(LOG_ERROR, "Contents of config file '%s' are invalid and cannot be parsed\n", config->filename);
 		return;
-	} else if (cfg == CONFIG_STATUS_FILEMISSING) {
-		ast_log(LOG_ERROR, "Config file '%s' is missing\n", config->filename);
-		return;
 	}
 
 	if (!(objects = ao2_container_alloc(config->buckets, sorcery_config_hash, sorcery_config_cmp))) {
 		ast_log(LOG_ERROR, "Could not create bucket for new objects from '%s', keeping existing objects\n",
 			config->filename);
+		ast_config_destroy(cfg);
 		return;
 	}
 

Modified: team/file/sorcery/res/res_sorcery_memory.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorcery/res/res_sorcery_memory.c?view=diff&rev=380041&r1=380040&r2=380041
==============================================================================
--- team/file/sorcery/res/res_sorcery_memory.c (original)
+++ team/file/sorcery/res/res_sorcery_memory.c Thu Jan 24 08:24:34 2013
@@ -106,7 +106,8 @@
 	 */
 	if (params->fields &&
 	    (!(objset = ast_sorcery_objectset_create(params->sorcery, obj)) ||
-	     (diff = ast_sorcery_changeset_create(objset, params->fields)))) {
+	     (ast_sorcery_changeset_create(objset, params->fields, &diff)) ||
+	     diff)) {
 		return 0;
 	}
 

Modified: team/file/sorcery/tests/test_sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorcery/tests/test_sorcery.c?view=diff&rev=380041&r1=380040&r2=380041
==============================================================================
--- team/file/sorcery/tests/test_sorcery.c (original)
+++ team/file/sorcery/tests/test_sorcery.c Thu Jan 24 08:24:34 2013
@@ -577,7 +577,9 @@
        obj2->bob = 99;
        obj2->joe = 42;
 
-       if (!(changes = ast_sorcery_diff(sorcery, obj1, obj2))) {
+       if (ast_sorcery_diff(sorcery, obj1, obj2, &changes)) {
+	       ast_test_status_update(test, "Failed to diff obj1 and obj2\n");
+       } else if (!changes) {
 	       ast_test_status_update(test, "Failed to produce a diff of two objects, despite there being differences\n");
 	       return AST_TEST_FAIL;
        }
@@ -759,7 +761,7 @@
 		ast_test_status_update(test, "Failed to open sorcery structure\n");
 		return AST_TEST_FAIL;
 	}
-	
+
 	if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
 		ast_test_status_update(test, "Failed to set a known wizard as a default\n");
 		return AST_TEST_FAIL;
@@ -850,7 +852,10 @@
 	tmp->next = modified;
 	modified = tmp;
 
-	if (!(changes = ast_sorcery_changeset_create(original, modified))) {
+	if (ast_sorcery_changeset_create(original, modified, &changes)) {
+		ast_test_status_update(test, "Failed to create a changeset due to an error\n");
+		return AST_TEST_FAIL;
+	} else if (!changes) {
 		ast_test_status_update(test, "Failed to produce a changeset when there should be one\n");
 		return AST_TEST_FAIL;
 	}
@@ -903,7 +908,10 @@
 	tmp->next = original;
 	original = tmp;
 
-	if ((changes = ast_sorcery_changeset_create(original, original))) {
+	if (ast_sorcery_changeset_create(original, original, &changes)) {
+		ast_test_status_update(test, "Failed to create a changeset due to an error\n");
+		return AST_TEST_FAIL;
+	} else if (changes) {
 		ast_test_status_update(test, "Created a changeset when no changes actually exist\n");
 		return AST_TEST_FAIL;
 	}
@@ -922,7 +930,10 @@
 	tmp->next = same;
 	same = tmp;
 
-	if ((changes = ast_sorcery_changeset_create(original, same))) {
+	if (ast_sorcery_changeset_create(original, same, &changes)) {
+		ast_test_status_update(test, "Failed to create a changeset due to an error\n");
+		return AST_TEST_FAIL;
+	} else if (changes) {
 		ast_test_status_update(test, "Created a changeset between two different objectsets when no changes actually exist\n");
 		return AST_TEST_FAIL;
 	}
@@ -1011,7 +1022,7 @@
 
 	ao2_cleanup(obj);
 
-	if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Failed to retrieve properly created object using id of 'blah'\n");
 		return AST_TEST_FAIL;
 	} else if (strcmp(ast_sorcery_object_get_id(obj), "blah")) {
@@ -1026,6 +1037,7 @@
 {
 	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
 	RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "42", ""), ast_variables_destroy);
 
 	switch (cmd) {
 	case TEST_INIT:
@@ -1037,6 +1049,11 @@
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
+	}
+
+	if (!fields) {
+		ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
+		return AST_TEST_FAIL;
 	}
 
 	if (!(sorcery = alloc_and_initialize_sorcery())) {
@@ -1058,14 +1075,20 @@
 
 	ao2_cleanup(obj);
 
-	if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_FIELD, "joe", "42", AST_RETRIEVE_PARAM_END))) {
+	if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
 		ast_test_status_update(test, "Failed to retrieve properly created object using 'joe' field\n");
 		return AST_TEST_FAIL;
 	}
 
 	ao2_cleanup(obj);
-
-	if ((obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_FIELD, "joe", "49", AST_RETRIEVE_PARAM_END))) {
+	ast_variables_destroy(fields);
+
+	if (!(fields = ast_variable_new("joe", "49", ""))) {
+		ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
+		return AST_TEST_FAIL;
+	}
+
+	if ((obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
 		ast_test_status_update(test, "Retrieved an object using a field with an in-correct value... that should not happen\n");
 		return AST_TEST_FAIL;
 	}
@@ -1118,7 +1141,7 @@
 		return AST_TEST_FAIL;
 	}
 
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_PARAM_END))) {
+	if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
 		ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects) != 2) {
@@ -1134,6 +1157,7 @@
 	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
 	RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
 	RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "6", ""), ast_variables_destroy);
 
 	switch (cmd) {
 	case TEST_INIT:
@@ -1145,6 +1169,11 @@
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
+	}
+
+	if (!fields) {
+		ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
+		return AST_TEST_FAIL;
 	}
 
 	if (!(sorcery = alloc_and_initialize_sorcery())) {
@@ -1164,7 +1193,7 @@
 		return AST_TEST_FAIL;
 	}
 
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, AST_RETRIEVE_PARAM_FIELD, "joe", "6", AST_RETRIEVE_PARAM_END))) {
+	if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
 		ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects) != 1) {
@@ -1173,8 +1202,12 @@
 	}
 
 	ao2_cleanup(objects);
-
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, AST_RETRIEVE_PARAM_FIELD, "joe", "7", AST_RETRIEVE_PARAM_END))) {
+	ast_variables_destroy(fields);
+
+	if (!(fields = ast_variable_new("joe", "7", ""))) {
+		ast_test_status_update(test, "Failed to create fields for multiple retrieval\n");
+		return AST_TEST_FAIL;
+	} else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
 		ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects)) {
@@ -1230,7 +1263,7 @@
 		return AST_TEST_FAIL;
 	}
 
-	if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Failed to retrieve properly updated object\n");
 		return AST_TEST_FAIL;
 	} else if (obj != obj2) {
@@ -1315,7 +1348,7 @@
 
 	ao2_cleanup(obj);
 
-	if ((obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Retrieved deleted object that should not be there\n");
 		return AST_TEST_FAIL;
 	}
@@ -1424,13 +1457,13 @@
 
 	ao2_cleanup(obj);
 
-	if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Failed to retrieve just created object\n");
 		goto end;
 	} else if (!cache.created) {
 		ast_test_status_update(test, "Caching wizard was not told to cache just created object\n");
 		goto end;
-	} else if (!(obj2 = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	} else if (!(obj2 = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Failed to retrieve just cached object\n");
 		goto end;
 	} else if (obj == obj2) {
@@ -1452,7 +1485,7 @@
 
 	ao2_cleanup(obj2);
 
-	if ((obj2 = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "blah", AST_RETRIEVE_PARAM_END))) {
+	if ((obj2 = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
 		ast_test_status_update(test, "Retrieved an object that should have been deleted\n");
 		goto end;
 	}
@@ -1517,10 +1550,10 @@
 
 	ast_sorcery_load(sorcery);
 
-	if ((obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "hey2", AST_RETRIEVE_PARAM_END))) {
+	if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey2"))) {
 		ast_test_status_update(test, "Retrieved object which has an unknown field\n");
 		return AST_TEST_FAIL;
-	} else if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "hey", AST_RETRIEVE_PARAM_END))) {
+	} else if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
 		ast_test_status_update(test, "Failed to retrieve a known object that has been configured in the configuration file\n");
 		return AST_TEST_FAIL;
 	} else if (obj->bob != 98) {
@@ -1580,7 +1613,7 @@
 
 	ast_sorcery_load(sorcery);
 
-	if ((obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "hey", AST_RETRIEVE_PARAM_END))) {
+	if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
 		ast_test_status_update(test, "Retrieved object which has an unknown field\n");
 		return AST_TEST_FAIL;
 	}
@@ -1635,10 +1668,10 @@
 
 	ast_sorcery_load(sorcery);
 
-	if ((obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "hey", AST_RETRIEVE_PARAM_END))) {
+	if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
 		ast_test_status_update(test, "Retrieved object which did not match criteria\n");
 		return AST_TEST_FAIL;
-	} else if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_ID, "hey2", AST_RETRIEVE_PARAM_END))) {
+	} else if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey2"))) {
 		ast_test_status_update(test, "Failed to retrieve a known object which matches criteria\n");
 		return AST_TEST_FAIL;
 	}
@@ -1652,6 +1685,7 @@
 	struct ast_config *config;
 	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
 	RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "41", ""), ast_variables_destroy);
 
 	switch (cmd) {
 	case TEST_INIT:
@@ -1692,7 +1726,7 @@
 
 	ast_sorcery_load(sorcery);
 
-	if (!(obj = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, AST_RETRIEVE_PARAM_FIELD, "joe", "41", AST_RETRIEVE_PARAM_END))) {
+	if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
 		ast_test_status_update(test, "Failed to retrieve a known object that has been configured with the correct field\n");
 		return AST_TEST_FAIL;
 	} else if (strcmp(ast_sorcery_object_get_id(obj), "hey")) {
@@ -1709,6 +1743,7 @@
 	struct ast_config *config;
 	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
 	RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "99", ""), ast_variables_destroy);
 
 	switch (cmd) {
 	case TEST_INIT:
@@ -1729,6 +1764,11 @@
 
 	ast_config_destroy(config);
 
+	if (!fields) {
+		ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
+		return AST_TEST_FAIL;
+	}
+
 	if (!(sorcery = ast_sorcery_open())) {
 		ast_test_status_update(test, "Failed to open sorcery structure\n");
 		return AST_TEST_FAIL;
@@ -1749,7 +1789,7 @@
 
 	ast_sorcery_load(sorcery);
 
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, AST_RETRIEVE_PARAM_FIELD, "joe", "99", AST_RETRIEVE_PARAM_END))) {
+	if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
 		ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects)) {
@@ -1758,8 +1798,12 @@
 	}
 
 	ao2_cleanup(objects);
-
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, AST_RETRIEVE_PARAM_FIELD, "joe", "41", AST_RETRIEVE_PARAM_END))) {
+	ast_variables_destroy(fields);
+
+	if (!(fields = ast_variable_new("joe", "41", ""))) {
+		ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
+		return AST_TEST_FAIL;
+	} else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
 		ast_test_status_update(test, "Failed to retrieve a container when retrieving multiple\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects) != 1) {
@@ -1816,7 +1860,7 @@
 
 	ast_sorcery_load(sorcery);
 
-	if (!(objects = ast_sorcery_retrieve(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_PARAM_END))) {
+	if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
 		ast_test_status_update(test, "Failed to retrieve a container with all objects when there should be one\n");
 		return AST_TEST_FAIL;
 	} else if (ao2_container_count(objects) != 2) {




More information about the asterisk-commits mailing list