ab918eac825c9be6471a310e0dae8fd043af2f4b
[obnox/glusterfs.git] / xlators / features / changetimerecorder / src / ctr-helper.c
1 /*
2    Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
3    This file is part of GlusterFS.
4
5    This file is licensed to you under your choice of the GNU Lesser
6    General Public License, version 3 or any later version (LGPLv3 or
7    later), or the GNU General Public License, version 2 (GPLv2), in all
8    cases as published by the Free Software Foundation.
9 */
10
11 #include "gfdb_sqlite3.h"
12 #include "ctr-helper.h"
13 #include "ctr-messages.h"
14
15 /*******************************************************************************
16  *
17  *                      Fill unwind into db record
18  *
19  ******************************************************************************/
20 int
21 fill_db_record_for_unwind(xlator_t              *this,
22                           gf_ctr_local_t        *ctr_local,
23                           gfdb_fop_type_t       fop_type,
24                           gfdb_fop_path_t       fop_path)
25 {
26         int ret                         = -1;
27         gfdb_time_t *ctr_uwtime         = NULL;
28         gf_ctr_private_t *_priv                 = NULL;
29
30         GF_ASSERT (this);
31         _priv = this->private;
32         GF_ASSERT (_priv);
33
34         GF_ASSERT(ctr_local);
35
36         /*If not unwind path error*/
37         if (!isunwindpath(fop_path)) {
38                 gf_msg (this->name, GF_LOG_ERROR, 0, CTR_MSG_WRONG_FOP_PATH,
39                         "Wrong fop_path. Should be unwind");
40                 goto out;
41         }
42
43         ctr_uwtime = &CTR_DB_REC(ctr_local).gfdb_unwind_change_time;
44         CTR_DB_REC(ctr_local).gfdb_fop_path = fop_path;
45         CTR_DB_REC(ctr_local).gfdb_fop_type = fop_type;
46
47         ret = gettimeofday (ctr_uwtime, NULL);
48         if (ret == -1) {
49                         gf_msg (this->name, GF_LOG_ERROR, errno,
50                                 CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, "Error "
51                                 "filling unwind time record %s",
52                                 strerror(errno));
53                         goto out;
54                 }
55
56         /* Special case i.e if its a tier rebalance
57          * + cold tier brick
58          * + its a create/mknod FOP
59          * we record unwind time as zero */
60         if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG
61                 && (!_priv->ctr_hot_brick)
62                 && isdentrycreatefop(fop_type)) {
63                 memset(ctr_uwtime, 0, sizeof(*ctr_uwtime));
64         }
65         ret = 0;
66 out:
67         return ret;
68 }
69
70
71 /*******************************************************************************
72  *
73  *                      Fill wind into db record
74  *
75  ******************************************************************************/
76 int
77 fill_db_record_for_wind (xlator_t               *this,
78                         gf_ctr_local_t          *ctr_local,
79                         gf_ctr_inode_context_t  *ctr_inode_cx)
80 {
81         int ret                                 = -1;
82         gfdb_time_t *ctr_wtime                  = NULL;
83         gf_ctr_private_t *_priv                 = NULL;
84
85         GF_ASSERT (this);
86         _priv = this->private;
87         GF_ASSERT (_priv);
88         GF_ASSERT (ctr_local);
89         IS_CTR_INODE_CX_SANE (ctr_inode_cx);
90
91         /*if not wind path error!*/
92         if (!iswindpath(ctr_inode_cx->fop_path)) {
93                 gf_msg (this->name, GF_LOG_ERROR, 0,
94                         CTR_MSG_WRONG_FOP_PATH,
95                         "Wrong fop_path. Should be wind");
96                 goto out;
97         }
98
99         ctr_wtime = &CTR_DB_REC(ctr_local).gfdb_wind_change_time;
100         CTR_DB_REC(ctr_local).gfdb_fop_path = ctr_inode_cx->fop_path;
101         CTR_DB_REC(ctr_local).gfdb_fop_type = ctr_inode_cx->fop_type;
102         CTR_DB_REC(ctr_local).link_consistency = _priv->ctr_link_consistency;
103
104         ret = gettimeofday (ctr_wtime, NULL);
105         if (ret) {
106                         gf_msg (this->name, GF_LOG_ERROR, errno,
107                                 CTR_MSG_FILL_UNWIND_TIME_REC_ERROR,
108                                 "Error filling wind time record %s",
109                                 strerror(errno));
110                         goto out;
111         }
112
113         /* Special case i.e if its a tier rebalance
114          * + cold tier brick
115          * + its a create/mknod FOP
116          * we record wind time as zero */
117         if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG
118                 && (!_priv->ctr_hot_brick)
119                 && isdentrycreatefop(ctr_inode_cx->fop_type)) {
120                 memset(ctr_wtime, 0, sizeof(*ctr_wtime));
121         }
122
123         /*Copy gfid into db record*/
124         gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, *(ctr_inode_cx->gfid));
125
126         /*Hard Links*/
127         if (isdentryfop(ctr_inode_cx->fop_type)) {
128                 /*new link fop*/
129                 if (NEW_LINK_CX(ctr_inode_cx)) {
130                         gf_uuid_copy (CTR_DB_REC(ctr_local).pargfid,
131                                 *((NEW_LINK_CX(ctr_inode_cx))->pargfid));
132                         strcpy (CTR_DB_REC(ctr_local).file_name,
133                                 NEW_LINK_CX(ctr_inode_cx)->basename);
134                         strcpy (CTR_DB_REC(ctr_local).file_path,
135                                 NEW_LINK_CX(ctr_inode_cx)->basepath);
136                 }
137                 /*rename fop*/
138                 if (OLD_LINK_CX(ctr_inode_cx)) {
139                         gf_uuid_copy (CTR_DB_REC(ctr_local).old_pargfid,
140                                 *((OLD_LINK_CX(ctr_inode_cx))->pargfid));
141                         strcpy (CTR_DB_REC(ctr_local).old_file_name,
142                                 OLD_LINK_CX(ctr_inode_cx)->basename);
143                         strcpy (CTR_DB_REC(ctr_local).old_path,
144                                 OLD_LINK_CX(ctr_inode_cx)->basepath);
145                 }
146         }
147
148         ret = 0;
149 out:
150         /*On error roll back and clean the record*/
151         if (ret == -1) {
152                 CLEAR_CTR_DB_RECORD (ctr_local);
153         }
154         return ret;
155 }
156
157
158 /******************************************************************************
159  *
160  *                      CTR xlator init related functions
161  *
162  *
163  * ****************************************************************************/
164 static int
165 extract_sql_params(xlator_t *this, dict_t *params_dict)
166 {
167         int ret                         = -1;
168         char *db_path                   = NULL;
169         char *db_name                   = NULL;
170         char *db_full_path              = NULL;
171
172         GF_ASSERT (this);
173         GF_ASSERT (params_dict);
174
175         /*Extract the path of the db*/
176         db_path = NULL;
177         GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-path",
178                                         db_path, "/var/run/gluster/");
179
180         /*Extract the name of the db*/
181         db_name = NULL;
182         GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-name",
183                                         db_name, "gf_ctr_db.db");
184
185         /*Construct full path of the db*/
186         ret = gf_asprintf(&db_full_path, "%s/%s", db_path, db_name);
187         if (ret < 0) {
188                 gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
189                         CTR_MSG_CONSTRUCT_DB_PATH_FAILED,
190                         "Construction of full db path failed!");
191                 goto out;
192         }
193
194         /*Setting the SQL DB Path*/
195         SET_DB_PARAM_TO_DICT(this->name, params_dict, GFDB_SQL_PARAM_DBPATH,
196                                 db_full_path, ret, out);
197
198         /*Extact rest of the sql params*/
199         ret = gfdb_set_sql_params(this->name, this->options, params_dict);
200         if (ret) {
201                 gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
202                         CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED,
203                         "Failed setting values to sql param dict!");
204         }
205
206         ret = 0;
207
208 out:
209         if (ret)
210                 GF_FREE (db_full_path);
211         return ret;
212 }
213
214
215
216 int extract_db_params(xlator_t *this, dict_t *params_dict,
217                                                 gfdb_db_type_t db_type) {
218
219         int ret = -1;
220
221         GF_ASSERT (this);
222         GF_ASSERT (params_dict);
223
224         switch (db_type) {
225         case GFDB_SQLITE3:
226                 ret = extract_sql_params(this, params_dict);
227                 if (ret)
228                         goto out;
229                 break;
230         case GFDB_ROCKS_DB:
231         case GFDB_HYPERDEX:
232         case GFDB_HASH_FILE_STORE:
233         case GFDB_INVALID_DB:
234         case GFDB_DB_END:
235                 ret = -1;
236                 break;
237         }
238         ret = 0;
239 out:
240         return ret;
241 }
242
243 int extract_ctr_options (xlator_t *this, gf_ctr_private_t *_priv) {
244         int ret         = -1;
245         char *_val_str  = NULL;
246
247         GF_ASSERT (this);
248         GF_ASSERT (_priv);
249
250         /*Checking if the CTR Translator is enabled. By default its disabled*/
251         _priv->enabled = _gf_false;
252         GF_OPTION_INIT ("ctr-enabled", _priv->enabled, bool, out);
253         if (!_priv->enabled) {
254                 gf_msg (GFDB_DATA_STORE, GF_LOG_INFO, 0,
255                         CTR_MSG_XLATOR_DISABLED,
256                         "CTR Xlator is disabled.");
257                 ret = 0;
258                 goto out;
259         }
260
261         /*Extract db type*/
262         GF_OPTION_INIT ("db-type", _val_str, str, out);
263         _priv->gfdb_db_type = gf_string2gfdbdbtype(_val_str);
264
265         /*Extract flag for record on wind*/
266         GF_OPTION_INIT ("record-entry", _priv->ctr_record_wind, bool, out);
267
268         /*Extract flag for record on unwind*/
269         GF_OPTION_INIT ("record-exit", _priv->ctr_record_unwind, bool, out);
270
271         /*Extract flag for record on counters*/
272         GF_OPTION_INIT ("record-counters", _priv->ctr_record_counter, bool,
273                         out);
274
275         /* Extract flag for record metadata heat */
276         GF_OPTION_INIT ("ctr-record-metadata-heat",
277                         _priv->ctr_record_metadata_heat, bool,
278                         out);
279
280         /*Extract flag for link consistency*/
281         GF_OPTION_INIT ("ctr_link_consistency", _priv->ctr_link_consistency,
282                         bool, out);
283
284         /*Extract ctr_inode_heal_expire_period */
285         GF_OPTION_INIT ("ctr_inode_heal_expire_period",
286                         _priv->ctr_inode_heal_expire_period,
287                         uint64, out);
288
289         /*Extract ctr_hardlink_heal_expire_period*/
290         GF_OPTION_INIT ("ctr_hardlink_heal_expire_period",
291                         _priv->ctr_hardlink_heal_expire_period,
292                         uint64, out);
293
294         /*Extract flag for hot tier brick*/
295         GF_OPTION_INIT ("hot-brick", _priv->ctr_hot_brick, bool, out);
296
297         /*Extract flag for sync mode*/
298         GF_OPTION_INIT ("db-sync", _val_str, str, out);
299         _priv->gfdb_sync_type = gf_string2gfdbdbsync(_val_str);
300
301         ret = 0;
302
303 out:
304         return ret;
305 }