Enclose DB upgrade in a single transaction (improves performance and in

case of an error does a rollback, keeping the db in a valid state)
This commit is contained in:
chme 2015-02-26 14:09:14 +01:00
parent a9a8c6a3d4
commit 1bbfcf61a5

143
src/db.c
View File

@ -5790,57 +5790,10 @@ db_upgrade_v16(void)
}
static int
db_check_version(void)
db_upgrade(int db_ver)
{
#define Q_VACUUM "VACUUM;"
char *buf;
char *errmsg;
int db_ver_major;
int db_ver_minor;
int db_ver;
int vacuum;
int ret;
vacuum = cfg_getbool(cfg_getsec(cfg, "sqlite"), "vacuum");
buf = db_admin_get("schema_version_major");
if (!buf)
buf = db_admin_get("schema_version"); // Pre schema v15.1
if (!buf)
return 1; // Will create new database
safe_atoi32(buf, &db_ver_major);
free(buf);
buf = db_admin_get("schema_version_minor");
if (buf)
{
safe_atoi32(buf, &db_ver_minor);
free(buf);
}
else
db_ver_minor = 0;
db_ver = db_ver_major * 100 + db_ver_minor;
if (db_ver_major < 10)
{
DPRINTF(E_FATAL, L_DB, "Database schema v%d too old, cannot upgrade\n", db_ver_major);
return -1;
}
else if (db_ver_major > SCHEMA_VERSION_MAJOR)
{
DPRINTF(E_FATAL, L_DB, "Database schema v%d is newer than the supported version\n", db_ver_major);
return -1;
}
else if (db_ver < (SCHEMA_VERSION_MAJOR * 100 + SCHEMA_VERSION_MINOR))
{
DPRINTF(E_LOG, L_DB, "Database schema outdated, upgrading schema v%d.%d -> v%d.%d...\n",
db_ver_major, db_ver_minor, SCHEMA_VERSION_MAJOR, SCHEMA_VERSION_MINOR);
ret = db_drop_indices();
if (ret < 0)
return -1;
@ -5919,11 +5872,101 @@ db_check_version(void)
return -1;
}
vacuum = 1;
ret = db_create_indices();
if (ret < 0)
return -1;
return 0;
}
static int
db_check_version(void)
{
#define Q_VACUUM "VACUUM;"
char *buf;
char *errmsg;
int db_ver_major;
int db_ver_minor;
int db_ver;
int vacuum;
int ret;
vacuum = cfg_getbool(cfg_getsec(cfg, "sqlite"), "vacuum");
buf = db_admin_get("schema_version_major");
if (!buf)
buf = db_admin_get("schema_version"); // Pre schema v15.1
if (!buf)
return 1; // Will create new database
safe_atoi32(buf, &db_ver_major);
free(buf);
buf = db_admin_get("schema_version_minor");
if (buf)
{
safe_atoi32(buf, &db_ver_minor);
free(buf);
}
else
db_ver_minor = 0;
db_ver = db_ver_major * 100 + db_ver_minor;
if (db_ver_major < 10)
{
DPRINTF(E_FATAL, L_DB, "Database schema v%d too old, cannot upgrade\n", db_ver_major);
return -1;
}
else if (db_ver_major > SCHEMA_VERSION_MAJOR)
{
DPRINTF(E_FATAL, L_DB, "Database schema v%d is newer than the supported version\n", db_ver_major);
return -1;
}
else if (db_ver < (SCHEMA_VERSION_MAJOR * 100 + SCHEMA_VERSION_MINOR))
{
DPRINTF(E_LOG, L_DB, "Database schema outdated, upgrading schema v%d.%d -> v%d.%d...\n",
db_ver_major, db_ver_minor, SCHEMA_VERSION_MAJOR, SCHEMA_VERSION_MINOR);
ret = sqlite3_exec(hdl, "BEGIN TRANSACTION;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "DB error while running 'BEGIN TRANSACTION': %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
ret = db_upgrade(db_ver);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Database upgrade errored out, rolling back changes ...\n");
ret = sqlite3_exec(hdl, "ROLLBACK TRANSACTION;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "DB error while running 'ROLLBACK TRANSACTION': %s\n", errmsg);
sqlite3_free(errmsg);
}
return -1;
}
ret = sqlite3_exec(hdl, "COMMIT TRANSACTION;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "DB error while running 'COMMIT TRANSACTION': %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
DPRINTF(E_LOG, L_DB, "Upgrading schema to v%d.%d completed\n", SCHEMA_VERSION_MAJOR, SCHEMA_VERSION_MINOR);
vacuum = 1;
}
if (vacuum)