Sqlite3: make busy_timeout configurable.

Enables runtime configuration of busy_timeout for sqlite databases.
Default timeout remains 1000ms.

ASTERISK-27014 #close

Change-Id: I8921a3aac3c335843be4cb17d2dd0a5c157a36da
This commit is contained in:
Martin Tomec
2017-05-23 18:07:53 +02:00
parent dece2eb892
commit 44c5a144ce
6 changed files with 41 additions and 4 deletions

View File

@@ -61,6 +61,7 @@ static sqlite3 *db = NULL;
static char table[80]; static char table[80];
static char *columns; static char *columns;
static int busy_timeout;
struct values { struct values {
AST_LIST_ENTRY(values) list; AST_LIST_ENTRY(values) list;
@@ -181,6 +182,15 @@ static int load_config(int reload)
strcpy(table, "cdr"); strcpy(table, "cdr");
} }
/* sqlite3_busy_timeout in miliseconds */
if ((tmp = ast_variable_retrieve(cfg, "master", "busy_timeout")) != NULL) {
if (ast_parse_arg(tmp, PARSE_INT32|PARSE_DEFAULT, &busy_timeout, 1000) != 0) {
ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' specified. Using 1000 instead.\n", tmp);
}
} else {
busy_timeout = 1000;
}
/* Columns */ /* Columns */
if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
ast_config_destroy(cfg); ast_config_destroy(cfg);
@@ -305,7 +315,7 @@ static int load_module(void)
free_config(0); free_config(0);
return AST_MODULE_LOAD_DECLINE; return AST_MODULE_LOAD_DECLINE;
} }
sqlite3_busy_timeout(db, 1000); sqlite3_busy_timeout(db, busy_timeout);
/* is the table there? */ /* is the table there? */
sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
res = sqlite3_exec(db, sql, NULL, NULL, NULL); res = sqlite3_exec(db, sql, NULL, NULL, NULL);

View File

@@ -68,6 +68,7 @@ static char table[80];
* \bug Handling of this var is crash prone on reloads * \bug Handling of this var is crash prone on reloads
*/ */
static char *columns; static char *columns;
static int busy_timeout;
struct values { struct values {
char *expression; char *expression;
@@ -187,6 +188,15 @@ static int load_config(int reload)
strcpy(table, "cel"); strcpy(table, "cel");
} }
/* sqlite3_busy_timeout in miliseconds */
if ((tmp = ast_variable_retrieve(cfg, "master", "busy_timeout")) != NULL) {
if (ast_parse_arg(tmp, PARSE_INT32|PARSE_DEFAULT, &busy_timeout, 1000) != 0) {
ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' specified. Using 1000 instead.\n", tmp);
}
} else {
busy_timeout = 1000;
}
/* Columns */ /* Columns */
if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
ast_config_destroy(cfg); ast_config_destroy(cfg);
@@ -306,7 +316,7 @@ static int load_module(void)
free_config(); free_config();
return AST_MODULE_LOAD_DECLINE; return AST_MODULE_LOAD_DECLINE;
} }
sqlite3_busy_timeout(db, 1000); sqlite3_busy_timeout(db, busy_timeout);
/* is the table there? */ /* is the table there? */
sql = sqlite3_mprintf("SELECT COUNT(*) FROM %q;", table); sql = sqlite3_mprintf("SELECT COUNT(*) FROM %q;", table);
res = sqlite3_exec(db, sql, NULL, NULL, NULL); res = sqlite3_exec(db, sql, NULL, NULL, NULL);

View File

@@ -5,6 +5,7 @@
;table => cdr ;table => cdr
;columns => calldate, clid, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield, test ;columns => calldate, clid, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield, test
;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}','${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}' ;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}','${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}'
;busy_timeout => 1000
;Enable High Resolution Times for billsec and duration fields ;Enable High Resolution Times for billsec and duration fields
;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration,f)}','${CDR(billsec,f)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}' ;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration,f)}','${CDR(billsec,f)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}'

View File

@@ -22,3 +22,4 @@
;table => cel ;table => cel
;columns => eventtype, eventtime, cidname, cidnum, cidani, cidrdnis, ciddnid, context, exten, channame, appname, appdata, amaflags, accountcode, uniqueid, userfield, peer, userdeftype, eventextra ;columns => eventtype, eventtime, cidname, cidnum, cidani, cidrdnis, ciddnid, context, exten, channame, appname, appdata, amaflags, accountcode, uniqueid, userfield, peer, userdeftype, eventextra
;values => '${eventtype}','${eventtime}','${CALLERID(name)}','${CALLERID(num)}','${CALLERID(ANI)}','${CALLERID(RDNIS)}','${CALLERID(DNID)}','${CHANNEL(context)}','${CHANNEL(exten)}','${CHANNEL(channame)}','${CHANNEL(appname)}','${CHANNEL(appdata)}','${CHANNEL(amaflags)}','${CHANNEL(accountcode)}','${CHANNEL(uniqueid)}','${CHANNEL(userfield)}','${BRIDGEPEER}','${userdeftype}','${eventextra}' ;values => '${eventtype}','${eventtime}','${CALLERID(name)}','${CALLERID(num)}','${CALLERID(ANI)}','${CALLERID(RDNIS)}','${CALLERID(DNID)}','${CHANNEL(context)}','${CHANNEL(exten)}','${CHANNEL(channame)}','${CHANNEL(appname)}','${CHANNEL(appdata)}','${CHANNEL(amaflags)}','${CHANNEL(accountcode)}','${CHANNEL(uniqueid)}','${CHANNEL(userfield)}','${BRIDGEPEER}','${userdeftype}','${eventextra}'
;busy_timeout => 1000

View File

@@ -28,4 +28,8 @@
; to lock for writing. ; to lock for writing.
; ;
;batch=1000 ;batch=1000
;
; busy timeout - timeout in miliseconds to stop waiting for locked database.
; More info at https://www.sqlite.org/c3ref/busy_timeout.html
;
;busy_timeout=1000

View File

@@ -103,6 +103,7 @@ struct realtime_sqlite3_db {
unsigned int exiting:1; unsigned int exiting:1;
unsigned int wakeup:1; unsigned int wakeup:1;
unsigned int batch; unsigned int batch;
int busy_timeout;
}; };
struct ao2_container *databases; struct ao2_container *databases;
@@ -342,7 +343,7 @@ static int db_open(struct realtime_sqlite3_db *db)
ao2_unlock(db); ao2_unlock(db);
return -1; return -1;
} }
sqlite3_busy_timeout(db->handle, 1000); sqlite3_busy_timeout(db->handle, db->busy_timeout);
if (db->debug) { if (db->debug) {
sqlite3_trace(db->handle, trace_cb, db); sqlite3_trace(db->handle, trace_cb, db);
@@ -400,6 +401,7 @@ static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *co
db->requirements = REALTIME_SQLITE3_REQ_WARN; db->requirements = REALTIME_SQLITE3_REQ_WARN;
db->batch = 100; db->batch = 100;
ast_string_field_set(db, name, cat); ast_string_field_set(db, name, cat);
db->busy_timeout = 1000;
for (var = ast_variable_browse(config, cat); var; var = var->next) { for (var = ast_variable_browse(config, cat); var; var = var->next) {
if (!strcasecmp(var->name, "dbfile")) { if (!strcasecmp(var->name, "dbfile")) {
@@ -410,6 +412,10 @@ static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *co
ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS); ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS);
} else if (!strcasecmp(var->name, "debug")) { } else if (!strcasecmp(var->name, "debug")) {
db->debug = ast_true(var->value); db->debug = ast_true(var->value);
} else if (!strcasecmp(var->name, "busy_timeout")) {
if (ast_parse_arg(var->value, PARSE_INT32|PARSE_DEFAULT, &(db->busy_timeout), 1000) != 0) {
ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' at res_config_sqlite3.conf:%d. Using 1000 instead.\n", var->value, var->lineno);
}
} }
} }
@@ -454,6 +460,11 @@ static int update_realtime_sqlite3_db(struct realtime_sqlite3_db *db, struct ast
db_open(db); /* Also handles setting appropriate debug on new handle */ db_open(db); /* Also handles setting appropriate debug on new handle */
} }
if (db->busy_timeout != new->busy_timeout) {
db->busy_timeout = new->busy_timeout;
sqlite3_busy_timeout(db->handle, db->busy_timeout);
}
if (db->batch != new->batch) { if (db->batch != new->batch) {
if (db->batch == 0) { if (db->batch == 0) {
db->batch = new->batch; db->batch = new->batch;