diff options
Diffstat (limited to 'libglusterfs/src/gfdb/gfdb_sqlite3.c')
-rw-r--r-- | libglusterfs/src/gfdb/gfdb_sqlite3.c | 187 |
1 files changed, 183 insertions, 4 deletions
diff --git a/libglusterfs/src/gfdb/gfdb_sqlite3.c b/libglusterfs/src/gfdb/gfdb_sqlite3.c index 04781be562a..094028361c5 100644 --- a/libglusterfs/src/gfdb/gfdb_sqlite3.c +++ b/libglusterfs/src/gfdb/gfdb_sqlite3.c @@ -239,6 +239,7 @@ gf_sqlite3_fill_db_operations(gfdb_db_operations_t *gfdb_db_ops) gfdb_db_ops->insert_record_op = gf_sqlite3_insert; gfdb_db_ops->delete_record_op = gf_sqlite3_delete; + gfdb_db_ops->compact_db_op = gf_sqlite3_vacuum; gfdb_db_ops->find_all_op = gf_sqlite3_find_all; gfdb_db_ops->find_unchanged_for_time_op = @@ -1327,10 +1328,14 @@ gf_sqlite3_pragma (void *db_conn, char *pragma_key, char **pragma_value) goto out; } - ret = gf_asprintf (pragma_value, "%s", sqlite3_column_text (pre_stmt, 0)); - if (ret <= 0) { - gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_QUERY_FAILED, - "Failed to get %s from db", pragma_key); + if (pragma_value) { + ret = gf_asprintf (pragma_value, "%s", + sqlite3_column_text (pre_stmt, 0)); + if (ret <= 0) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_QUERY_FAILED, "Failed to get %s from db", + pragma_key); + } } ret = 0; @@ -1382,3 +1387,177 @@ out: return ret; } + +/* Function to vacuum of sqlite db + * Input: + * void *db_conn : Sqlite connection + * gf_boolean_t compact_active : Is compaction on? + * gf_boolean_t compact_mode_switched : Did we just flip the compaction swtich? + * Return: + * On success return 0 + * On failure return -1 + * */ +int +gf_sqlite3_vacuum (void *db_conn, gf_boolean_t compact_active, + gf_boolean_t compact_mode_switched) +{ + int ret = -1; + gf_sql_connection_t *sql_conn = db_conn; + char *sqlstring = NULL; + char *sql_strerror = NULL; + gf_boolean_t changing_pragma = _gf_true; + + CHECK_SQL_CONN (sql_conn, out); + + if (GF_SQL_COMPACT_DEF == GF_SQL_COMPACT_NONE) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_INFO, 0, + LG_MSG_COMPACT_STATUS, + "VACUUM type is off: no VACUUM to do"); + goto out; + } + + if (compact_mode_switched) { + if (compact_active) { /* Then it was OFF before. + So turn everything on */ + ret = 0; + switch (GF_SQL_COMPACT_DEF) { + case GF_SQL_COMPACT_FULL: + ret = gf_sqlite3_set_pragma (db_conn, + "auto_vacuum", + GF_SQL_AV_FULL); + break; + case GF_SQL_COMPACT_INCR: + ret = gf_sqlite3_set_pragma (db_conn, + "auto_vacuum", + GF_SQL_AV_INCR); + break; + case GF_SQL_COMPACT_MANUAL: + changing_pragma = _gf_false; + default: + ret = -1; + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_COMPACT_FAILED, + "VACUUM type undefined"); + goto out; + break; + } + + } else { /* Then it was ON before, so turn it all off */ + if (GF_SQL_COMPACT_DEF == GF_SQL_COMPACT_FULL || + GF_SQL_COMPACT_DEF == GF_SQL_COMPACT_INCR) { + ret = gf_sqlite3_set_pragma (db_conn, + "auto_vacuum", + GF_SQL_AV_NONE); + } else { + changing_pragma = _gf_false; + } + } + + if (ret) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_TRACE, 0, + LG_MSG_PREPARE_FAILED, + "Failed to set the pragma"); + goto out; + } + + gf_msg (GFDB_STR_SQLITE3, GF_LOG_INFO, 0, + LG_MSG_COMPACT_STATUS, "Turning compaction %i", + GF_SQL_COMPACT_DEF); + + /* If we move from an auto_vacuum scheme to off, */ + /* or vice-versa, we must VACUUM to save the change. */ + /* In the case of a manual VACUUM scheme, we might as well */ + /* run a manual VACUUM now if we */ + if (changing_pragma || compact_active) { + ret = gf_asprintf (&sqlstring, "VACUUM;"); + if (ret <= 0) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_PREPARE_FAILED, + "Failed allocating memory"); + goto out; + } + gf_msg(GFDB_STR_SQLITE3, GF_LOG_INFO, 0, + LG_MSG_COMPACT_STATUS, "Sealed with a VACUUM"); + } + } else { /* We are active, so it's time to VACUUM */ + if (!compact_active) { /* Did we somehow enter an inconsistent + state? */ + ret = -1; + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_PREPARE_FAILED, + "Tried to VACUUM when compaction inactive"); + goto out; + } + + gf_msg(GFDB_STR_SQLITE3, GF_LOG_TRACE, 0, + LG_MSG_COMPACT_STATUS, + "Doing regular vacuum of type %i", GF_SQL_COMPACT_DEF); + + switch (GF_SQL_COMPACT_DEF) { + case GF_SQL_COMPACT_INCR: /* INCR auto_vacuum */ + ret = gf_asprintf(&sqlstring, + "PRAGMA incremental_vacuum;"); + if (ret <= 0) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_PREPARE_FAILED, + "Failed allocating memory"); + goto out; + } + gf_msg(GFDB_STR_SQLITE3, GF_LOG_INFO, 0, + LG_MSG_COMPACT_STATUS, + "Will commence an incremental VACUUM"); + break; + /* (MANUAL) Invoke the VACUUM command */ + case GF_SQL_COMPACT_MANUAL: + ret = gf_asprintf(&sqlstring, "VACUUM;"); + if (ret <= 0) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_PREPARE_FAILED, + "Failed allocating memory"); + goto out; + } + gf_msg(GFDB_STR_SQLITE3, GF_LOG_INFO, 0, + LG_MSG_COMPACT_STATUS, + "Will commence a VACUUM"); + break; + /* (FULL) The database does the compaction itself. */ + /* We cannot do anything else, so we can leave */ + /* without sending anything to the database */ + case GF_SQL_COMPACT_FULL: + ret = 0; + goto success; + /* Any other state must be an error. Note that OFF */ + /* cannot hit this statement since we immediately leave */ + /* in that case */ + default: + ret = -1; + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_COMPACT_FAILED, + "VACUUM type undefined"); + goto out; + break; + } + } + + gf_msg(GFDB_STR_SQLITE3, GF_LOG_TRACE, 0, LG_MSG_COMPACT_STATUS, + "SQLString == %s", sqlstring); + + ret = sqlite3_exec(sql_conn->sqlite3_db_conn, sqlstring, NULL, NULL, + &sql_strerror); + + if (ret != SQLITE_OK) { + gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, + LG_MSG_GET_RECORD_FAILED, "Failed to vacuum " + "the db : %s", sqlite3_errmsg (db_conn)); + ret = -1; + goto out; + } +success: + gf_msg(GFDB_STR_SQLITE3, GF_LOG_INFO, 0, LG_MSG_COMPACT_STATUS, + compact_mode_switched ? "Successfully changed VACUUM on/off" + : "DB successfully VACUUM"); +out: + GF_FREE(sqlstring); + + return ret; +} |