summaryrefslogtreecommitdiffstats
path: root/xlators/features/changetimerecorder
diff options
context:
space:
mode:
authorJoseph Fernandes <josferna@redhat.com>2015-09-18 19:57:54 +0530
committerDan Lambright <dlambrig@redhat.com>2015-10-08 12:00:31 -0700
commit58d1a9be562630bd1ed8af3e496ca05e087adece (patch)
tree5feb32ff9e6ad3c38d87759589426471a4044671 /xlators/features/changetimerecorder
parent81d4aa18b3a1cdad0e0e8df43fe4c8c141c06618 (diff)
tier/ctr: Solution for db locks for tier migrator and ctr using sqlite version less than 3.7 i.e rhel 6.7
Problem: On RHEL 6.7, we have sqlite version 3.6.2 which doesnt support WAL journaling mode, as this journaling mode is only available in sqlite 3.7 and above. As a result we cannot have to progreses concurrently accessing sqlite, without running into db locks! Well WAL is also need for performace on CTR side. Solution: This solution is to use CTR db connection for doing queries when WAL mode is absent. i,e tier migrator will send sync_op ipc calls to CTR, which in turn will do the query and create/update the query file suggested by tier migrator. Pending: Well this solution will stop the db locks but the performance is still an issue for CTR. We are developing an in-Memory Transaction Log (iMeTaL) which will help boost the CTR performance by doing in memory udpates on the IO path and later flush the updates to the db in a batch/segment flush. Change-Id: Ie3149643ded159234b5cc6aa6cf93b9022c2f124 BUG: 1240577 Signed-off-by: Joseph Fernandes <josferna@redhat.com> Signed-off-by: Dan Lambright <dlambrig@redhat.com> Signed-off-by: Joseph Fernandes <josferna@redhat.com> Reviewed-on: http://review.gluster.org/12191 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Luis Pabon <lpabon@redhat.com>
Diffstat (limited to 'xlators/features/changetimerecorder')
-rw-r--r--xlators/features/changetimerecorder/src/changetimerecorder.c332
-rw-r--r--xlators/features/changetimerecorder/src/ctr-helper.h7
2 files changed, 302 insertions, 37 deletions
diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.c b/xlators/features/changetimerecorder/src/changetimerecorder.c
index 609be07fa7e..89445b47bca 100644
--- a/xlators/features/changetimerecorder/src/changetimerecorder.c
+++ b/xlators/features/changetimerecorder/src/changetimerecorder.c
@@ -1382,29 +1382,287 @@ out:
/*******************************ctr_ipc****************************************/
+/*This is the call back function per record/file from data base*/
+static int
+ctr_db_query_callback (gfdb_query_record_t *gfdb_query_record,
+ void *args) {
+ int ret = -1;
+ char gfid_str[UUID_CANONICAL_FORM_LEN+1] = "";
+ ctr_query_cbk_args_t *query_cbk_args = args;
+
+ GF_VALIDATE_OR_GOTO ("ctr", query_cbk_args, out);
+
+ gf_uuid_unparse (gfdb_query_record->gfid, gfid_str);
+ fprintf (query_cbk_args->queryFILE, "%s|%s|%ld\n", gfid_str,
+ gfdb_query_record->_link_info_str,
+ gfdb_query_record->link_info_size);
+
+ query_cbk_args->count++;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+/* This function does all the db queries related to tiering and
+ * generates/populates new/existing query file
+ * inputs:
+ * xlator_t *this : CTR Translator
+ * void *conn_node : Database connection
+ * char *query_file: the query file that needs to be updated
+ * gfdb_ipc_ctr_params_t *ipc_ctr_params: the query parameters
+ * Return:
+ * On success 0
+ * On failure -1
+ * */
+int
+ctr_db_query (xlator_t *this,
+ void *conn_node,
+ char *query_file,
+ gfdb_ipc_ctr_params_t *ipc_ctr_params)
+{
+ int ret = -1;
+ ctr_query_cbk_args_t query_cbk_args = {0};
+
+ GF_VALIDATE_OR_GOTO ("ctr", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, conn_node, out);
+ GF_VALIDATE_OR_GOTO (this->name, query_file, out);
+ GF_VALIDATE_OR_GOTO (this->name, ipc_ctr_params, out);
+
+ /*Query for eligible files from db*/
+ query_cbk_args.queryFILE = fopen(query_file, "a+");
+ if (!query_cbk_args.queryFILE) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ CTR_MSG_FATAL_ERROR,
+ "Failed to open query file %s", query_file);
+ goto out;
+ }
+ if (!ipc_ctr_params->is_promote) {
+ if (ipc_ctr_params->write_freq_threshold == 0 &&
+ ipc_ctr_params->read_freq_threshold == 0) {
+ ret = find_unchanged_for_time (
+ conn_node,
+ ctr_db_query_callback,
+ (void *)&query_cbk_args,
+ &ipc_ctr_params->time_stamp);
+ } else {
+ ret = find_unchanged_for_time_freq (
+ conn_node,
+ ctr_db_query_callback,
+ (void *)&query_cbk_args,
+ &ipc_ctr_params->time_stamp,
+ ipc_ctr_params->write_freq_threshold,
+ ipc_ctr_params->read_freq_threshold,
+ _gf_false);
+ }
+ } else {
+ if (ipc_ctr_params->write_freq_threshold == 0 &&
+ ipc_ctr_params->read_freq_threshold == 0) {
+ ret = find_recently_changed_files (
+ conn_node,
+ ctr_db_query_callback,
+ (void *)&query_cbk_args,
+ &ipc_ctr_params->time_stamp);
+ } else {
+ ret = find_recently_changed_files_freq (
+ conn_node,
+ ctr_db_query_callback,
+ (void *)&query_cbk_args,
+ &ipc_ctr_params->time_stamp,
+ ipc_ctr_params->write_freq_threshold,
+ ipc_ctr_params->read_freq_threshold,
+ _gf_false);
+ }
+ }
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ CTR_MSG_FATAL_ERROR,
+ "FATAL: query from db failed");
+ goto out;
+ }
+
+ ret = clear_files_heat (conn_node);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ CTR_MSG_FATAL_ERROR,
+ "FATAL: Failed to clear db entries");
+ goto out;
+ }
+
+ ret = 0;
+out:
+
+ if (!ret)
+ ret = query_cbk_args.count;
+
+ if (query_cbk_args.queryFILE) {
+ fclose (query_cbk_args.queryFILE);
+ query_cbk_args.queryFILE = NULL;
+ }
+
+ return ret;
+}
+
+
+int
+ctr_ipc_helper (xlator_t *this, dict_t *in_dict,
+ dict_t *out_dict)
+{
+ int ret = -1;
+ char *ctr_ipc_ops = NULL;
+ gf_ctr_private_t *priv = NULL;
+ char *db_version = NULL;
+ char *db_param_key = NULL;
+ char *db_param = NULL;
+ char *query_file = NULL;
+ gfdb_ipc_ctr_params_t *ipc_ctr_params = NULL;
+
+
+ GF_VALIDATE_OR_GOTO ("ctr", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, this->private, out);
+ priv = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, priv->_db_conn, out);
+ GF_VALIDATE_OR_GOTO (this->name, in_dict, out);
+ GF_VALIDATE_OR_GOTO (this->name, out_dict, out);
+
+ GET_DB_PARAM_FROM_DICT(this->name, in_dict, GFDB_IPC_CTR_KEY,
+ ctr_ipc_ops, out);
+
+ /*if its a db clear operation */
+ if (strncmp (ctr_ipc_ops, GFDB_IPC_CTR_CLEAR_OPS,
+ strlen (GFDB_IPC_CTR_CLEAR_OPS)) == 0) {
+
+ ret = clear_files_heat (priv->_db_conn);
+ if (ret)
+ goto out;
+
+ } /* if its a query operation, in which case its query + clear db*/
+ else if (strncmp (ctr_ipc_ops, GFDB_IPC_CTR_QUERY_OPS,
+ strlen (GFDB_IPC_CTR_QUERY_OPS)) == 0) {
+
+ ret = dict_get_str (in_dict, GFDB_IPC_CTR_GET_QFILE_PATH,
+ &query_file);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed extracting query file path");
+ goto out;
+ }
+
+ ret = dict_get_bin (in_dict, GFDB_IPC_CTR_GET_QUERY_PARAMS,
+ (void *)&ipc_ctr_params);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed extracting query parameters");
+ goto out;
+ }
+
+ ret = ctr_db_query (this, priv->_db_conn, query_file,
+ ipc_ctr_params);
+
+ ret = dict_set_int32 (out_dict,
+ GFDB_IPC_CTR_RET_QUERY_COUNT, ret);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed setting query reply");
+ goto out;
+ }
+
+ } /* if its a query for db version */
+ else if (strncmp (ctr_ipc_ops, GFDB_IPC_CTR_GET_DB_VERSION_OPS,
+ strlen (GFDB_IPC_CTR_GET_DB_VERSION_OPS)) == 0) {
+
+ ret = get_db_version (priv->_db_conn, &db_version);
+ if (ret == -1 || !db_version) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed extracting db version ");
+ goto out;
+ }
+
+ SET_DB_PARAM_TO_DICT(this->name, out_dict,
+ GFDB_IPC_CTR_RET_DB_VERSION,
+ db_version, ret, error);
+
+ } /* if its a query for a db setting */
+ else if (strncmp (ctr_ipc_ops, GFDB_IPC_CTR_GET_DB_PARAM_OPS,
+ strlen (GFDB_IPC_CTR_GET_DB_PARAM_OPS)) == 0) {
+
+ ret = dict_get_str (in_dict, GFDB_IPC_CTR_GET_DB_KEY,
+ &db_param_key);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed extracting db param key");
+ goto out;
+ }
+
+ ret = get_db_setting (priv->_db_conn, db_param_key, &db_param);
+ if (ret == -1 || !db_param) {
+ goto out;
+ }
+
+ SET_DB_PARAM_TO_DICT(this->name, out_dict,
+ db_param_key,
+ db_param, ret, error);
+ } /* default case */
+ else {
+ goto out;
+ }
+
+
+ ret = 0;
+ goto out;
+error:
+ GF_FREE (db_param_key);
+ GF_FREE (db_param);
+ GF_FREE (db_version);
+out:
+ return ret;
+}
+
+
/* IPC Call from tier migrator to clear the heat on the DB */
int32_t
-ctr_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata)
+ctr_ipc (call_frame_t *frame, xlator_t *this, int32_t op,
+ dict_t *in_dict)
{
int ret = -1;
- gf_ctr_private_t *_priv = NULL;
+ gf_ctr_private_t *priv = NULL;
+ dict_t *out_dict = NULL;
GF_ASSERT(this);
- _priv = this->private;
- GF_ASSERT (_priv);
- GF_ASSERT(_priv->_db_conn);
+ priv = this->private;
+ GF_ASSERT (priv);
+ GF_ASSERT(priv->_db_conn);
+ GF_VALIDATE_OR_GOTO (this->name, in_dict, wind);
+
if (op != GF_IPC_TARGET_CTR)
goto wind;
- ret = clear_files_heat (_priv->_db_conn);
+ out_dict = dict_new();
+ if (!out_dict) {
+ goto out;
+ }
+
+ ret = ctr_ipc_helper (this, in_dict, out_dict);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET,
+ "Failed in ctr_ipc_helper");
+ }
+out:
+
+ STACK_UNWIND_STRICT (ipc, frame, ret, 0, out_dict);
+
+ if (out_dict)
+ dict_unref(out_dict);
- STACK_UNWIND_STRICT (ipc, frame, ret, 0, NULL);
return 0;
wind:
STACK_WIND (frame, default_ipc_cbk, FIRST_CHILD (this),
- FIRST_CHILD (this)->fops->ipc, op, xdata);
+ FIRST_CHILD (this)->fops->ipc, op, in_dict);
+
+
+
return 0;
}
@@ -1416,35 +1674,35 @@ reconfigure (xlator_t *this, dict_t *options)
{
char *temp_str = NULL;
int ret = 0;
- gf_ctr_private_t *_priv = NULL;
+ gf_ctr_private_t *priv = NULL;
- _priv = this->private;
+ priv = this->private;
if (dict_get_str(options, "changetimerecorder.frequency",
&temp_str)) {
gf_msg(this->name, GF_LOG_INFO, 0, CTR_MSG_SET, "set!");
}
- GF_OPTION_RECONF ("ctr-enabled", _priv->enabled, options,
+ GF_OPTION_RECONF ("ctr-enabled", priv->enabled, options,
bool, out);
- GF_OPTION_RECONF ("record-counters", _priv->ctr_record_counter, options,
+ GF_OPTION_RECONF ("record-counters", priv->ctr_record_counter, options,
bool, out);
- GF_OPTION_RECONF ("ctr_link_consistency", _priv->ctr_link_consistency,
+ GF_OPTION_RECONF ("ctr_link_consistency", priv->ctr_link_consistency,
options, bool, out);
GF_OPTION_RECONF ("ctr_inode_heal_expire_period",
- _priv->ctr_inode_heal_expire_period,
+ priv->ctr_inode_heal_expire_period,
options, uint64, out);
GF_OPTION_RECONF ("ctr_hardlink_heal_expire_period",
- _priv->ctr_hardlink_heal_expire_period,
+ priv->ctr_hardlink_heal_expire_period,
options, uint64, out);
- GF_OPTION_RECONF ("record-exit", _priv->ctr_record_unwind, options,
+ GF_OPTION_RECONF ("record-exit", priv->ctr_record_unwind, options,
bool, out);
- GF_OPTION_RECONF ("record-entry", _priv->ctr_record_wind, options,
+ GF_OPTION_RECONF ("record-entry", priv->ctr_record_wind, options,
bool, out);
out:
@@ -1457,7 +1715,7 @@ out:
int32_t
init (xlator_t *this)
{
- gf_ctr_private_t *_priv = NULL;
+ gf_ctr_private_t *priv = NULL;
int ret_db = -1;
dict_t *params_dict = NULL;
@@ -1476,8 +1734,8 @@ init (xlator_t *this)
"dangling volume. check volfile ");
}
- _priv = GF_CALLOC (1, sizeof (*_priv), gf_ctr_mt_private_t);
- if (!_priv) {
+ priv = GF_CALLOC (1, sizeof (*priv), gf_ctr_mt_private_t);
+ if (!priv) {
gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
CTR_MSG_CALLOC_FAILED,
"Calloc didnt work!!!");
@@ -1485,20 +1743,20 @@ init (xlator_t *this)
}
/*Default values for the translator*/
- _priv->ctr_record_wind = _gf_true;
- _priv->ctr_record_unwind = _gf_false;
- _priv->ctr_hot_brick = _gf_false;
- _priv->gfdb_db_type = GFDB_SQLITE3;
- _priv->gfdb_sync_type = GFDB_DB_SYNC;
- _priv->enabled = _gf_true;
- _priv->_db_conn = NULL;
- _priv->ctr_hardlink_heal_expire_period =
+ priv->ctr_record_wind = _gf_true;
+ priv->ctr_record_unwind = _gf_false;
+ priv->ctr_hot_brick = _gf_false;
+ priv->gfdb_db_type = GFDB_SQLITE3;
+ priv->gfdb_sync_type = GFDB_DB_SYNC;
+ priv->enabled = _gf_true;
+ priv->_db_conn = NULL;
+ priv->ctr_hardlink_heal_expire_period =
CTR_DEFAULT_HARDLINK_EXP_PERIOD;
- _priv->ctr_inode_heal_expire_period =
+ priv->ctr_inode_heal_expire_period =
CTR_DEFAULT_INODE_EXP_PERIOD;
/*Extract ctr xlator options*/
- ret_db = extract_ctr_options (this, _priv);
+ ret_db = extract_ctr_options (this, priv);
if (ret_db) {
gf_msg (this->name, GF_LOG_ERROR, 0,
CTR_MSG_EXTRACT_CTR_XLATOR_OPTIONS_FAILED,
@@ -1515,7 +1773,7 @@ init (xlator_t *this)
}
/*Extract db params options*/
- ret_db = extract_db_params(this, params_dict, _priv->gfdb_db_type);
+ ret_db = extract_db_params(this, params_dict, priv->gfdb_db_type);
if (ret_db) {
gf_msg (this->name, GF_LOG_ERROR, 0,
CTR_MSG_EXTRACT_DB_PARAM_OPTIONS_FAILED,
@@ -1533,8 +1791,8 @@ init (xlator_t *this)
}
/*Initialize Database Connection*/
- _priv->_db_conn = init_db(params_dict, _priv->gfdb_db_type);
- if (!_priv->_db_conn) {
+ priv->_db_conn = init_db(params_dict, priv->gfdb_db_type);
+ if (!priv->_db_conn) {
gf_msg (this->name, GF_LOG_ERROR, 0,
CTR_MSG_FATAL_ERROR,
"FATAL: Failed initializing data base");
@@ -1550,10 +1808,10 @@ error:
if (this)
mem_pool_destroy (this->local_pool);
- if (_priv) {
- GF_FREE (_priv->ctr_db_path);
+ if (priv) {
+ GF_FREE (priv->ctr_db_path);
}
- GF_FREE (_priv);
+ GF_FREE (priv);
if (params_dict)
dict_unref (params_dict);
@@ -1565,7 +1823,7 @@ out:
if (params_dict)
dict_unref (params_dict);
- this->private = (void *)_priv;
+ this->private = (void *)priv;
return 0;
}
diff --git a/xlators/features/changetimerecorder/src/ctr-helper.h b/xlators/features/changetimerecorder/src/ctr-helper.h
index cff79756603..dbad3029462 100644
--- a/xlators/features/changetimerecorder/src/ctr-helper.h
+++ b/xlators/features/changetimerecorder/src/ctr-helper.h
@@ -30,6 +30,13 @@
#define CTR_DEFAULT_HARDLINK_EXP_PERIOD 300 /* Five mins */
#define CTR_DEFAULT_INODE_EXP_PERIOD 300 /* Five mins */
+
+typedef struct ctr_query_cbk_args {
+ FILE *queryFILE;
+ int count;
+} ctr_query_cbk_args_t;
+
+
/*CTR Xlator Private structure*/
typedef struct gf_ctr_private {
gf_boolean_t enabled;