diff --git a/query_classifier/makefile b/query_classifier/makefile index 67554007a..41dd1593f 100644 --- a/query_classifier/makefile +++ b/query_classifier/makefile @@ -18,8 +18,8 @@ clean: all: utils lib utils: - make -C $(ROOT_PATH)/utils clean all - $(COPY) $(ROOT_PATH)/utils/skygw_utils.o ./ + make -C $(QUERY_CLASSIFIER_PATH)/utils clean all + $(COPY) $(QUERY_CLASSIFIER_PATH)/utils/skygw_utils.o ./ lib: libcomp liblink diff --git a/utils/makefile b/utils/makefile new file mode 100644 index 000000000..267d29bea --- /dev/null +++ b/utils/makefile @@ -0,0 +1,18 @@ +include ../build_gateway.inc +include ../makefile.inc + +CC = gcc +CPP = g++ + +makeall: clean all + +clean: + - $(DEL) *.o + - $(DEL) *.so + - $(DEL) *.a + - $(DEL) *~ + +all: + $(CPP) -c $(CFLAGS) \ + -fPIC skygw_utils.cc -o skygw_utils.o + diff --git a/utils/skygw_debug.h b/utils/skygw_debug.h new file mode 100644 index 000000000..aba167f51 --- /dev/null +++ b/utils/skygw_debug.h @@ -0,0 +1,126 @@ +#include + +#if !defined(SKYGW_DEBUG_H) +#define SKYGW_DEBUG_H + + +#ifdef __cplusplus +#define EXTERN_C_BLOCK_BEGIN extern "C" { +#define EXTERN_C_BLOCK_END } +#define EXTERN_C_FUNC extern "C" +#else +#define EXTERN_C_BLOCK_BEGIN +#define EXTERN_C_BLOCK_END +#define EXTERN_C_FUNC +#endif + +#if defined(SS_DEBUG) + +# define STRBOOL(b) ((b) ? "TRUE" : "FALSE") +# define STRQTYPE(t) ((t) == QUERY_TYPE_WRITE ? "QUERY_TYPE_WRITE" : \ + ((t) == QUERY_TYPE_READ ? "QUERY_TYPE_READ" : \ + ((t) == QUERY_TYPE_SESSION_WRITE ? "QUERY_TYPE_SESSION_WRITE" : \ + "QUERY_TYPE_UNKNOWN"))) +# define ss_dfprintf fprintf +# define ss_dfflush fflush +# define ss_dfwrite fwrite + +# define ss_dassert(exp) \ + { \ + if (!(exp)) { \ + ss_dfprintf(stderr, \ + "debug assert %s:%d\n", \ + (char*)__FILE__, \ + __LINE__); \ + ss_dfflush(stderr); \ + assert(exp); \ + } \ + } + +# define ss_info_dassert(exp, info) \ + { \ + if (!(exp)) { \ + ss_dfprintf(stderr, "debug assert %s:%d, %s\n", \ + (char *)__FILE__, \ + __LINE__, \ + info); \ + ss_dfflush(stderr); \ + assert((exp)); \ + } \ + } + +#else /* SS_DEBUG */ + +# define STRBOOL(b) +# define ss_dfprintf(a, b, ...) +# define ss_dfflush +# define ss_dfwrite +# define ss_dassert +# define ss_info_dassert(exp, info) + +#endif /* SS_DEBUG */ + +#define CHK_NUM_BASE 101 + +typedef enum skygw_chk_t { + CHK_NUM_SLIST = CHK_NUM_BASE, + CHK_NUM_SLIST_NODE, + CHK_NUM_SLIST_CURSOR, + CHK_NUM_QUERY_TEST, + CHK_NUM_LOGFILE +} skygw_chk_t; + +#define CHK_SLIST(l) { \ + ss_info_dassert((l->slist_chk_top == CHK_NUM_SLIST && \ + l->slist_chk_tail == CHK_NUM_SLIST), \ + "Single-linked list structure under- or overflow"); \ + if (l->slist_head == NULL) { \ + ss_info_dassert(l->slist_nelems == 0, \ + "List head is NULL but element counter is not zero."); \ + ss_info_dassert(l->slist_tail == NULL, \ + "List head is NULL but tail has node"); \ + } else { \ + ss_info_dassert(l->slist_nelems > 0, \ + "List head has node but element counter is not " \ + "positive."); \ + CHK_SLIST_NODE(l->slist_head); \ + CHK_SLIST_NODE(l->slist_tail); \ + } \ + if (l->slist_nelems == 0) { \ + ss_info_dassert(l->slist_head == NULL, \ + "Element counter is zero but head has node"); \ + ss_info_dassert(l->slist_tail == NULL, \ + "Element counter is zero but tail has node"); \ + } \ + } + +#define CHK_SLIST_NODE(n) { \ + ss_info_dassert((n->slnode_chk_top == CHK_NUM_SLIST_NODE && \ + n->slnode_chk_tail == CHK_NUM_SLIST_NODE), \ + "Single-linked list node under- or overflow"); \ + } + +#define CHK_SLIST_CURSOR(c) { \ + ss_info_dassert(c->slcursor_chk_top == CHK_NUM_SLIST_CURSOR && \ + c->slcursor_chk_tail == CHK_NUM_SLIST_CURSOR, \ + "List cursor under- or overflow"); \ + ss_info_dassert(c->slcursor_list != NULL, \ + "List cursor doesn't have list"); \ + ss_info_dassert(c->slcursor_pos != NULL || \ + (c->slcursor_pos == NULL && \ + c->slcursor_list->slist_head == NULL), \ + "List cursor doesn't have position"); \ + } + +#define CHK_QUERY_TEST(q) { \ + ss_info_dassert(q->qt_chk_top == CHK_NUM_QUERY_TEST && \ + q->qt_chk_tail == CHK_NUM_QUERY_TEST, \ + "Query test under- or overflow."); \ + } + +#define CHK_LOGFILE(lf) { \ + ss_info_assert(lf->lf_chk_top == CHK_NUM_LOGFILE && \ + lf->lf_chk_tail == CHK_NUM_LOGFILE, \ + "Logfile struct under- or overflow"); \ + } +#endif /* SKYGW_DEBUG_H */ diff --git a/utils/skygw_types.h b/utils/skygw_types.h new file mode 100644 index 000000000..7345074f9 --- /dev/null +++ b/utils/skygw_types.h @@ -0,0 +1,49 @@ +/** + * @section LICENCE + * + * This file is distributed as part of the SkySQL Gateway. It is + * free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * Copyright SkySQL Ab + * + * @file + * @brief + * + */ + +#if !defined(SKYGW_TYPES_H) +#define SKYGW_TYPES_H + +#define SECOND_USEC (1024*1024L) +#define MSEC_USEC (1024L) + +#define KILOBYTE_BYTE (1024L) +#define MEGABYTE_BYTE (1024*1024L) +#define GIGABYTE_BYTE (1024*1024*1024L) + +#define KB KILOBYTE_BYTE +#define MB MEGABYTE_BYTE +#define GB GIGABYTE_BYTE + + + +#if defined(__cplusplus) +#define TRUE true +#define FALSE false +#else +typedef enum {FALSE=0, TRUE} bool; +#endif + +#endif /* SKYGW_TYPES_H */ diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc new file mode 100644 index 000000000..ea0126057 --- /dev/null +++ b/utils/skygw_utils.cc @@ -0,0 +1,354 @@ +#include +#include + +#include "skygw_debug.h" +#include "skygw_types.h" +#include "skygw_utils.h" + + + +/** Single-linked list for storing test cases */ +typedef struct slist_node_st slist_node_t; +typedef struct slist_st slist_t; +typedef struct slist_cursor_st slist_cursor_t; + +struct slist_node_st { + skygw_chk_t slnode_chk_top; + slist_t* slnode_list; + slist_node_t* slnode_next; + void* slnode_data; + size_t slnode_cursor_refcount; + skygw_chk_t slnode_chk_tail; +}; + +struct slist_st { + skygw_chk_t slist_chk_top; + slist_node_t* slist_head; + slist_node_t* slist_tail; + size_t slist_nelems; + slist_t* slist_cursors_list; + skygw_chk_t slist_chk_tail; +}; + +struct slist_cursor_st { + skygw_chk_t slcursor_chk_top; + slist_t* slcursor_list; + slist_node_t* slcursor_pos; + skygw_chk_t slcursor_chk_tail; +}; + + +/** End of structs and types */ + + +static slist_cursor_t* slist_cursor_init( + slist_t* list); + +static slist_t* slist_init_ex( + bool create_cursors); + +static slist_node_t* slist_node_init( + void* data, + slist_cursor_t* cursor); + +static void slist_add_node( + slist_t* list, + slist_node_t* node); + +static slist_node_t* slist_node_get_next( + slist_node_t* curr_node); + +static slist_node_t* slist_get_first( + slist_t* list); + +static slist_cursor_t* slist_get_cursor( + slist_t* list); + +/** End of static function declarations */ + + +static slist_t* slist_init_ex( + bool create_cursors) +{ + slist_t* list; + + list = (slist_t*)calloc(1, sizeof(slist_t)); + list->slist_chk_top = CHK_NUM_SLIST; + list->slist_chk_tail = CHK_NUM_SLIST; + + if (create_cursors) { + list->slist_cursors_list = slist_init_ex(FALSE); + } + + return list; +} + +static slist_node_t* slist_node_init( + void* data, + slist_cursor_t* cursor) +{ + slist_node_t* node; + + node = (slist_node_t*)calloc(1, sizeof(slist_node_t)); + node->slnode_chk_top = CHK_NUM_SLIST_NODE; + node->slnode_chk_tail = CHK_NUM_SLIST_NODE; + node->slnode_data = data; + CHK_SLIST_NODE(node); + + if (cursor != NULL) { + node->slnode_cursor_refcount += 1; + cursor->slcursor_pos = node; + } + + return node; +} + +static void slist_add_node( + slist_t* list, + slist_node_t* node) +{ + CHK_SLIST(list); + CHK_SLIST_NODE(node); + + if (list->slist_tail != NULL) { + CHK_SLIST_NODE(list->slist_tail); + CHK_SLIST_NODE(list->slist_head); + ss_dassert(list->slist_tail->slnode_next == NULL); + list->slist_tail->slnode_next = node; + } else { + list->slist_head = node; + } + list->slist_tail = node; + node->slnode_list = list; + list->slist_nelems += 1; + CHK_SLIST(list); +} + + +static slist_node_t* slist_node_get_next( + slist_node_t* curr_node) +{ + CHK_SLIST_NODE(curr_node); + + if (curr_node->slnode_next != NULL) { + CHK_SLIST_NODE(curr_node->slnode_next); + return (curr_node->slnode_next); + } + + return NULL; +} + +static slist_node_t* slist_get_first( + slist_t* list) +{ + CHK_SLIST(list); + + if (list->slist_head != NULL) { + CHK_SLIST_NODE(list->slist_head); + return list->slist_head; + } + return NULL; +} + +static slist_cursor_t* slist_cursor_init( + slist_t* list) +{ + CHK_SLIST(list); + slist_cursor_t* c; + + c = (slist_cursor_t *)calloc(1, sizeof(slist_cursor_t)); + c->slcursor_chk_top = CHK_NUM_SLIST_CURSOR; + c->slcursor_chk_tail = CHK_NUM_SLIST_CURSOR; + c->slcursor_list = list; + + /** Set cursor position is list is not empty */ + if (list->slist_head != NULL) { + list->slist_head->slnode_cursor_refcount += 1; + c->slcursor_pos = list->slist_head; + } + /** Add cursor to cursor list */ + slist_add_node(list->slist_cursors_list, slist_node_init(c, NULL)); + + CHK_SLIST_CURSOR(c); + return c; +} + +static slist_cursor_t* slist_get_cursor( + slist_t* list) +{ + CHK_SLIST(list); + + slist_cursor_t* c; + + c = slist_cursor_init(list); + return c; +} + + + +/** + * @node Create a cursor and a list with cursors supported + * + * Parameters: + * @param void - + * + * + * @return returns a pointer to cursor, which is not positioned + * because the list is empty. + * + * + * @details (write detailed description here) + * + */ +slist_cursor_t* slist_init(void) +{ + slist_t* list; + slist_cursor_t* slc; + + list = slist_init_ex(TRUE); + CHK_SLIST(list); + slc = slist_cursor_init(list); + CHK_SLIST_CURSOR(slc); + + return slc; +} + + + +/** + * @node moves cursor to the first node of list. + * + * Parameters: + * @param c - + * + * + * @return TRUE if there is first node in the list + * FALSE is the list is empty. + * + * + * @details (write detailed description here) + * + */ +bool slcursor_move_to_begin( + slist_cursor_t* c) +{ + bool succp = TRUE; + slist_t* list; + + CHK_SLIST_CURSOR(c); + list = c->slcursor_list; + CHK_SLIST(list); + c->slcursor_pos = list->slist_head; + if (c->slcursor_pos == NULL) { + succp = FALSE; + } + return succp; +} + +/** + * @node moves cursor to next node + * + * Parameters: + * @param c - + * + * + * @return TRUE in success, FALSE is there is no next node on the list. + * + * + * @details (write detailed description here) + * + */ +bool slcursor_step_ahead( + slist_cursor_t* c) +{ + bool succp = FALSE; + slist_node_t* node; + CHK_SLIST_CURSOR(c); + CHK_SLIST_NODE(c->slcursor_pos); + + node = c->slcursor_pos->slnode_next; + + if (node != NULL) { + CHK_SLIST_NODE(node); + c->slcursor_pos = node; + succp = TRUE; + } + return succp; +} + + +void* slcursor_get_data( + slist_cursor_t* c) +{ + slist_node_t* node; + void* data = NULL; + + CHK_SLIST_CURSOR(c); + node = c->slcursor_pos; + + if (node != NULL) { + CHK_SLIST_NODE(node); + data = node->slnode_data; + } + return data; +} + + +/** + * @node Add data to the list by using cursor. + * + * Parameters: + * @param c - + * + * + * @param data - + * + * + * @return void + * + * + * @details (write detailed description here) + * + */ +void slcursor_add_data( + slist_cursor_t* c, + void* data) +{ + slist_t* list; + slist_node_t* pos; + + CHK_SLIST_CURSOR(c); + list = c->slcursor_list; + CHK_SLIST(list); + pos = c->slcursor_pos; + + if (pos != NULL) { + CHK_SLIST_NODE(pos); + pos = list->slist_tail->slnode_next; + } + ss_dassert(pos == NULL); + pos = slist_node_init(data, c); + slist_add_node(list, pos); + CHK_SLIST(list); + CHK_SLIST_CURSOR(c); +} + +void slist_done( + slist_cursor_t* c) +{ + bool succp; + void* data; + + succp = slcursor_move_to_begin(c); + + while (succp) { + data = slcursor_get_data(c); + free(data); + succp = slcursor_step_ahead(c); + } + free(c->slcursor_list); + free(c); +} + + +/** End of list implementation */ diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h new file mode 100644 index 000000000..4e34667df --- /dev/null +++ b/utils/skygw_utils.h @@ -0,0 +1,26 @@ +#if !defined(SKYGW_UTILS_H) +#define SKYGW_UTILS_H + +#include "skygw_types.h" +#include "skygw_debug.h" + +EXTERN_C_BLOCK_BEGIN + +typedef struct slist_node_st slist_node_t; +typedef struct slist_st slist_t; +typedef struct slist_cursor_st slist_cursor_t; + +slist_cursor_t* slist_init(void); +void slist_done(slist_cursor_t* c); + +void slcursor_add_data(slist_cursor_t* c, void* data); +void* slcursor_get_data(slist_cursor_t* c); + +bool slcursor_move_to_begin(slist_cursor_t* c); +bool slcursor_step_ahead(slist_cursor_t* c); + +EXTERN_C_BLOCK_END + + + +#endif /* SKYGW_UTILS_H */