[asterisk-commits] tilghman: branch group/ast_storage r48342 - in /team/group/ast_storage: inclu...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Dec 6 17:55:46 MST 2006


Author: tilghman
Date: Wed Dec  6 18:55:45 2006
New Revision: 48342

URL: http://svn.digium.com/view/asterisk?view=rev&rev=48342
Log:
Add directory reading APIs

Modified:
    team/group/ast_storage/include/asterisk/storage.h
    team/group/ast_storage/main/storage.c
    team/group/ast_storage/res/res_storage_file.c
    team/group/ast_storage/res/res_storage_odbc.c

Modified: team/group/ast_storage/include/asterisk/storage.h
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/include/asterisk/storage.h?view=diff&rev=48342&r1=48341&r2=48342
==============================================================================
--- team/group/ast_storage/include/asterisk/storage.h (original)
+++ team/group/ast_storage/include/asterisk/storage.h Wed Dec  6 18:55:45 2006
@@ -31,15 +31,18 @@
 extern "C" {
 #endif
 
+struct ast_storage_dirent;
+
 struct ast_storage_be {
 	const char *name;
 	struct ast_storage *(*new)(const char *uri);
 	int (*free)(struct ast_storage *st);
-	int (*get)(struct ast_storage *st, const char *objectname, char *localfile, size_t localfilesize);
-	int (*put)(struct ast_storage *st, const char *objectname, const char *localfile);
-	int (*delete)(struct ast_storage *st, const char *objectname);
-	int (*count)(struct ast_storage *st, const char *objectpath);
-	int (*parseoptions)(struct ast_storage *st, const char *var, const char *value);
+	int (*get)(struct ast_storage *st, const char *objectname, const char *fileformats, char *localfile, size_t localfilesize);
+	int (*put)(struct ast_storage *st, const char *objectname, const char *fileformats, const char *localfile);
+	int (*delete)(struct ast_storage *st, const char *objectname, const char *fileformats);
+	void *(*opendir)(struct ast_storage *st, const char *objectpath);
+	int (*readdir)(struct ast_storage *st, void *dirptr, struct ast_storage_dirent *dirent);
+	int (*closedir)(struct ast_storage *st, void *dirptr);
 	AST_LIST_ENTRY(ast_storage_be) list;
 	struct ast_module *module;
 };
@@ -47,6 +50,11 @@
 /* Most specific backends will have longer structures */
 struct ast_storage {
 	struct ast_storage_be *be;
+};
+
+struct ast_storage_dirent {
+	char name[256];
+	char format[10];
 };
 
 int __ast_register_storage(const struct ast_storage_be *e, struct ast_module *mod);
@@ -58,10 +66,7 @@
 
 /*! \brief Retrieves an instance of a storage method
  * \param storage_type Name of the backend
- * \param root Backend specific parameter.  Generally is a hostname or path.
- * \param auth Backend specific parameter.  Generally is the user in an authentication scheme.
- * \param passwd Backend specific parameter.  Generally is the password in an authentication scheme.
- * \param flags Backend specific parameter
+ * \param uri Backend specific URI to the resource
  */
 struct ast_storage *ast_storage_request(const char *storage_type, const char *uri);
 
@@ -72,23 +77,46 @@
 /*! \brief Retrieves a file from the storage medium
  * \param st Storage instance
  * \param objectname Logical name of the file
+ * \param fileformats Formats to retrieve
  * \param localfile Buffer in which to place the name of the resulting temporary file.
  * \param localfilesize Length of the above buffer
  */
-int ast_storage_get(struct ast_storage *st, const char *objectname, char *localfile, size_t localfilesize);
+int ast_storage_get(struct ast_storage *st, const char *objectname, const char *fileformats, char *localfile, size_t localfilesize);
 
 /*! \brief Stores a file into the storage medium
  * \param st Storage instance
  * \param objectname Logical name of the file
+ * \param fileformats Formats to store
  * \param localfile Location of the file to store
  */
-int ast_storage_put(struct ast_storage *st, const char *objectname, const char *localfile);
+int ast_storage_put(struct ast_storage *st, const char *objectname, const char *fileformats, const char *localfile);
 
 /*! \brief Removes a file from the storage medium
  * \param st Storage instance
  * \param objectname Logical name of the file
+ * \param fileformats Formats to delete
  */
-int ast_storage_delete(struct ast_storage *st, const char *objectname);
+int ast_storage_delete(struct ast_storage *st, const char *objectname, const char *fileformats);
+
+/*! \brief Starts retrieval of objects in a resource path
+ * \param st Storage instance
+ * \param pathname Logical name of the path
+ * \return Pointer identifying this listing, or NULL on error.
+ */
+void *ast_storage_opendir(struct ast_storage *st, const char *objectname);
+
+/*! \brief Retrieves an objectname from a previously opened path
+ * \param st Storage instance
+ * \param dirptr Pointer returned by ast_storage_opendir
+ * \param dirent Pointer to a storage area for the object
+ */
+int ast_storage_readdir(struct ast_storage *st, void *dirptr, struct ast_storage_dirent *dirent);
+
+/*! \brief Ends retrieval of objects in a resource path
+ * \param st Storage instance
+ * \param dirptr Pointer returned by ast_storage_opendir
+ */
+int ast_storage_closedir(struct ast_storage *st, void *dirptr);
 
 /*! \brief Retrieves a count of objects at a particular path
  * \param st Storage instance

Modified: team/group/ast_storage/main/storage.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/main/storage.c?view=diff&rev=48342&r1=48341&r2=48342
==============================================================================
--- team/group/ast_storage/main/storage.c (original)
+++ team/group/ast_storage/main/storage.c Wed Dec  6 18:55:45 2006
@@ -111,29 +111,56 @@
 	return st && st->be->free ? st->be->free(st) : -1;
 }
 
-int ast_storage_get(struct ast_storage *st, const char *objectname, char *localfile, size_t localfilesize)
-{
-	return st->be->get ? st->be->get(st, objectname, localfile, localfilesize) : -1;
-}
-
-int ast_storage_put(struct ast_storage *st, const char *objectname, const char *localfile)
-{
-	return st->be->put ? st->be->put(st, objectname, localfile) : -1;
-}
-
-int ast_storage_delete(struct ast_storage *st, const char *objectname)
-{
-	return st->be->delete ? st->be->delete(st, objectname) : -1;
+int ast_storage_get(struct ast_storage *st, const char *objectname, const char *fileformats, char *localfile, size_t localfilesize)
+{
+	return st->be->get ? st->be->get(st, objectname, fileformats, localfile, localfilesize) : -1;
+}
+
+int ast_storage_put(struct ast_storage *st, const char *objectname, const char *fileformats, const char *localfile)
+{
+	return st->be->put ? st->be->put(st, objectname, fileformats, localfile) : -1;
+}
+
+int ast_storage_delete(struct ast_storage *st, const char *objectname, const char *fileformats)
+{
+	return st->be->delete ? st->be->delete(st, objectname, fileformats) : -1;
+}
+
+void *ast_storage_opendir(struct ast_storage *st, const char *objectpath)
+{
+	return st->be->opendir ? st->be->opendir(st, objectpath) : NULL;
+}
+
+int ast_storage_readdir(struct ast_storage *st, void *dirptr, struct ast_storage_dirent *dirent)
+{
+	return st->be->readdir ? st->be->readdir(st, dirptr, dirent) : -1;
+}
+
+int ast_storage_closedir(struct ast_storage *st, void *dirptr)
+{
+	return st->be->closedir ? st->be->closedir(st, dirptr) : -1;
 }
 
 int ast_storage_count(struct ast_storage *st, const char *objectpath)
 {
-	return st->be->count ? st->be->count(st, objectpath) : -1;
-}
-
-int ast_storage_parseoptions(struct ast_storage *st, const char *var, const char *value)
-{
-	return st->be->parseoptions ? st->be->parseoptions(st, var, value) : -1;
+	void *dirptr;
+	struct ast_storage_dirent dirent;
+	int count = 0;
+
+	if (!(st->be->opendir && st->be->readdir && st->be->closedir))
+		return -1;
+
+	dirptr = st->be->opendir(st, objectpath);
+	if (!dirptr)
+		return -1;
+
+	while (st->be->readdir(st, dirptr, &dirent) == 0) {
+		if (strcmp(dirent.format, "txt") == 0)
+			count++;
+	}
+
+	st->be->closedir(st, dirptr);
+	return count;
 }
 
 static int show_storage_engines(int fd, int argc, char *argv[])

Modified: team/group/ast_storage/res/res_storage_file.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/res/res_storage_file.c?view=diff&rev=48342&r1=48341&r2=48342
==============================================================================
--- team/group/ast_storage/res/res_storage_file.c (original)
+++ team/group/ast_storage/res/res_storage_file.c Wed Dec  6 18:55:45 2006
@@ -41,6 +41,11 @@
 	char rootpath[128];
 };
 
+struct file_storage_dir {
+	DIR *dir;
+	char path[256];
+};
+
 static const struct ast_storage_be file_se;
 
 static struct ast_storage *se_new_file(const char *uri)
@@ -57,7 +62,7 @@
 	return 0;
 }
 
-static int se_get_file(struct ast_storage *st, const char *objectname, char *localfile, size_t localfilesize)
+static int se_get_file(struct ast_storage *st, const char *objectname, const char *fileformats, char *localfile, size_t localfilesize)
 {
 	struct ast_storage_file *fst = (struct ast_storage_file *)st;
 	char dirname[256], *dirnameptr;
@@ -89,7 +94,7 @@
 	return res;
 }
 
-static int se_put_file(struct ast_storage *st, const char *objectname, const char *localfile)
+static int se_put_file(struct ast_storage *st, const char *objectname, const char *fileformats, const char *localfile)
 {
 	struct ast_storage_file *fst = (struct ast_storage_file *)st;
 	int ifd;
@@ -133,35 +138,66 @@
 	return res;
 }
 
-static int se_delete_file(struct ast_storage *st, const char *objectname)
+static int se_delete_file(struct ast_storage *st, const char *objectname, const char *fileformats)
 {
 	struct ast_storage_file *fst = (struct ast_storage_file *)st;
 	char dest[256];
-	snprintf(dest, sizeof(dest), "%s/%s", fst->rootpath, objectname);
-	return unlink(dest);
-}
-
-static int se_count_file(struct ast_storage *st, const char *objectpath)
-{
-	struct ast_storage_file *fst = (struct ast_storage_file *)st;
-	char dest[256];
-	DIR *dir;
-	struct dirent *dirent;
-	int count = 0;
-	snprintf(dest, sizeof(dest), "%s/%s", fst->rootpath, objectpath);
-	dir = opendir(dest);
-	while ((dirent = readdir(dir))) {
-		/* Probably not exactly correct */
-		if (strncmp(dirent->d_name, ".", 1) != 0)
-			count++;
-	}
-	closedir(dir);
-
+
+	if (objectname[0] == '/')
+		return unlink(objectname);
+	else {
+		snprintf(dest, sizeof(dest), "%s/%s", fst->rootpath, objectname);
+		return unlink(dest);
+	}
+}
+
+static void *se_opendir_file(struct ast_storage *st, const char *objectpath)
+{
+	struct ast_storage_file *fst = (struct ast_storage_file *)st;
+	struct file_storage_dir *dir = malloc(sizeof *dir);
+
+	if (objectpath[0] == '/')
+		ast_copy_string(dir->path, objectpath, sizeof(dir->path));
+	else
+		snprintf(dir->path, sizeof(dir->path), "%s/%s", fst->rootpath, objectpath);
+
+	if ((dir->dir = opendir(dir->path)))
+		return dir;
+	else {
+		free(dir);
+		return NULL;
+	}
+}
+
+static int se_readdir_file(struct ast_storage *st, void *dirptr, struct ast_storage_dirent *dirent)
+{
+	struct dirent *f;
+	struct file_storage_dir *dir = dirptr;
+	char *fmt;
+
+	if (dirent == NULL)
+		return EINVAL;
+
+	memset(dirent, 0, sizeof(*dirent));
+
+	if ((f = readdir(dir->dir))) {
+		/* Parse out the file format */
+		ast_copy_string(dirent->name, f->d_name, sizeof(dirent->name));
+		if ((fmt = strrchr(dirent->name, '.'))) {
+			*fmt++ = '\0';
+			ast_copy_string(dirent->format, fmt, sizeof(dirent->format));
+		}
+	}
 	return 0;
 }
 
-static int se_parseoptions_file(struct ast_storage *st, const char *var, const char *value)
-{
+static int se_closedir_file(struct ast_storage *st, void *dirptr)
+{
+	struct file_storage_dir *dir = dirptr;
+	if (dir == NULL)
+		return EINVAL;
+	closedir(dir->dir);
+	free(dir);
 	return 0;
 }
 
@@ -172,8 +208,9 @@
 	.get = se_get_file,
 	.put = se_put_file,
 	.delete = se_delete_file,
-	.count = se_count_file,
-	.parseoptions = se_parseoptions_file,
+	.opendir = se_opendir_file,
+	.readdir = se_readdir_file,
+	.closedir = se_closedir_file,
 };
 
 static int load_module(void)

Modified: team/group/ast_storage/res/res_storage_odbc.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/res/res_storage_odbc.c?view=diff&rev=48342&r1=48341&r2=48342
==============================================================================
--- team/group/ast_storage/res/res_storage_odbc.c (original)
+++ team/group/ast_storage/res/res_storage_odbc.c Wed Dec  6 18:55:45 2006
@@ -41,15 +41,15 @@
 #include <fcntl.h>
 #include <errno.h>
 
-/* Number of bytes to transfer when moving a large field */
-#define	CHUNKSIZE	65536
-
 struct ast_storage_odbc {
 	const struct ast_storage_be *be;
 	char odbc_class[128];
 	char tablename[128];
 	char pathname[128];
 	struct odbc_obj *conn;
+};
+
+struct odbc_storage_dir {
 	SQLHSTMT sth;
 };
 
@@ -126,8 +126,6 @@
 static int se_free_odbc(struct ast_storage *st)
 {
 	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
-	if (ost->sth)
-		SQLFreeHandle(SQL_HANDLE_STMT, ost->sth);
 	ast_odbc_release_obj(ost->conn);
 	free(ost);
 	return 0;
@@ -158,7 +156,7 @@
 	ast_copy_string(filename, filename2, filenamesize);
 }
 
-static int se_get_odbc(struct ast_storage *st, const char *objectname, char *localfile, size_t localfilesize)
+static int se_get_odbc(struct ast_storage *st, const char *objectname, const char *fileformats, char *localfile, size_t localfilesize)
 {
 	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
 	int res = -1, tempfd, x, gotten = 0;
@@ -241,6 +239,7 @@
 
 			if (!strcasecmp(coltitle, "recording")) {
 				int fdlen;
+				int chunksize = 0x4000000; /* Try 64MB chunks initially */
 				off_t chunk_offset;
 				void *fdm = NULL;
 				SQLINTEGER colsize2;
@@ -273,13 +272,20 @@
 				}
 
 				/* Grab data in 64k chunks */
-				for (chunk_offset = 0; chunk_offset < fdlen; chunk_offset += CHUNKSIZE) {
-					/* Add one to the CHUNKSIZE, because ODBC always adds a terminating NULL */
-					if ((fdm = mmap(NULL, CHUNKSIZE + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, chunk_offset)) == (void *)-1) {
-						ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
-						goto endget;
+				for (chunk_offset = 0; chunk_offset < fdlen; chunk_offset += chunksize) {
+					/* Add one to the chunksize, because ODBC always adds a terminating NULL */
+					if ((fdm = mmap(NULL, chunksize + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, chunk_offset)) == (void *)-1) {
+						/* Reduce chunk size and try again */
+						chunk_offset--;
+						chunksize >>= 1;
+						/* Don't try anything less than 2k */
+						if (chunksize < 2048) {
+							ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
+							goto endget;
+						}
+						continue;
 					} else {
-						res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE + 1, NULL);
+						res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, chunksize + 1, NULL);
 						munmap(fdm, 0);
 						if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 							ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
@@ -324,7 +330,7 @@
 	return res ? -1 : 0;
 }
 
-static int se_put_odbc(struct ast_storage *st, const char *objectname, const char *localfile)
+static int se_put_odbc(struct ast_storage *st, const char *objectname, const char *fileformats, const char *localfile)
 {
 	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
 	int res = -1, x;
@@ -337,6 +343,7 @@
 	SQLHSTMT stmt = NULL;
 	DIR *dir;
 	struct dirent *dirent;
+	int chunksize = 0x4000000; /* 64 MB initially */
 
 	snprintf(reallocalfile, sizeof(reallocalfile), "%s.txt", localfile);
 	cfg = ast_config_load(reallocalfile);
@@ -425,14 +432,19 @@
 		res = SQLExecute(stmt);
 
 		if (res == SQL_NEED_DATA) {
-			for (offset = 0; offset < filesize; offset += CHUNKSIZE) {
-				void *fdm = mmap(NULL, CHUNKSIZE + 1, PROT_READ, MAP_SHARED, fd, offset);
+			for (offset = 0; offset < filesize; offset += chunksize) {
+				void *fdm = mmap(NULL, chunksize + 1, PROT_READ, MAP_SHARED, fd, offset);
 				if (fdm == (void *)-1) {
-					ast_log(LOG_ERROR, "Unable to mmap file %s: %s (%d)\n", reallocalfile, strerror(errno), errno);
-					goto endput;
+					offset--;
+					chunksize >>= 1;
+					if (chunksize < 2048) {
+						ast_log(LOG_ERROR, "Unable to mmap file %s: %s (%d)\n", reallocalfile, strerror(errno), errno);
+						goto endput;
+					}
+					continue;
 				}
-				SQLPutData(stmt, fdm, CHUNKSIZE);
-				munmap(fdm, 0);
+				SQLPutData(stmt, fdm, chunksize + offset > filesize ? filesize - offset : chunksize);
+				munmap(fdm, chunksize);
 			}
 		} else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 			ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n", sql);
@@ -450,7 +462,7 @@
 	return res ? -1 : 0;
 }
 
-static int se_delete_odbc(struct ast_storage *st, const char *objectname)
+static int se_delete_odbc(struct ast_storage *st, const char *objectname, const char *fileformats)
 {
 	char pathname[256], filename[256], sql[256];
 	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
@@ -488,14 +500,19 @@
 	return res ? -1 : 0;
 }
 
-static int se_count_odbc(struct ast_storage *st, const char *objectpath)
+static void *se_opendir_odbc(struct ast_storage *st, const char *objectpath)
+{
+	return NULL;
+}
+
+static int se_readdir_odbc(struct ast_storage *st, void *dirptr, struct ast_storage_dirent *dirent)
 {
 	return -1;
 }
 
-static int se_parseoptions_odbc(struct ast_storage *st, const char *var, const char *value)
-{
-	return 0;
+static int se_closedir_odbc(struct ast_storage *st, void *dirptr)
+{
+	return -1;
 }
 
 static const struct ast_storage_be odbc_se = {
@@ -505,8 +522,9 @@
 	.get = se_get_odbc,
 	.put = se_put_odbc,
 	.delete = se_delete_odbc,
-	.count = se_count_odbc,
-	.parseoptions = se_parseoptions_odbc,
+	.opendir = se_opendir_odbc,
+	.readdir = se_readdir_odbc,
+	.closedir = se_closedir_odbc,
 };
 
 static int load_module(void)



More information about the asterisk-commits mailing list