From 46c0239a79b50515ac2b3b7f7ebb9148e0e9df5e Mon Sep 17 00:00:00 2001 From: chme Date: Sun, 8 Jun 2014 08:25:58 +0200 Subject: [PATCH] Added options to modify the operation of the SQLite database (through PRAGMA statements) - set cache size (in number of pages) - set synchronous flag - set journal mode --- src/conffile.c | 3 + src/db.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/src/conffile.c b/src/conffile.c index 7392dd68..aa0b039f 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -48,6 +48,9 @@ static cfg_opt_t sec_general[] = CFG_STR("admin_password", NULL, CFGF_NONE), CFG_STR("logfile", STATEDIR "/log/" PACKAGE ".log", CFGF_NONE), CFG_STR("db_path", STATEDIR "/cache/" PACKAGE "/songs3.db", CFGF_NONE), + CFG_INT("db_pragma_cache_size", -1, CFGF_NONE), + CFG_STR("db_pragma_journal_mode", NULL, CFGF_NONE), + CFG_INT("db_pragma_synchronous", -1, CFGF_NONE), CFG_INT_CB("loglevel", E_LOG, CFGF_NONE, &cb_loglevel), CFG_BOOL("ipv6", cfg_false, CFGF_NONE), CFG_END() diff --git a/src/db.c b/src/db.c index 12ed79e1..fb759982 100644 --- a/src/db.c +++ b/src/db.c @@ -4338,12 +4338,182 @@ db_xprofile(void *notused, const char *pquery, sqlite3_uint64 ptime) } #endif +static int +db_pragma_get_cache_size() +{ + sqlite3_stmt *stmt; + char *query = "PRAGMA cache_size;"; + int ret; + + DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); + + ret = db_blocking_prepare_v2(query, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + + sqlite3_free(query); + return 0; + } + + ret = db_blocking_step(stmt); + if (ret == SQLITE_DONE) + { + DPRINTF(E_DBG, L_DB, "End of query results\n"); + sqlite3_free(query); + return 0; + } + else if (ret != SQLITE_ROW) + { + DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl)); + sqlite3_free(query); + return -1; + } + + ret = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + return ret; +} + +static int +db_pragma_set_cache_size(int pages) +{ +#define Q_TMPL "PRAGMA cache_size=%d;" + sqlite3_stmt *stmt; + char *query; + int ret; + + query = sqlite3_mprintf(Q_TMPL, pages); + DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); + + ret = db_blocking_prepare_v2(query, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + + sqlite3_free(query); + return 0; + } + + sqlite3_finalize(stmt); + sqlite3_free(query); + return 0; +} + +static char * +db_pragma_set_journal_mode(char *mode) +{ +#define Q_TMPL "PRAGMA journal_mode=%s;" + sqlite3_stmt *stmt; + char *query; + int ret; + char *new_mode; + + query = sqlite3_mprintf(Q_TMPL, mode); + DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); + + ret = db_blocking_prepare_v2(query, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + + sqlite3_free(query); + return NULL; + } + + ret = db_blocking_step(stmt); + if (ret == SQLITE_DONE) + { + DPRINTF(E_DBG, L_DB, "End of query results\n"); + sqlite3_free(query); + return NULL; + } + else if (ret != SQLITE_ROW) + { + DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl)); + sqlite3_free(query); + return NULL; + } + + new_mode = (char *) sqlite3_column_text(stmt, 0); + sqlite3_finalize(stmt); + sqlite3_free(query); + return new_mode; +#undef Q_TMPL +} + +static int +db_pragma_get_synchronous() +{ + sqlite3_stmt *stmt; + char *query = "PRAGMA synchronous;"; + int ret; + + DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); + + ret = db_blocking_prepare_v2(query, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + + sqlite3_free(query); + return 0; + } + + ret = db_blocking_step(stmt); + if (ret == SQLITE_DONE) + { + DPRINTF(E_DBG, L_DB, "End of query results\n"); + sqlite3_free(query); + return 0; + } + else if (ret != SQLITE_ROW) + { + DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl)); + sqlite3_free(query); + return -1; + } + + ret = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + return ret; +} + +static int +db_pragma_set_synchronous(int synchronous) +{ +#define Q_TMPL "PRAGMA synchronous=%d;" + sqlite3_stmt *stmt; + char *query; + int ret; + + query = sqlite3_mprintf(Q_TMPL, synchronous); + DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); + + ret = db_blocking_prepare_v2(query, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + + sqlite3_free(query); + return 0; + } + + sqlite3_finalize(stmt); + sqlite3_free(query); + return 0; +} int db_perthread_init(void) { char *errmsg; int ret; + int cache_size; + char *journal_mode; + int synchronous; ret = sqlite3_open(db_path, &hdl); if (ret != SQLITE_OK) @@ -4392,6 +4562,29 @@ db_perthread_init(void) sqlite3_profile(hdl, db_xprofile, NULL); #endif + cache_size = cfg_getint(cfg_getsec(cfg, "general"), "db_pragma_cache_size"); + if (cache_size > -1) + { + db_pragma_set_cache_size(cache_size); + cache_size = db_pragma_get_cache_size(); + DPRINTF(E_DBG, L_DB, "Database cache size in pages: %d\n", cache_size); + } + + journal_mode = cfg_getstr(cfg_getsec(cfg, "general"), "db_pragma_journal_mode"); + if (journal_mode) + { + journal_mode = db_pragma_set_journal_mode(journal_mode); + DPRINTF(E_DBG, L_DB, "Database journal mode: %s\n", journal_mode); + } + + synchronous = cfg_getint(cfg_getsec(cfg, "general"), "db_pragma_synchronous"); + if (synchronous > -1) + { + db_pragma_set_synchronous(synchronous); + synchronous = db_pragma_get_synchronous(); + DPRINTF(E_DBG, L_DB, "Database synchronous: %d\n", synchronous); + } + return 0; }