Author: file
Date: Thu Aug 15 10:25:04 2013
New Revision: 396743

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

Still need to document stuff some more and take care of temporary file stuff.

Modified:
    team/file/bucket/build_tools/menuselect-deps.in
    team/file/bucket/configure
    team/file/bucket/configure.ac
    team/file/bucket/include/asterisk/autoconfig.h.in
    team/file/bucket/include/asterisk/bucket.h
    team/file/bucket/include/asterisk/config_options.h
    team/file/bucket/main/Makefile
    team/file/bucket/main/bucket.c
    team/file/bucket/main/config_options.c
    team/file/bucket/makeopts.in
    team/file/bucket/tests/test_bucket.c

Modified: team/file/bucket/build_tools/menuselect-deps.in
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/build_tools/menuselect-deps.in?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/build_tools/menuselect-deps.in (original)
+++ team/file/bucket/build_tools/menuselect-deps.in Thu Aug 15 10:25:04 2013
@@ -26,6 +26,7 @@
 IXJUSER=@PBX_IXJUSER@
 JACK=@PBX_JACK@
 JANSSON=@PBX_JANSSON@
+URIPARSER=@PBX_URIPARSER@
 KQUEUE=@PBX_KQUEUE@
 LDAP=@PBX_LDAP@
 LIBEDIT=@PBX_LIBEDIT@

Modified: team/file/bucket/configure.ac
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/configure.ac?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/configure.ac (original)
+++ team/file/bucket/configure.ac Thu Aug 15 10:25:04 2013
@@ -408,6 +408,7 @@
 AST_EXT_LIB_SETUP([ISDNNET], [ISDN4Linux], [isdnnet])
 AST_EXT_LIB_SETUP([JACK], [Jack Audio Connection Kit], [jack])
 AST_EXT_LIB_SETUP([JANSSON], [Jansson JSON library], [jansson])
+AST_EXT_LIB_SETUP([URIPARSER], [uriparser library], [uriparser])
 AST_EXT_LIB_SETUP([KQUEUE], [kqueue support], [kqueue])
 AST_EXT_LIB_SETUP([LDAP], [OpenLDAP], [ldap])
 AST_LIBCURL_CHECK_CONFIG([], [7.10.1])
@@ -541,6 +542,13 @@
 
 if test "x$JANSSON_LIB" == "x"; then
   AC_MSG_ERROR([*** JSON support not found (this typically means the 
libjansson development package is missing)])
+fi
+
+# Find required uriparser support.
+AST_EXT_LIB_CHECK([URIPARSER], [uriparser], [uriParseUriA], [uriparser/Uri.h])
+
+if test "x$URIPARSER_LIB" == "x"; then
+   AC_MSG_ERROR([*** uriparser support not found (this typically means the 
liburiparser development package is missing)])
 fi
 
 # Another mandatory item (unless it's explicitly disabled)

Modified: team/file/bucket/include/asterisk/autoconfig.h.in
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/include/asterisk/autoconfig.h.in?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/include/asterisk/autoconfig.h.in (original)
+++ team/file/bucket/include/asterisk/autoconfig.h.in Thu Aug 15 10:25:04 2013
@@ -1018,6 +1018,9 @@
 
 /* Define to 1 if you have the `unsetenv' function. */
 #undef HAVE_UNSETENV
+
+/* Define to 1 if you have the uriparser library library. */
+#undef HAVE_URIPARSER
 
 /* Define to 1 if you have the `utime' function. */
 #undef HAVE_UTIME

Modified: team/file/bucket/include/asterisk/bucket.h
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/include/asterisk/bucket.h?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/include/asterisk/bucket.h (original)
+++ team/file/bucket/include/asterisk/bucket.h Thu Aug 15 10:25:04 2013
@@ -28,7 +28,8 @@
  * Bucket is an API which provides directory and file access in a generic 
fashion. It is
  * implemented as a thin wrapper over the sorcery data access layer API and is 
written in
  * a pluggable fashion to allow different backend storage mechanisms.
-  */
+ *
+ */
 
 #ifndef _ASTERISK_BUCKET_H
 #define _ASTERISK_BUCKET_H

Modified: team/file/bucket/include/asterisk/config_options.h
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/include/asterisk/config_options.h?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/include/asterisk/config_options.h (original)
+++ team/file/bucket/include/asterisk/config_options.h Thu Aug 15 10:25:04 2013
@@ -53,17 +53,6 @@
        ACO_EXACT = 1,
        ACO_REGEX,
 };
-
-
-/*! \brief A callback function for handling a particular option
- * \param opt The option being configured
- * \param var The config variable to use to configure \a obj
- * \param obj The object to be configured
- *
- * \retval 0 Parsing and recording the config value succeeded
- * \retval non-zero Failure. Parsing should stop and no reload applied
- */
-typedef int (*aco_option_handler)(const struct aco_option *opt, struct 
ast_variable *var, void *obj);
 
 /*! Callback functions for option parsing via aco_process_config() */
 
@@ -448,21 +437,15 @@
        OPT_UINT_T,
 };
 
-/*! \brief Configuration option structure */
-struct aco_option {
-       const char *name;
-       const char *aliased_to;
-       const char *default_val;
-       enum aco_matchtype match_type;
-       regex_t *name_regex;
-       struct aco_type **obj;
-       enum aco_option_type type;
-       aco_option_handler handler;
-       unsigned int flags;
-       unsigned char deprecated:1;
-       size_t argc;
-       intptr_t args[0];
-};
+/*! \brief A callback function for handling a particular option
+ * \param opt The option being configured
+ * \param var The config variable to use to configure \a obj
+ * \param obj The object to be configured
+ *
+ * \retval 0 Parsing and recording the config value succeeded
+ * \retval non-zero Failure. Parsing should stop and no reload applied
+ */
+typedef int (*aco_option_handler)(const struct aco_option *opt, struct 
ast_variable *var, void *obj);
 
 /*! \brief Allocate a container to hold config options */
 struct ao2_container *aco_option_container_alloc(void);
@@ -605,6 +588,16 @@
  * \retval value of the flags on the config option
  */
 unsigned int aco_option_get_flags(const struct aco_option *option);
+
+/*!
+ * \brief Get the offset position for an argument within a config option
+ *
+ * \param option Pointer to the aco_option struct
+ * \param arg Argument number
+ *
+ * \retval position of the argument
+ */
+intptr_t aco_option_get_argument(const struct aco_option *option, unsigned int 
position);
 
 /*! \note  Everything below this point is to handle converting varargs
  * containing field names, to varargs containing a count of args, followed

Modified: team/file/bucket/main/Makefile
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/main/Makefile?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/main/Makefile (original)
+++ team/file/bucket/main/Makefile Thu Aug 15 10:25:04 2013
@@ -36,6 +36,7 @@
 AST_LIBS+=$(SQLITE3_LIB)
 AST_LIBS+=$(ASTSSL_LIBS)
 AST_LIBS+=$(JANSSON_LIB)
+AST_LIBS+=$(URIPARSER_LIB)
 AST_LIBS+=$(UUID_LIB)
 AST_LIBS+=$(CRYPT_LIB)
 
@@ -154,6 +155,7 @@
 asterisk.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
 cli.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
 json.o: _ASTCFLAGS+=$(JANSSON_INCLUDE)
+bucket.o: _ASTCFLAGS+=$(URIPARSER_INCLUDE)
 crypt.o: _ASTCFLAGS+=$(CRYPT_INCLUDE)
 uuid.o: _ASTCFLAGS+=$(UUID_INCLUDE)
 

Modified: team/file/bucket/main/bucket.c
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/main/bucket.c?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/main/bucket.c (original)
+++ team/file/bucket/main/bucket.c Thu Aug 15 10:25:04 2013
@@ -24,12 +24,15 @@
  */
 
 /*** MODULEINFO
+       <depend>uriparser</depend>
        <support_level>core</support_level>
  ***/
 
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <uriparser/Uri.h>
 
 #include "asterisk/logger.h"
 #include "asterisk/sorcery.h"
@@ -72,48 +75,6 @@
        char name[0];
 };
 
-/*!
- * \brief Simple URI parser
- *
- * \param uri Full URI
- * \param scheme The scheme in the URI
- * \param name The name of the object in the URI
- *
- * \retval 0 success
- * \retval -1 failure
- *
- * \note The URI passed in will be modified
- */
-static int bucket_uri_parse(char *uri, char **scheme, char **name)
-{
-       char *tmp;
-
-       /* If no URI has been specified this is invalid */
-       if (ast_strlen_zero(uri)) {
-               return -1;
-       }
-
-       *scheme = DEFAULT_UNSPECIFIED_SCHEME;
-       *name = NULL;
-
-       /* Assume the naming starts at the front until proven otherwise */
-       *name = uri;
-
-       /* Determine the scheme from the provided URI */
-       if ((tmp = strstr(uri, "://"))) {
-               *scheme = uri;
-               *tmp++ = '\0';
-               *name = tmp;
-       }
-
-       /* Determine the name */
-       if ((tmp = strrchr(*name, '/'))) {
-               *name = tmp + 1;
-       }
-
-       return 0;
-}
-
 /*! \brief Callback function for creating a bucket */
 static int bucket_wizard_create(const struct ast_sorcery *sorcery, void *data, 
void *object)
 {
@@ -132,20 +93,28 @@
 static void *bucket_wizard_retrieve(const struct ast_sorcery *sorcery, void 
*data, const char *type,
        const char *id)
 {
-       char *uri, *uri_scheme, *uri_name;
+       UriParserStateA state;
+       UriUriA uri;
        SCOPED_AO2RDLOCK(lock, schemes);
+       size_t len;
+       char *uri_scheme;
        RAII_VAR(struct bucket_scheme *, scheme, NULL, ao2_cleanup);
 
-       if (!(uri = ast_strdupa(id))) {
-               return NULL;
-       }
-
-       if (bucket_uri_parse(uri, &uri_scheme, &uri_name) ||
-               ast_strlen_zero(uri_scheme) || ast_strlen_zero(uri_name)) {
-               return NULL;
-       }
+       state.uri = &uri;
+       if (uriParseUriA(&state, id) != URI_SUCCESS ||
+               !uri.scheme.first || !uri.scheme.afterLast) {
+               uriFreeUriMembersA(&uri);
+               return NULL;
+       }
+
+       len = (uri.scheme.afterLast - uri.scheme.first) + 1;
+       uri_scheme = ast_alloca(len);
+       ast_copy_string(uri_scheme, uri.scheme.first, len);
 
        scheme = ao2_find(schemes, uri_scheme, OBJ_KEY | OBJ_NOLOCK);
+
+       uriFreeUriMembersA(&uri);
+
        if (!scheme) {
                return NULL;
        }
@@ -193,20 +162,28 @@
 static void *bucket_file_wizard_retrieve(const struct ast_sorcery *sorcery, 
void *data, const char *type,
        const char *id)
 {
-       char *uri, *uri_scheme, *uri_name;
+       UriParserStateA state;
+       UriUriA uri;
+       size_t len;
+       char *uri_scheme;
        SCOPED_AO2RDLOCK(lock, schemes);
        RAII_VAR(struct bucket_scheme *, scheme, NULL, ao2_cleanup);
 
-       if (!(uri = ast_strdupa(id))) {
-               return NULL;
-       }
-
-       if (bucket_uri_parse(uri, &uri_scheme, &uri_name) ||
-               ast_strlen_zero(uri_scheme) || ast_strlen_zero(uri_name)) {
-               return NULL;
-       }
+       state.uri = &uri;
+       if (uriParseUriA(&state, id) != URI_SUCCESS ||
+               !uri.scheme.first || !uri.scheme.afterLast) {
+               uriFreeUriMembersA(&uri);
+               return NULL;
+       }
+
+       len = (uri.scheme.afterLast - uri.scheme.first) + 1;
+       uri_scheme = ast_alloca(len);
+       ast_copy_string(uri_scheme, uri.scheme.first, len);
 
        scheme = ao2_find(schemes, uri_scheme, OBJ_KEY | OBJ_NOLOCK);
+
+       uriFreeUriMembersA(&uri);
+
        if (!scheme) {
                return NULL;
        }
@@ -344,6 +321,26 @@
        ao2_cleanup(bucket->files);
 }
 
+/*! \brief Sorting function for red black tree string container */
+static int bucket_rbtree_str_sort_cmp(const void *obj_left, const void 
*obj_right, int flags)
+{
+       const char *str_left = obj_left;
+       const char *str_right = obj_right;
+       int cmp = 0;
+
+       switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+       default:
+       case OBJ_POINTER:
+       case OBJ_KEY:
+               cmp = strcmp(str_left, str_right);
+               break;
+       case OBJ_PARTIAL_KEY:
+               cmp = strncmp(str_left, str_right, strlen(str_right));
+               break;
+       }
+       return cmp;
+}
+
 /*! \brief Allocator for buckets */
 static void *bucket_alloc(const char *name)
 {
@@ -358,12 +355,14 @@
                return NULL;
        }
 
-       bucket->buckets = 
ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, BUCKET_BUCKETS);
+       bucket->buckets = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
+               AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, 
bucket_rbtree_str_sort_cmp, NULL);
        if (!bucket->buckets) {
                return NULL;
        }
 
-       bucket->files = 
ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, FILE_BUCKETS);
+       bucket->files = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
+               AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, 
bucket_rbtree_str_sort_cmp, NULL);
        if (!bucket->files) {
                return NULL;
        }
@@ -374,17 +373,29 @@
 
 struct ast_bucket *ast_bucket_alloc(const char *uri)
 {
-       char *full_uri, *uri_scheme, *uri_name;
+       UriParserStateA state;
+       UriUriA full_uri;
+       size_t len;
+       char *uri_scheme, *uri_name;
        struct ast_bucket *bucket;
 
-       if (!(full_uri = ast_strdupa(uri))) {
-               return NULL;
-       }
-
-       if (bucket_uri_parse(full_uri, &uri_scheme, &uri_name) ||
-               ast_strlen_zero(uri_scheme) || ast_strlen_zero(uri_name)) {
-               return NULL;
-       }
+       state.uri = &full_uri;
+       if (uriParseUriA(&state, uri) != URI_SUCCESS ||
+               !full_uri.scheme.first || !full_uri.scheme.afterLast ||
+               !full_uri.pathTail) {
+               uriFreeUriMembersA(&full_uri);
+               return NULL;
+       }
+
+       len = (full_uri.scheme.afterLast - full_uri.scheme.first) + 1;
+       uri_scheme = ast_alloca(len);
+       ast_copy_string(uri_scheme, full_uri.scheme.first, len);
+
+       len = (full_uri.pathTail->text.afterLast - 
full_uri.pathTail->text.first) + 1;
+       uri_name = ast_alloca(len);
+       ast_copy_string(uri_name, full_uri.pathTail->text.first, len);
+
+       uriFreeUriMembersA(&full_uri);
 
        if (!(bucket = ast_sorcery_alloc(bucket_sorcery, "bucket", uri))) {
                return NULL;
@@ -444,12 +455,15 @@
        }
 
        if (ast_json_object_set(json, "id", id)) {
-               ast_json_unref(id);
                return NULL;
        }
 
        buckets = ast_json_array_create();
        if (!buckets) {
+               return NULL;
+       }
+
+       if (ast_json_object_set(json, "buckets", buckets)) {
                return NULL;
        }
 
@@ -457,24 +471,23 @@
        for (; (uri = ao2_iterator_next(&i)); ao2_ref(uri, -1)) {
                struct ast_json *bucket_uri = ast_json_string_create(uri);
 
-               if (!bucket_uri) {
+               if (!bucket_uri || ast_json_array_append(buckets, bucket_uri)) {
                        res = -1;
                        break;
                }
-
-               ast_json_array_append(buckets, bucket_uri);
        }
        ao2_iterator_destroy(&i);
 
        if (res) {
-               ast_json_unref(buckets);
-               return NULL;
-       }
-
-       ast_json_object_set(json, "buckets", buckets);
+               return NULL;
+       }
 
        files = ast_json_array_create();
        if (!files) {
+               return NULL;
+       }
+
+       if (ast_json_object_set(json, "files", files)) {
                return NULL;
        }
 
@@ -482,21 +495,16 @@
        for (; (uri = ao2_iterator_next(&i)); ao2_ref(uri, -1)) {
                struct ast_json *file_uri = ast_json_string_create(uri);
 
-               if (!file_uri) {
+               if (!file_uri || ast_json_array_append(files, file_uri)) {
                        res = -1;
                        break;
                }
-
-               ast_json_array_append(files, file_uri);
        }
        ao2_iterator_destroy(&i);
 
        if (res) {
-               ast_json_unref(files);
-               return NULL;
-       }
-
-       ast_json_object_set(json, "files", files);
+               return NULL;
+       }
 
        ast_json_ref(json);
        return json;
@@ -505,10 +513,21 @@
 /*! \brief Hashing function for file metadata */
 static int bucket_file_metadata_hash(const void *obj, const int flags)
 {
-       const struct ast_bucket_metadata *metadata = obj;
-       const char *name = obj;
-
-       return ast_str_hash(flags & OBJ_KEY ? name : metadata->name);
+       const struct ast_bucket_metadata *object;
+       const char *key;
+
+       switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+       case OBJ_KEY:
+               key = obj;
+               return ast_str_hash(key);
+       case OBJ_POINTER:
+               object = obj;
+               return ast_str_hash(object->name);
+       default:
+               /* Hash can only work on something with a full key */
+               ast_assert(0);
+               return 0;
+       }
 }
 
 /*! \brief Comparison function for file metadata */
@@ -558,18 +577,30 @@
 
 struct ast_bucket_file *ast_bucket_file_alloc(const char *uri)
 {
-       char *full_uri, *uri_scheme, *uri_name;
+       UriParserStateA state;
+       UriUriA full_uri;
+       size_t len;
+       char *uri_scheme, *uri_name;
        struct ast_bucket_file *file;
        int fd;
 
-       if (!(full_uri = ast_strdupa(uri))) {
-               return NULL;
-       }
-
-       if (bucket_uri_parse(full_uri, &uri_scheme, &uri_name) ||
-               ast_strlen_zero(uri_scheme) || ast_strlen_zero(uri_name)) {
-               return NULL;
-       }
+       state.uri = &full_uri;
+       if (uriParseUriA(&state, uri) != URI_SUCCESS ||
+               !full_uri.scheme.first || !full_uri.scheme.afterLast ||
+               !full_uri.pathTail) {
+               uriFreeUriMembersA(&full_uri);
+               return NULL;
+       }
+
+       len = (full_uri.scheme.afterLast - full_uri.scheme.first) + 1;
+       uri_scheme = ast_alloca(len);
+       ast_copy_string(uri_scheme, full_uri.scheme.first, len);
+
+       len = (full_uri.pathTail->text.afterLast - 
full_uri.pathTail->text.first) + 1;
+       uri_name = ast_alloca(len);
+       ast_copy_string(uri_name, full_uri.pathTail->text.first, len);
+
+       uriFreeUriMembersA(&full_uri);
 
        if (!(file = ast_sorcery_alloc(bucket_sorcery, "file", uri))) {
                return NULL;
@@ -601,11 +632,11 @@
        char buf[4096]; /* XXX make it lerger. */
 
        if ((ifd = open(infile, O_RDONLY)) < 0) {
-               ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", 
infile);
+               ast_log(LOG_WARNING, "Unable to open %s in read-only mode, 
error: %s\n", infile, strerror(errno));
                return -1;
        }
        if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, AST_FILE_MODE)) 
< 0) {
-               ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", 
outfile);
+               ast_log(LOG_WARNING, "Unable to open %s in write-only mode, 
error: %s\n", outfile, strerror(errno));
                close(ifd);
                return -1;
        }
@@ -634,25 +665,20 @@
 
 struct ast_bucket_file *ast_bucket_file_copy(struct ast_bucket_file *file, 
const char *uri)
 {
-       struct ast_bucket_file *copy;
-
-       copy = ast_bucket_file_alloc(uri);
+       RAII_VAR(struct ast_bucket_file *, copy, ast_bucket_file_alloc(uri), 
ao2_cleanup);
+
        if (!copy) {
                return NULL;
        }
 
        ao2_cleanup(copy->metadata);
        copy->metadata = ao2_container_clone(file->metadata, 0);
-       if (!copy->metadata) {
-               ao2_ref(copy, -1);
-               return NULL;
-       }
-
-       if (bucket_copy(file->path, copy->path)) {
-               ao2_ref(copy, -1);
-               return NULL;
-       }
-
+       if (!copy->metadata ||
+               bucket_copy(file->path, copy->path)) {
+               return NULL;
+       }
+
+       ao2_ref(copy, +1);
        return copy;
 }
 
@@ -704,12 +730,15 @@
        }
 
        if (ast_json_object_set(json, "id", id)) {
-               ast_json_unref(id);
                return NULL;
        }
 
        metadata = ast_json_object_create();
        if (!metadata) {
+               return NULL;
+       }
+
+       if (ast_json_object_set(json, "metadata", metadata)) {
                return NULL;
        }
 
@@ -717,21 +746,16 @@
        for (; (attribute = ao2_iterator_next(&i)); ao2_ref(attribute, -1)) {
                struct ast_json *value = 
ast_json_string_create(attribute->value);
 
-               if (!value) {
+               if (!value || ast_json_object_set(metadata, attribute->name, 
value)) {
                        res = -1;
                        break;
                }
-
-               ast_json_object_set(metadata, attribute->name, value);
        }
        ao2_iterator_destroy(&i);
 
        if (res) {
-               ast_json_unref(metadata);
-               return NULL;
-       }
-
-       ast_json_object_set(json, "metadata", metadata);
+               return NULL;
+       }
 
        ast_json_ref(json);
        return json;
@@ -740,10 +764,21 @@
 /*! \brief Hashing function for scheme container */
 static int bucket_scheme_hash(const void *obj, const int flags)
 {
-       const struct bucket_scheme *scheme = obj;
-       const char *name = obj;
-
-       return ast_str_hash(flags & OBJ_KEY ? name : scheme->name);
+       const struct bucket_scheme *object;
+       const char *key;
+
+       switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+       case OBJ_KEY:
+               key = obj;
+               return ast_str_hash(key);
+       case OBJ_POINTER:
+               object = obj;
+               return ast_str_hash(object->name);
+       default:
+               /* Hash can only work on something with a full key */
+               ast_assert(0);
+               return 0;
+       }
 }
 
 /*! \brief Comparison function for scheme container */
@@ -771,7 +806,7 @@
 /*! \brief Custom handler for translating from a string timeval to actual 
structure */
 static int timeval_str2struct(const struct aco_option *opt, struct 
ast_variable *var, void *obj)
 {
-       struct timeval *field = (struct timeval *)(obj + opt->args[0]);
+       struct timeval *field = (struct timeval *)(obj + 
aco_option_get_argument(opt, 0));
        return ast_get_timeval(var->value, field, ast_tv(0, 0), NULL);
 }
 
@@ -785,36 +820,38 @@
 /*! \brief Initialize bucket support */
 int ast_bucket_init(void)
 {
+       ast_register_cleanup(&bucket_cleanup);
+
        schemes = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 
SCHEME_BUCKETS, bucket_scheme_hash,
                bucket_scheme_cmp);
        if (!schemes) {
                ast_log(LOG_ERROR, "Failed to create container for Bucket 
schemes\n");
-               goto failure;
+               return -1;
        }
 
        if (__ast_sorcery_wizard_register(&bucket_wizard, NULL)) {
                ast_log(LOG_ERROR, "Failed to register sorcery wizard for 
'bucket' intermediary\n");
-               goto failure;
+               return -1;
        }
 
        if (__ast_sorcery_wizard_register(&bucket_file_wizard, NULL)) {
                ast_log(LOG_ERROR, "Failed to register sorcery wizard for 
'file' intermediary\n");
-               goto failure;
+               return -1;
        }
 
        if (!(bucket_sorcery = ast_sorcery_open())) {
                ast_log(LOG_ERROR, "Failed to create sorcery instance for 
Bucket support\n");
-               goto failure;
+               return -1;
        }
 
        if (ast_sorcery_apply_default(bucket_sorcery, "bucket", "bucket", 
NULL)) {
                ast_log(LOG_ERROR, "Failed to apply intermediary for 'bucket' 
object type in Bucket sorcery\n");
-               goto failure;
+               return -1;
        }
 
        if (ast_sorcery_object_register(bucket_sorcery, "bucket", bucket_alloc, 
NULL, NULL)) {
                ast_log(LOG_ERROR, "Failed to register 'bucket' object type in 
Bucket sorcery\n");
-               goto failure;
+               return -1;
        }
 
        ast_sorcery_object_field_register(bucket_sorcery, "bucket", "name", "", 
OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_bucket, name));
@@ -824,12 +861,12 @@
 
        if (ast_sorcery_apply_default(bucket_sorcery, "file", "bucket_file", 
NULL)) {
                ast_log(LOG_ERROR, "Failed to apply intermediary for 'file' 
object type in Bucket sorcery\n");
-               goto failure;
+               return -1;
        }
 
        if (ast_sorcery_object_register(bucket_sorcery, "file", 
bucket_file_alloc, NULL, NULL)) {
                ast_log(LOG_ERROR, "Failed to register 'file' object type in 
Bucket sorcery\n");
-               goto failure;
+               return -1;
        }
 
        ast_sorcery_object_field_register(bucket_sorcery, "file", "name", "", 
OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_bucket_file, name));
@@ -837,11 +874,5 @@
        ast_sorcery_object_field_register_custom(bucket_sorcery, "file", 
"created", "", timeval_str2struct, timeval_struct2str, 0, FLDSET(struct 
ast_bucket_file, created));
        ast_sorcery_object_field_register_custom(bucket_sorcery, "file", 
"modified", "", timeval_str2struct, timeval_struct2str, 0, FLDSET(struct 
ast_bucket_file, modified));
 
-       ast_register_cleanup(bucket_cleanup);
-
        return 0;
-
-failure:
-       bucket_cleanup();
-       return -1;
-}
+}

Modified: team/file/bucket/main/config_options.c
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/main/config_options.c?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/main/config_options.c (original)
+++ team/file/bucket/main/config_options.c Thu Aug 15 10:25:04 2013
@@ -59,6 +59,21 @@
        struct ao2_container *opts; /*!< The container of options registered to 
the aco_info */
 };
 
+struct aco_option {
+       const char *name;
+       const char *aliased_to;
+       const char *default_val;
+       enum aco_matchtype match_type;
+       regex_t *name_regex;
+       struct aco_type **obj;
+       enum aco_option_type type;
+       aco_option_handler handler;
+       unsigned int flags;
+       unsigned char deprecated:1;
+       size_t argc;
+       intptr_t args[0];
+};
+
 #ifdef AST_XML_DOCS
 static struct ao2_container *xmldocs;
 #endif /* AST_XML_DOCS */
@@ -211,6 +226,11 @@
 unsigned int aco_option_get_flags(const struct aco_option *option)
 {
        return option->flags;
+}
+
+intptr_t aco_option_get_argument(const struct aco_option *option, unsigned int 
position)
+{
+       return option->args[position];
 }
 
 #ifdef AST_XML_DOCS

Modified: team/file/bucket/makeopts.in
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/makeopts.in?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/makeopts.in (original)
+++ team/file/bucket/makeopts.in Thu Aug 15 10:25:04 2013
@@ -173,6 +173,9 @@
 JANSSON_INCLUDE=@JANSSON_INCLUDE@
 JANSSON_LIB=@JANSSON_LIB@
 
+URIPARSER_INCLUDE=@URIPARSER_INCLUDE@
+URIPARSER_LIB=@URIPARSER_LIB@
+
 LDAP_INCLUDE=@LDAP_INCLUDE@
 LDAP_LIB=@LDAP_LIB@
 

Modified: team/file/bucket/tests/test_bucket.c
URL: 
http://svnview.digium.com/svn/asterisk/team/file/bucket/tests/test_bucket.c?view=diff&rev=396743&r1=396742&r2=396743
==============================================================================
--- team/file/bucket/tests/test_bucket.c (original)
+++ team/file/bucket/tests/test_bucket.c Thu Aug 15 10:25:04 2013
@@ -290,8 +290,8 @@
 AST_TEST_DEFINE(bucket_json)
 {
        RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
+       RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
        RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
-       struct ast_json_iter *field;
 
        switch (cmd) {
        case TEST_INIT:
@@ -312,6 +312,17 @@
 
        ast_str_container_add(bucket->buckets, "test:///tmp/bob/joe");
        ast_str_container_add(bucket->files, "test:///tmp/bob/recording.wav");
+
+       expected = ast_json_pack("{s: s, s: s, s: [s], s: s, s: s, s: [s], s: 
s}",
+               "modified", "0.000000", "created", "0.000000",
+               "buckets", "test:///tmp/bob/joe",
+               "name", "bob", "scheme", "test",
+               "files", "test:///tmp/bob/recording.wav",
+               "id", "test:///tmp/bob");
+       if (!expected) {
+               ast_test_status_update(test, "Could not produce JSON for 
expected bucket value\n");
+               return AST_TEST_FAIL;
+       }
 
        json = ast_bucket_json(bucket);
        if (!json) {
@@ -319,72 +330,9 @@
                return AST_TEST_FAIL;
        }
 
-       for (field = ast_json_object_iter(json); field; field = 
ast_json_object_iter_next(json, field)) {
-               struct ast_json *value = ast_json_object_iter_value(field);
-
-               if (!strcmp(ast_json_object_iter_key(field), "id")) {
-                       if (strcmp(ast_json_string_get(value), "bob")) {
-                               ast_test_status_update(test, "Expected id of 
'bob' in bucket JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), 
"modified")) {
-                       if (strcmp(ast_json_string_get(value), "0")) {
-                               ast_test_status_update(test, "Expected modified 
time of '0' in bucket JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "created")) 
{
-                       if (strcmp(ast_json_string_get(value), "0")) {
-                               ast_test_status_update(test, "Expected created 
time of '0' in bucket JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "scheme")) {
-                       if (strcmp(ast_json_string_get(value), "test")) {
-                               ast_test_status_update(test, "Expected scheme 
of 'test' in bucket JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "uri")) {
-                       if (strcmp(ast_json_string_get(value), 
"test:///tmp/bob")) {
-                               ast_test_status_update(test, "Expected URI of 
'test:///tmp/bob' in bucket JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "buckets")) 
{
-                       struct ast_json *uri;
-
-                       if (ast_json_array_size(value) != 1) {
-                               ast_test_status_update(test, "Expected buckets 
array size of '1' in bucket JSON but got '%zd'\n",
-                                       ast_json_array_size(value));
-                               return AST_TEST_FAIL;
-                       }
-
-                       uri = ast_json_array_get(value, 0);
-
-                       if (strcmp(ast_json_string_get(uri), 
"test:///tmp/bob/joe")) {
-                               ast_test_status_update(test, "Expected URI of 
'test:///tmp/bob/joe' in buckets array but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "files")) {
-                       struct ast_json *uri;
-
-                       if (ast_json_array_size(value) != 1) {
-                               ast_test_status_update(test, "Expected files 
array size of '1' in bucket JSON but got '%zd'\n",
-                                       ast_json_array_size(value));
-                               return AST_TEST_FAIL;
-                       }
-
-                       uri = ast_json_array_get(value, 0);
-
-                       if (strcmp(ast_json_string_get(uri), 
"test:///tmp/bob/recording.wav")) {
-                               ast_test_status_update(test, "Expected URI of 
'test:///tmp/bob/recording.wav' in buckets array but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               }
+       if (!ast_json_equal(json, expected)) {
+               ast_test_status_update(test, "Bucket JSON does not match 
expected output\n");
+               return AST_TEST_FAIL;
        }
 
        return AST_TEST_PASS;
@@ -495,12 +443,6 @@
                return AST_TEST_FAIL;
        }
 
-       if (!stat(file->path, &st)) {
-               ast_test_status_update(test, "Temporary file '%s' existed 
before creating it\n",
-                       file->path);
-               return AST_TEST_FAIL;
-       }
-
        if (!(temporary = fopen(file->path, "w"))) {
                ast_test_status_update(test, "Failed to open temporary file 
'%s'\n",
                        file->path);
@@ -579,6 +521,7 @@
        RAII_VAR(struct ast_bucket_file *, copy, NULL, ao2_cleanup);
        FILE *temporary;
        struct stat old, new;
+       RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
 
        switch (cmd) {
        case TEST_INIT:
@@ -633,6 +576,17 @@
                return AST_TEST_FAIL;
        }
 
+       metadata = ast_bucket_file_metadata_get(copy, "bob");
+       if (!metadata) {
+               ast_test_status_update(test, "Copy of file does not have 
expected metadata\n");
+               return AST_TEST_FAIL;
+       }
+
+       if (strcmp(metadata->value, "joe")) {
+               ast_test_status_update(test, "Copy of file contains metadata 
for 'bob' but value is not what it should be\n");
+               return AST_TEST_FAIL;
+       }
+
        return AST_TEST_PASS;
 }
 
@@ -884,14 +838,20 @@
                return AST_TEST_FAIL;
        }
 
+       if (strcmp(metadata->value, "joe")) {
+               ast_test_status_update(test, "Retrieved metadata value is '%s' 
while it should be 'joe'\n",
+                       metadata->value);
+               return AST_TEST_FAIL;
+       }
+
        return AST_TEST_PASS;
 }
 
 AST_TEST_DEFINE(bucket_file_json)
 {
        RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+       RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
        RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
-       struct ast_json_iter *field;
 
        switch (cmd) {
        case TEST_INIT:
@@ -912,6 +872,14 @@
 
        if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
                ast_test_status_update(test, "Failed to set metadata 'bob' to 
'joe' on newly allocated file\n");
+               return AST_TEST_FAIL;
+       }
+
+       expected = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: {s :s}}",
+               "modified", "0.000000", "created", "0.000000", "name", "bob", 
"scheme", "test",
+               "id", "test:///tmp/bob", "metadata", "bob", "joe");
+       if (!expected) {
+               ast_test_status_update(test, "Could not produce JSON for 
expected bucket file value\n");
                return AST_TEST_FAIL;
        }
 
@@ -921,53 +889,9 @@
                return AST_TEST_FAIL;
        }
 
-       for (field = ast_json_object_iter(json); field; field = 
ast_json_object_iter_next(json, field)) {
-               struct ast_json *value = ast_json_object_iter_value(field);
-
-               if (!strcmp(ast_json_object_iter_key(field), "id")) {
-                       if (strcmp(ast_json_string_get(value), "bob")) {
-                               ast_test_status_update(test, "Expected id of 
'bob' in file JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), 
"modified")) {
-                       if (strcmp(ast_json_string_get(value), "0")) {
-                               ast_test_status_update(test, "Expected modified 
time of '0' in file JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "created")) 
{
-                       if (strcmp(ast_json_string_get(value), "0")) {
-                               ast_test_status_update(test, "Expected created 
time of '0' in file JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "scheme")) {
-                       if (strcmp(ast_json_string_get(value), "test")) {
-                               ast_test_status_update(test, "Expected scheme 
of 'test' in file JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), "uri")) {
-                       if (strcmp(ast_json_string_get(value), 
"test:///tmp/bob")) {
-                               ast_test_status_update(test, "Expected URI of 
'test:///tmp/bob' in file JSON but got '%s'\n",
-                                       ast_json_string_get(value));
-                               return AST_TEST_FAIL;
-                       }
-               } else if (!strcmp(ast_json_object_iter_key(field), 
"metadata")) {
-                       struct ast_json *bob = ast_json_object_get(value, 
"bob");
-
-                       if (!bob) {
-                               ast_test_status_update(test, "Failed to get 
'bob' metadata in JSON\n");
-                               return AST_TEST_FAIL;
-                       }
-
-                       if (strcmp(ast_json_string_get(bob), "joe")) {
-                               ast_test_status_update(test, "Retrieved 'bob' 
metadata has value '%s' instead of 'joe'\n",
-                                       ast_json_string_get(bob));
-                               return AST_TEST_FAIL;
-                       }
-               }
+       if (!ast_json_equal(json, expected)) {
+               ast_test_status_update(test, "Bucket file JSON does not match 
expected output\n");
+               return AST_TEST_FAIL;
        }
 
        return AST_TEST_PASS;


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to