summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/gfdb/gfdb_sqlite3.h
blob: d8240e905f713001f8ac51160b23448c6f7ef236 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
/*
   Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
   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.
*/
#ifndef __GFDB_SQLITE3_H
#define __GFDB_SQLITE3_H

/*Sqlite3 header file*/
#include <sqlite3.h>

#include "glusterfs/logging.h"
#include "gfdb_data_store_types.h"
#include "gfdb_mem-types.h"
#include "glusterfs/libglusterfs-messages.h"

#define GF_STMT_SIZE_MAX 2048

#define GF_DB_NAME "gfdb.db"
#define GF_FILE_TABLE "GF_FILE_TB"
#define GF_FILE_LINK_TABLE "GF_FLINK_TB"
#define GF_MASTER_TABLE "sqlite_master"

/*Since we have multiple tables to be created we put it in a transaction*/
#define GF_CREATE_STMT(out_str)                                                \
    do {                                                                       \
        sprintf(out_str, "BEGIN; CREATE TABLE IF NOT EXISTS " GF_FILE_TABLE    \
                         "(GF_ID TEXT PRIMARY KEY NOT NULL, "                  \
                         "W_SEC INTEGER NOT NULL DEFAULT 0, "                  \
                         "W_MSEC INTEGER NOT NULL DEFAULT 0, "                 \
                         "UW_SEC INTEGER NOT NULL DEFAULT 0, "                 \
                         "UW_MSEC INTEGER NOT NULL DEFAULT 0, "                \
                         "W_READ_SEC INTEGER NOT NULL DEFAULT 0, "             \
                         "W_READ_MSEC INTEGER NOT NULL DEFAULT 0, "            \
                         "UW_READ_SEC INTEGER NOT NULL DEFAULT 0, "            \
                         "UW_READ_MSEC INTEGER NOT NULL DEFAULT 0, "           \
                         "WRITE_FREQ_CNTR INTEGER NOT NULL DEFAULT 1, "        \
                         "READ_FREQ_CNTR INTEGER NOT NULL DEFAULT 1); "        \
                         "CREATE TABLE IF NOT EXISTS " GF_FILE_LINK_TABLE      \
                         "(GF_ID TEXT NOT NULL, "                              \
                         "GF_PID TEXT NOT NULL, "                              \
                         "FNAME TEXT NOT NULL, "                               \
                         "W_DEL_FLAG INTEGER NOT NULL DEFAULT 0, "             \
                         "LINK_UPDATE INTEGER NOT NULL DEFAULT 0, "            \
                         "PRIMARY KEY ( GF_ID, GF_PID, FNAME) "                \
                         ");"                                                  \
                         "COMMIT;");                                           \
        ;                                                                      \
    } while (0)

#define GF_COL_TB_WSEC GF_FILE_TABLE "." GF_COL_WSEC
#define GF_COL_TB_WMSEC GF_FILE_TABLE "." GF_COL_WMSEC
#define GF_COL_TB_UWSEC GF_FILE_TABLE "." GF_COL_UWSEC
#define GF_COL_TB_UWMSEC GF_FILE_TABLE "." GF_COL_UWMSEC
#define GF_COL_TB_RWSEC GF_FILE_TABLE "." GF_COL_WSEC_READ
#define GF_COL_TB_RWMSEC GF_FILE_TABLE "." GF_COL_WMSEC_READ
#define GF_COL_TB_RUWSEC GF_FILE_TABLE "." GF_COL_UWSEC_READ
#define GF_COL_TB_RUWMSEC GF_FILE_TABLE "." GF_COL_UWMSEC_READ
#define GF_COL_TB_WFC GF_FILE_TABLE "." GF_COL_WRITE_FREQ_CNTR
#define GF_COL_TB_RFC GF_FILE_TABLE "." GF_COL_READ_FREQ_CNTR

/*******************************************************************************
 *                      SQLITE3 Connection details and PRAGMA
 * ****************************************************************************/

#define GF_SQL_AV_NONE "none"
#define GF_SQL_AV_FULL "full"
#define GF_SQL_AV_INCR "incremental"

#define GF_SQL_SYNC_OFF "off"
#define GF_SQL_SYNC_NORMAL "normal"
#define GF_SQL_SYNC_FULL "full"

#define GF_SQL_JM_DELETE "delete"
#define GF_SQL_JM_TRUNCATE "truncate"
#define GF_SQL_JM_PERSIST "persist"
#define GF_SQL_JM_MEMORY "memory"
#define GF_SQL_JM_WAL "wal"
#define GF_SQL_JM_OFF "off"

#define GF_SQL_COMPACT_NONE 0
#define GF_SQL_COMPACT_FULL 1
#define GF_SQL_COMPACT_INCR 2
#define GF_SQL_COMPACT_MANUAL 3

#define GF_SQL_COMPACT_DEF GF_SQL_COMPACT_INCR
typedef enum gf_sql_auto_vacuum {
    gf_sql_av_none = 0,
    gf_sql_av_full,
    gf_sql_av_incr,
    gf_sql_av_invalid
} gf_sql_auto_vacuum_t;

typedef enum gf_sql_sync {
    gf_sql_sync_off = 0,
    gf_sql_sync_normal,
    gf_sql_sync_full,
    gf_sql_sync_invalid
} gf_sql_sync_t;

typedef enum gf_sql_journal_mode {
    gf_sql_jm_wal = 0,
    gf_sql_jm_delete,
    gf_sql_jm_truncate,
    gf_sql_jm_persist,
    gf_sql_jm_memory,
    gf_sql_jm_off,
    gf_sql_jm_invalid
} gf_sql_journal_mode_t;

typedef struct gf_sql_connection {
    char sqlite3_db_path[PATH_MAX];
    sqlite3 *sqlite3_db_conn;
    ssize_t cache_size;
    ssize_t page_size;
    ssize_t wal_autocheckpoint;
    gf_sql_journal_mode_t journal_mode;
    gf_sql_sync_t synchronous;
    gf_sql_auto_vacuum_t auto_vacuum;
} gf_sql_connection_t;

#define CHECK_SQL_CONN(sql_conn, out)                                          \
    do {                                                                       \
        GF_VALIDATE_OR_GOTO(GFDB_STR_SQLITE3, sql_conn, out);                  \
        if (!sql_conn->sqlite3_db_conn) {                                      \
            gf_msg(GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,                          \
                   LG_MSG_CONNECTION_INIT_FAILED,                              \
                   "sqlite3 connection not initialized");                      \
            goto out;                                                          \
        };                                                                     \
    } while (0)

#define GF_SQLITE3_SET_PRAGMA(sqlite3_config_str, param_key, format, value,    \
                              ret, error)                                      \
    do {                                                                       \
        sprintf(sqlite3_config_str, "PRAGMA %s = " format, param_key, value);  \
        ret = sqlite3_exec(sql_conn->sqlite3_db_conn, sqlite3_config_str,      \
                           NULL, NULL, NULL);                                  \
        if (ret != SQLITE_OK) {                                                \
            gf_msg(GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_EXEC_FAILED,      \
                   "Failed executing: %s : %s", sqlite3_config_str,            \
                   sqlite3_errmsg(sql_conn->sqlite3_db_conn));                 \
            ret = -1;                                                          \
            goto error;                                                        \
        };                                                                     \
    } while (0)

/************************SQLITE3 PARAMS KEYS***********************************/
#define GFDB_SQL_PARAM_DBPATH "sql-db-path"
#define GFDB_SQL_PARAM_CACHE_SIZE "sql-db-cachesize"
#define GFDB_SQL_PARAM_PAGE_SIZE "sql-db-pagesize"
#define GFDB_SQL_PARAM_JOURNAL_MODE "sql-db-journalmode"
#define GFDB_SQL_PARAM_WAL_AUTOCHECK "sql-db-wal-autocheckpoint"
#define GFDB_SQL_PARAM_SYNC "sql-db-sync"
#define GFDB_SQL_PARAM_AUTO_VACUUM "sql-db-autovacuum"

#define GF_SQL_DEFAULT_DBPATH ""
#define GF_SQL_DEFAULT_PAGE_SIZE "4096"
#define GF_SQL_DEFAULT_CACHE_SIZE "12500"
#define GF_SQL_DEFAULT_WAL_AUTOCHECKPOINT "25000"
#define GF_SQL_DEFAULT_JOURNAL_MODE GF_SQL_JM_WAL
#define GF_SQL_DEFAULT_SYNC GF_SQL_SYNC_OFF
#define GF_SQL_DEFAULT_AUTO_VACUUM GF_SQL_AV_NONE

/* Defines the indexs for sqlite params
 * The order should be maintained*/
typedef enum sqlite_param_index {
    sql_dbpath_ix = 0,
    sql_pagesize_ix,
    sql_cachesize_ix,
    sql_journalmode_ix,
    sql_walautocheck_ix,
    sql_dbsync_ix,
    sql_autovacuum_ix,
    /*This should be in the end*/
    sql_index_max
} sqlite_param_index_t;

/* Array to hold the sqlite param keys
 * The order should be maintained as sqlite_param_index_t*/
static char *sqlite_params_keys[] = {
    GFDB_SQL_PARAM_DBPATH,        GFDB_SQL_PARAM_PAGE_SIZE,
    GFDB_SQL_PARAM_CACHE_SIZE,    GFDB_SQL_PARAM_JOURNAL_MODE,
    GFDB_SQL_PARAM_WAL_AUTOCHECK, GFDB_SQL_PARAM_SYNC,
    GFDB_SQL_PARAM_AUTO_VACUUM};

/* Array of default values for sqlite params
 * The order should be maintained as sqlite_param_index_t*/
static char *sqlite_params_default_value[] = {GF_SQL_DEFAULT_DBPATH,
                                              GF_SQL_DEFAULT_PAGE_SIZE,
                                              GF_SQL_DEFAULT_CACHE_SIZE,
                                              GF_SQL_DEFAULT_JOURNAL_MODE,
                                              GF_SQL_DEFAULT_WAL_AUTOCHECKPOINT,
                                              GF_SQL_DEFAULT_SYNC,
                                              GF_SQL_DEFAULT_AUTO_VACUUM};

/*Extract sql params from page_size to auto_vacumm
 * The dbpath is extracted in a different way*/
static inline int
gfdb_set_sql_params(char *comp_name, dict_t *from_dict, dict_t *to_dict)
{
    sqlite_param_index_t sql_index = sql_pagesize_ix;
    char *_val_str = NULL;
    int ret = -1;

    GF_ASSERT(comp_name);
    GF_ASSERT(from_dict);
    GF_ASSERT(to_dict);

    /*Extract and Set of the sql params from page_size*/
    for (sql_index = sql_pagesize_ix; sql_index < sql_index_max; sql_index++) {
        _val_str = NULL;
        GET_DB_PARAM_FROM_DICT_DEFAULT(comp_name, from_dict,
                                       sqlite_params_keys[sql_index], _val_str,
                                       sqlite_params_default_value[sql_index]);
        SET_DB_PARAM_TO_DICT(comp_name, to_dict, sqlite_params_keys[sql_index],
                             _val_str, ret, out);
    }
out:
    return ret;
}

/*************************SQLITE3 GFDB PLUGINS*********************************/

/*Db init and fini modules*/
int
gf_sqlite3_fini(void **db_conn);
int
gf_sqlite3_init(dict_t *args, void **db_conn);

/*insert/update/delete modules*/
int
gf_sqlite3_insert(void *db_conn, gfdb_db_record_t *);
int
gf_sqlite3_delete(void *db_conn, gfdb_db_record_t *);

/*querying modules*/
int
gf_sqlite3_find_all(void *db_conn, gf_query_callback_t, void *_query_cbk_args,
                    int query_limit);
int
gf_sqlite3_find_unchanged_for_time(void *db_conn,
                                   gf_query_callback_t query_callback,
                                   void *_query_cbk_args,
                                   gfdb_time_t *for_time);
int
gf_sqlite3_find_recently_changed_files(void *db_conn,
                                       gf_query_callback_t query_callback,
                                       void *_query_cbk_args,
                                       gfdb_time_t *from_time);
int
gf_sqlite3_find_unchanged_for_time_freq(void *db_conn,
                                        gf_query_callback_t query_callback,
                                        void *_query_cbk_args,
                                        gfdb_time_t *for_time,
                                        int write_freq_cnt, int read_freq_cnt,
                                        gf_boolean_t clear_counters);
int
gf_sqlite3_find_recently_changed_files_freq(
    void *db_conn, gf_query_callback_t query_callback, void *_query_cbk_args,
    gfdb_time_t *from_time, int write_freq_cnt, int read_freq_cnt,
    gf_boolean_t clear_counters);

int
gf_sqlite3_clear_files_heat(void *db_conn);

/* Function to extract version of sqlite db
 * Input:
 * void *db_conn        : Sqlite connection
 * char **version  : the version is extracted as a string and will be stored in
 *                   this variable. The freeing of the memory should be done by
 *                   the caller.
 * Return:
 *      On success return the length of the version string that is
 *      extracted.
 *      On failure return -1
 * */
int
gf_sqlite3_version(void *db_conn, char **version);

/* Function to extract PRAGMA or setting from sqlite db
 * Input:
 * void *db_conn        : Sqlite connection
 * char *pragma_key     : PRAGMA or setting to be extracted
 * char **pragma_value  : the value of the PRAGMA or setting that is
 *                        extracted. This function will allocate memory
 *                        to pragma_value. The caller should free the memory
 * Return:
 *      On success return the length of the pragma/setting value that is
 *      extracted.
 *      On failure return -1
 * */
int
gf_sqlite3_pragma(void *db_conn, char *pragma_key, char **pragma_value);

/* Function to set PRAGMA to sqlite db
 * Input:
 * void *db_conn        : Sqlite connection
 * char *pragma_key     : PRAGMA to be set
 * char *pragma_value   : the value of the PRAGMA
 * Return:
 *      On success return 0
 *      On failure return -1
 * */
int
gf_sqlite3_set_pragma(void *db_conn, char *pragma_key, char *pragma_value);

/* 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 switch?
 * 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);

void
gf_sqlite3_fill_db_operations(gfdb_db_operations_t *gfdb_db_ops);

#endif