/* Copyright (c) 2015 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #include "gfdb_sqlite3.h" #include "ctr-helper.h" #include "ctr-messages.h" /******************************************************************************* * * Fill unwind into db record * ******************************************************************************/ int fill_db_record_for_unwind(xlator_t *this, gf_ctr_local_t *ctr_local, gfdb_fop_type_t fop_type, gfdb_fop_path_t fop_path) { int ret = -1; gfdb_time_t *ctr_uwtime = NULL; gf_ctr_private_t *_priv = NULL; GF_ASSERT (this); _priv = this->private; GF_ASSERT (_priv); GF_ASSERT(ctr_local); /*If not unwind path error*/ if (!isunwindpath(fop_path)) { gf_msg (this->name, GF_LOG_ERROR, 0, CTR_MSG_WRONG_FOP_PATH, "Wrong fop_path. Should be unwind"); goto out; } ctr_uwtime = &CTR_DB_REC(ctr_local).gfdb_unwind_change_time; CTR_DB_REC(ctr_local).gfdb_fop_path = fop_path; CTR_DB_REC(ctr_local).gfdb_fop_type = fop_type; ret = gettimeofday (ctr_uwtime, NULL); if (ret == -1) { gf_msg (this->name, GF_LOG_ERROR, errno, CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, "Error " "filling unwind time record %s", strerror(errno)); goto out; } /* Special case i.e if its a tier rebalance * + cold tier brick * + its a create/mknod FOP * we record unwind time as zero */ if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG && (!_priv->ctr_hot_brick) && isdentrycreatefop(fop_type)) { memset(ctr_uwtime, 0, sizeof(*ctr_uwtime)); } ret = 0; out: return ret; } /******************************************************************************* * * Fill wind into db record * ******************************************************************************/ int fill_db_record_for_wind (xlator_t *this, gf_ctr_local_t *ctr_local, gf_ctr_inode_context_t *ctr_inode_cx) { int ret = -1; gfdb_time_t *ctr_wtime = NULL; gf_ctr_private_t *_priv = NULL; GF_ASSERT (this); _priv = this->private; GF_ASSERT (_priv); GF_ASSERT (ctr_local); IS_CTR_INODE_CX_SANE (ctr_inode_cx); /*if not wind path error!*/ if (!iswindpath(ctr_inode_cx->fop_path)) { gf_msg (this->name, GF_LOG_ERROR, 0, CTR_MSG_WRONG_FOP_PATH, "Wrong fop_path. Should be wind"); goto out; } ctr_wtime = &CTR_DB_REC(ctr_local).gfdb_wind_change_time; CTR_DB_REC(ctr_local).gfdb_fop_path = ctr_inode_cx->fop_path; CTR_DB_REC(ctr_local).gfdb_fop_type = ctr_inode_cx->fop_type; CTR_DB_REC(ctr_local).link_consistency = _priv->ctr_link_consistency; ret = gettimeofday (ctr_wtime, NULL); if (ret) { gf_msg (this->name, GF_LOG_ERROR, errno, CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, "Error filling wind time record %s", strerror(errno)); goto out; } /* Special case i.e if its a tier rebalance * + cold tier brick * + its a create/mknod FOP * we record wind time as zero */ if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG && (!_priv->ctr_hot_brick) && isdentrycreatefop(ctr_inode_cx->fop_type)) { memset(ctr_wtime, 0, sizeof(*ctr_wtime)); } /* Copy gfid into db record */ gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, *(ctr_inode_cx->gfid)); /* Copy older gfid if any */ if (ctr_inode_cx->old_gfid && (!gf_uuid_is_null (*(ctr_inode_cx->old_gfid)))) { gf_uuid_copy (CTR_DB_REC(ctr_local).old_gfid, *(ctr_inode_cx->old_gfid)); } /*Hard Links*/ if (isdentryfop(ctr_inode_cx->fop_type)) { /*new link fop*/ if (NEW_LINK_CX(ctr_inode_cx)) { gf_uuid_copy (CTR_DB_REC(ctr_local).pargfid, *((NEW_LINK_CX(ctr_inode_cx))->pargfid)); strcpy (CTR_DB_REC(ctr_local).file_name, NEW_LINK_CX(ctr_inode_cx)->basename); strcpy (CTR_DB_REC(ctr_local).file_path, NEW_LINK_CX(ctr_inode_cx)->basepath); } /*rename fop*/ if (OLD_LINK_CX(ctr_inode_cx)) { gf_uuid_copy (CTR_DB_REC(ctr_local).old_pargfid, *((OLD_LINK_CX(ctr_inode_cx))->pargfid)); strcpy (CTR_DB_REC(ctr_local).old_file_name, OLD_LINK_CX(ctr_inode_cx)->basename); strcpy (CTR_DB_REC(ctr_local).old_path, OLD_LINK_CX(ctr_inode_cx)->basepath); } } ret = 0; out: /*On error roll back and clean the record*/ if (ret == -1) { CLEAR_CTR_DB_RECORD (ctr_local); } return ret; } /****************************************************************************** * * CTR xlator init related functions * * * ****************************************************************************/ static int extract_sql_params(xlator_t *this, dict_t *params_dict) { int ret = -1; char *db_path = NULL; char *db_name = NULL; char *db_full_path = NULL; GF_ASSERT (this); GF_ASSERT (params_dict); /*Extract the path of the db*/ db_path = NULL; GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-path", db_path, "/var/run/gluster/"); /*Extract the name of the db*/ db_name = NULL; GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-name", db_name, "gf_ctr_db.db"); /*Construct full path of the db*/ ret = gf_asprintf(&db_full_path, "%s/%s", db_path, db_name); if (ret < 0) { gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0, CTR_MSG_CONSTRUCT_DB_PATH_FAILED, "Construction of full db path failed!"); goto out; } /*Setting the SQL DB Path*/ SET_DB_PARAM_TO_DICT(this->name, params_dict, GFDB_SQL_PARAM_DBPATH, db_full_path, ret, out); /*Extact rest of the sql params*/ ret = gfdb_set_sql_params(this->name, this->options, params_dict); if (ret) { gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0, CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED, "Failed setting values to sql param dict!"); } ret = 0; out: if (ret) GF_FREE (db_full_path); return ret; } int extract_db_params(xlator_t *this, dict_t *params_dict, gfdb_db_type_t db_type) { int ret = -1; GF_ASSERT (this); GF_ASSERT (params_dict); switch (db_type) { case GFDB_SQLITE3: ret = extract_sql_params(this, params_dict); if (ret) goto out; break; case GFDB_ROCKS_DB: case GFDB_HYPERDEX: case GFDB_HASH_FILE_STORE: case GFDB_INVALID_DB: case GFDB_DB_END: ret = -1; break; } ret = 0; out: return ret; } int extract_ctr_options (xlator_t *this, gf_ctr_private_t *_priv) { int ret = -1; char *_val_str = NULL; GF_ASSERT (this); GF_ASSERT (_priv); /*Checking if the CTR Translator is enabled. By default its disabled*/ _priv->enabled = _gf_false; GF_OPTION_INIT ("ctr-enabled", _priv->enabled, bool, out); if (!_priv->enabled) { gf_msg (GFDB_DATA_STORE, GF_LOG_INFO, 0, CTR_MSG_XLATOR_DISABLED, "CTR Xlator is disabled."); ret = 0; goto out; } /*Extract db type*/ GF_OPTION_INIT ("db-type", _val_str, str, out); _priv->gfdb_db_type = gf_string2gfdbdbtype(_val_str); /*Extract flag for record on wind*/ GF_OPTION_INIT ("record-entry", _priv->ctr_record_wind, bool, out); /*Extract flag for record on unwind*/ GF_OPTION_INIT ("record-exit", _priv->ctr_record_unwind, bool, out); /*Extract flag for record on counters*/ GF_OPTION_INIT ("record-counters", _priv->ctr_record_counter, bool, out); /* Extract flag for record metadata heat */ GF_OPTION_INIT ("ctr-record-metadata-heat", _priv->ctr_record_metadata_heat, bool, out); /*Extract flag for link consistency*/ GF_OPTION_INIT ("ctr_link_consistency", _priv->ctr_link_consistency, bool, out); /*Extract ctr_lookupheal_inode_timeout */ GF_OPTION_INIT ("ctr_lookupheal_inode_timeout", _priv->ctr_lookupheal_inode_timeout, uint64, out); /*Extract ctr_lookupheal_link_timeout*/ GF_OPTION_INIT ("ctr_lookupheal_link_timeout", _priv->ctr_lookupheal_link_timeout, uint64, out); /*Extract flag for hot tier brick*/ GF_OPTION_INIT ("hot-brick", _priv->ctr_hot_brick, bool, out); /*Extract flag for sync mode*/ GF_OPTION_INIT ("db-sync", _val_str, str, out); _priv->gfdb_sync_type = gf_string2gfdbdbsync(_val_str); ret = 0; out: return ret; }