diff --git a/cdr/cdr_sqlite3_custom.c b/cdr/cdr_sqlite3_custom.c index e8d763edd5..2212d04992 100644 --- a/cdr/cdr_sqlite3_custom.c +++ b/cdr/cdr_sqlite3_custom.c @@ -61,6 +61,7 @@ static sqlite3 *db = NULL; static char table[80]; static char *columns; +static int busy_timeout; struct values { AST_LIST_ENTRY(values) list; @@ -181,6 +182,15 @@ static int load_config(int reload) 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 */ if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { ast_config_destroy(cfg); @@ -305,7 +315,7 @@ static int load_module(void) free_config(0); return AST_MODULE_LOAD_DECLINE; } - sqlite3_busy_timeout(db, 1000); + sqlite3_busy_timeout(db, busy_timeout); /* is the table there? */ sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); res = sqlite3_exec(db, sql, NULL, NULL, NULL); diff --git a/cel/cel_sqlite3_custom.c b/cel/cel_sqlite3_custom.c index 6075b8a2b5..5675da6b33 100644 --- a/cel/cel_sqlite3_custom.c +++ b/cel/cel_sqlite3_custom.c @@ -68,6 +68,7 @@ static char table[80]; * \bug Handling of this var is crash prone on reloads */ static char *columns; +static int busy_timeout; struct values { char *expression; @@ -187,6 +188,15 @@ static int load_config(int reload) 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 */ if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { ast_config_destroy(cfg); @@ -306,7 +316,7 @@ static int load_module(void) free_config(); return AST_MODULE_LOAD_DECLINE; } - sqlite3_busy_timeout(db, 1000); + sqlite3_busy_timeout(db, busy_timeout); /* is the table there? */ sql = sqlite3_mprintf("SELECT COUNT(*) FROM %q;", table); res = sqlite3_exec(db, sql, NULL, NULL, NULL); diff --git a/configs/samples/cdr_sqlite3_custom.conf.sample b/configs/samples/cdr_sqlite3_custom.conf.sample index 0d5dc091c4..4b88d58d48 100644 --- a/configs/samples/cdr_sqlite3_custom.conf.sample +++ b/configs/samples/cdr_sqlite3_custom.conf.sample @@ -5,6 +5,7 @@ ;table => cdr ;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)}' +;busy_timeout => 1000 ;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)}' diff --git a/configs/samples/cel_sqlite3_custom.conf.sample b/configs/samples/cel_sqlite3_custom.conf.sample index 2d9a24fc7b..aa908a4f36 100644 --- a/configs/samples/cel_sqlite3_custom.conf.sample +++ b/configs/samples/cel_sqlite3_custom.conf.sample @@ -22,3 +22,4 @@ ;table => cel ;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}' +;busy_timeout => 1000 \ No newline at end of file diff --git a/configs/samples/res_config_sqlite3.conf.sample b/configs/samples/res_config_sqlite3.conf.sample index 5416c809e8..2588b26c93 100644 --- a/configs/samples/res_config_sqlite3.conf.sample +++ b/configs/samples/res_config_sqlite3.conf.sample @@ -28,4 +28,8 @@ ; to lock for writing. ; ;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 \ No newline at end of file diff --git a/res/res_config_sqlite3.c b/res/res_config_sqlite3.c index 0025548be3..bbf6db211e 100644 --- a/res/res_config_sqlite3.c +++ b/res/res_config_sqlite3.c @@ -103,6 +103,7 @@ struct realtime_sqlite3_db { unsigned int exiting:1; unsigned int wakeup:1; unsigned int batch; + int busy_timeout; }; struct ao2_container *databases; @@ -342,7 +343,7 @@ static int db_open(struct realtime_sqlite3_db *db) ao2_unlock(db); return -1; } - sqlite3_busy_timeout(db->handle, 1000); + sqlite3_busy_timeout(db->handle, db->busy_timeout); if (db->debug) { 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->batch = 100; ast_string_field_set(db, name, cat); + db->busy_timeout = 1000; for (var = ast_variable_browse(config, cat); var; var = var->next) { 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); } else if (!strcasecmp(var->name, "debug")) { 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 */ } + 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 == 0) { db->batch = new->batch;