2
0
Эх сурвалжийг харах

- new version of flatstore module for new db api in SER 2.1

Jan Janak 17 жил өмнө
parent
commit
3e87a030be

+ 216 - 0
modules/db_flatstore/flat_cmd.c

@@ -0,0 +1,216 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
+ *
+ * This file is part of SER, a free SIP server.
+ *
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Inmplementation of flatstore commands.
+ */
+
+#include "flat_cmd.h"
+#include "flat_con.h"
+#include "flatstore_mod.h"
+
+#include "../../mem/mem.h"
+
+#include <string.h>
+#include <errno.h>
+
+
+/** Destroys a flat_cmd structure.
+ * This function frees all memory used by flat_cmd structure.
+ * @param cmd A pointer to generic db_cmd command being freed.
+ * @param payload A pointer to flat_cmd structure to be freed.
+ */
+static void flat_cmd_free(db_cmd_t* cmd, struct flat_cmd* payload)
+{
+	db_drv_free(&payload->gen);
+	pkg_free(payload);
+}
+
+
+int flat_cmd(db_cmd_t* cmd)
+{
+	struct flat_cmd* fcmd;
+	db_con_t* con;
+
+	if (cmd->type != DB_PUT) {
+		ERR("flatstore: The driver supports PUT operation only.\n");
+		return -1;
+	}
+
+	if (DB_FLD_EMPTY(cmd->vals)) {
+		ERR("flatstore: PUT command with no values encountered\n");
+		return -1;
+	}
+
+	fcmd = (struct flat_cmd*)pkg_malloc(sizeof(struct flat_cmd));
+	if (fcmd == NULL) {
+		ERR("flatstore: No memory left\n");
+		return -1;
+	}
+	memset(fcmd, '\0', sizeof(struct flat_cmd));
+	if (db_drv_init(&fcmd->gen, flat_cmd_free) < 0) goto error;
+
+	/* FIXME */
+	con = cmd->ctx->con[db_payload_idx];
+	if (flat_open_table(&fcmd->file_index, con, &cmd->table) < 0) goto error;
+
+	DB_SET_PAYLOAD(cmd, fcmd);
+	return 0;
+
+ error:
+	if (fcmd) {
+		DB_SET_PAYLOAD(cmd, NULL);
+		db_drv_free(&fcmd->gen);
+		pkg_free(fcmd);
+	}
+	return -1;
+}
+
+
+int flat_put(db_res_t* res, db_cmd_t* cmd)
+{
+	struct flat_cmd* fcmd;
+	struct flat_con* fcon;
+	db_con_t* con;
+	int i;
+	FILE* f;
+	char delims[4], *s;
+	size_t len;
+
+	fcmd = DB_GET_PAYLOAD(cmd);
+	/* FIXME */
+	con = cmd->ctx->con[db_payload_idx];
+	fcon = DB_GET_PAYLOAD(con);
+
+	f = fcon->file[fcmd->file_index].f;
+	if (f == NULL) {
+		ERR("flatstore: Cannot write, file handle not open\n");
+		return -1;
+	}
+
+	if (flat_local_timestamp < *flat_rotate) {
+		flat_con_disconnect(con);
+		if (flat_con_connect(con) < 0) {
+			ERR("flatstore: Error while rotating files\n");
+			return -1;
+		}
+		flat_local_timestamp = *flat_rotate;
+	}
+
+	for(i = 0; !DB_FLD_EMPTY(cmd->vals) && !DB_FLD_LAST(cmd->vals[i]); i++) {
+		if (i) {
+			if (fprintf(f, "%c", flat_delimiter.s[0]) < 0) goto error;
+		}
+
+		/* TODO: how to distinguish NULL from empty */
+		if (cmd->vals[i].flags & DB_NULL) continue;
+		
+		switch(cmd->vals[i].type) {
+		case DB_INT:
+			if (fprintf(f, "%d", cmd->vals[i].v.int4) < 0) goto error;
+			break;
+
+		case DB_FLOAT:
+			if (fprintf(f, "%f", cmd->vals[i].v.flt) < 0) goto error;
+			break;
+
+		case DB_DOUBLE:
+			if (fprintf(f, "%f", cmd->vals[i].v.dbl) < 0) goto error;
+			break;
+
+		case DB_DATETIME:
+			if (fprintf(f, "%u", (unsigned int)cmd->vals[i].v.time) < 0) 
+				goto error;
+			break;
+
+		case DB_CSTR:
+			s = cmd->vals[i].v.cstr;
+			delims[0] = flat_delimiter.s[0];
+			delims[1] = flat_record_delimiter.s[0];
+			delims[2] = flat_escape.s[0];
+			delims[3] = '\0';
+			while (*s) {
+				len = strcspn(s, delims);
+				if (fprintf(f, "%.*s", (int)len, s) < 0) goto error;
+				s += len;
+				if (*s) {
+					/* FIXME: do not use the escaped value for easier parsing */
+					if (fprintf(f, "%c%c", flat_escape.s[0], *s) < 0) goto error;
+					s++;
+				}
+			}
+			break;
+
+		case DB_STR:
+		case DB_BLOB:
+			/* FIXME: rewrite */
+			s = cmd->vals[i].v.lstr.s;
+			len = cmd->vals[i].v.lstr.len;
+			while (len > 0) {
+				char *c;
+				for (c = s; len > 0 && 
+						 *c != flat_delimiter.s[0] && 
+						 *c != flat_record_delimiter.s[0] && 
+						 *c != flat_escape.s[0]; 
+					 c++, len--);
+				if (fprintf(f, "%.*s", (int)(c-s), s) < 0) goto error;
+				s = c;
+				if (len > 0) {
+					if (fprintf(f, "%c%c", flat_escape.s[0], *s) < 0) goto error;
+					s++;
+					len--;
+				}
+			}
+			break;
+
+		case DB_BITMAP:
+			if (fprintf(f, "%u", cmd->vals[i].v.bitmap) < 0) goto error;
+			break;
+
+		default:
+			BUG("flatstore: Unsupported field type %d\n", cmd->vals[i].type);
+			return -1;
+		}
+	}
+
+	if (fprintf(f, "%c", flat_record_delimiter.s[0]) < 0) goto error;
+
+	if (flat_flush && (fflush(f) != 0)) {
+		ERR("flatstore: Error while flushing file: %s\n", strerror(errno));
+		return -1;
+	}
+
+	return 0;
+
+ error:
+	ERR("flastore: Error while writing data to file\n");
+	return -1;
+}
+
+
+/** @} */

+ 75 - 0
modules/db_flatstore/flat_cmd.h

@@ -0,0 +1,75 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
+ *
+ * This file is part of SER, a free SIP server.
+ *
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _FLAT_CMD_H
+#define _FLAT_CMD_H
+
+#include "../../db/db_drv.h"
+#include "../../db/db_cmd.h"
+
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Inmplementation of flatstore commands.
+ */
+
+
+/** Extension structure of db_cmd adding flatstore specific data.
+ * This data structure extends the generic data structure db_cmd in the
+ * database API with data specific to the flatstore driver.
+ */
+struct flat_cmd {
+	db_drv_t gen; /**< Generic part of the data structure (must be first) */
+	int file_index;
+};
+
+
+/** Creates a new flat_cmd data structure.
+ * This function allocates and initializes memory for a new flat_cmd data
+ * structure. The data structure is then attached to the generic db_cmd
+ * structure in cmd parameter.
+ * @param cmd A generic db_cmd structure to which the newly created flat_cmd
+ *            structure will be attached.
+ */
+int flat_cmd(db_cmd_t* cmd);
+
+
+/** The main execution function in flat SER driver.
+ * This is the main execution function in this driver. It is executed whenever
+ * a SER module calls db_exec and the target database of the commands is
+ * flatstore.
+ * @param res A pointer to (optional) result structure if the command returns
+ *            a result.
+ * @retval 0 if executed successfully
+ * @retval A negative number if the database server failed to execute command
+ * @retval A positive number if there was an error on client side (SER)
+ */
+int flat_put(db_res_t* res, db_cmd_t* cmd);
+
+
+/** @} */
+
+#endif /* _FLAT_CMD_H */

+ 244 - 133
modules/db_flatstore/flat_con.c

@@ -1,184 +1,295 @@
 /*
  * $Id$
  *
- * Flastore module connection structure
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * Copyright (C) 2004 FhG Fokus
+ * This file is part of SER, a free SIP server.
  *
- * This file is part of ser, a free SIP server.
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <string.h>
-#include <errno.h>
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Inmplementation of flatstore "connections".
+ */
+
+#include "flat_con.h"
+#include "flatstore_mod.h"
+
 #include "../../mem/mem.h"
 #include "../../dprint.h"
 #include "../../ut.h"
-#include "flatstore_mod.h"
-#include "flat_con.h"
 
-#define FILE_SUFFIX ".log"
-#define FILE_SUFFIX_LEN (sizeof(FILE_SUFFIX) - 1)
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
 
-/* returns a pkg_malloc'ed file name */
-static char* get_name(struct flat_id* id)
+
+/** Free all memory allocated for a flat_con structure.
+ * This function function frees all memory that is in use by
+ * a flat_con structure.
+ * @param con A generic db_con connection structure.
+ * @param payload Flatstore specific payload to be freed.
+ */
+static void flat_con_free(db_con_t* con, struct flat_con* payload)
 {
-	char* buf;
-	int buf_len;
-	char* num, *ptr;
-	int num_len;
-	int total_len;
-
-	buf_len=pathmax();
-	if (!id) {
-		LOG(L_ERR, "get_name: Invalid parameter value\n");
-		return 0;
-	}
-	total_len=id->dir.len+1 /* / */+id->table.len+1 /* _ */+
-				FILE_SUFFIX_LEN+1 /* \0 */; /* without pid*/
-	if (buf_len<total_len){
-		LOG(L_ERR, "get_name: the path is too long (%d and PATHMAX is %d)\n",
-					total_len, buf_len);
-		return 0;
+	int i;
+	if (!payload) return;
+
+	/* delete the structure only if there are no more references
+	 * to it in the connection pool
+	 */
+	if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
+	
+	db_pool_entry_free(&payload->gen);
+
+	if (payload->file) {
+		for(i = 0; i < payload->n; i++) {
+			if (payload->file[i].filename) pkg_free(payload->file[i].filename);
+			if (payload->file[i].table.s) pkg_free(payload->file[i].table.s);
+			if (payload->file[i].f) fclose(payload->file[i].f);
+		}
+		pkg_free(payload->file);
 	}
+	pkg_free(payload);
+}
 
-	buf=pkg_malloc(buf_len);
-	if (buf==0){
-		LOG(L_ERR, "ERROR: get_name: memory allocation failure\n");
-		return 0;
-	}
 
-	ptr = buf;
+int flat_con(db_con_t* con)
+{
+	struct flat_con* fcon;
+
+	/* First try to lookup the connection in the connection pool and
+	 * re-use it if a match is found
+	 */
+	fcon = (struct flat_con*)db_pool_get(con->uri);
+	if (fcon) {
+		DBG("flatstore: A handle to %.*s found in the connection pool\n",
+			STR_FMT(&con->uri->body));
+		goto found;
+	}
 
-	memcpy(ptr, id->dir.s, id->dir.len);
-	ptr += id->dir.len;
-	*ptr++ = '/';
+	fcon = (struct flat_con*)pkg_malloc(sizeof(struct flat_con));
+	if (fcon == NULL) {
+		ERR("flatstore: No memory left\n");
+		goto error;
+	}
+	memset(fcon, '\0', sizeof(struct flat_con));
+	if (db_pool_entry_init(&fcon->gen, flat_con_free, con->uri) < 0) goto error;
+
+	DBG("flastore: Preparing new file handles to files in %.*s\n", 
+		STR_FMT(&con->uri->body));
+	
+	/* Put the newly created flatstore connection into the pool */
+	db_pool_put((struct db_pool_entry*)fcon);
+	DBG("flatstore: Handle stored in connection pool\n");
+
+ found:
+	/* Attach driver payload to the db_con structure and set connect and
+	 * disconnect functions
+	 */
+	DB_SET_PAYLOAD(con, fcon);
+	con->connect = flat_con_connect;
+	con->disconnect = flat_con_disconnect;
+	return 0;
 
-	memcpy(ptr, id->table.s, id->table.len);
-	ptr += id->table.len;
+ error:
+	if (fcon) {
+		db_pool_entry_free(&fcon->gen);
+		pkg_free(fcon);
+	}
+	return -1;
+}
 
-	*ptr++ = '_';
 
-	num = int2str(flat_pid, &num_len);
-	if (buf_len<(total_len+num_len)){
-		LOG(L_ERR, "ERROR:  get_name: the path is too long (%d and PATHMAX is"
-				" %d)\n", total_len+num_len, buf_len);
-		pkg_free(buf);
-		return 0;
+int flat_con_connect(db_con_t* con)
+{
+	struct flat_con* fcon;
+	int i;
+	
+	fcon = DB_GET_PAYLOAD(con);
+	
+	/* Do not reconnect already connected connections */
+	if (fcon->flags & FLAT_OPENED) return 0;
+
+	DBG("flatstore: Opening handles to files in '%.*s'\n", 
+		STR_FMT(&con->uri->body));
+
+	/* FIXME: Make sure the directory exists, is accessible,
+	 * and we can create files there
+	 */
+
+	DBG("flatstore: Directory '%.*s' opened successfully\n", 
+		STR_FMT(&con->uri->body));
+
+	for(i = 0; i < fcon->n; i++) {
+		if (fcon->file[i].f) {
+			fclose(fcon->file[i].f);
+		}
+		fcon->file[i].f = fopen(fcon->file[i].filename, "a");
+		if (fcon->file[i].f == NULL) {
+			ERR("flatstore: Error while opening file handle to '%s': %s\n", 
+				fcon->file[i].filename, strerror(errno));
+			return -1;
+		}
 	}
-	memcpy(ptr, num, num_len);
-	ptr += num_len;
 
-	memcpy(ptr, FILE_SUFFIX, FILE_SUFFIX_LEN);
-	ptr += FILE_SUFFIX_LEN;
+	fcon->flags |= FLAT_OPENED;
+	return 0;
 
-	*ptr = '\0';
-	return buf;
 }
 
 
-struct flat_con* flat_new_connection(struct flat_id* id)
+void flat_con_disconnect(db_con_t* con)
 {
-	char* fn;
+	struct flat_con* fcon;
+	int i;
 
-	struct flat_con* res;
+	fcon = DB_GET_PAYLOAD(con);
 
-	if (!id) {
-		LOG(L_ERR, "flat_new_connection: Invalid parameter value\n");
-		return 0;
-	}
+	if ((fcon->flags & FLAT_OPENED) == 0) return;
+
+	DBG("flatstore: Closing handles to files in '%.*s'\n", 
+		STR_FMT(&con->uri->body));
 
-	res = (struct flat_con*)pkg_malloc(sizeof(struct flat_con));
-	if (!res) {
-		LOG(L_ERR, "flat_new_connection: No memory left\n");
-		return 0;
+	for(i = 0; i < fcon->n; i++) {
+		if (fcon->file[i].f == NULL) continue;
+		fclose(fcon->file[i].f);
+		fcon->file[i].f = NULL;
 	}
 
-	memset(res, 0, sizeof(struct flat_con));
-	res->ref = 1;
+	fcon->flags &= ~FLAT_OPENED;
+}
 
-	res->id = id;
 
-	fn = get_name(id);
-	if (fn==0){
-		LOG(L_ERR, "flat_new_connection: get_name() failed\n");
-		return 0;
-	}
+/* returns a pkg_malloc'ed file name */
+static char* get_filename(str* dir, str* name)
+{
+    char* buf, *p;
+    int buf_len, total_len;
 
-	res->file = fopen(fn, "a");
-	pkg_free(fn); /* we don't need fn anymore */
-	if (!res->file) {
-		LOG(L_ERR, "flat_new_connection: %s\n", strerror(errno));
-		pkg_free(res);
-		return 0;
-	}
+    buf_len = pathmax();
 
-	return res;
-}
+    total_len = dir->len + 1 /* / */ + 
+		name->len + 1 /* _ */+
+		flat_pid.len +
+		flat_suffix.len + 1 /* \0 */;
 
+    if (buf_len < total_len) {
+        ERR("flatstore: The path is too long (%d and PATHMAX is %d)\n",
+            total_len, buf_len);
+        return 0;
+    }
 
-/*
- * Close the connection and release memory
- */
-void flat_free_connection(struct flat_con* con)
-{
-	if (!con) return;
-	if (con->id) free_flat_id(con->id);
-	if (con->file) {
-		fclose(con->file);
-	}
-	pkg_free(con);
-}
+    if ((buf = pkg_malloc(buf_len)) == NULL) {
+        ERR("flatstore: No memory left\n");
+        return 0;
+    }
+    p = buf;
 
+    memcpy(p, dir->s, dir->len);
+    p += dir->len;
 
-/*
- * Reopen a connection
- */
-int flat_reopen_connection(struct flat_con* con)
-{
-	char* fn;
+    *p++ = '/';
 
-	if (!con) {
-		LOG(L_ERR, "flat_reopen_connection: Invalid parameter value\n");
-		return -1;
-	}
+    memcpy(p, name->s, name->len);
+    *p += name->len;
 
-	if (con->file) {
-		fclose(con->file);
-		con->file = 0;
+    *p++ = '_';
 
-		fn = get_name(con->id);
-		if (fn == 0) {
-			LOG(L_ERR, "flat_reopen_connection: get_name() failed\n");
-		        return -1;
-		}
+    memcpy(p, flat_pid.s, flat_pid.len);
+    p += flat_pid.len;
 
-		con->file = fopen(fn, "a");
-		pkg_free(fn);
+    memcpy(p, flat_suffix.s, flat_suffix.len);
+    p += flat_suffix.len;
 
-		if (!con->file) {
-			LOG(L_ERR, "flat_reopen_connection: Invalid parameter value\n");
-			return -1;
+    *p = '\0';
+    return buf;
+}
+
+
+
+int flat_open_table(int* idx, db_con_t* con, str* name)
+{
+	struct flat_con* fcon;
+	struct flat_file* new;
+	int i;
+	char* filename, *table;
+
+	new = NULL;
+	filename = NULL;
+	table = NULL;
+	fcon = DB_GET_PAYLOAD(con);
+	
+	for(i = 0; i < fcon->n; i++) {
+		if (name->len == fcon->file[i].table.len &&
+			!strncmp(name->s, fcon->file[i].table.s, name->len))
+			break;
+	}
+	if (fcon->n == i) {
+		/* Perform operations that can fail first (before resizing
+		 * fcon->file, so that we can fail gracefully if one of the
+		 * operations fail. 
+		 */
+		if ((filename = get_filename(&con->uri->body, name)) == NULL)
+			goto no_mem;
+
+		if ((table = pkg_malloc(name->len)) == NULL) goto no_mem;
+		memcpy(table, name->s, name->len);
+
+		new = pkg_realloc(fcon->file, sizeof(struct flat_file) * (fcon->n + 1));
+		if (new == NULL) goto no_mem;
+
+		fcon->file = new;
+		new = new + fcon->n; /* Advance to the new (last) element */
+		fcon->n++;
+
+		new->table.s = table;
+		new->table.len = name->len;
+		new->filename = filename;
+
+		/* Also open the file if we are connected already */
+		if (fcon->flags & FLAT_OPENED) {
+			if ((new->f = fopen(new->filename, "a")) == NULL) {
+				ERR("flatstore: Error while opening file handle to '%s': %s\n", 
+					new->filename, strerror(errno));
+				return -1;
+			}			
+		} else {
+			new[fcon->n].f = NULL;
 		}
+		
+		*idx = fcon->n - 1;
+	} else {
+		*idx = i;
 	}
-
+	
 	return 0;
+
+ no_mem:
+	ERR("flatstore: No memory left\n");
+	if (filename) pkg_free(filename);
+	if (table) pkg_free(table);
+	return -1;
 }
+
+
+/** @} */

+ 65 - 43
modules/db_flatstore/flat_con.h

@@ -1,70 +1,92 @@
-/* 
+/*
  * $Id$
  *
- * Flatstore module connection structure
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * This file is part of SER, a free SIP server.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #ifndef _FLAT_CON_H
 #define _FLAT_CON_H
 
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Inmplementation of flatstore "connections".
+ */
+
+#include "../../db/db_pool.h"
+#include "../../db/db_con.h"
+#include "../../db/db_uri.h"
+
 #include <stdio.h>
-#include <time.h>
-#include "flat_id.h"
 
-struct flat_con {
-	struct flat_id* id;    /* Connection identifier */
-	int ref;               /* Reference count */
-	FILE* file;            /* File descriptor structure */
-	struct flat_con* next; /* Next connection in the pool */
+
+/** 
+ * Per-connection flags for flatstore connections.
+ */
+enum flat_con_flags {
+	FLAT_OPENED      = (1 << 0), /**< Handle opened successfully */
 };
 
 
-/*
- * Some convenience wrappers
- */
-#define CON_FILE(db_con) (((struct flat_con*)((db_con)->tail))->file)
+struct flat_file {
+	char* filename; /**< Name of file within the directory */
+	str table;      /**< Table name the file belongs to */
+	FILE* f;        /**< File handle of the file */
+};
 
 
-/*
- * Create a new connection structure,
- * open the MySQL connection and set reference count to 1
+/** A structure representing flatstore virtual connections.
+ * Flatstore module is writing data to files on a local filesystem only so
+ * there is no concept of real database connections.  In flatstore module a
+ * connection is related with a directory on the filesystem and it contains
+ * file handles to files in that directory. The file handles are then used
+ * from commands to write data in them.
  */
-struct flat_con* flat_new_connection(struct flat_id* id);
+struct flat_con {
+	db_pool_entry_t gen;    /**< Generic part of the structure */
+	struct flat_file* file;
+	int n;                  /**< Size of the file array */
+	unsigned int flags;     /**< Flags */
+};
 
 
-/*
- * Close the connection and release memory
+/** Create a new flat_con structure.
+ * This function creates a new flat_con structure and attachs the structure to
+ * the generic db_con structure in the parameter.
+ * @param con A generic db_con structure to be extended with flatstore payload
+ * @retval 0 on success
+ * @retval A negative number on error
  */
-void flat_free_connection(struct flat_con* con);
+int flat_con(db_con_t* con);
 
 
-/*
- * Reopen a connection
- */
-int flat_reopen_connection(struct flat_con* con);
+int flat_con_connect(db_con_t* con);
+
+
+void flat_con_disconnect(db_con_t* con);
+
+
+int flat_open_table(int *idx, db_con_t* con, str* name);
 
 
 #endif /* _FLAT_CON_H */

+ 0 - 87
modules/db_flatstore/flat_id.c

@@ -1,87 +0,0 @@
-/* 
- * $Id$
- *
- * Flatstore module connection identifier
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <string.h>
-#include "../../dprint.h"
-#include "../../mem/mem.h"
-#include "flat_id.h"
-
-
-
-/*
- * Create a new connection identifier
- */
-struct flat_id* new_flat_id(char* dir, char* table)
-{
-	struct flat_id* ptr;
-
-	if (!dir || !table) {
-		LOG(L_ERR, "new_flat_id: Invalid parameter(s)\n");
-		return 0;
-	}
-
-	ptr = (struct flat_id*)pkg_malloc(sizeof(struct flat_id));
-	if (!ptr) {
-		LOG(L_ERR, "new_flat_id: No memory left\n");
-		return 0;
-	}
-	memset(ptr, 0, sizeof(struct flat_id));
-
-	ptr->dir.s = dir;
-	ptr->dir.len = strlen(dir);
-	ptr->table.s = table;
-	ptr->table.len = strlen(table);
-
-	return ptr;
-}
-
-
-/*
- * Compare two connection identifiers
- */
-unsigned char cmp_flat_id(struct flat_id* id1, struct flat_id* id2)
-{
-	if (!id1 || !id2) return 0;
-	if (id1->dir.len != id2->dir.len) return 0;
-	if (id1->table.len != id2->table.len) return 0;
-
-	if (memcmp(id1->dir.s, id2->dir.s, id1->dir.len)) return 0;
-	if (memcmp(id1->table.s, id2->table.s, id1->table.len)) return 0;
-	return 1;
-}
-
-
-/*
- * Free a connection identifier
- */
-void free_flat_id(struct flat_id* id)
-{
-	if (!id) return;
-	pkg_free(id);
-}

+ 0 - 60
modules/db_flatstore/flat_id.h

@@ -1,60 +0,0 @@
-/* 
- * $Id$
- *
- * Flatstore connection identifier
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _FLAT_ID_H
-#define _FLAT_ID_H
-
-#include "../../str.h"
-
-
-struct flat_id {
-	str dir;   /* Database directory */ 
-	str table; /* Name of table */
-};
-
-
-/*
- * Create a new connection identifier
- */
-struct flat_id* new_flat_id(char* dir, char* table);
-
-
-/*
- * Compare two connection identifiers
- */
-unsigned char cmp_flat_id(struct flat_id* id1, struct flat_id* id2);
-
-
-/*
- * Free a connection identifier
- */
-void free_flat_id(struct flat_id* id);
-
-
-#endif /* _FLAT_ID_H */

+ 0 - 156
modules/db_flatstore/flat_pool.c

@@ -1,156 +0,0 @@
-/* 
- * $Id$
- *
- * Flatstore module connection pool
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <unistd.h>
-#include "../../dprint.h"
-#include "flat_pool.h"
-#include "flat_id.h"
-
-
-/* The head of the pool */
-static struct flat_con* pool = 0;
-
-/*
- * Pid of the process that added the last
- * connection to the pool. This is used to
- * check for inherited database connections.
- */
-static int pool_pid;
-
-
-
-/*
- * Get a connection from the pool, reuse existing
- * if possible, otherwise create a new one
- */
-struct flat_con* flat_get_connection(char* dir, char* table)
-{
-	struct flat_id* id;
-	struct flat_con* ptr;
-	int pid;
-
-	if (!dir || !table) {
-		LOG(L_ERR, "flat_get_connection: Invalid parameter value\n");
-		return 0;
-	}
-
-	pid = getpid();
-	if (pool && (pool_pid != pid)) {
-		LOG(L_ERR, "flat_get_connection: Inherited open database connections, this is not a good idea\n");
-		return 0;
-	}
-
-	pool_pid = pid;
-
-	id = new_flat_id(dir, table);
-	if (!id) return 0;
-
-	ptr = pool;
-	while (ptr) {
-		if (cmp_flat_id(id, ptr->id)) {
-			DBG("flat_get_connection: Connection found in the pool\n");
-			ptr->ref++;
-			free_flat_id(id);
-			return ptr;
-		}
-		ptr = ptr->next;
-	}
-
-	DBG("flat_get_connection: Connection not found in the pool\n");
-	ptr = flat_new_connection(id);
-	if (!ptr) {
-		free_flat_id(id);
-		return 0;
-	}
-
-	ptr->next = pool;
-	pool = ptr;
-	return ptr;
-}
-
-
-/*
- * Release a connection, the connection will be left
- * in the pool if ref count != 0, otherwise it
- * will be delete completely
- */
-void flat_release_connection(struct flat_con* con)
-{
-	struct flat_con* ptr;
-
-	if (!con) return;
-
-	if (con->ref > 1) {
-		     /* There are still other users, just
-		      * decrease the reference count and return
-		      */
-		DBG("flat_release_connection: Connection still kept in the pool\n");
-		con->ref--;
-		return;
-	}
-
-	DBG("flat_release_connection: Removing connection from the pool\n");
-
-	if (pool == con) {
-		pool = pool->next;
-	} else {
-		ptr = pool;
-		while(ptr) {
-			if (ptr->next == con) break;
-			ptr = ptr->next;
-		}
-		if (!ptr) {
-			LOG(L_ERR, "flat_release_connection: Weird, connection not found in the pool\n");
-		} else {
-			     /* Remove the connection from the pool */
-			ptr->next = con->next;
-		}
-	}
-
-	flat_free_connection(con);
-}
-
-
-/*
- * Close and reopen all opened connections
- */
-int flat_rotate_logs(void)
-{
-	struct flat_con* ptr;
-
-	ptr = pool;
-	while(ptr) {
-		if (flat_reopen_connection(ptr)) {
-			return -1;
-		}
-		ptr = ptr->next;
-	}
-
-	return 0;
-}

+ 0 - 62
modules/db_flatstore/flat_pool.h

@@ -1,62 +0,0 @@
-/* 
- * $Id$
- *
- * Flatstore module connection pool
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _FLAT_POOL_H
-#define _FLAT_POOL_H
-
-#include "flat_con.h"
-
-/*
- * Get a connection from the pool, reuse existing
- * if possible, otherwise create a new one
- */
-struct flat_con* flat_get_connection(char* dir, char* table);
-
-
-/*
- * Release a connection, the connection will be left
- * in the pool if ref count != 0, otherwise it
- * will be delete completely
- */
-void flat_release_connection(struct flat_con* con);
-
-
-/*
- * Close and reopen all opened connections
- */
-int flat_rotate_logs(void);
-
-
-/*
- * Reopen a connection
- */
-int flat_reopen_connection(struct flat_con* con);
-
-
-#endif /* _FLAT_POOL_H */

+ 35 - 23
modules/db_flatstore/flat_rpc.c

@@ -1,36 +1,46 @@
-/* 
- * $Id$ 
+/*
+ * $Id$
  *
- * Flatstore module interface
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * Copyright (C) 2004 FhG Fokus
+ * This file is part of SER, a free SIP server.
  *
- * This file is part of ser, a free SIP server.
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Flatstore management interface
  */
 
-#include "flatstore_mod.h"
 #include "flat_rpc.h"
+#include "flatstore_mod.h"
 
+#include <time.h>
 
+/** Register a new file rotation request.
+ * This function can be called through the management interface in SER and it
+ * will register a new file rotation request. This function only registers the
+ * request, it will be carried out next time SER attempts to write new data
+ * into the file.
+ */
 static void rotate(rpc_t* rpc, void* c)
 {
 	*flat_rotate = time(0);
@@ -47,3 +57,5 @@ rpc_export_t flat_rpc[] = {
 	{"flatstore.rotate", rotate, flat_rotate_doc, 0},
 	{0, 0, 0, 0},
 };
+
+/** @} */

+ 27 - 22
modules/db_flatstore/flat_rpc.h

@@ -1,37 +1,42 @@
-/* 
- * $Id$ 
+/*
+ * $Id$
  *
- * Flatstore module interface
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * Copyright (C) 2004-2005 FhG FOKUS
+ * This file is part of SER, a free SIP server.
  *
- * This file is part of ser, a free SIP server.
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #ifndef _FLAT_RPC_H
 #define _FLAT_RPC_H
 
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Flatstore management interface
+ */
+
 #include "../../rpc.h"
 
 extern rpc_export_t flat_rpc[];
 
+/** @} */
+
 #endif /* _FLAT_RPC_H */

+ 0 - 249
modules/db_flatstore/flatstore.c

@@ -1,249 +0,0 @@
-/*
- * $Id$
- *
- * Flatstore module interface
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- */
-
-#include <string.h>
-#include "../../mem/mem.h"
-#include "../../dprint.h"
-#include "flat_pool.h"
-#include "flat_con.h"
-#include "flatstore_mod.h"
-#include "flatstore.h"
-
-
-static int parse_flat_url(const char* url, const char** path)
-{
-	int len;
-
-	if (!url || !path) {
-		LOG(L_ERR, "parse_flat_url: Invalid parameter value\n");
-		return -1;
-	}
-
-	len = strlen(url);
-
-	*path = strchr(url, ':') + 1;
-	return 0;
-}
-
-
-
-/*
- * Initialize database module
- * No function should be called before this
- */
-db_con_t* flat_db_init(const char* url)
-{
-	db_con_t* res;
-
-	if (!url) {
-		LOG(L_ERR, "flat_db_init: Invalid parameter value\n");
-		return 0;
-	}
-
-	     /* We do not know the name of the table (and the name of the corresponding file)
-	      * at this point, we will simply store the path taken from url parameter in the
-	      * table variable, flat_use_table will then pick that value and open file
-	      */
-	res = pkg_malloc(sizeof(db_con_t) + sizeof(struct flat_con*));
-	if (!res) {
-		LOG(L_ERR, "flat_db_init: No memory left\n");
-		return 0;
-	}
-	memset(res, 0, sizeof(db_con_t) + sizeof(struct flat_con*));
-
-	if (parse_flat_url(url, &res->table) < 0) {
-		pkg_free(res);
-		return 0;
-	}
-
-	return res;
-}
-
-
-/*
- * Store name of table that will be used by
- * subsequent database functions
- */
-int flat_use_table(db_con_t* h, const char* t)
-{
-	struct flat_con* con;
-
-	if (!h || !t) {
-		LOG(L_ERR, "flat_use_table: Invalid parameter value\n");
-		return -1;
-	}
-
-	if (CON_TABLE(h) != t) {
-		if (CON_TAIL(h)) {
-			     /* Decrement the reference count
-			      * of the connection but do not remove
-			      * it from the connection pool
-			      */
-			con = (struct flat_con*)CON_TAIL(h);
-			con->ref--;
-
-		}
-
-		CON_TAIL(h) = (unsigned long)flat_get_connection((char*)CON_TABLE(h), (char*)t);
-		if (!CON_TAIL(h)) {
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-void flat_db_close(db_con_t* h)
-{
-	struct flat_con* con;
-
-	if (!h) {
-		LOG(L_ERR, "db_close: Invalid parameter value\n");
-		return;
-	}
-
-	con = (struct flat_con*)CON_TAIL(h);
-
-	if (con) {
-		flat_release_connection(con);
-	}
-	pkg_free(h);
-}
-
-
-/*
- * Insert a row into specified table
- * h: structure representing database connection
- * k: key names
- * v: values of the keys
- * n: number of key=value pairs
- */
-int flat_db_insert(db_con_t* h, db_key_t* k, db_val_t* v, int n)
-{
-	FILE* f;
-	int i;
-	char delims[4], *s;
-	size_t len;
-
-	f = CON_FILE(h);
-	if (!f) {
-		LOG(L_CRIT, "BUG: flat_db_insert: Uninitialized connection\n");
-		return -1;
-	}
-
-	if (local_timestamp < *flat_rotate) {
-		flat_rotate_logs();
-		local_timestamp = *flat_rotate;
-	}
-
-	for(i = 0; i < n; i++) {
-
-		if (!VAL_NULL(v + i)) {   // TODO: how to distinguish NULL from empty
-			switch(VAL_TYPE(v + i)) {
-				case DB_INT:
-					fprintf(f, "%d", VAL_INT(v + i));
-					break;
-
-				case DB_FLOAT:
-					fprintf(f, "%f", VAL_FLOAT(v + i));
-					break;
-
-				case DB_DOUBLE:
-					fprintf(f, "%f", VAL_DOUBLE(v + i));
-					break;
-
-				case DB_STRING: {
-					s = (char*) VAL_STRING(v + i);
-					delims[0] = flat_delimiter[0];
-					delims[1] = flat_record_delimiter[0];
-					delims[2] = flat_escape[0];
-					delims[3] = '\0';
-					while (*s) {
-						len = strcspn(s, delims);
-						fprintf(f, "%.*s", (int)len, s);
-						s+= len;
-						if (*s) {
-							fprintf(f, "%c%c", flat_escape[0], *s);
-							s++;
-						}
-					}
-					break;
-				}
-				case DB_STR:
-				case DB_BLOB:
-					if (VAL_TYPE(v + i) == DB_STR) {
-						s = VAL_STR(v + i).s;
-						len = VAL_STR(v + i).len;
-					}
-					else {
-						s = VAL_BLOB(v + i).s;
-						len = VAL_BLOB(v + i).len;
-					}
-					while (len > 0) {
-						char *c;
-						for (c = s; len > 0 && *c != flat_delimiter[0] && *c != flat_record_delimiter[0] && *c != flat_escape[0]; c++, len--);
-						fprintf(f, "%.*s", (int)(c-s), s);
-						s = c;
-						if (len > 0) {
-							fprintf(f, "%c%c", flat_escape[0], *s);
-							s++;
-							len--;
-						}
-					}
-					break;
-
-				case DB_DATETIME:
-					fprintf(f, "%u", (unsigned int)VAL_TIME(v + i));
-					break;
-
-				case DB_BITMAP:
-					fprintf(f, "%u", VAL_BITMAP(v + i));
-					break;
-			}
-		}
-		if (i < (n - 1)) {
-			fprintf(f, "%c", flat_delimiter[0]);
-		}
-	}
-
-	fprintf(f, "%c", flat_record_delimiter[0]);
-
-	if (flat_flush) {
-		fflush(f);
-	}
-
-	return 0;
-}

+ 0 - 71
modules/db_flatstore/flatstore.h

@@ -1,71 +0,0 @@
-/* 
- * $Id$ 
- *
- * Flatstore module interface
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- */
-
-#ifndef _FLATSTORE_H
-#define _FLATSTORE_H
-
-#include "../../db/db_val.h"
-#include "../../db/db_key.h"
-#include "../../db/db_con.h"
-
-
-/*
- * Initialize database module
- * No function should be called before this
- */
-db_con_t* flat_db_init(const char* _url);
-
-
-/*
- * Store name of table that will be used by
- * subsequent database functions
- */
-int flat_use_table(db_con_t* h, const char* t);
-
-
-void flat_db_close(db_con_t* h);
-
-
-/*
- * Insert a row into specified table
- * h: structure representing database connection
- * k: key names
- * v: values of the keys
- * n: number of key=value pairs
- */
-int flat_db_insert(db_con_t* h, db_key_t* k, db_val_t* v, int n);
-
-
-#endif /* _FLATSTORE_H */

+ 118 - 71
modules/db_flatstore/flatstore_mod.c

@@ -1,43 +1,46 @@
 /*
  * $Id$
  *
- * Flatstore module interface
+ * Copyright (C) 2004 FhG FOKUS
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * Copyright (C) 2004 FhG Fokus
+ * This file is part of SER, a free SIP server.
  *
- * This file is part of ser, a free SIP server.
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
+
+/** \addtogroup flatstore
+ * @{ 
+ */
+
+/** \file 
+ * Flatstore module interface.
  */
 
+#include "flatstore_mod.h"
+#include "flat_con.h"
+#include "flat_cmd.h"
+#include "flat_rpc.h"
+
 #include "../../sr_module.h"
 #include "../../mem/shm_mem.h"
-#include "flatstore.h"
-#include "flat_rpc.h"
-#include "flatstore_mod.h"
+#include "../../ut.h"
+
+#include <stdlib.h>
+#include <string.h>
 
 MODULE_VERSION
 
@@ -48,59 +51,83 @@ static int mod_init(void);
 static void mod_destroy(void);
 
 
-/*
- * Process number used in filenames
+/** PID to be used in file names.  
+ * The flatstore module generates one file per SER process to ensure that
+ * every SER process has its own file and no locking/synchronization is
+ * necessary.  This variable contains a unique id of the SER process which
+ * will be added to the file name.
  */
-int flat_pid;
+str flat_pid = STR_NULL;
 
-/*
- * Should we flush after each write to the database ?
- */
+
+/** Enable/disable flushing after eaach write. */
 int flat_flush = 1;
 
-/*
- * Delimiter delimiting rows
+
+/** Row delimiter.
+ * The character in this variable will be used to delimit rows.
  */
-char *flat_record_delimiter = "\n";
+str flat_record_delimiter = STR_STATIC_INIT("\n");
 
-/*
- * Delimiter delimiting columns
+
+/** Field delimiter.
+ * The character in this variable will be used to delimit fields.
  */
-char *flat_delimiter = "|";
+str flat_delimiter = STR_STATIC_INIT("|");
 
-/*
- * Escape char escaping delimiters
+
+/** Escape character.
+ * The character in this variable will be used to escape specia characters,
+ * such as row and field delimiters, if they appear in the data being written
+ * in the files.
  */
-char *flat_escape = "\\";
+str flat_escape = STR_STATIC_INIT("\\");
 
-/*
- * Timestamp of the last log rotation request from
- * the FIFO interface
+
+/** Filename suffix.
+ * This is the suffix of newly created files.
+ */
+str flat_suffix = STR_STATIC_INIT(".log");
+
+
+/** Timestamp of last file rotation request.
+ * This variable holds the timestamp of the last file rotation request
+ * received through the management interface.
  */
 time_t* flat_rotate;
 
-time_t local_timestamp;
 
-/*
- * Flatstore database module interface
+/** Timestamp of last file rotation.
+ * This variable contains the time of the last rotation of files.
  */
+time_t flat_local_timestamp;
+
+
+/* Flatstore database module interface */
 static cmd_export_t cmds[] = {
-	{"db_use_table",   (cmd_function)flat_use_table, 2, 0, 0},
-	{"db_init",        (cmd_function)flat_db_init,   1, 0, 0},
-	{"db_close",       (cmd_function)flat_db_close,  2, 0, 0},
-	{"db_insert",      (cmd_function)flat_db_insert, 2, 0, 0},
+	{"db_ctx",    (cmd_function)NULL,     0, 0, 0},
+	{"db_con",    (cmd_function)flat_con, 0, 0, 0},
+	{"db_uri",    (cmd_function)NULL,     0, 0, 0},
+	{"db_cmd",    (cmd_function)flat_cmd, 0, 0, 0},
+	{"db_put",    (cmd_function)flat_put, 0, 0, 0},
+	{"db_del",    (cmd_function)NULL,     0, 0, 0},
+	{"db_get",    (cmd_function)NULL,     0, 0, 0},
+	{"db_upd",    (cmd_function)NULL,     0, 0, 0},
+	{"db_sql",    (cmd_function)NULL,     0, 0, 0},
+	{"db_fld",    (cmd_function)NULL,     0, 0, 0},
+	{"db_setopt", (cmd_function)NULL,     0, 0, 0},
+	{"db_getopt", (cmd_function)NULL,     0, 0, 0},
 	{0, 0, 0, 0, 0}
 };
 
 
-/*
- * Exported parameters
- */
+/* Exported parameters */
 static param_export_t params[] = {
-	{"flush", PARAM_INT, &flat_flush},
-	{"field_delimiter", PARAM_STRING, &flat_delimiter},
-	{"record_delimiter", PARAM_STRING, &flat_record_delimiter},
-	{"escape_char", PARAM_STRING, &flat_escape},
+	{"flush",            PARAM_INT, &flat_flush},
+	{"field_delimiter",  PARAM_STR, &flat_delimiter},
+	{"record_delimiter", PARAM_STR, &flat_record_delimiter},
+	{"escape_char",      PARAM_STR, &flat_escape},
+	{"file_suffix",      PARAM_STR, &flat_suffix},
 	{0, 0, 0}
 };
 
@@ -120,46 +147,66 @@ struct module_exports exports = {
 
 static int mod_init(void)
 {
-	if (strlen(flat_delimiter) > 1) {
-		LOG(L_ERR, "flatstore:mod_init: Column delimiter has to be max. one character\n");
+	if (flat_delimiter.len != 1) {
+		ERR("flatstore: Parameter 'field_delimiter' "
+			"must be exactly one character long.\n");
 		return -1;
 	}
 
-	if (strlen(flat_record_delimiter) > 1) {
-		LOG(L_ERR, "flatstore:mod_init: Record delimiter has to be max. one character\n");
+	if (flat_record_delimiter.len != 1) {
+		ERR("flatstore: Parameter 'record_delimiter' "
+			"must be exactly one character long.\n");
 		return -1;
 	}
 
-	if (strlen(flat_escape) > 1) {
-		LOG(L_ERR, "flatstore:mod_init: Escape char has to be max. one character\n");
+	if (flat_escape.len != 1) {
+		ERR("flatstore: Parameter 'escape_char' "
+			"must be exaactly one character long.\n");
 		return -1;
 	}
 
 	flat_rotate = (time_t*)shm_malloc(sizeof(time_t));
 	if (!flat_rotate) {
-		LOG(L_ERR, "flatstore: No shared memory left\n");
+		ERR("flatstore: Not enough shared memory left\n");
 		return -1;
 	}
 
 	*flat_rotate = time(0);
-	local_timestamp = *flat_rotate;
-
+	flat_local_timestamp = *flat_rotate;
 	return 0;
 }
 
 
 static void mod_destroy(void)
 {
+	if (flat_pid.s) free(flat_pid.s);
 	if (flat_rotate) shm_free(flat_rotate);
 }
 
 
 static int child_init(int rank)
 {
+	char* tmp;
+	unsigned int v;
+
 	if (rank <= 0) {
-		flat_pid = - rank;
+		v = -rank;
 	} else {
-		flat_pid = rank - PROC_MIN;
+		v = rank - PROC_MIN;
+	}
+
+    if ((tmp = int2str(v, &flat_pid.len)) == NULL) {
+		BUG("flatstore: Error while converting process id to number\n");
+		return -1;
+	}
+
+	if ((flat_pid.s = strdup(tmp)) == NULL) {
+		ERR("flatstore: No memory left\n");
+		return -1;
 	}
+
 	return 0;
 }
+
+/** @} */
+

+ 32 - 61
modules/db_flatstore/flatstore_mod.h

@@ -1,80 +1,51 @@
 /*
  * $Id$
  *
- * Flatstore module interface
- *
  * Copyright (C) 2004 FhG Fokus
+ * Copyright (C) 2008 iptelorg GmbH
+ * Written by Jan Janak <[email protected]>
  *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
+ * This file is part of SER, a free SIP server.
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    [email protected]
+ * SER is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
  *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#ifndef FLATSTORE_MOD_H
-#define FLATSTORE_MOD_H
-
-#include <time.h>
-
-/*
- * Process number used in filenames
- */
-extern int flat_pid;
+#ifndef _FLATSTORE_MOD_H
+#define _FLATSTORE_MOD_H
 
-/*
- * Should we flush after each write to the database ?
+/** @defgroup flatstore Fast plain-text write-only DB driver.
+ * @ingroup DB_API
  */
-extern int flat_flush;
+/** @{ */
 
-/*
- * Delimiter delimiting rows
+/** \file 
+ * Flatstore module interface.
  */
-extern char *flat_record_delimiter;
 
-/*
- * Delimiter delimiting columns
- */
-extern char *flat_delimiter;
-
-/*
- * Escape char escaning delimiters and itself
- */
-extern char *flat_escape;
+#include "../../str.h"
+#include <time.h>
 
-/*
- * The timestamp of log rotation request from
- * the FIFO interface
- */
+extern str     flat_pid;
+extern int     flat_flush;
+extern str     flat_record_delimiter;
+extern str     flat_delimiter;
+extern str     flat_escape;
+extern str     flat_suffix;
 extern time_t* flat_rotate;
+extern time_t  flat_local_timestamp;
 
+/** @} */
 
-/*
- * Local timestamp marking the time of the
- * last log rotation in the process
- */
-extern time_t local_timestamp;
-
-
-#endif /* FLATSTORE_MOD_H */
+#endif /* _FLATSTORE_MOD_H */