New, yet primitive version of log writing functionality. Fixed some things in utils.
This commit is contained in:
parent
33b5d9c62b
commit
8178e4e239
BIN
log_manager/liblog_manager.so.1.0.1
Executable file
BIN
log_manager/liblog_manager.so.1.0.1
Executable file
Binary file not shown.
1191
log_manager/log_manager.cc
Normal file
1191
log_manager/log_manager.cc
Normal file
File diff suppressed because it is too large
Load Diff
65
log_manager/log_manager.h
Normal file
65
log_manager/log_manager.h
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
|
||||
typedef struct filewriter_st filewriter_t;
|
||||
typedef struct logfile_st logfile_t;
|
||||
typedef struct fnames_conf_st fnames_conf_t;
|
||||
typedef struct logmanager_st logmanager_t;
|
||||
|
||||
typedef enum {
|
||||
LOGFILE_FIRST = 0,
|
||||
LOGFILE_TRACE = LOGFILE_FIRST,
|
||||
LOGFILE_MESSAGE,
|
||||
LOGFILE_ERROR,
|
||||
LOGFILE_LAST = LOGFILE_ERROR
|
||||
} logfile_id_t;
|
||||
|
||||
typedef enum { FILEWRITER_INIT, FILEWRITER_RUN, FILEWRITER_DONE }
|
||||
filewriter_state_t;
|
||||
typedef enum { LOGFILE_INIT, LOGFILE_OPENED, LOGFILE_DONE } logfile_state_t;
|
||||
|
||||
EXTERN_C_BLOCK_BEGIN
|
||||
|
||||
logmanager_t* skygw_logmanager_init(void** ctx, int argc, char* argv[]);
|
||||
void skygw_logmanager_done(void** ctx, logmanager_t** lm);
|
||||
int skygw_log_write(void* ctx, logmanager_t* lmgr, logfile_id_t id, char* str);
|
||||
int skygw_log_flush(logmanager_t* lmgr, logfile_id_t id);
|
||||
int skygw_log_write_flush(void* ctx,
|
||||
logmanager_t* lmgr,
|
||||
logfile_id_t id,
|
||||
char* str);
|
||||
|
||||
EXTERN_C_BLOCK_END
|
||||
|
||||
const char* get_trace_prefix_default(void);
|
||||
const char* get_trace_suffix_default(void);
|
||||
const char* get_msg_prefix_default(void);
|
||||
const char* get_msg_suffix_default(void);
|
||||
const char* get_err_prefix_default(void);
|
||||
const char* get_err_suffix_default(void);
|
||||
const char* get_logpath_default(void);
|
||||
|
||||
/*
|
||||
bool logfile_write(
|
||||
skygw_ctx_t* ctx,
|
||||
logmgr_t* mgr,
|
||||
logfile_id_t id,
|
||||
char* msg);
|
||||
|
||||
bool logfile_write_flush(
|
||||
skygw_ctx_t* ctx,
|
||||
logmgr_t* mgr,
|
||||
logfile_id_t id,
|
||||
char* msg);
|
||||
|
||||
bool logfile_flush(
|
||||
logmgr_t* mgr,
|
||||
logfile_id_t id);
|
||||
|
||||
bool logfile_init(
|
||||
logmgr_t* mgr,
|
||||
logfile_id_t id);
|
||||
|
||||
void logfile_done(
|
||||
logmgr_t* mgr,
|
||||
logfile_id_t id);
|
||||
*/
|
38
log_manager/makefile
Normal file
38
log_manager/makefile
Normal file
@ -0,0 +1,38 @@
|
||||
include ../build_gateway.inc
|
||||
include ../makefile.inc
|
||||
|
||||
CC = gcc
|
||||
CPP = g++
|
||||
|
||||
LOG_WRITER_PATH := $(shell pwd)
|
||||
|
||||
makeall: clean all
|
||||
|
||||
clean:
|
||||
make -C ../utils clean
|
||||
- $(DEL) *.o
|
||||
- $(DEL) *.so
|
||||
- $(DEL) *.so.1.0.1
|
||||
- $(DEL) *~
|
||||
|
||||
all: utils lib
|
||||
|
||||
utils:
|
||||
make -C $(ROOT_PATH)/utils clean all
|
||||
$(COPY) $(ROOT_PATH)/utils/skygw_utils.o ./
|
||||
|
||||
lib: libcomp liblink
|
||||
|
||||
libcomp:
|
||||
$(CPP) -c $(CFLAGS) \
|
||||
-I$(MARIADB_SRC_PATH)/include/ \
|
||||
-I../utils/ -I./ \
|
||||
-fPIC ./log_manager.cc -o log_manager.o $(LDLIBS)
|
||||
|
||||
liblink:
|
||||
$(CPP) -shared \
|
||||
-Wl,-soname,liblog_manager.so \
|
||||
-o liblog_manager.so.1.0.1 log_manager.o \
|
||||
$(LDLIBS) $(CPP_LDLIBS)
|
||||
$(DEL) ./liblog_manager.so
|
||||
$(LINK) ./liblog_manager.so.1.0.1 ./liblog_manager.so
|
BIN
log_manager/test/core
Normal file
BIN
log_manager/test/core
Normal file
Binary file not shown.
34
log_manager/test/makefile
Normal file
34
log_manager/test/makefile
Normal file
@ -0,0 +1,34 @@
|
||||
include ../../build_gateway.inc
|
||||
include ../../makefile.inc
|
||||
|
||||
CC = gcc
|
||||
CPP = g++
|
||||
|
||||
TESTPATH := $(shell pwd)
|
||||
LOG_MANAGER_PATH := $(ROOT_PATH)/log_manager
|
||||
TESTAPP = $(TESTPATH)/testlog
|
||||
|
||||
runtest: makeall testall
|
||||
|
||||
makeall: clean all
|
||||
|
||||
clean:
|
||||
- $(DEL) *.o
|
||||
- $(DEL) testlog
|
||||
- $(DEL) *~
|
||||
|
||||
all: testcomp testall
|
||||
|
||||
testcomp:
|
||||
$(CC) $(CFLAGS) \
|
||||
-L$(LOG_MANAGER_PATH) \
|
||||
-Wl,-rpath,$(LOG_MANAGER_PATH)/ \
|
||||
-o testlog -DSS_DEBUG \
|
||||
-I$(SOLIDDB_SRC_PATH)/include \
|
||||
-I$(MARIADB_SRC_PATH)/include \
|
||||
-I$(LOG_MANAGER_PATH) -I$(ROOT_PATH)/utils testlog.c \
|
||||
-llog_manager $(LDLIBS) \
|
||||
$(LOG_MANAGER_PATH)/skygw_utils.o
|
||||
|
||||
testall:
|
||||
- $(LAUNCH_DEBUGGER) $(TESTAPP) $(BACKGR)
|
65
log_manager/test/nohup.out
Normal file
65
log_manager/test/nohup.out
Normal file
@ -0,0 +1,65 @@
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
Warning:
|
||||
Name: menubar
|
||||
Class: XmRowColumn
|
||||
XtGrabPointer failed.
|
||||
|
||||
(Annoyed? Try 'Edit->Preferences->General->Suppress X Warnings'!)
|
||||
/bin/sh -c 'exec gdb -q -fullname '\''/home/raatikka/src/bazaar/shared/skygateway/log_manager/test/testlog'\''' [26040]: Agent wouldn't die (Terminated)
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
/bin/sh -c 'exec gdb -q -fullname '\''/home/raatikka/src/bazaar/shared/skygateway/log_manager/test/testlog'\''' [26458]: Agent wouldn't die (Terminated)
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
||||
WARNING:
|
||||
UTF-8 charmap detected. Switching off UTF-8 as ddd has problems with it. See
|
||||
README.SUSE for futher information. Use -x parameter to bypass this wrapper.
|
BIN
log_manager/test/testlog
Executable file
BIN
log_manager/test/testlog
Executable file
Binary file not shown.
45
log_manager/test/testlog.c
Normal file
45
log_manager/test/testlog.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <skygw_utils.h>
|
||||
#include <log_manager.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int err;
|
||||
logmanager_t* lmgr;
|
||||
char* logstr;
|
||||
|
||||
lmgr = skygw_logmanager_init(NULL, argc, argv);
|
||||
|
||||
logstr = strdup("My name is Tracey");
|
||||
err = skygw_log_write(NULL, lmgr, LOGFILE_TRACE, logstr);
|
||||
free(logstr);
|
||||
|
||||
logstr = strdup("My name is Stacey");
|
||||
err = skygw_log_write_flush(NULL, lmgr, LOGFILE_TRACE, logstr);
|
||||
free(logstr);
|
||||
|
||||
skygw_logmanager_done(NULL, &lmgr);
|
||||
|
||||
logstr = strdup("My name is Philip");
|
||||
err = skygw_log_write(NULL, lmgr, LOGFILE_TRACE, logstr);
|
||||
free(logstr);
|
||||
|
||||
lmgr = skygw_logmanager_init(NULL, argc, argv);
|
||||
|
||||
logstr = strdup("A terrible error has occurred!");
|
||||
err = skygw_log_write_flush(NULL, lmgr, LOGFILE_ERROR, logstr);
|
||||
free(logstr);
|
||||
|
||||
logstr = strdup("Hi, how are you?");
|
||||
err = skygw_log_write(NULL, lmgr, LOGFILE_MESSAGE, logstr);
|
||||
free(logstr);
|
||||
|
||||
logstr = strdup("I'm doing fine!");
|
||||
err = skygw_log_write(NULL, lmgr, LOGFILE_MESSAGE, logstr);
|
||||
free(logstr);
|
||||
|
||||
return_err:
|
||||
skygw_logmanager_done(NULL, &lmgr);
|
||||
return err;
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(SKYGW_DEBUG_H)
|
||||
#define SKYGW_DEBUG_H
|
||||
@ -21,6 +23,10 @@
|
||||
((t) == QUERY_TYPE_READ ? "QUERY_TYPE_READ" : \
|
||||
((t) == QUERY_TYPE_SESSION_WRITE ? "QUERY_TYPE_SESSION_WRITE" : \
|
||||
"QUERY_TYPE_UNKNOWN")))
|
||||
#define STRLOGID(i) ((i) == LOGFILE_TRACE ? "LOGFILE_TRACE" : \
|
||||
((i) == LOGFILE_MESSAGE ? "LOGFILE_MESSAGE" : \
|
||||
((i) == LOGFILE_ERROR ? "LOGFILE_ERROR" : \
|
||||
"Unknown logfile type")))
|
||||
# define ss_dfprintf fprintf
|
||||
# define ss_dfflush fflush
|
||||
# define ss_dfwrite fwrite
|
||||
@ -72,15 +78,68 @@ typedef enum skygw_chk_t {
|
||||
CHK_NUM_SLIST = CHK_NUM_BASE,
|
||||
CHK_NUM_SLIST_NODE,
|
||||
CHK_NUM_SLIST_CURSOR,
|
||||
CHK_NUM_MLIST,
|
||||
CHK_NUM_MLIST_NODE,
|
||||
CHK_NUM_MLIST_CURSOR,
|
||||
CHK_NUM_QUERY_TEST,
|
||||
CHK_NUM_LOGFILE,
|
||||
CHK_NUM_FILEWRITER,
|
||||
CHK_NUM_THREAD,
|
||||
CHK_NUM_SIMPLE_MUTEX,
|
||||
CHK_NUM_MESSAGE
|
||||
CHK_NUM_MESSAGE,
|
||||
CHK_NUM_RWLOCK,
|
||||
CHK_NUM_FNAMES,
|
||||
CHK_NUM_LOGMANAGER,
|
||||
CHK_NUM_FILE,
|
||||
CHK_NUM_WRITEBUF
|
||||
} skygw_chk_t;
|
||||
|
||||
#define CHK_SLIST(l) { \
|
||||
|
||||
#define CHK_MLIST(l) { \
|
||||
ss_info_dassert((l->mlist_chk_top == CHK_NUM_MLIST && \
|
||||
l->mlist_chk_tail == CHK_NUM_MLIST), \
|
||||
"Single-linked list structure under- or overflow"); \
|
||||
if (l->mlist_first == NULL) { \
|
||||
ss_info_dassert(l->mlist_nodecount == 0, \
|
||||
"List head is NULL but element counter is not zero."); \
|
||||
ss_info_dassert(l->mlist_last == NULL, \
|
||||
"List head is NULL but tail has node"); \
|
||||
} else { \
|
||||
ss_info_dassert(l->mlist_nodecount > 0, \
|
||||
"List head has node but element counter is not " \
|
||||
"positive."); \
|
||||
CHK_MLIST_NODE(l->mlist_first); \
|
||||
CHK_MLIST_NODE(l->mlist_last); \
|
||||
} \
|
||||
if (l->mlist_nodecount == 0) { \
|
||||
ss_info_dassert(l->mlist_first == NULL, \
|
||||
"Element counter is zero but head has node"); \
|
||||
ss_info_dassert(l->mlist_last == NULL, \
|
||||
"Element counter is zero but tail has node"); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CHK_MLIST_NODE(n) { \
|
||||
ss_info_dassert((n->mlnode_chk_top == CHK_NUM_MLIST_NODE && \
|
||||
n->mlnode_chk_tail == CHK_NUM_MLIST_NODE), \
|
||||
"Single-linked list node under- or overflow"); \
|
||||
}
|
||||
|
||||
#define CHK_MLIST_CURSOR(c) { \
|
||||
ss_info_dassert(c->mlcursor_chk_top == CHK_NUM_MLIST_CURSOR && \
|
||||
c->mlcursor_chk_tail == CHK_NUM_MLIST_CURSOR, \
|
||||
"List cursor under- or overflow"); \
|
||||
ss_info_dassert(c->mlcursor_list != NULL, \
|
||||
"List cursor doesn't have list"); \
|
||||
ss_info_dassert(c->mlcursor_pos != NULL || \
|
||||
(c->mlcursor_pos == NULL && \
|
||||
c->mlcursor_list->mlist_first == NULL), \
|
||||
"List cursor doesn't have position"); \
|
||||
}
|
||||
|
||||
#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"); \
|
||||
@ -104,6 +163,8 @@ typedef enum skygw_chk_t {
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CHK_SLIST_NODE(n) { \
|
||||
ss_info_dassert((n->slnode_chk_top == CHK_NUM_SLIST_NODE && \
|
||||
n->slnode_chk_tail == CHK_NUM_SLIST_NODE), \
|
||||
@ -128,10 +189,29 @@ typedef enum skygw_chk_t {
|
||||
"Query test under- or overflow."); \
|
||||
}
|
||||
|
||||
#define CHK_LOGFILE(lf) { \
|
||||
ss_info_dassert(lf->lf_chk_top == CHK_NUM_LOGFILE && \
|
||||
lf->lf_chk_tail == CHK_NUM_LOGFILE, \
|
||||
"Logfile struct under- or overflow"); \
|
||||
#define CHK_LOGFILE(lf) { \
|
||||
ss_info_dassert(lf->lf_chk_top == CHK_NUM_LOGFILE && \
|
||||
lf->lf_chk_tail == CHK_NUM_LOGFILE, \
|
||||
"Logfile struct under- or overflow"); \
|
||||
ss_info_dassert(lf->lf_logpath != NULL && \
|
||||
lf->lf_name_prefix != NULL && \
|
||||
lf->lf_name_suffix != NULL && \
|
||||
lf->lf_full_name != NULL, \
|
||||
"NULL in name variable\n"); \
|
||||
ss_info_dassert(lf->lf_id >= LOGFILE_FIRST && \
|
||||
lf->lf_id <= LOGFILE_LAST, \
|
||||
"Invalid logfile id\n"); \
|
||||
ss_info_dassert(lf->lf_writebuf_size > 0, \
|
||||
"Error, logfile's writebuf size is zero " \
|
||||
"or negative\n"); \
|
||||
(lf->lf_chk_top != CHK_NUM_LOGFILE || \
|
||||
lf->lf_chk_tail != CHK_NUM_LOGFILE ? \
|
||||
FALSE : \
|
||||
(lf->lf_logpath == NULL || \
|
||||
lf->lf_name_prefix == NULL || \
|
||||
lf->lf_name_suffix == NULL || \
|
||||
lf->lf_writebuf_size == 0 || \
|
||||
lf->lf_full_name == NULL ? FALSE : TRUE)); \
|
||||
}
|
||||
|
||||
#define CHK_FILEWRITER(fwr) { \
|
||||
@ -150,11 +230,43 @@ typedef enum skygw_chk_t {
|
||||
ss_info_dassert(sm->sm_chk_top == CHK_NUM_SIMPLE_MUTEX && \
|
||||
sm->sm_chk_tail == CHK_NUM_SIMPLE_MUTEX, \
|
||||
"Simple mutex struct under- or overflow"); \
|
||||
}
|
||||
}
|
||||
|
||||
#define CHK_MESSAGE(mes) { \
|
||||
ss_info_dassert(mes->mes_chk_top == CHK_NUM_MESSAGE && \
|
||||
mes->mes_chk_tail == CHK_NUM_MESSAGE, \
|
||||
"Message struct under- or overflow"); \
|
||||
}
|
||||
ss_info_dassert(mes->mes_chk_top == CHK_NUM_MESSAGE && \
|
||||
mes->mes_chk_tail == CHK_NUM_MESSAGE, \
|
||||
"Message struct under- or overflow"); \
|
||||
}
|
||||
|
||||
|
||||
#define CHK_MLIST_ISLOCKED(l) { \
|
||||
ss_info_dassert((l.mlist_uselock && l.mlist_islocked) || \
|
||||
!(l.mlist_uselock || l.mlist_islocked), \
|
||||
("mlist is not locked although it should.")); \
|
||||
CHK_MUTEXED_FOR_THR(l.mlist_uselock,l.mlist_rwlock); \
|
||||
}
|
||||
|
||||
#define CHK_MUTEXED_FOR_THR(b,l) { \
|
||||
ss_info_dassert(!b || \
|
||||
(b && (l->srw_rwlock_thr == pthread_self())), \
|
||||
"rwlock is not acquired although it should be."); \
|
||||
}
|
||||
|
||||
#define CHK_FNAMES_CONF(fn) { \
|
||||
ss_info_dassert(fn->fn_chk_top == CHK_NUM_FNAMES && \
|
||||
fn->fn_chk_tail == CHK_NUM_FNAMES, \
|
||||
"File names confs struct under- or overflow"); \
|
||||
}
|
||||
|
||||
#define CHK_LOGMANAGER(lm) { \
|
||||
ss_info_dassert(lm->lm_chk_top == CHK_NUM_LOGMANAGER && \
|
||||
lm->lm_chk_tail == CHK_NUM_LOGMANAGER, \
|
||||
"Log manager struct under- or overflow"); \
|
||||
}
|
||||
|
||||
#define CHK_FILE(f) { \
|
||||
ss_info_dassert(f->sf_chk_top == CHK_NUM_FILE && \
|
||||
f->sf_chk_tail == CHK_NUM_FILE, \
|
||||
"File struct under- or overflow"); \
|
||||
}
|
||||
#endif /* SKYGW_DEBUG_H */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "skygw_debug.h"
|
||||
#include "skygw_types.h"
|
||||
@ -31,25 +32,16 @@ struct slist_st {
|
||||
};
|
||||
|
||||
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;
|
||||
skygw_chk_t slcursor_chk_top;
|
||||
slist_t* slcursor_list;
|
||||
slist_node_t* slcursor_pos;
|
||||
skygw_chk_t slcursor_chk_tail;
|
||||
};
|
||||
|
||||
struct simple_mutex_st {
|
||||
skygw_chk_t sm_chk_top;
|
||||
pthread_mutex_t sm_mutex;
|
||||
pthread_t sm_owner;
|
||||
bool sm_locked;
|
||||
bool sm_enabled;
|
||||
char* sm_name;
|
||||
skygw_chk_t sm_chk_tail;
|
||||
};
|
||||
|
||||
struct skygw_thread_st {
|
||||
skygw_chk_t sth_chk_top;
|
||||
bool sth_must_exit;
|
||||
simple_mutex_t* sth_mutex;
|
||||
pthread_t sth_parent;
|
||||
pthread_t sth_thr;
|
||||
int sth_errno;
|
||||
@ -68,8 +60,33 @@ struct skygw_message_st {
|
||||
skygw_chk_t mes_chk_tail;
|
||||
};
|
||||
|
||||
struct skygw_file_st {
|
||||
skygw_chk_t sf_chk_top;
|
||||
char* sf_fname;
|
||||
FILE* sf_file;
|
||||
skygw_chk_t sf_chk_tail;
|
||||
};
|
||||
|
||||
/** End of structs and types */
|
||||
|
||||
#if defined(MLIST)
|
||||
|
||||
|
||||
static mlist_node_t* mlist_node_init(void* data, mlist_cursor_t* cursor);
|
||||
|
||||
static mlist_node_t* mlist_node_get_next(
|
||||
mlist_node_t* curr_node);
|
||||
static mlist_node_t* mlist_get_first(
|
||||
mlist_t* list);
|
||||
|
||||
static mlist_cursor_t* mlist_get_cursor(
|
||||
mlist_t* list);
|
||||
|
||||
static void mlist_add_node_nomutex(
|
||||
mlist_t* list,
|
||||
mlist_node_t* newnode);
|
||||
|
||||
#endif /* MLIST */
|
||||
|
||||
static slist_cursor_t* slist_cursor_init(
|
||||
slist_t* list);
|
||||
@ -94,8 +111,391 @@ static slist_node_t* slist_get_first(
|
||||
static slist_cursor_t* slist_get_cursor(
|
||||
slist_t* list);
|
||||
|
||||
static bool file_write_header(skygw_file_t* file);
|
||||
static void simple_mutex_free_memory(simple_mutex_t* sm);
|
||||
static void mlist_free_memory(mlist_t* ml, char* name);
|
||||
static void thread_free_memory(skygw_thread_t* th, char* name);
|
||||
|
||||
|
||||
/** End of static function declarations */
|
||||
|
||||
/** mutexed list, mlist */
|
||||
|
||||
#if defined(MLIST)
|
||||
|
||||
int skygw_rwlock_rdlock(
|
||||
skygw_rwlock_t* rwlock)
|
||||
{
|
||||
int err = pthread_rwlock_rdlock(rwlock->srw_rwlock);
|
||||
|
||||
if (err == 0) {
|
||||
rwlock->srw_rwlock_thr = pthread_self();
|
||||
} else {
|
||||
rwlock->srw_rwlock_thr = 0;
|
||||
ss_dfprintf(stderr, "pthread_rwlock_rdlock : %s\n", strerror(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int skygw_rwlock_wrlock(
|
||||
skygw_rwlock_t* rwlock)
|
||||
{
|
||||
int err = pthread_rwlock_wrlock(rwlock->srw_rwlock);
|
||||
|
||||
if (err == 0) {
|
||||
rwlock->srw_rwlock_thr = pthread_self();
|
||||
} else {
|
||||
rwlock->srw_rwlock_thr = 0;
|
||||
ss_dfprintf(stderr, "pthread_rwlock_wrlock : %s\n", strerror(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int skygw_rwlock_unlock(
|
||||
skygw_rwlock_t* rwlock)
|
||||
{
|
||||
int err = pthread_rwlock_rdlock(rwlock->srw_rwlock);
|
||||
|
||||
if (err == 0) {
|
||||
rwlock->srw_rwlock_thr = 0;
|
||||
} else {
|
||||
ss_dfprintf(stderr, "pthread_rwlock_unlock : %s\n", strerror(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int skygw_rwlock_destroy(
|
||||
skygw_rwlock_t* rwlock)
|
||||
{
|
||||
int err = pthread_rwlock_destroy(rwlock->srw_rwlock);
|
||||
|
||||
if (err == 0) {
|
||||
rwlock->srw_rwlock_thr = 0;
|
||||
rwlock->srw_rwlock = NULL;
|
||||
} else {
|
||||
ss_dfprintf(stderr, "pthread_rwlock_destroy : %s\n", strerror(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int skygw_rwlock_init(
|
||||
skygw_rwlock_t** rwlock)
|
||||
{
|
||||
skygw_rwlock_t* rwl;
|
||||
int err;
|
||||
|
||||
rwl = (skygw_rwlock_t *)calloc(1, sizeof(skygw_rwlock_t));
|
||||
rwl->srw_chk_top = CHK_NUM_RWLOCK;
|
||||
rwl->srw_chk_tail = CHK_NUM_RWLOCK;
|
||||
err = pthread_rwlock_init(rwl->srw_rwlock, NULL);
|
||||
ss_dassert(err == 0);
|
||||
|
||||
if (err != 0) {
|
||||
ss_dfprintf(stderr,
|
||||
"Creating pthread_rwlock failed : %s\n",
|
||||
strerror(err));
|
||||
goto return_err;
|
||||
}
|
||||
return_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @node Create a list with rwlock and optional read-only cursor
|
||||
*
|
||||
* Parameters:
|
||||
* @param listp - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @param cursor - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @param name - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return Address of mlist_t struct.
|
||||
*
|
||||
*
|
||||
* @details Cursor must protect its reads with read lock, and after acquiring
|
||||
* read lock reader must check whether the list is deleted (mlist_deleted).
|
||||
*
|
||||
*/
|
||||
mlist_t* mlist_init(
|
||||
mlist_t* listp,
|
||||
mlist_cursor_t** cursor,
|
||||
char* name)
|
||||
{
|
||||
mlist_cursor_t* c;
|
||||
mlist_t* list;
|
||||
|
||||
if (cursor != NULL) {
|
||||
ss_dassert(*cursor == NULL);
|
||||
}
|
||||
/** listp is not NULL if caller wants flat list */
|
||||
if (listp == NULL) {
|
||||
list = (mlist_t*)calloc(1, sizeof(mlist_t));
|
||||
} else {
|
||||
/** Caller wants list flat, memory won't be freed */
|
||||
list = listp;
|
||||
list->mlist_flat = TRUE;
|
||||
}
|
||||
ss_dassert(list != NULL);
|
||||
|
||||
if (list == NULL) {
|
||||
fprintf(stderr, "Allocating memory for mlist failed\n");
|
||||
mlist_free_memory(list, name);
|
||||
goto return_list;
|
||||
}
|
||||
list->mlist_chk_top = CHK_NUM_MLIST;
|
||||
list->mlist_chk_tail = CHK_NUM_MLIST;
|
||||
|
||||
if (name != NULL) {
|
||||
list->mlist_name = name;
|
||||
}
|
||||
/** Create mutex, return NULL if fails. */
|
||||
if (simple_mutex_init(
|
||||
&list->mlist_mutex,
|
||||
strdup("writebuf mutex")) == NULL)
|
||||
{
|
||||
ss_dfprintf(stderr, "Creating rwlock for mlist failed\n");
|
||||
mlist_free_memory(list, name);
|
||||
list = NULL;
|
||||
goto return_list;
|
||||
}
|
||||
|
||||
/** Create cursor for reading the list */
|
||||
if (cursor != NULL) {
|
||||
c = mlist_cursor_init(list);
|
||||
|
||||
if (c == NULL) {
|
||||
simple_mutex_done(&list->mlist_mutex);
|
||||
mlist_free_memory(list, name);
|
||||
goto return_list;
|
||||
}
|
||||
CHK_MLIST_CURSOR(c);
|
||||
*cursor = c;
|
||||
}
|
||||
CHK_MLIST(list);
|
||||
|
||||
return_list:
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @node Free mlist memory allocations. name must be explicitly
|
||||
* set if mlist has one.
|
||||
*
|
||||
* Parameters:
|
||||
* @param ml - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @param name - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*
|
||||
* @details (write detailed description here)
|
||||
*
|
||||
*/
|
||||
static void mlist_free_memory(
|
||||
mlist_t* ml,
|
||||
char* name)
|
||||
{
|
||||
mlist_node_t* node;
|
||||
|
||||
/** name */
|
||||
if (name != NULL) {
|
||||
free(name);
|
||||
}
|
||||
if (ml != NULL) {
|
||||
/** list data */
|
||||
while(ml->mlist_first != NULL) {
|
||||
/** Scan list and free nodes and data inside nodes */
|
||||
node = ml->mlist_first->mlnode_next;
|
||||
mlist_node_done(ml->mlist_first);
|
||||
ml->mlist_first = node;
|
||||
}
|
||||
|
||||
/** list structure */
|
||||
if (!ml->mlist_flat) {
|
||||
free(ml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mlist_node_done(
|
||||
mlist_node_t* n)
|
||||
{
|
||||
CHK_MLIST_NODE(n);
|
||||
if (n->mlnode_data != NULL) {
|
||||
free(n->mlnode_data);
|
||||
}
|
||||
free(n);
|
||||
}
|
||||
|
||||
void* mlist_node_get_data(
|
||||
mlist_node_t* node)
|
||||
{
|
||||
CHK_MLIST_NODE(node);
|
||||
return node->mlnode_data;
|
||||
}
|
||||
|
||||
mlist_cursor_t* mlist_cursor_init(
|
||||
mlist_t* list)
|
||||
{
|
||||
CHK_MLIST(list);
|
||||
mlist_cursor_t* c;
|
||||
|
||||
/** acquire shared lock to the list */
|
||||
simple_mutex_lock(&list->mlist_mutex, TRUE);
|
||||
|
||||
c = (mlist_cursor_t *)calloc(1, sizeof(mlist_cursor_t));
|
||||
|
||||
if (c == NULL) {
|
||||
goto return_cursor;
|
||||
}
|
||||
c->mlcursor_chk_top = CHK_NUM_MLIST_CURSOR;
|
||||
c->mlcursor_chk_tail = CHK_NUM_MLIST_CURSOR;
|
||||
c->mlcursor_list = list;
|
||||
|
||||
/** Set cursor position if list is not empty */
|
||||
if (list->mlist_first != NULL) {
|
||||
c->mlcursor_pos = list->mlist_first;
|
||||
}
|
||||
simple_mutex_unlock(&list->mlist_mutex);
|
||||
|
||||
CHK_MLIST_CURSOR(c);
|
||||
|
||||
return_cursor:
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @node Mark list as deleted and free the memory.
|
||||
*
|
||||
* Parameters:
|
||||
* @param list - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*
|
||||
* @details (write detailed description here)
|
||||
*
|
||||
*/
|
||||
void mlist_done(
|
||||
mlist_t* list)
|
||||
{
|
||||
CHK_MLIST(list);
|
||||
simple_mutex_lock(&list->mlist_mutex, TRUE);
|
||||
list->mlist_deleted = TRUE;
|
||||
simple_mutex_unlock(&list->mlist_mutex);
|
||||
|
||||
simple_mutex_done(&list->mlist_mutex);
|
||||
mlist_free_memory(list, list->mlist_name);
|
||||
}
|
||||
|
||||
|
||||
void* mlist_cursor_get_data_nomutex(
|
||||
mlist_cursor_t* mc)
|
||||
{
|
||||
CHK_MLIST_CURSOR(mc);
|
||||
return (mc->mlcursor_pos->mlnode_data);
|
||||
}
|
||||
|
||||
void mlist_add_data_nomutex(
|
||||
mlist_t* list,
|
||||
void* data)
|
||||
{
|
||||
mlist_add_node_nomutex(list, mlist_node_init(data, NULL));
|
||||
}
|
||||
|
||||
|
||||
static mlist_node_t* mlist_node_init(
|
||||
void* data,
|
||||
mlist_cursor_t* cursor)
|
||||
{
|
||||
mlist_node_t* node;
|
||||
|
||||
node = (mlist_node_t*)calloc(1, sizeof(mlist_node_t));
|
||||
node->mlnode_chk_top = CHK_NUM_MLIST_NODE;
|
||||
node->mlnode_chk_tail = CHK_NUM_MLIST_NODE;
|
||||
node->mlnode_data = data;
|
||||
CHK_MLIST_NODE(node);
|
||||
|
||||
if (cursor != NULL) {
|
||||
cursor->mlcursor_pos = node;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void mlist_add_node_nomutex(
|
||||
mlist_t* list,
|
||||
mlist_node_t* newnode)
|
||||
{
|
||||
|
||||
CHK_MLIST(list);
|
||||
// CHK_MLIST_ISLOCKED(list);
|
||||
CHK_MLIST_NODE(newnode);
|
||||
ss_dassert(!list->mlist_deleted);
|
||||
|
||||
/** Find location for new node */
|
||||
if (list->mlist_last != NULL) {
|
||||
ss_dassert(!list->mlist_last->mlnode_deleted);
|
||||
CHK_MLIST_NODE(list->mlist_last);
|
||||
CHK_MLIST_NODE(list->mlist_first);
|
||||
ss_dassert(list->mlist_last->mlnode_next == NULL);
|
||||
list->mlist_last->mlnode_next = newnode;
|
||||
} else {
|
||||
list->mlist_first = newnode;
|
||||
}
|
||||
list->mlist_last = newnode;
|
||||
newnode->mlnode_list = list;
|
||||
list->mlist_nodecount += 1;
|
||||
CHK_MLIST(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool mlist_cursor_move_to_first(
|
||||
mlist_cursor_t* mc)
|
||||
{
|
||||
bool succp = FALSE;
|
||||
mlist_t* list;
|
||||
|
||||
CHK_MLIST_CURSOR(mc);
|
||||
list = mc->mlcursor_list;
|
||||
CHK_MLIST(list);
|
||||
simple_mutex_lock(&list->mlist_mutex, TRUE);
|
||||
|
||||
if (mc->mlcursor_list->mlist_deleted) {
|
||||
return FALSE;
|
||||
}
|
||||
/** Set position point to first node */
|
||||
mc->mlcursor_pos = list->mlist_first;
|
||||
|
||||
if (mc->mlcursor_pos != NULL) {
|
||||
CHK_MLIST_NODE(mc->mlcursor_pos);
|
||||
succp = TRUE;
|
||||
}
|
||||
simple_mutex_unlock(&list->mlist_mutex);
|
||||
return succp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* MLIST */
|
||||
|
||||
|
||||
/** End of mlist */
|
||||
|
||||
|
||||
|
||||
static slist_t* slist_init_ex(
|
||||
bool create_cursors)
|
||||
@ -113,6 +513,7 @@ static slist_t* slist_init_ex(
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static slist_node_t* slist_node_init(
|
||||
void* data,
|
||||
slist_cursor_t* cursor)
|
||||
@ -147,7 +548,7 @@ static void slist_add_node(
|
||||
list->slist_tail->slnode_next = node;
|
||||
} else {
|
||||
list->slist_head = node;
|
||||
}
|
||||
}
|
||||
list->slist_tail = node;
|
||||
node->slnode_list = list;
|
||||
list->slist_nelems += 1;
|
||||
@ -155,6 +556,8 @@ static void slist_add_node(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static slist_node_t* slist_node_get_next(
|
||||
slist_node_t* curr_node)
|
||||
{
|
||||
@ -180,28 +583,6 @@ static slist_node_t* slist_get_first(
|
||||
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)
|
||||
@ -215,9 +596,32 @@ static slist_cursor_t* slist_get_cursor(
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @node Create a cursor and a list with cursors supported
|
||||
* @node Create a cursor and a list with cursors supported. 19.6.2013 :
|
||||
* supports only cursor per list.
|
||||
*
|
||||
* Parameters:
|
||||
* @param void - <usage>
|
||||
@ -245,6 +649,7 @@ slist_cursor_t* slist_init(void)
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @node moves cursor to the first node of list.
|
||||
*
|
||||
@ -362,7 +767,8 @@ void slcursor_add_data(
|
||||
CHK_SLIST(list);
|
||||
CHK_SLIST_CURSOR(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void slist_done(
|
||||
slist_cursor_t* c)
|
||||
{
|
||||
@ -379,6 +785,8 @@ void slist_done(
|
||||
free(c->slcursor_list);
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
/** End of list implementation */
|
||||
|
||||
/**
|
||||
@ -404,11 +812,21 @@ skygw_thread_t* skygw_thread_init(
|
||||
{
|
||||
skygw_thread_t* th =
|
||||
(skygw_thread_t *)calloc(1, sizeof(skygw_thread_t));
|
||||
|
||||
if (th == NULL) {
|
||||
fprintf(stderr, "FATAL: memory allocation for thread failed\n");
|
||||
}
|
||||
ss_dassert(th != NULL);
|
||||
th->sth_chk_top = CHK_NUM_THREAD;
|
||||
th->sth_chk_tail = CHK_NUM_THREAD;
|
||||
th->sth_parent = pthread_self();
|
||||
th->sth_state = THR_INIT;
|
||||
th->sth_name = name;
|
||||
th->sth_mutex = simple_mutex_init(NULL, strdup(name));
|
||||
|
||||
if (th->sth_mutex == NULL) {
|
||||
thread_free_memory(th, th->sth_name);
|
||||
}
|
||||
th->sth_thrfun = sth_thrfun;
|
||||
th->sth_data = data;
|
||||
CHK_THREAD(th);
|
||||
@ -416,8 +834,42 @@ skygw_thread_t* skygw_thread_init(
|
||||
return th;
|
||||
}
|
||||
|
||||
void skygw_thread_start(
|
||||
skygw_thread_t* thr)
|
||||
static void thread_free_memory(
|
||||
skygw_thread_t* th,
|
||||
char* name)
|
||||
{
|
||||
if (name != NULL) {
|
||||
free(name);
|
||||
}
|
||||
free(th);
|
||||
}
|
||||
|
||||
/**
|
||||
* @node Release skygw_thread data except filewriter.
|
||||
*
|
||||
* Parameters:
|
||||
* @param th - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*
|
||||
* @details (write detailed description here)
|
||||
*
|
||||
*/
|
||||
void skygw_thread_done(
|
||||
skygw_thread_t* th)
|
||||
{
|
||||
CHK_THREAD(th);
|
||||
ss_dassert(th->sth_state == THR_STOPPED);
|
||||
th->sth_state = THR_DONE;
|
||||
simple_mutex_done(th->sth_mutex);
|
||||
thread_free_memory(th, th->sth_name);
|
||||
}
|
||||
|
||||
|
||||
int skygw_thread_start(
|
||||
skygw_thread_t* thr)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -426,6 +878,7 @@ void skygw_thread_start(
|
||||
NULL,
|
||||
thr->sth_thrfun,
|
||||
thr);
|
||||
ss_dassert(err == 0);
|
||||
|
||||
if (err != 0) {
|
||||
fprintf(stderr,
|
||||
@ -433,11 +886,15 @@ void skygw_thread_start(
|
||||
"errno %d : %s\n",
|
||||
err,
|
||||
strerror(errno));
|
||||
perror("file writer thread : ");
|
||||
goto return_err;
|
||||
}
|
||||
ss_dfprintf(stderr, "Started %s thread\n", thr->sth_name);
|
||||
|
||||
return_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
skygw_thr_state_t skygw_thread_get_state(
|
||||
skygw_thread_t* thr)
|
||||
{
|
||||
@ -446,13 +903,68 @@ skygw_thr_state_t skygw_thread_get_state(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @node Update thread state
|
||||
*
|
||||
* Parameters:
|
||||
* @param thr - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @param state - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*
|
||||
* @details Thread must check state with mutex.
|
||||
*
|
||||
*/
|
||||
void skygw_thread_set_state(
|
||||
skygw_thread_t* thr,
|
||||
skygw_thr_state_t state)
|
||||
{
|
||||
CHK_THREAD(thr);
|
||||
ss_dassert(!thr->sth_must_exit);
|
||||
simple_mutex_lock(thr->sth_mutex, TRUE);
|
||||
thr->sth_state = state;
|
||||
simple_mutex_unlock(thr->sth_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @node Set exit flag for thread from other thread
|
||||
*
|
||||
* Parameters:
|
||||
* @param thr - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*
|
||||
* @details This call informs thread about exit flag and waits the response.
|
||||
*
|
||||
*/
|
||||
bool skygw_thread_set_exitflag(
|
||||
skygw_thread_t* thr,
|
||||
skygw_message_t* sendmes,
|
||||
skygw_message_t* recmes)
|
||||
{
|
||||
bool succp = FALSE;
|
||||
|
||||
CHK_THREAD(thr);
|
||||
CHK_MESSAGE(sendmes);
|
||||
CHK_MESSAGE(recmes);
|
||||
|
||||
simple_mutex_lock(thr->sth_mutex, TRUE);
|
||||
succp = !thr->sth_must_exit;
|
||||
thr->sth_must_exit = TRUE;
|
||||
simple_mutex_unlock(thr->sth_mutex);
|
||||
|
||||
/** Inform thread and wait for response */
|
||||
if (succp) {
|
||||
skygw_message_send(sendmes);
|
||||
skygw_message_wait(recmes);
|
||||
}
|
||||
ss_dassert(thr->sth_state == THR_STOPPED);
|
||||
return succp;
|
||||
}
|
||||
|
||||
void* skygw_thread_get_data(
|
||||
@ -465,18 +977,46 @@ void* skygw_thread_get_data(
|
||||
bool skygw_thread_must_exit(
|
||||
skygw_thread_t* thr)
|
||||
{
|
||||
CHK_THREAD(thr);
|
||||
return thr->sth_must_exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @node Create a simple_mutex structure which encapsulates pthread_mutex.
|
||||
*
|
||||
* Parameters:
|
||||
* @param name - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*
|
||||
* @details If mutex is flat, sm_enabled can be read if the memory is not freed.
|
||||
* If flat mutex exists, sm_enabled is TRUE.
|
||||
* If mutex allocates its own memory, the pointer is NULL if mutex doesn't
|
||||
* exist.
|
||||
*
|
||||
*/
|
||||
simple_mutex_t* simple_mutex_init(
|
||||
char* name)
|
||||
simple_mutex_t* mutexptr,
|
||||
char* name)
|
||||
{
|
||||
int err;
|
||||
|
||||
int err;
|
||||
simple_mutex_t* sm;
|
||||
|
||||
sm = (simple_mutex_t *)calloc(1, sizeof(simple_mutex_t));
|
||||
/** Copy pointer only if flat, allocate memory otherwise. */
|
||||
if (mutexptr != NULL) {
|
||||
sm = mutexptr;
|
||||
sm->sm_flat = TRUE;
|
||||
} else {
|
||||
sm = (simple_mutex_t *)calloc(1, sizeof(simple_mutex_t));
|
||||
}
|
||||
ss_dassert(sm != NULL);
|
||||
sm->sm_chk_top = CHK_NUM_SIMPLE_MUTEX;
|
||||
sm->sm_chk_tail = CHK_NUM_SIMPLE_MUTEX;
|
||||
sm->sm_name = name;
|
||||
|
||||
/** Create pthread mutex */
|
||||
err = pthread_mutex_init(&sm->sm_mutex, NULL);
|
||||
|
||||
if (err != 0) {
|
||||
@ -487,14 +1027,21 @@ simple_mutex_t* simple_mutex_init(
|
||||
err,
|
||||
strerror(errno));
|
||||
perror("simple_mutex : ");
|
||||
sm = NULL;
|
||||
|
||||
/** Write zeroes if flat, free otherwise. */
|
||||
if (sm->sm_flat) {
|
||||
memset(sm, 0, sizeof(sm));
|
||||
} else {
|
||||
simple_mutex_free_memory(sm);
|
||||
sm = NULL;
|
||||
}
|
||||
goto return_sm;
|
||||
}
|
||||
sm->sm_chk_top = CHK_NUM_SIMPLE_MUTEX;
|
||||
sm->sm_chk_tail = CHK_NUM_SIMPLE_MUTEX;
|
||||
sm->sm_name = strdup(name);
|
||||
sm->sm_enabled = TRUE;
|
||||
CHK_SIMPLE_MUTEX(sm);
|
||||
ss_dfprintf(stderr, "Initialized simple mutex %s.\n", name);
|
||||
|
||||
return_sm:
|
||||
return sm;
|
||||
}
|
||||
|
||||
@ -517,6 +1064,12 @@ int simple_mutex_done(
|
||||
}
|
||||
err = pthread_mutex_destroy(&sm->sm_mutex);
|
||||
|
||||
if (err != 0) {
|
||||
goto return_err;
|
||||
}
|
||||
simple_mutex_free_memory(sm);
|
||||
|
||||
|
||||
return_err:
|
||||
if (err != 0) {
|
||||
fprintf(stderr,
|
||||
@ -530,6 +1083,17 @@ return_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void simple_mutex_free_memory(
|
||||
simple_mutex_t* sm)
|
||||
{
|
||||
if (sm->sm_name != NULL) {
|
||||
free(sm->sm_name);
|
||||
}
|
||||
if (!sm->sm_flat) {
|
||||
free(sm);
|
||||
}
|
||||
}
|
||||
|
||||
int simple_mutex_lock(
|
||||
simple_mutex_t* sm,
|
||||
bool block)
|
||||
@ -550,6 +1114,9 @@ int simple_mutex_lock(
|
||||
err,
|
||||
strerror(errno));
|
||||
perror("simple_mutex : ");
|
||||
} else {
|
||||
sm->sm_locked = TRUE;
|
||||
sm->sm_lock_thr = pthread_self();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@ -569,6 +1136,9 @@ int simple_mutex_unlock(
|
||||
err,
|
||||
strerror(errno));
|
||||
perror("simple_mutex : ");
|
||||
} else {
|
||||
sm->sm_locked = FALSE;
|
||||
sm->sm_lock_thr = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@ -754,3 +1324,137 @@ void skygw_message_reset(
|
||||
return_mes_rc:
|
||||
ss_dassert(err == 0);
|
||||
}
|
||||
|
||||
static bool file_write_header(
|
||||
skygw_file_t* file)
|
||||
{
|
||||
bool succp = FALSE;
|
||||
size_t wbytes1;
|
||||
size_t wbytes2;
|
||||
size_t len1;
|
||||
size_t len2;
|
||||
const char* header_buf1;
|
||||
char* header_buf2 = NULL;
|
||||
time_t* t;
|
||||
struct tm* tm;
|
||||
|
||||
t = (time_t *)malloc(sizeof(time_t));
|
||||
tm = (struct tm *)malloc(sizeof(struct tm));
|
||||
*t = time(NULL);
|
||||
*tm = *localtime(t);
|
||||
|
||||
CHK_FILE(file);
|
||||
header_buf1 = "\n----------\nSkySQL Gateway ";
|
||||
|
||||
header_buf2 = strdup(asctime(tm));
|
||||
|
||||
if (header_buf2 == NULL) {
|
||||
goto return_succp;
|
||||
}
|
||||
len1 = strlen(header_buf1);
|
||||
len2 = strlen(header_buf2);
|
||||
|
||||
wbytes1=fwrite((void*)header_buf1, len1, 1, file->sf_file);
|
||||
wbytes2=fwrite((void*)header_buf2, len2, 1, file->sf_file);
|
||||
|
||||
if (wbytes1 != 1 || wbytes2 != 1) {
|
||||
fprintf(stderr,
|
||||
"Writing header %s %s to %s failed.\n",
|
||||
header_buf1,
|
||||
header_buf2,
|
||||
file->sf_fname);
|
||||
perror("Logfile header write.\n");
|
||||
goto return_succp;
|
||||
}
|
||||
|
||||
CHK_FILE(file);
|
||||
|
||||
succp = TRUE;
|
||||
return_succp:
|
||||
free(header_buf2);
|
||||
free(t);
|
||||
free(tm);
|
||||
return succp;
|
||||
}
|
||||
|
||||
bool skygw_file_write(
|
||||
skygw_file_t* file,
|
||||
void* data,
|
||||
size_t nbytes)
|
||||
{
|
||||
size_t nwritten;
|
||||
bool succp = FALSE;
|
||||
|
||||
CHK_FILE(file);
|
||||
nwritten = fwrite(data, nbytes, 1, file->sf_file);
|
||||
|
||||
if (nwritten != 1) {
|
||||
fprintf(stderr,
|
||||
"Writing header %s to %s failed.\n",
|
||||
(char *)data,
|
||||
file->sf_fname);
|
||||
perror("Logfile write.\n");
|
||||
goto return_succp;
|
||||
}
|
||||
succp = TRUE;
|
||||
CHK_FILE(file);
|
||||
return_succp:
|
||||
return succp;
|
||||
}
|
||||
|
||||
skygw_file_t* skygw_file_init(
|
||||
char* fname)
|
||||
|
||||
{
|
||||
skygw_file_t* file;
|
||||
file = (skygw_file_t *)calloc(1, sizeof(skygw_file_t));
|
||||
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Memory allocation for skygw file failed.\n");
|
||||
perror("SkyGW file allocation\n");
|
||||
}
|
||||
ss_dassert(file != NULL);
|
||||
file->sf_chk_top = CHK_NUM_FILE;
|
||||
file->sf_chk_tail = CHK_NUM_FILE;
|
||||
file->sf_fname = strdup(fname);
|
||||
file->sf_file = fopen(file->sf_fname, "a");
|
||||
|
||||
if (file->sf_file == NULL) {
|
||||
fprintf(stderr, "Opening file %s failed.\n", file->sf_fname);
|
||||
perror("SkyGW file open\n");
|
||||
free(file);
|
||||
file = NULL;
|
||||
goto return_file;
|
||||
}
|
||||
|
||||
file_write_header(file);
|
||||
CHK_FILE(file);
|
||||
fprintf(stderr, "Opened %s\n", file->sf_fname);
|
||||
return_file:
|
||||
ss_dassert(file->sf_file != NULL);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
void skygw_file_done(
|
||||
skygw_file_t* file)
|
||||
{
|
||||
int fd;
|
||||
int err;
|
||||
CHK_FILE(file);
|
||||
|
||||
fd = fileno(file->sf_file);
|
||||
fsync(fd);
|
||||
err = fclose(file->sf_file);
|
||||
|
||||
if (err != 0) {
|
||||
fprintf(stderr,
|
||||
"Closing file %s failed : %s.\n",
|
||||
file->sf_fname,
|
||||
strerror(err));
|
||||
}
|
||||
ss_dassert(err == 0);
|
||||
free(file->sf_fname);
|
||||
free(file);
|
||||
}
|
||||
|
@ -1,21 +1,77 @@
|
||||
#if !defined(SKYGW_UTILS_H)
|
||||
#define SKYGW_UTILS_H
|
||||
|
||||
#define MLIST
|
||||
#define MIN(a,b) (a<b ? a : b)
|
||||
|
||||
#include "skygw_types.h"
|
||||
#include "skygw_debug.h"
|
||||
|
||||
typedef struct slist_node_st slist_node_t;
|
||||
typedef struct slist_st slist_t;
|
||||
typedef struct slist_cursor_st slist_cursor_t;
|
||||
typedef struct simple_mutex_st simple_mutex_t;
|
||||
typedef struct skygw_thread_st skygw_thread_t;
|
||||
typedef struct slist_node_st slist_node_t;
|
||||
typedef struct slist_st slist_t;
|
||||
typedef struct slist_cursor_st slist_cursor_t;
|
||||
typedef struct mlist_node_st mlist_node_t;
|
||||
typedef struct skygw_file_st skygw_file_t;
|
||||
typedef struct skygw_thread_st skygw_thread_t;
|
||||
typedef struct skygw_message_st skygw_message_t;
|
||||
|
||||
typedef enum { THR_INIT, THR_RUNNING, THR_EXIT } skygw_thr_state_t;
|
||||
typedef struct simple_mutex_st {
|
||||
skygw_chk_t sm_chk_top;
|
||||
pthread_mutex_t sm_mutex;
|
||||
pthread_t sm_lock_thr;
|
||||
bool sm_locked;
|
||||
bool sm_enabled;
|
||||
bool sm_flat;
|
||||
char* sm_name;
|
||||
skygw_chk_t sm_chk_tail;
|
||||
} simple_mutex_t;
|
||||
|
||||
|
||||
typedef struct skygw_rwlock_st {
|
||||
skygw_chk_t srw_chk_top;
|
||||
pthread_rwlock_t* srw_rwlock;
|
||||
pthread_t srw_rwlock_thr;
|
||||
skygw_chk_t srw_chk_tail;
|
||||
} skygw_rwlock_t;
|
||||
|
||||
|
||||
typedef struct mlist_st {
|
||||
skygw_chk_t mlist_chk_top;
|
||||
char* mlist_name;
|
||||
/** CREW concurrency, protects node updates and clean-up */
|
||||
simple_mutex_t mlist_mutex;
|
||||
bool mlist_uselock;
|
||||
bool mlist_islocked;
|
||||
bool mlist_deleted;
|
||||
size_t mlist_nodecount;
|
||||
bool mlist_flat;
|
||||
mlist_node_t* mlist_first;
|
||||
mlist_node_t* mlist_last;
|
||||
skygw_chk_t mlist_chk_tail;
|
||||
} mlist_t;
|
||||
|
||||
typedef struct mlist_cursor_st {
|
||||
skygw_chk_t mlcursor_chk_top;
|
||||
mlist_t* mlcursor_list;
|
||||
mlist_node_t* mlcursor_pos;
|
||||
pthread_t* mlcursor_owner_thr;
|
||||
skygw_chk_t mlcursor_chk_tail;
|
||||
} mlist_cursor_t;
|
||||
|
||||
typedef struct mlist_node_st {
|
||||
skygw_chk_t mlnode_chk_top;
|
||||
mlist_t* mlnode_list;
|
||||
mlist_node_t* mlnode_next;
|
||||
void* mlnode_data;
|
||||
bool mlnode_deleted;
|
||||
skygw_chk_t mlnode_chk_tail;
|
||||
} mlist_node_t;
|
||||
|
||||
|
||||
typedef enum { THR_INIT, THR_RUNNING, THR_STOPPED, THR_DONE } skygw_thr_state_t;
|
||||
typedef enum { MES_RC_FAIL, MES_RC_SUCCESS, MES_RC_TIMEOUT } skygw_mes_rc_t;
|
||||
|
||||
EXTERN_C_BLOCK_BEGIN
|
||||
|
||||
slist_cursor_t* slist_init(void);
|
||||
void slist_done(slist_cursor_t* c);
|
||||
|
||||
@ -25,26 +81,54 @@ 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
|
||||
|
||||
mlist_t* mlist_init(mlist_t* mlist, mlist_cursor_t** cursor, char* name);
|
||||
void mlist_done(mlist_t* list);
|
||||
void mlist_add_data_nomutex(mlist_t* list, void* data);
|
||||
void* mlist_node_get_data(mlist_node_t* node);
|
||||
void mlist_node_done(mlist_node_t* n);
|
||||
int mlist_cursor_done(mlist_cursor_t* c);
|
||||
mlist_cursor_t* mlist_cursor_init(mlist_t* ml);
|
||||
|
||||
void mlist_cursor_add_data(mlist_cursor_t* c, void* data);
|
||||
void* mlist_cursor_get_data_nomutex(mlist_cursor_t* c);
|
||||
|
||||
bool mlist_cursor_move_to_first(mlist_cursor_t* c);
|
||||
bool mlist_cursor_step_ahead(mlist_cursor_t* c);
|
||||
|
||||
/** Skygw thread routines */
|
||||
skygw_thread_t* skygw_thread_init(
|
||||
char* name,
|
||||
void* (*sth_thrfun)(void* data),
|
||||
void* data);
|
||||
|
||||
EXTERN_C_BLOCK_END
|
||||
|
||||
void skygw_thread_start(skygw_thread_t* thr);
|
||||
void skygw_thread_done(skygw_thread_t* th);
|
||||
int skygw_thread_start(skygw_thread_t* thr);
|
||||
skygw_thr_state_t skygw_thread_get_state(skygw_thread_t* thr);
|
||||
void skygw_thread_set_state(
|
||||
skygw_thread_t* thr,
|
||||
skygw_thr_state_t state);
|
||||
void* skygw_thread_get_data(skygw_thread_t* thr);
|
||||
bool skygw_thread_must_exit(skygw_thread_t* thr);
|
||||
bool skygw_thread_set_exitflag(
|
||||
skygw_thread_t* thr,
|
||||
skygw_message_t* sendmes,
|
||||
skygw_message_t* recmes);
|
||||
/** Skygw thread routines */
|
||||
|
||||
simple_mutex_t* simple_mutex_init(char* name);
|
||||
/** Skygw file routines */
|
||||
skygw_file_t* skygw_file_init(char* fname);
|
||||
void skygw_file_done(skygw_file_t* file);
|
||||
bool skygw_file_write(skygw_file_t* file, void* data, size_t nbytes);
|
||||
/** Skygw file routines */
|
||||
|
||||
|
||||
simple_mutex_t* simple_mutex_init(simple_mutex_t* mutexptr, char* name);
|
||||
int simple_mutex_done(simple_mutex_t* sm);
|
||||
int simple_mutex_lock(simple_mutex_t* sm, bool block);
|
||||
int simple_mutex_unlock(simple_mutex_t* sm);
|
||||
|
||||
/** Skygw message routines */
|
||||
skygw_message_t* skygw_message_init(void);
|
||||
|
||||
void skygw_message_done(
|
||||
@ -61,6 +145,11 @@ skygw_mes_rc_t skygw_message_request(
|
||||
|
||||
void skygw_message_reset(
|
||||
skygw_message_t* mes);
|
||||
/** Skygw message routines */
|
||||
|
||||
int skygw_rwlock_wrlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_rdlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_unlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_init(skygw_rwlock_t** rwlock);
|
||||
|
||||
#endif /* SKYGW_UTILS_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user