From aefe50a99a33d3fdab08f302689f0abf79e06aeb Mon Sep 17 00:00:00 2001 From: Julien Chavanton Date: Fri, 19 May 2017 10:30:43 -0700 Subject: [PATCH] db_sqlite: new param to open some database in read-only --- src/modules/db_sqlite/db_sqlite.c | 79 ++++++++++++++++++- src/modules/db_sqlite/db_sqlite.h | 37 +++++++++ src/modules/db_sqlite/dbase.c | 14 +++- src/modules/db_sqlite/doc/db_sqlite.xml | 16 ++++ src/modules/db_sqlite/doc/db_sqlite_admin.xml | 26 +++++- 5 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 src/modules/db_sqlite/db_sqlite.h diff --git a/src/modules/db_sqlite/db_sqlite.c b/src/modules/db_sqlite/db_sqlite.c index f3b98b9250d..6a733907869 100644 --- a/src/modules/db_sqlite/db_sqlite.c +++ b/src/modules/db_sqlite/db_sqlite.c @@ -29,6 +29,7 @@ #include "../../lib/srdb1/db_query.h" #include "../../lib/srdb1/db.h" #include "dbase.h" +#include "db_sqlite.h" MODULE_VERSION @@ -52,6 +53,82 @@ static int sqlite_bind_api(db_func_t *dbb) return 0; } +static db_param_list_t *db_param_list = NULL; + +static void db_param_list_add(db_param_list_t *e) { + if (!db_param_list) { + db_param_list = e; + LM_DBG("adding readonly database [%s]\n", e->database.s); + clist_init(db_param_list, next, prev); + } else { + LM_DBG("adding append constraint [%s]\n", e->database.s); + clist_append(db_param_list, e, next, prev); + } +} + +static void db_param_list_destroy(db_param_list_t *e) { + if (!e) + return; + if (e->database.s) + pkg_free(e->database.s); + pkg_free(e); + e = NULL; +} + +static db_param_list_t *db_param_list_new(const char *db_filename) { + db_param_list_t *e = pkg_malloc(sizeof(db_param_list_t)); + if (!e) + return NULL; + memset(e, 0, sizeof(db_param_list_t)); + + e->database.len = strlen(db_filename); + e->database.s = pkg_malloc(e->database.len+1); + if (!e->database.s) goto error; + strcpy(e->database.s, db_filename); + + db_param_list_add(e); + return e; +error: + db_param_list_destroy(e); + return NULL; +} + +db_param_list_t *db_param_list_search(char *db_filename) { + db_param_list_t *e; + if (!db_param_list) { + return NULL; + } + if (strcmp(db_filename, db_param_list->database.s) == 0) { + return db_param_list; + } + clist_foreach(db_param_list, e, next){ + if (strcmp(db_filename, e->database.s) == 0) { + return e; + } + } + return NULL; +} + +int db_set_readonly(modparam_t type, void *val) { + if(val==NULL) + return -1; + db_param_list_t *e = db_param_list_search((char*)val); + if (!e) + e = db_param_list_new((char *)val); + if (!e) { + LM_ERR("can't create a new db_param for [%s]\n", (char*) val); + return -1; + } + e->readonly = 1; + db_param_list_search((char *)val); + return 1; +} + +static param_export_t params[] = { + {"db_set_readonly", PARAM_STRING|USE_FUNC_PARAM, (void*)db_set_readonly}, + {0,0,0} +}; + static cmd_export_t cmds[] = { {"db_bind_api", (cmd_function)sqlite_bind_api, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} @@ -86,7 +163,7 @@ struct module_exports exports = { "db_sqlite", DEFAULT_DLFLAGS, /* dlopen flags */ cmds, /* module commands */ - 0, /* module parameters */ + params, /* module parameters */ 0, /* exported statistics */ 0, /* exported MI functions */ 0, /* exported pseudo-variables */ diff --git a/src/modules/db_sqlite/db_sqlite.h b/src/modules/db_sqlite/db_sqlite.h new file mode 100644 index 00000000000..ff22fd197dc --- /dev/null +++ b/src/modules/db_sqlite/db_sqlite.h @@ -0,0 +1,37 @@ +/* + * $Id$ + * + * SQlite module interface + * + * Copyright (C) 2017 Julien Chavanton, Flowroute + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio 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 + * + * Kamailio 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DBSQLITE_H +#define DBSQLITE_H + +typedef struct db_param_list { + struct db_param_list* next; + struct db_param_list* prev; + str database; + int readonly; +} db_param_list_t; + +db_param_list_t *db_param_list_search(char *db_filename); + +#endif diff --git a/src/modules/db_sqlite/dbase.c b/src/modules/db_sqlite/dbase.c index 126590cfa99..cf33c83086a 100644 --- a/src/modules/db_sqlite/dbase.c +++ b/src/modules/db_sqlite/dbase.c @@ -29,6 +29,7 @@ #include "../../lib/srdb1/db_res.h" #include "../../lib/srdb1/db_query.h" #include "dbase.h" +#include "db_sqlite.h" static time_t sqlite_to_timet(double rT) { @@ -60,8 +61,17 @@ static struct sqlite_connection * db_sqlite_new_connection(const struct db_id* i con->hdr.ref = 1; con->hdr.id = (struct db_id*) id; /* set here - freed on error */ - rc = sqlite3_open_v2(id->database, &con->conn, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + int flags = 0; + db_param_list_t *db_param = db_param_list_search(id->database); + if (db_param && db_param->readonly) { + // The database is opened in read-only mode. If the database does not already exist, an error is returned. + flags |= SQLITE_OPEN_READONLY; + LM_DBG("[%s] opened with [SQLITE_OPEN_READONLY]\n", id->database); + } else { + flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + LM_DBG("[%s] opened with [SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]\n", id->database); + } + rc = sqlite3_open_v2(id->database, &con->conn, flags, NULL); if (rc != SQLITE_OK) { pkg_free(con); LM_ERR("failed to open sqlite database '%s'\n", id->database); diff --git a/src/modules/db_sqlite/doc/db_sqlite.xml b/src/modules/db_sqlite/doc/db_sqlite.xml index 502637db368..2517ed5f29c 100644 --- a/src/modules/db_sqlite/doc/db_sqlite.xml +++ b/src/modules/db_sqlite/doc/db_sqlite.xml @@ -32,6 +32,22 @@ 2011 Timo Teräs + + + Julien + Chavanton + flowroute.com + jchavanton@gmail.com +
+ + + +
+
+
+ + 2017 + diff --git a/src/modules/db_sqlite/doc/db_sqlite_admin.xml b/src/modules/db_sqlite/doc/db_sqlite_admin.xml index aa39b224ac5..534cf871012 100644 --- a/src/modules/db_sqlite/doc/db_sqlite_admin.xml +++ b/src/modules/db_sqlite/doc/db_sqlite_admin.xml @@ -62,9 +62,31 @@
- Parameters + Parameters - NONE +
+ <varname>db_set_readonly</varname> (string) + + This will set the db connection to "SQLITE_OPEN_READONLY", useful if another program is writing to the DB. + The value is the full path to the sqlite file used for example in any db_url or sqlops/sqlcon + + This parameter may be set multiple times to set many DB connections to readonly in the same configuration file. + + + + By default all the db connection are using "SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE" + + + + Set <varname>db_set_readonly</varname> parameter + +... +modparam("db_sqlite","db_set_readonly","/var/mydb.sqlite") +modparam("sqlops","sqlcon","lrn=>sqlite:////var/mydb.sqlite") # Example if using the sqlops module +... + + +