diff --git a/inc/common/common.h b/inc/common/common.h new file mode 100644 index 0000000000000000000000000000000000000000..09d87d2d509af17bb1e02fa8f0ea9ab8a80dd553 --- /dev/null +++ b/inc/common/common.h @@ -0,0 +1,7 @@ +#pragma once + +#include <common/define.h> +#include <common/macro.h> + +#define not_implemented() __not_implemented(__func__,__FILE__,__LINE__) +extern void __not_implemented(const char *func, char *file, int line); diff --git a/inc/common/define.h b/inc/common/define.h new file mode 100644 index 0000000000000000000000000000000000000000..3fd65003f2c1f471413b237d3729e0936506567e --- /dev/null +++ b/inc/common/define.h @@ -0,0 +1,9 @@ +#pragma once + +/* Max value for any buffer, to not squash the stack. */ +#define BUFFER_MAX 4096 + +#ifndef __GNUC__ +#define inline +#endif + diff --git a/inc/common/macro.h b/inc/common/macro.h new file mode 100644 index 0000000000000000000000000000000000000000..b2b3340067b940ff9498ab4449c27025fcb05fe4 --- /dev/null +++ b/inc/common/macro.h @@ -0,0 +1,53 @@ +#pragma once + +#define BRACKETS_THAT(that) (that) + +#ifndef MAX +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif /* MAX */ + +#ifndef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#endif /* MIN */ + +#define RETURN_IF(cond, msg, ret) \ + if (cond) { \ + LOG_ERROR("%s", msg); \ + return ret; \ + } +#define GOTO_IF(cond, msg, label) \ + if (cond) { \ + LOG_ERROR("%s", msg); \ + goto label; \ + } + +#define GOTO_UNLESS(cond, msg, label) GOTO_IF(!(cond), msg, label) +#define RETURN_UNLESS(cond, msg, ret) RETURN_IF(!(cond), msg, ret) +#define NOTHING /* Usefull to return nothing. */ + +#define STRTOL(ret, str, endptr, err_flag) \ +{ \ + err_flag = 0; \ + errno = 0; \ + ret = str == NULL ? 0 : strtol(str, &(endptr), 0); \ + err_flag = errno != 0 || endptr == str; \ +} + +#define ERROR 1 +#define WARN 2 +#define INFO 3 +#define DEBUG 4 +#define LOG(format, level, section, ...) \ + fprintf(stderr, " %c %s%s: " format "\n", \ + level == ERROR ? '!' : level == WARN ? '*' : level == INFO ? '.' : ' ', \ + sizeof(section) > sizeof("") ? ("[" section "] ") : "", \ + __func__, \ + __VA_ARGS__) +#define LOG_INFO_SCT(section, format, ...) LOG(format, INFO, section, __VA_ARGS__) +#define LOG_WARN_SCT(section, format, ...) LOG(format, WARN, section, __VA_ARGS__) +#define LOG_ERROR_SCT(section, format, ...) LOG(format, ERROR, section, __VA_ARGS__) +#define LOG_DEBUG_SCT(section, format, ...) LOG(format, DEBUG, section, __VA_ARGS__) +#define LOG_INFO(format, ...) LOG_INFO_SCT("", format, __VA_ARGS__) +#define LOG_WARN(format, ...) LOG_WARN_SCT("", format, __VA_ARGS__) +#define LOG_ERROR(format, ...) LOG_DEBUG_SCT("", format, __VA_ARGS__) +#define LOG_DEBUG(format, ...) LOG_DEBUG_SCT("", format, __VA_ARGS__) diff --git a/inc/lektor/bufferfd.h b/inc/lektor/bufferfd.h index 52649e158a55d45ea763f6be220800f6d00e8f85..97bc0237268efdc33f5757032c108be91187dc35 100644 --- a/inc/lektor/bufferfd.h +++ b/inc/lektor/bufferfd.h @@ -23,7 +23,7 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdint.h> #include <stdlib.h> diff --git a/inc/lektor/cmd.h b/inc/lektor/cmd.h index 98817754a011d9eae462de1cd8520880c3c0adc8..3ac6c3ad47698fa9996cce8320b3462ce945bc5e 100644 --- a/inc/lektor/cmd.h +++ b/inc/lektor/cmd.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdnoreturn.h> #include <stddef.h> diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h index a9091eacff72fa2ff1d33b97efd1e8155258af27..9e029011cb6b3c482da6393a6b2cea5ff9d7678d 100644 --- a/inc/lektor/commands.h +++ b/inc/lektor/commands.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <lektor/net.h> #include <lektor/window.h> diff --git a/inc/lektor/config.h b/inc/lektor/config.h index 75aaced78226f816388555dae0994c879fafdb93..fc013160204b3dd3f45f7fc5ff0aa9789a38da8a 100644 --- a/inc/lektor/config.h +++ b/inc/lektor/config.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stddef.h> #include <sqlite3.h> diff --git a/inc/lektor/database.h b/inc/lektor/database.h index d1bce791f8824e3a9547e96888df225670deb8b8..3ec3f63d3cb119d57f6a03b60b7cb23132aa7866 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <lektor/mkv.h> #include <lektor/uri.h> diff --git a/inc/lektor/defines.h b/inc/lektor/define.h similarity index 97% rename from inc/lektor/defines.h rename to inc/lektor/define.h index 8d71316b3d8d499888b1ccc9d1d31ce98e82b21c..d68144f42a19e9dae0c1378489aa92e005361c8e 100644 --- a/inc/lektor/defines.h +++ b/inc/lektor/define.h @@ -1,8 +1,9 @@ #pragma once +#include <common/define.h> + #define LKT_MAX_SQLITE_STATEMENT 1024 #define PROTECTED_DATABASE "disk" -#define BUFFER_MAX 4096 #define LKT_DATABASE_NAME_KID "id" #define LKT_DATABASE_NAME_KNAME "source_name" diff --git a/inc/lektor/macro.h b/inc/lektor/macro.h index f5a3209085b35d737e6533afefe815e883b2b4bd..48c66716fec43acae1c01471611bcd0c95a87113 100644 --- a/inc/lektor/macro.h +++ b/inc/lektor/macro.h @@ -1,37 +1,38 @@ #pragma once +#include <common/macro.h> #define SQLITE_PREPARE(db, stmt, SQL, goto_label) \ if (sqlite3_prepare_v2(db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \ - fprintf(stderr, " ! %s: Failed to prepare statement: %s\n", \ - __func__, sqlite3_errmsg(db)); \ + LOG_ERROR_SCT("DB", "Failed to prepare statement: %s", \ + sqlite3_errmsg(db)); \ goto goto_label; \ } #define SQLITE_EXEC(db, SQL, goto_label) \ if (sqlite3_exec(db, SQL, NULL, NULL, NULL) != SQLITE_OK) { \ - fprintf(stderr, " ! %s: Failed to exec statement: %s\n", \ - __func__, sqlite3_errmsg(db)); \ + LOG_ERROR_SCT("DB", "Failed to exec statement: %s", \ + sqlite3_errmsg(db)); \ goto goto_label; \ } #define SQLITE_BIND_TEXT(db, stmt, pos, text, error) \ if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) { \ - fprintf(stderr, " ! %s: Failed to bind text %s at position" \ - "%d: %s\n", __func__, text, pos, sqlite3_errmsg(db)); \ + LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s", \ + text, pos, sqlite3_errmsg(db)); \ goto error; \ } #define SQLITE_BIND_INT(db, stmt, pos, integer, error) \ if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) { \ - fprintf(stderr, " ! %s: Failed to bind int %d at position %d:" \ - "%s\n", __func__, integer, pos, sqlite3_errmsg(db)); \ + LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s", \ + integer, pos, sqlite3_errmsg(db)); \ goto error; \ } #define SQLITE_STEP(db, stmt, code, error) \ if (sqlite3_step(stmt) != code) { \ - fprintf(stderr, " ! %s: Failed to step and get a row: %s\n", \ - __func__, sqlite3_errmsg(db)); \ + LOG_ERROR_SCT("DB", "Failed to step and get a row: %s", \ + sqlite3_errmsg(db)); \ goto error; \ } @@ -41,34 +42,3 @@ #define SQLITE_DO_ROLLBACK(db) \ sqlite3_exec(db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); - -#ifndef MAX -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#endif /* MAX */ - -#ifndef MIN -#define MIN(a, b) ((a) > (b) ? (b) : (a)) -#endif /* MIN */ - -#define RETURN_IF(cond, msg, ret) \ - if (cond) { \ - fprintf(stderr, " ! %s: %s\n", __func__, msg); \ - return ret; \ - } -#define GOTO_IF(cond, msg, label) \ - if (cond) { \ - fprintf(stderr, " ! %s: %s\n", __func__, msg); \ - goto label; \ - } - -#define GOTO_UNLESS(cond, msg, label) GOTO_IF(!(cond), msg, ret) -#define RETURN_UNLESS(cond, msg, ret) RETURN_IF(!(cond), msg, ret) -#define NOTHING /* Usefull to return nothing. */ - -#define STRTOL(ret, str, endptr, err_flag) \ -{ \ - err_flag = 0; \ - errno = 0; \ - ret = str == NULL ? 0 : strtol(str, &(endptr), 0); \ - err_flag = errno != 0 || endptr == str; \ -} diff --git a/inc/lektor/mkv.h b/inc/lektor/mkv.h index 447a58eee6455cbcc44d5290a5b6786d31ad8295..681315934b96e0b0b5557ef0dbaaeea50d20f71b 100644 --- a/inc/lektor/mkv.h +++ b/inc/lektor/mkv.h @@ -23,7 +23,7 @@ */ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <linux/limits.h> #include <stddef.h> diff --git a/inc/lektor/module/module_sdl2.h b/inc/lektor/module/module_sdl2.h index 8caa155f641e8196519d9d3ff5c415778ab99cba..e4a2dd2c8c602baa453b69c8e20233f6e9cbd1e1 100644 --- a/inc/lektor/module/module_sdl2.h +++ b/inc/lektor/module/module_sdl2.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdbool.h> #include <sqlite3.h> #include <lektor/window.h> diff --git a/inc/lektor/module/module_x11.h b/inc/lektor/module/module_x11.h index 29f943a99fdc43eec72ff7fa91e3468665124700..880452463c30b72ac7f1e6405a91abf92a6df7ba 100644 --- a/inc/lektor/module/module_x11.h +++ b/inc/lektor/module/module_x11.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdbool.h> #include <sqlite3.h> #include <lektor/window.h> diff --git a/inc/lektor/net.h b/inc/lektor/net.h index 0b29e70f41dcafa1f28fc3e345d1863bcba9b975..20caa955aaee2f512405b8f5d9458824073df24a 100644 --- a/inc/lektor/net.h +++ b/inc/lektor/net.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <lektor/config.h> #include <lektor/window.h> #include <sqlite3.h> diff --git a/inc/lektor/repo.h b/inc/lektor/repo.h index 40953c69ddae0f67d69e196cfbf20449b3b51161..11b127e9cad0febc66484c4b30392a6fc90590a9 100644 --- a/inc/lektor/repo.h +++ b/inc/lektor/repo.h @@ -1,11 +1,11 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <lektor/mkv.h> #include <lektor/thread.h> #include <curl/curl.h> #include <sqlite3.h> -#include <json.h> +#include <json-c/json.h> #include <inttypes.h> #include <stdbool.h> diff --git a/inc/lektor/thread.h b/inc/lektor/thread.h index 553333b8690ba4b090c9ee1af3d5db6d89fe66da..dcd3d75c23ede39f42f314ea098e04c1bb1a812b 100644 --- a/inc/lektor/thread.h +++ b/inc/lektor/thread.h @@ -1,10 +1,10 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <pthread.h> #include <sys/types.h> -struct lkt_thread { +struct poller_thread { /* The input poll. */ volatile unsigned int input_len; volatile unsigned int input_size; @@ -21,25 +21,25 @@ struct lkt_thread { pthread_mutex_t output_lock; }; -struct lkt_thread_arg { - struct lkt_thread *self; +struct poller_thread_arg { + struct poller_thread *self; void *args; }; /* Create a new thread. Returns 0 on success, a non zero value on error. */ -int lkt_th_new(struct lkt_thread *th, unsigned int init_sizes, - void *(*func)(struct lkt_thread_arg *), void *args); +int lkt_th_new(struct poller_thread *th, unsigned int init_sizes, + void *(*func)(struct poller_thread_arg *), void *args); /* Joins a thread. Returns 0 on success, a non zero value on error. */ -int lkt_th_join(struct lkt_thread *th, void **ret); +int lkt_th_join(struct poller_thread *th, void **ret); /* Input qeueu manipulations. */ -int lkt_th_append_input(struct lkt_thread *th, void *ptr); -int lkt_th_pop_input(struct lkt_thread *th, void **ptr); -int lkt_th_head_input(struct lkt_thread *th, void **ptr); +int lkt_th_append_input(struct poller_thread *th, void *ptr); +int lkt_th_pop_input(struct poller_thread *th, void **ptr); +int lkt_th_head_input(struct poller_thread *th, void **ptr); /* Output qeueu manipulations. */ -int lkt_th_append_output(struct lkt_thread *th, void *ptr); -int lkt_th_pop_output(struct lkt_thread *th, void **ptr); -int lkt_th_head_output(struct lkt_thread *th, void **ptr); +int lkt_th_append_output(struct poller_thread *th, void *ptr); +int lkt_th_pop_output(struct poller_thread *th, void **ptr); +int lkt_th_head_output(struct poller_thread *th, void **ptr); diff --git a/inc/lektor/uri.h b/inc/lektor/uri.h index 4466334f9191f9e8b993a06f05d93a7c0ee946b0..ea2d76631c7e5990d02bc5c43856e16d30486496 100644 --- a/inc/lektor/uri.h +++ b/inc/lektor/uri.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stddef.h> #include <stddef.h> #include <stdbool.h> diff --git a/inc/lektor/utils.h b/inc/lektor/utils.h index 27755675b6499a30f388a97e1cb84bd20a0ddbe2..aa175cc8f40d0410a82acdd9677487e98a7edfb3 100644 --- a/inc/lektor/utils.h +++ b/inc/lektor/utils.h @@ -1,7 +1,7 @@ /* Random things. */ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdint.h> #include <stdlib.h> diff --git a/inc/lektor/window.h b/inc/lektor/window.h index 87644c98f139d81ce4c35d8b36dd21019926d467..35d87fbccbab09cdc17f8537d9b87527dc7b0975 100644 --- a/inc/lektor/window.h +++ b/inc/lektor/window.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/defines.h> +#include <lektor/define.h> #include <stdbool.h> #include <sqlite3.h> diff --git a/inc/mthread/mthread.h b/inc/mthread/mthread.h new file mode 100644 index 0000000000000000000000000000000000000000..c708a4414d54bce351aaa564ee4a5b4da46c9f2d --- /dev/null +++ b/inc/mthread/mthread.h @@ -0,0 +1,109 @@ +#pragma once + +/* Types */ +typedef volatile unsigned int mthread_tst_t; + +struct mthread_list_s; +typedef struct mthread_list_s mthread_list_t; + +struct mthread_s; +typedef struct mthread_s *mthread_t; + +struct mthread_attr_s; +typedef struct mthread_attr_s mthread_attr_t; + +struct mthread_mutex_s { + volatile int nb_thread; + mthread_tst_t lock; + mthread_list_t *list; /* lock management already handled */ +}; +typedef struct mthread_mutex_s mthread_mutex_t; + +#define MTHREAD_MUTEX_INITIALIZER { .nb_thread = 0, .lock = 0, .list = NULL } + +struct mthread_mutexattr_s; +typedef struct mthread_mutexattr_s mthread_mutexattr_t; + +struct mthread_cond_s { + mthread_tst_t lock; /* Protects the structure. */ + mthread_list_t *list; /* List of waiting threads. */ +}; +typedef struct mthread_cond_s mthread_cond_t; + +struct mthread_condattr_s; +typedef struct mthread_condattr_s mthread_condattr_t; + +typedef unsigned int mthread_key_t; + +typedef mthread_tst_t mthread_once_t; + +struct mthread_sem_s { + volatile unsigned int value; /* Number of wait that are done at the same time. */ + mthread_mutex_t mutex; /* Protect max_permit. */ +}; +typedef struct mthread_sem_s mthread_sem_t; + +/* Function for handling threads. */ + +int mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, void *(*__start_routine) (void *), + void *__arg); + +mthread_t mthread_self(void); +int mthread_equal(mthread_t __thread1, mthread_t __thread2); +void mthread_exit(void *__retval); +int mthread_join(mthread_t __th, void **__thread_return); + +/* Functions for mutex handling. */ + +int mthread_mutex_init (mthread_mutex_t *__mutex, + const mthread_mutexattr_t *__mutex_attr); +int mthread_mutex_destroy(mthread_mutex_t *__mutex); +int mthread_mutex_trylock(mthread_mutex_t *__mutex); +int mthread_mutex_lock(mthread_mutex_t *__mutex); +int mthread_mutex_unlock(mthread_mutex_t *__mutex); + +/* Functions for handling conditional variables. */ + +int mthread_cond_init(mthread_cond_t *__cond, + const mthread_condattr_t *__cond_attr); +int mthread_cond_destroy(mthread_cond_t *__cond); +int mthread_cond_signal(mthread_cond_t *__cond); +int mthread_cond_broadcast(mthread_cond_t *__cond); +int mthread_cond_wait(mthread_cond_t *__cond, mthread_mutex_t *__mutex); + +/* Functions for handling thread-specific data. */ + +int mthread_key_create(mthread_key_t *__key, void (*__destr_function) (void *)); +int mthread_key_delete(mthread_key_t __key); +int mthread_setspecific(mthread_key_t __key, const void *__pointer); +void *mthread_getspecific(mthread_key_t __key); + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if mthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + variable initialized to MTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with . */ +int mthread_once(mthread_once_t *__once_control, void (*__init_routine) (void)); + +/* Functions for handling semaphore. */ + +int mthread_sem_init(mthread_sem_t *sem, unsigned int value); +int mthread_sem_wait(mthread_sem_t *sem); /* P(sem), wait(sem) */ +int mthread_sem_post(mthread_sem_t *sem); /* V(sem), signal(sem) */ + +int mthread_sem_getvalue(mthread_sem_t *sem, int *sval); +int mthread_sem_trywait(mthread_sem_t *sem); + +int mthread_sem_destroy(mthread_sem_t *sem); /* undo sem_init() */ + +void mthread_yield(); + +/* Initialize mthread. */ + +void mthread_init(void); +void *mthread_main(void *arg); diff --git a/inc/mthread/mthread_internal.h b/inc/mthread/mthread_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..c4eb661d17602bc96fd4bb81395e9176ae039a26 --- /dev/null +++ b/inc/mthread/mthread_internal.h @@ -0,0 +1,69 @@ +#pragma once + +#define TWO_LEVEL + +#include <stdlib.h> +#include <stdio.h> +#include <ucontext.h> + +#include <mthread/mthread.h> +#include <common/common.h> + +#define MTHREAD_DEFAULT_STACK BRACKETS_THAT(128*1024) /* 128 kB */ +#define MTHREAD_MAX_VIRUTAL_PROCESSORS 256 + +struct mthread_list_s { + volatile struct mthread_s *first; + volatile struct mthread_s *last; + mthread_tst_t lock; +}; + +typedef struct { + struct mthread_s *idle; + volatile struct mthread_s *current; + mthread_list_t ready_list; + int rank; + volatile int state; + volatile struct mthread_s *resched; + volatile mthread_tst_t *p; +} mthread_virtual_processor_t; + +typedef enum { RUNNING, BLOCKED, ZOMBIE } mthread_status_t; + +#define INIT_KEYS_LIST 48 + +struct keys_list { + volatile mthread_key_t *list; + unsigned int first_avail; + unsigned int size; +}; + +struct mthread_s { + ucontext_t uc; + volatile void *res; + void *arg; + void *(*__start_routine) (void *); + volatile struct mthread_s *next; + volatile mthread_status_t status; + int not_migrable; + mthread_virtual_processor_t *vp; + void *stack; + struct keys_list keys; +}; + +#define MTHREAD_LIST_INIT { .first = NULL, .last = NULL, .lock = 0 } + +int mthread_test_and_set(mthread_tst_t *atomic); +void mthread_spinlock_lock(mthread_tst_t *atomic); +void mthread_spinlock_unlock(mthread_tst_t *atomic); +int mthread_get_vp_rank(); + +void *safe_malloc(size_t size); + +void mthread_insert_first(struct mthread_s *item, mthread_list_t *list); +void mthread_insert_last(struct mthread_s *item, mthread_list_t *list); +struct mthread_s *mthread_remove_first(mthread_list_t *list); +int mthread_list_test(struct mthread_s *item, mthread_list_t *list); + +void __mthread_yield(mthread_virtual_processor_t *vp); +mthread_virtual_processor_t *mthread_get_vp(); diff --git a/meson.build b/meson.build index cd546e9d1bf2632598879b827ef67417ea074eeb..f0ab5baa0a7cd7152eab37b7b0fabbc9b72ff50d 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,28 @@ dep_x11 = dependency('x11', required : false) dep_mpv = dependency('mpv', required : false) dep_sdl = dependency('sdl2', required : false) +## Get architecture +archi = run_command('uname', '-p').stdout().strip() +if archi == 'unknown' + archi = run_command('uname', '-m').stdout().strip() +endif +if archi == 'unknown' + archi = run_command('arch').stdout().strip() +endif +add_global_arguments('-D' + archi + '_ARCH', language : 'c') +add_global_arguments('-D_REENTRANT', language : 'c') + +## Sources for mthread +mthread_sources = [ 'src/mthread/mthread.c' + , 'src/mthread/mthread_cond.c' + , 'src/mthread/mthread_debug.c' + , 'src/mthread/mthread_key.c' + , 'src/mthread/mthread_mutex.c' + , 'src/mthread/mthread_once.c' + , 'src/mthread/mthread_sem.c' + , 'src/mthread/mthread_tst.c' + ] + ## Sources for the server core_sources = [ 'src/mkv/bufferfd.c' , 'src/mkv/write.c' @@ -53,18 +75,29 @@ core_deps = [ dependency('sqlite3', version : '>= 3.31.0') , dependency('threads', required : true) ] +common_deps = [ declare_dependency( link_with: static_library( 'common' + , files('src/common.c') + , include_directories : includes ) + , include_directories: includes ) ] + +mthread_deps = [ declare_dependency( link_with: static_library( 'mthread' + , files(mthread_sources) + , include_directories : includes ) + , include_directories: includes + , dependencies : [ common_deps ] ) ] + lib = static_library( meson.project_name() , files(core_sources) , include_directories : includes - , dependencies : [ core_deps, libdl ] + , dependencies : [ core_deps, libdl, common_deps ] ) -bin_deps = core_deps + [ declare_dependency( link_with: lib, include_directories: includes) ] +bin_deps = [ declare_dependency( link_with: lib, include_directories: includes) ] srv = executable( meson.project_name() + 'd' , files('src/main/server.c') , include_directories : includes - , dependencies : [ bin_deps ] + , dependencies : [ bin_deps, mthread_deps ] , install : true ) @@ -88,7 +121,7 @@ if dep_x11.found() and dep_mpv.found() lib_mod_x11 = shared_library ( '_module_x11' , files(['src/module/module_x11.c', 'src/module/mpv.c']) , include_directories : includes - , dependencies : [ dep_x11, dep_mpv ] + , dependencies : [ dep_x11, dep_mpv, mthread_deps ] , link_with : lib , install : true , install_dir : 'lib/lektor' @@ -100,7 +133,7 @@ if dep_sdl.found() and dep_mpv.found() lib_mod_sdl = shared_library ( '_module_sdl2' , files(['src/module/module_sdl2.c', 'src/module/mpv.c']) , include_directories : includes - , dependencies : [ dep_sdl, dep_mpv ] + , dependencies : [ dep_sdl, dep_mpv, mthread_deps ] , link_with : lib , install : true , install_dir : 'lib/lektor' diff --git a/src/cmd.c b/src/cmd.c index e13fd7674a7bd31792693a0685ccb93a4f99f461..f5c0c61991087bd5e05d4e287b8e191aae8e6435 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -53,7 +53,7 @@ not_found: it->call(&arguments); } - fprintf(stderr, "Command '%s' could not be found\n", argv[0]); + LOG_ERROR_SCT("COMMAND", "Command '%s' could not be found", argv[0]); exit(EXIT_FAILURE); no_args: @@ -63,7 +63,7 @@ no_args: exit(EXIT_SUCCESS); not_exclusive: - fprintf(stderr, "Failed to determine which option to choose, '%s' is not exclusive\n", argv[0]); + LOG_ERROR_SCT("COMMAND", "Failed to determine option, '%s' not exclusive", argv[0]); exit(EXIT_FAILURE); } diff --git a/src/commands.c b/src/commands.c index 9c1184e14c4efec27df480bd244d273e0483bd66..23acfc3854697086a69b918456db801584ae076d 100644 --- a/src/commands.c +++ b/src/commands.c @@ -30,24 +30,24 @@ command_restart(struct lkt_state *srv, size_t c) RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false); if (readlink(SELF_EXECUTABLE_LINUX, exe, PATH_MAX - 1) > 0) { - fprintf(stderr, " * Restart lektord\n"); + LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); close(srv->fds[0].fd); execv(exe, argv); } if (readlink(SELF_EXECUTABLE_FREEBSD, exe, PATH_MAX - 1) > 0) { - fprintf(stderr, " * Restart lektord\n"); + LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); close(srv->fds[0].fd); execv(exe, argv); } if (readlink(SELF_EXECUTABLE_SOLARIS, exe, PATH_MAX - 1) > 0) { - fprintf(stderr, " * Restart lektord\n"); + LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); close(srv->fds[0].fd); execv(exe, argv); } - fprintf(stderr, " ! command_restart: Failed to exec lektor or OS not supported\n"); + LOG_ERROR_SCT("GENERAL", "%s", "Failed to exec lektor or OS not supported"); abort(); } @@ -63,7 +63,7 @@ inline bool command_kill(struct lkt_state *srv, size_t c) { RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false); - fprintf(stderr, " * Stopping lektord\n"); + LOG_INFO_SCT("GENERAL", "%s", "Stopping lektord"); close(srv->fds[0].fd); exit(EXIT_SUCCESS); } @@ -78,7 +78,7 @@ command_currentsong(struct lkt_state *srv, size_t c) memset(&kara, 0, sizeof(struct kara_metadata)); if (!database_queue_current_kara(srv->db, &kara, NULL)) - fprintf(stderr, " . command_currentsong: Failed to get information about the current kara\n"); + LOG_ERROR_SCT("COMMAND", "%s", "Failed to get information about the current kara"); out = lkt_message_new(); idx = snprintf(out->data, LKT_MESSAGE_MAX, @@ -415,7 +415,7 @@ command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd) if (!once) *clt_mask = MPD_IDLE_ALL; - fprintf(stderr, " * command_idle: idle mask for client number %ld is 0x%X\n", c, *clt_mask); + LOG_INFO_SCT("COMMAND", "Idle mask for client number %ld is 0x%X", c, *clt_mask); return true; } @@ -606,7 +606,7 @@ command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_o break; case lkt_playback_option_volume: ret = database_config_queue(srv->db, "volume", val); - fprintf(stderr, " . command_set_playback_option: set volume to %ld\n", val); + LOG_INFO_SCT("COMMAND", "Set volume to %ld", val); ret &= win->set_volume(win, val); srv->mpd_idle_events |= MPD_IDLE_MIXER; break; @@ -644,12 +644,12 @@ command_plt_add(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_fla else { if (!lkt_uri_from(&uri, args[1])) { - fprintf(stderr, " ! command_plt_add: Failed to get uri\n"); + LOG_ERROR_SCT("COMMAND", "%s", "Failed to get uri"); goto end_plt_add_uri; } else if (!database_plt_add_uri(db, args[0], &uri)) { - fprintf(stderr, " ! command_plt_add: Failed to add uri to playlist\n"); + LOG_ERROR_SCT("COMMAND", "Failed to add uri '%s' to playlist", args[1]); goto end_plt_add_uri; } @@ -711,7 +711,7 @@ command_plt_export(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_ RETURN_UNLESS(database_attach(db, args[0], args[1]), "Failed to attach database", false); RETURN_UNLESS(database_plt_export(db, args[0]), "Failed to export playlist", false); RETURN_UNLESS(database_detach(db, args[0]), "Failed to detach database", false); - fprintf(stderr, " * Exported playlist %s with path '%s'\n", args[0], args[1]); + LOG_INFO_SCT("COMMAND", "Exported playlist %s with path '%s'", args[0], args[1]); *watch_mask_ptr |= MPD_IDLE_PLAYLIST; return true; } @@ -723,7 +723,7 @@ command_plt_import(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_ RETURN_UNLESS(database_attach(db, args[0], args[1]), "Failed to attach database", false); RETURN_UNLESS(database_plt_import(db, args[0]), "Failed to import playlist", false); RETURN_UNLESS(database_detach(db, args[0]), "Failed to detach playlist", false); - fprintf(stderr, " * Imported playlist %s with path '%s'\n", args[0], args[1]); + LOG_INFO_SCT("COMMAND", "Imported playlist %s with path '%s'", args[0], args[1]); *watch_mask_ptr |= MPD_IDLE_PLAYLIST; return true; } @@ -789,10 +789,10 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_ to = labs(val); if (to < from) { - fprintf(stderr, " . command_queue_list: switch range values, wrong order\n"); tmp_switch = to; to = from; from = tmp_switch; + LOG_INFO_SCT("COMMAND", "Switch range values wrong order, now %d:%d", from, to); } goto is_a_range; @@ -1010,7 +1010,7 @@ list_stickers_check_value: } unknown: - fprintf(stderr, " . command_sticker_list: Specified command is invalid or unknown\n"); + LOG_ERROR_SCT("COMMAND", "%s", "Specified command is invalid or unknown"); return false; } diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000000000000000000000000000000000000..f0195a6c88ec9b2660bfd091499dceab267044de --- /dev/null +++ b/src/common.c @@ -0,0 +1,12 @@ +#include <common/common.h> +#include <stdio.h> +#include <stdlib.h> + +void +__not_implemented(const char *func, char *file, int line) +{ + LOG_ERROR_SCT("GENERAL", "Function %s in file %s at line %d not implemented", func, file, line); + abort(); +} + + diff --git a/src/config.c b/src/config.c index 0568353ecc6664f43f9abc37dd8271851d0a61e7..29b85b49cee97229cc2d4afb4b79102793c93855 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/config.h> #include <lektor/database.h> #include <ini/ini.h> @@ -27,7 +28,7 @@ load_so(const char *const mod_path, const char *const mod_init, void *mod) void *handle = dlopen(mod_path, RTLD_NOW); if (NULL == handle) { - fprintf(stderr, " ! load_so: libdl error in dlopen: %s\n", dlerror()); + LOG_ERROR("libdl error in dlopen on file '%s': %s", mod_path, dlerror()); return 1; } @@ -35,7 +36,7 @@ load_so(const char *const mod_path, const char *const mod_init, void *mod) *(void **) (&module_set_function) = dlsym(handle, mod_init); if ((error = dlerror()) != NULL) { - fprintf(stderr, " ! load_so: libdl error in dlsym: %s\n", error); + LOG_ERROR("libdl error in dlsym on file '%s': %s\n", mod_path, error); return 1; } @@ -49,8 +50,7 @@ load_module_by_name(sqlite3 *db, const char *name, void *mod) if (!database_config_get_text(db, name, "path", mod_path, PATH_MAX) || !database_config_get_text(db, name, "load_function", mod_load, INI_MAX_LINE)) { - fprintf(stderr, " ! load_module_by_name: Module named %s is incomplete or is not " - "defined in config file", name); + LOG_ERROR("Module named %s is incomplete or is not defined in config file", name); return 1; } @@ -60,10 +60,10 @@ load_module_by_name(sqlite3 *db, const char *name, void *mod) inline static int validate_conf(sqlite3 *db) { -#define CHK_OPTION(section, name) \ - if (!database_config_exists(db, section, name)) { \ - fprintf(stderr, " ! validate_conf: Missing option " name " in section " section "\n"); \ - return 1; \ +#define CHK_OPTION(section, name) \ + if (!database_config_exists(db, section, name)) { \ + LOG_ERROR("%s", "Missing option "name" in section "section); \ + return 1; \ } CHK_OPTION("externals", "mkvpropedit"); @@ -95,16 +95,8 @@ handler(void *user, const char *section, const char *name, const char *value, in handler(void *user, const char *section, const char *name, const char *value) { #endif - if (!section || !name || !value) { - fprintf(stderr, " . handler: I can't complete the database with incomplete lines\n"); - return 1; - } - - if (!database_config_set(user, section, name, value)) { - fprintf(stderr, " . handler: Failed to update the database\n"); - return 0; - } - + RETURN_UNLESS(section && name && value, "I can't complete the database with incomplete lines", 1); + RETURN_UNLESS(database_config_set(user, section, name, value), "Failed to update the database", 0); return 1; } @@ -123,7 +115,7 @@ config_detect_file(char *conf, size_t conf_len) /* Try the current working dir config file. */ if (getcwd(conf, conf_len - 1) != NULL) { strncat(conf, "/lektor.ini", conf_len - 1); - fprintf(stderr, " . config_detect_file: trying %s\n", conf); + LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; } @@ -138,37 +130,36 @@ config_detect_file(char *conf, size_t conf_len) goto no_config_directory; memcpy(conf, home, (strlen(home) + 1) * sizeof(char)); strncat(conf, "/.config/lektor/lektor.ini", conf_len - 1); - fprintf(stderr, " . config_detect_file: trying %s\n", conf); + LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; no_config_directory: /* Try the '/opt/lektor' file. */ memcpy(conf, "/opt/lektor/lektor.ini", sizeof("/opt/lektor/lektor.ini")); - fprintf(stderr, " . config_detect_file: trying %s\n", conf); + LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; /* Try the '/usr/local/etc/lektor.ini' file. */ memcpy(conf, "/usr/local/etc/lektor.ini", sizeof("/usr/local/etc/lektor.ini")); - fprintf(stderr, " . config_detect_file: trying %s\n", conf); + LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; /* Try the '/etc/lektor.ini' file. */ memcpy(conf, "/etc/lektor.ini", sizeof("/etc/lektor.ini")); - fprintf(stderr, " . config_detect_file: trying %s\n", conf); + LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; /* Error */ - fprintf(stderr, " ! config_detect_file: an error occured with file %s: %s\n", - conf, strerror(errno)); + LOG_ERROR("An error occured with file %s: %s", conf, strerror(errno)); if (is_malloc) free(conf); return 1; found: - fprintf(stderr, " . config_detect_file: using file %s\n", conf); + LOG_INFO("Using file %s", conf); return 0; } @@ -176,12 +167,12 @@ int config_new(sqlite3 *db, const char *conf) { if (ini_parse(conf, handler, db)) { - fprintf(stderr, " . config_new: Failed to parse file %s\n", conf); + LOG_ERROR("Failed to parse file %s", conf); return 1; } if (validate_conf(db)) { - fprintf(stderr, " . config_new: Configuration file %s is incomplete\n", conf); + LOG_ERROR("Configuration file %s is incomplete", conf); return 1; } @@ -193,17 +184,8 @@ config_open(sqlite3 *db) { char conf_file[PATH_MAX]; int ret = 1; - - if (config_detect_file(conf_file, PATH_MAX)) { - fprintf(stderr, " ! config_open: error while searching for a config file\n"); - goto error; - } - - if (config_new(db, conf_file)) { - fprintf(stderr, " ! config_open: failed to read configuration file\n"); - goto error; - } - + GOTO_IF(config_detect_file(conf_file, PATH_MAX), "Error while searching for a config file", error); + GOTO_IF(config_new(db, conf_file), "Failed to read configuration file", error); ret = 0; error: return ret; diff --git a/src/database/config.c b/src/database/config.c index f1311d3c2cfeafd0e46f1a486939f50bbb3e0715..a2aa57d5c9d17c37d66585e918b325dd4ce83d70 100644 --- a/src/database/config.c +++ b/src/database/config.c @@ -26,8 +26,7 @@ database_config_set(sqlite3 *db, const char *section, const char *key, const cha code = sqlite3_step(stmt); if (code != SQLITE_OK && code != SQLITE_DONE) { - fprintf(stderr, " ! database_config_set: Failed to insert or replace: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to insert or replace: %s", sqlite3_errmsg(db)); goto error; } @@ -51,12 +50,7 @@ database_config_get_text(sqlite3 *db, const char *section, const char *key, char SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_TEXT(db, stmt, 1, section, error); SQLITE_BIND_TEXT(db, stmt, 2, key, error); - - if (sqlite3_step(stmt) != SQLITE_ROW) { - fprintf(stderr, " ! database_config_get_text: Failed to insert or replace: %s\n", - sqlite3_errmsg(db)); - goto error; - } + SQLITE_STEP_ROW(db, stmt, error); row = (char *) sqlite3_column_text(stmt, 0); strncpy(value, row, len); @@ -80,12 +74,7 @@ database_config_exists(sqlite3 *db, const char *section, const char *key) SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_TEXT(db, stmt, 1, section, error); SQLITE_BIND_TEXT(db, stmt, 2, key, error); - - if (sqlite3_step(stmt) != SQLITE_ROW) { - fprintf(stderr, " ! database_config_exists: No rows: %s\n", - sqlite3_errmsg(db)); - goto error; - } + SQLITE_STEP_ROW(db, stmt, error); ret = true; error: @@ -107,11 +96,7 @@ database_config_get_int(sqlite3 *db, const char *section, const char *key, int * SQLITE_BIND_TEXT(db, stmt, 1, section, error); SQLITE_BIND_TEXT(db, stmt, 2, key, error); - if (sqlite3_step(stmt) != SQLITE_ROW) { - fprintf(stderr, " ! database_config_get_int: Failed to insert or replace: %s\n", - sqlite3_errmsg(db)); - goto error; - } + SQLITE_STEP_ROW(db, stmt, error); *value = sqlite3_column_int(stmt, 1); ret = true; diff --git a/src/database/find.c b/src/database/find.c index f76f556986fc660150160c44e76e350a72b82f9b..56ac88822330b08ef006a2050704fc3f8bb47447 100644 --- a/src/database/find.c +++ b/src/database/find.c @@ -10,11 +10,7 @@ bool database_search_database_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret) { - if (ret == NULL) { - fprintf(stderr, " ! database_search_init: Exit because return pointer is NULL\n"); - return false; - } - + RETURN_UNLESS(ret, "Exit because return pointer is NULL", false); static const char *SQL_STMT_TEMPLATE = "WITH content AS (" " SELECT kara.id AS id, string AS any_col, LENGTH(CAST(kara.id AS TEXT)) AS len" @@ -40,11 +36,7 @@ error: bool database_search_queue_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret) { - if (ret == NULL) { - fprintf(stderr, " ! database_search_init: Exit because return pointer is NULL\n"); - return false; - } - + RETURN_UNLESS(ret, "Exit because return pointer is NULL", false); static const char *SQL_STMT_TEMPLATE = "WITH content AS (" " SELECT kara_id AS id, string AS any_col, LENGTH(CAST(kara_id AS TEXT)) AS len" @@ -76,10 +68,7 @@ database_search_iter(struct lkt_search *item) code = sqlite3_step(item->stmt); - if (item == NULL) { - fprintf(stderr, " * database_search_iter: Exit function because the sqlite3_stmt* is NULL\n"); - return false; - } + RETURN_UNLESS(item, "Exit because item is NULL, end iterations", false); if (code == SQLITE_DONE) goto error_or_done; @@ -100,7 +89,7 @@ database_search_iter(struct lkt_search *item) } error: - fprintf(stderr, " ! database_search_iter: sqlite3_step failed: %s\n", sqlite3_errmsg(item->db)); + LOG_ERROR_SCT("DB", "sqlite3_step failed: %s", sqlite3_errmsg(item->db)); error_or_done: sqlite3_finalize(item->stmt); return false; diff --git a/src/database/open.c b/src/database/open.c index 424fe81006eeca8549e8523e0462982ee5ec3db5..e27425871c58f447f4d42e94274ad81830e57628 100644 --- a/src/database/open.c +++ b/src/database/open.c @@ -52,32 +52,15 @@ is_sql_str_invalid(const char *str) bool database_new(sqlite3 **db) { - if (SQLITE_OK != sqlite3_enable_shared_cache(1)) { - fprintf(stderr, " ! database_new: Failed to enable shared cache\n"); - return false; - } - - if (sqlite3_soft_heap_limit64(HEAP_LIMIT_SOFT) < 0) { - fprintf(stderr, " ! database_new: Failed to set soft heap limit to %u\n", HEAP_LIMIT_SOFT); - return false; - } - - if (sqlite3_hard_heap_limit64(HEAP_LIMIT_HARD) < 0) { - fprintf(stderr, " ! database_new: Failed to set soft heap limit to %u\n", HEAP_LIMIT_HARD); - return false; - } - /* SQLITE_OPEN_FULLMUTEX for serialized mode */ static int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_NOFOLLOW | SQLITE_OPEN_NOMUTEX; - - if (SQLITE_OK != sqlite3_open_v2(":memory:", db, flags, NULL)) { - fprintf(stderr, " ! database_open: Failed to open :memory: database\n"); - return false; - } - + RETURN_IF(SQLITE_OK != sqlite3_enable_shared_cache(1), "Failed to enable shared cache", false); + RETURN_IF(sqlite3_soft_heap_limit64(HEAP_LIMIT_SOFT) < 0, "Failed to set soft heap limit", false); + RETURN_IF(sqlite3_hard_heap_limit64(HEAP_LIMIT_HARD) < 0, "Failed to set soft heap limit", false); + RETURN_IF(SQLITE_OK != sqlite3_open_v2(":memory:", db, flags, NULL), "Failed to open :memory:", false); SQLITE_EXEC(*db, SQL_MEM_SCHEM, err_not_init); return true; err_not_init: @@ -95,7 +78,7 @@ __attach(sqlite3 *db, const char *name, const char *path) snprintf(SQL_ATTACH, LKT_MAX_SQLITE_STATEMENT - 1, SQL_ATTACH_TEMPLATE, path, name); SQL_ATTACH[LKT_MAX_SQLITE_STATEMENT - 1] = 0; SQLITE_EXEC(db, SQL_ATTACH, err_no_attach); - fprintf(stderr, " * Attached database '%s' with path '%s'\n", name, path); + LOG_INFO_SCT("DB", "Attached database '%s' with path '%s'", name, path); ret = true; err_no_attach: return ret; @@ -111,7 +94,7 @@ __detach(sqlite3 *db, const char *name) snprintf(SQL_DETACH, LKT_MAX_SQLITE_STATEMENT - 1, SQL_DETACH_TEMPLATE, name); SQL_DETACH[LKT_MAX_SQLITE_STATEMENT - 1] = 0; SQLITE_EXEC(db, SQL_DETACH, err_no_detach); - fprintf(stderr, " * Detached database '%s'\n", name); + LOG_INFO_SCT("DB", "Detached database '%s'", name); ret = true; err_no_detach: return ret; @@ -137,66 +120,58 @@ bool database_open(sqlite3 *db, const char *dbpath) { if (is_sql_str_invalid(dbpath)) { - fprintf(stderr, " ! database_open: The database path %s is invalid\n", dbpath); + LOG_ERROR("The database path '%s' is invalid", dbpath); return false; } - return __attach(db, PROTECTED_DATABASE, dbpath); } bool database_attach(sqlite3 *db, const char *name, const char *dbpath) { - if (!strcasecmp(PROTECTED_DATABASE, name)) { - fprintf(stderr, " ! database_attach: The database " PROTECTED_DATABASE - " is protected, can't attach a database with the same name\n"); - return false; - } + RETURN_UNLESS(strcasecmp(PROTECTED_DATABASE, name), " The database "PROTECTED_DATABASE + " is protected, can't attach a database with the same name", false); if (is_sql_str_invalid(name)) { - fprintf(stderr, " ! database_attach: The database name %s is invalid\n", name); + LOG_ERROR("The database name '%s' is invalid", name); return false; } if (__is_attached(db, name)) { - fprintf(stderr, " ! database_detach: Database named %s is already attached\n", name); + LOG_ERROR("The database '%s' is already attached", name); return false; } if (!__attach(db, name, dbpath)) { - fprintf(stderr, " ! database_attach: Failed to attach database named '%s' with path '%s'\n", - name, dbpath); + LOG_ERROR_SCT("DB", "Failed to attach database named '%s' with path '%s'", name, dbpath); return false; } - fprintf(stderr, " * Database %s attached\n", name); + LOG_INFO_SCT("DB", "Database '%s' attached", name); return true; } bool database_detach(sqlite3 *db, const char *name) { - if (!strcasecmp(PROTECTED_DATABASE, name)) { - fprintf(stderr, " ! database_detach: The database " PROTECTED_DATABASE - " is protected, can't detach it\n"); - return false; - } + RETURN_UNLESS(strcasecmp(PROTECTED_DATABASE, name), " The database "PROTECTED_DATABASE + " is protected, can't detach it", false); if (is_sql_str_invalid(name)) { - fprintf(stderr, " ! database_detach: The database name %s is invalid\n", name); + LOG_ERROR("The database name '%s' is invalid", name); return false; } if (!__is_attached(db, name)) { - fprintf(stderr, " ! database_detach: Database named %s is not attached\n", name); + LOG_ERROR("The database '%s' is not attached", name); return false; } if (!__detach(db, name)) { - fprintf(stderr, " ! database_detach: Failed to detach database named %s\n", name); + LOG_ERROR_SCT("DB", "Failed to detach database named %s", name); return false; } - fprintf(stderr, " * Database %s detached\n", name); + LOG_INFO_SCT("DB", "Database '%s' detached", name); return true; } diff --git a/src/database/playlist.c b/src/database/playlist.c index 07e3170aed33a82c0c5763a323afae37d0f2f48e..f1f458fc0c89e07402b42a12c2cd9a2358969d86 100644 --- a/src/database/playlist.c +++ b/src/database/playlist.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> #include <lektor/macro.h> #include <stdio.h> @@ -20,7 +21,6 @@ database_plt_create(sqlite3 *db, const char *name) SQLITE_BIND_TEXT(db, stmt, 1, name, error); SQLITE_STEP_DONE(db, stmt, error); sta = true; - fprintf(stderr, " . database_plt_create: Created playlist %s\n", name); error: sqlite3_finalize(stmt); return sta; @@ -102,16 +102,12 @@ database_plt_export(sqlite3 *db, const char *name) sqlite3_stmt *stmt; if (is_sql_str_invalid(name)) { - fprintf(stderr, " . database_plt_export: Name of playlist '%s' is invalid\n", - name); + LOG_ERROR("The playlist name '%s' is invalid", name); goto error; } - if (!strcasecmp(name, PROTECTED_DATABASE)) { - fprintf(stderr, " . database_plt_export: Name '" PROTECTED_DATABASE - "' is protected, you can't use it for a playlist name\n"); - goto error; - } + GOTO_UNLESS(strcasecmp(name, PROTECTED_DATABASE), "Name '"PROTECTED_DATABASE + "' is protected, you can't use it for a playlist name", error); snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_SCHEM, name); SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; @@ -119,8 +115,7 @@ database_plt_export(sqlite3 *db, const char *name) code = sqlite3_step(stmt); if (code != SQLITE_DONE && code != SQLITE_OK) { - fprintf(stderr, " . database_plt_export: Failed to create schema: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to create schema: %s", sqlite3_errmsg(db)); goto error; } @@ -140,16 +135,12 @@ database_plt_import(sqlite3 *db, const char *name) char SQL_STMT[LKT_MAX_SQLITE_STATEMENT], ret = false; if (is_sql_str_invalid(name)) { - fprintf(stderr, " . database_plt_import: Name of playlist '%s' is invalid\n", - name); + LOG_ERROR("The playlist name '%s' is invalid", name); goto error; } - if (!strcasecmp(name, PROTECTED_DATABASE)) { - fprintf(stderr, " . database_plt_import: Name '" PROTECTED_DATABASE - "' is protected, you can't use it for a playlist name\n"); - goto error; - } + GOTO_UNLESS(strcasecmp(name, PROTECTED_DATABASE), "Name '"PROTECTED_DATABASE + "' is protected, you can't use it for a playlist name", error); snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_SCHEM, name, name, name); SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0; diff --git a/src/database/queue.c b/src/database/queue.c index cfb55e007b66132320e051d74dbfbb11a0367359..6520009cfc38c2cc2e5f1ddd5f5227769ab90e80 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -87,10 +87,7 @@ error: static bool queue_add_with_col_like_str(sqlite3 *db, const char *col, const char *val, int priority) { - if (is_sql_str_invalid(col)) { - fprintf(stderr, " ! queue_add_with_col_like_str: Column name %s is invalid\n", col); - return false; - } + RETURN_IF(is_sql_str_invalid(col), "Column name is invalid", false); char SQL[LKT_MAX_SQLITE_STATEMENT]; static const char *SQL_STMT = @@ -117,10 +114,7 @@ error: static bool queue_insert_with_col_like_str(sqlite3 *db, const char *col, const char *val, int pos) { - if (is_sql_str_invalid(col)) { - fprintf(stderr, " ! queue_insert_with_col_like_str: Column name %s is invalid\n", col); - return false; - } + RETURN_IF(is_sql_str_invalid(col), "Column name is invalid", false); char SQL[LKT_MAX_SQLITE_STATEMENT]; static const char *SQL_STMT = @@ -165,8 +159,7 @@ bool database_queue_insert_query(sqlite3 *db, const char *query, int pos) { bool status = queue_insert_with_col_like_str(db, LKT_DATABASE_KARA_ALL, query, pos); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add query" : "Failed add query", query); + LOG_INFO("%s '%s' at %d", status ? "Successfull add query" : "Failed add query", query, pos); return status; } @@ -197,8 +190,7 @@ bool database_queue_add_query(sqlite3 *db, const char *query, int priority) { bool status = queue_add_with_col_like_str(db, LKT_DATABASE_KARA_ALL, query, priority); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add query" : "Failed add query", query); + LOG_INFO("%s '%s' with prio %d", status ? "Successfull add query" : "Failed add query", query, priority); return status; } @@ -206,8 +198,7 @@ bool database_queue_add_author(sqlite3 *db, const char *author, int priority) { bool status = queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KAUTHOR, author, priority); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add author" : "Failed add author", author); + LOG_INFO("%s '%s'", status ? "Successfull add author" : "Failed add author", author); return status; } @@ -215,8 +206,7 @@ bool database_queue_add_language(sqlite3 *db, const char *language, int priority) { bool status = queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KLANG, language, priority); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add language" : "Failed add language", language); + LOG_INFO("%s '%s'", status ? "Successfull add language" : "Failed add language", language); return status; } @@ -224,8 +214,7 @@ bool database_queue_add_category(sqlite3 *db, const char *cat, int priority) { bool status = queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KCAT, cat, priority); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add category" : "Failed add category", cat); + LOG_INFO("%s '%s'", status ? "Successfull add category" : "Failed add category", cat); return status; } @@ -233,8 +222,7 @@ bool database_queue_add_type(sqlite3 *db, const char *type, int priority) { bool status = queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KTYPE, type, priority); - fprintf(stderr, " . %s: %s '%s'\n", __func__, - status ? "Successfull add type" : "Failed add type", type); + LOG_INFO("%s '%s'", status ? "Successfull add type" : "Failed add type", type); return status; } @@ -306,19 +294,18 @@ database_queue_next(sqlite3 *db, char filepath[PATH_MAX]) if (filepath != NULL) strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); else { - fprintf(stderr, " ! database_queue_next: Failed to get file, id was %d\n", id); + LOG_ERROR("Failed to get file, id was %d", id); goto error; } } else if (code == SQLITE_DONE) { - fprintf(stderr, " * database_queue_next: Failed to get next, no setting current to NULL\n"); + LOG_ERROR("%s", "Failed to get next, don't set current to NULL"); goto error; } else { - fprintf(stderr, "database_queue_next: Failed to fetch next kara: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to fetch next kara: %s", sqlite3_errmsg(db)); goto error; } @@ -367,19 +354,18 @@ database_queue_prev(sqlite3 *db, char filepath[PATH_MAX]) if (filepath != NULL) strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); else { - fprintf(stderr, " ! database_queue_prev: Failed to get file, position was %d\n", id); + LOG_ERROR("Failed to get file, position was %d", id); goto error; } } else if (code == SQLITE_DONE) { - fprintf(stderr, " * database_queue_prev: Failed to get previous, no setting current to NULL\n"); + LOG_ERROR("%s", "Failed to get previous, don't set current to NULL"); goto error; } else { - fprintf(stderr, " ! database_queue_prev: Failed to fetch prev kara: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to fetch prev kara: %s", sqlite3_errmsg(db)); goto error; } @@ -439,7 +425,7 @@ database_queue_move(sqlite3 *db, int from, int to) code = sqlite3_step(stmt); if (code != SQLITE_ROW && code != SQLITE_DONE && code != SQLITE_OK) { - fprintf(stderr, " ! database_queue_move: move failed.\n"); + LOG_ERROR_SCT("DB", "%s", "Move failed"); goto error; } @@ -465,8 +451,7 @@ database_queue_play(sqlite3 *db, int pos) code = sqlite3_step(stmt); if (code != SQLITE_OK && code != SQLITE_DONE) { - fprintf(stderr, " ! database_queue_play: Failed to update queue_state: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to update queue_state: %s", sqlite3_errmsg(db)); goto error; } @@ -492,15 +477,12 @@ database_queue_set_current_index(sqlite3 *db, int idx) char SQL_GET[LKT_MAX_SQLITE_STATEMENT]; if (idx <= 0) { - fprintf(stderr, " ! database_queue_set_current_index: an idx of %d is invalid, must be >= 0\n", idx); - return false; - } - - if (snprintf(SQL_GET, LKT_MAX_SQLITE_STATEMENT - 1, SQL_GET_TEMPLATE, idx) < 0) { - fprintf(stderr, " ! database_queue_set_current_index: snprintf failed\n"); + LOG_ERROR_SCT("DB", "An idx of %d is invalid, must be >= 0", idx); return false; } + RETURN_IF(snprintf(SQL_GET, LKT_MAX_SQLITE_STATEMENT - 1, SQL_GET_TEMPLATE, idx) < 0, "Snprintf failed", + false); SQL_GET[LKT_MAX_SQLITE_STATEMENT - 1] = 0; SQLITE_EXEC(db, SQL_GET, error); return true; @@ -530,8 +512,7 @@ database_queue_get_current_file(sqlite3 *db, char filepath[PATH_MAX]) strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); else { - fprintf(stderr, "database_queue_get_current_file: Failed to fetch prev kara: %s\n", - sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to fetch prev kara: %s", sqlite3_errmsg(db)); goto error; } diff --git a/src/database/stickers.c b/src/database/stickers.c index b36b4c70fb9aa0456de8edb198db8a953fd74f31..9d172285c9d6c4cb235f734fbc456240665036db 100644 --- a/src/database/stickers.c +++ b/src/database/stickers.c @@ -20,12 +20,7 @@ database_sticker_create(sqlite3 *db, const char *name) "WHERE NOT EXISTS (SELECT 1 FROM 'stickers' WHERE name = ?);"; sqlite3_stmt *stmt; int ret = false; - - if (strlen(name) == 0) { - fprintf(stderr, " ! database_sticker_create: A sticker name must be at least one character long\n"); - return ret; - } - + RETURN_IF(strlen(name) == 0, "A sticker name must be at least one character long", ret); SQLITE_PREPARE(db, stmt, INSERT, error); SQLITE_BIND_TEXT(db, stmt, 1, name, error); SQLITE_BIND_TEXT(db, stmt, 2, name, error); @@ -43,12 +38,7 @@ database_sticker_delete(sqlite3 *db, const char *name) "DELETE FROM 'stickers' WHERE name = ?;"; sqlite3_stmt *stmt; int ret = false; - - if (strlen(name) == 0) { - fprintf(stderr, " ! database_sticker_delete: A sticker name must be at least one character long\n"); - return ret; - } - + RETURN_IF(strlen(name) == 0, "A sticker name must be at least one character long", ret); SQLITE_PREPARE(db, stmt, INSERT, error); SQLITE_BIND_TEXT(db, stmt, 1, name, error); SQLITE_STEP_OK(db, stmt, error); @@ -87,7 +77,7 @@ database_sticker_list(sqlite3 *db, const char *type, struct sticker_callback *ca "LEFT OUTER JOIN 'stickers' " "ON 'stickers'.id = 'stickers.song'.sticker;"; else { - fprintf(stderr, " . database_sticker_list: type '%s' is invalid\n", type); + LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); return false; } @@ -144,7 +134,7 @@ database_sticker_set(sqlite3 *db, const char *type, const char *name, int uri, i "FROM 'stickers'" "WHERE 'stickers'.id = ?;\n"; else { - fprintf(stderr, " . database_sticker_set: Type '%s' is invalid\n", type); + LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); return false; } @@ -181,7 +171,7 @@ database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri, s " ON 'stickers'.id = 'stickers.plt'.sticker" " AND 'stickers'.name = ?;\n"; else { - fprintf(stderr, " . database_sticker_get: Type '%s' is invalid\n", type); + LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); return false; } @@ -220,7 +210,7 @@ database_sticker_delete_specify(sqlite3 *db, const char *type, int uri, const ch /* Base query. */ if (strcasecmp("plt", type) && strcasecmp("song", type)) { - fprintf(stderr, " . database_sticker_get: Type '%s' is invalid\n", type); + LOG_ERROR_SCT("DB", "Type '%s' is invalid", type); return false; } diff --git a/src/database/update.c b/src/database/update.c index ae1c9c6dcd9c7cdf0c8fa2bba70a02c2c92030b7..a3b64b2a1cbac804dfa26fccf0c65f929d962291 100644 --- a/src/database/update.c +++ b/src/database/update.c @@ -15,11 +15,7 @@ static bool database_add_kara(sqlite3 *db, const char *filename) { - if (db == NULL || filename == NULL) { - fprintf(stderr, " ! database_add_kara: Invalid arguments\n"); - return false; - } - + RETURN_UNLESS(db || filename, "Invalid argument", false); static const char *SQL_STMT = "INSERT INTO " "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number)" @@ -32,15 +28,10 @@ database_add_kara(sqlite3 *db, const char *filename) struct tm *the_local_time = localtime(&the_time); char year[10]; code = snprintf(year, 10, "%d", the_local_time->tm_year + 1900); - - if (code < 0 || code >= 10) { - fprintf(stderr, " ! database_add_kara: Failed to get the year of the current date: %s\n", sqlite3_errmsg(db)); - return false; - } + RETURN_IF(code < 0 || code >= 10, "Failed to get the year of the current date", false); if (kara_metadata_read(&data, filename) != 0) { - fprintf(stderr, " ! database_add_kara: Failed to get matadata of the kara %s: %s\n", filename, - sqlite3_errmsg(db)); + LOG_ERROR("Failed to get mdt for the kara '%s'", filename); return false; } @@ -56,8 +47,7 @@ database_add_kara(sqlite3 *db, const char *filename) (sqlite3_bind_text(stmt, 8, data.author_name, -1, 0) != SQLITE_OK) || (sqlite3_bind_int(stmt, 9, data.song_number) != SQLITE_OK) ) { - fprintf(stderr, " ! database_add_kara: failed to bind argument to stmt statement for kara %s: %s\n", - filename, sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to bind for kara %s: %s", filename, sqlite3_errmsg(db)); goto error; } @@ -71,12 +61,7 @@ error: bool database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail) { - if (db == NULL || kara_path == NULL || mdt == NULL) { - fprintf(stderr, " ! database_add_kara: Invalid arguments\n"); - errno = EINVAL; - return false; - } - + RETURN_UNLESS(db && kara_path && mdt, "Invalid argument", false); static const char *SQL_STMT = "INSERT OR REPLACE INTO " "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id, available)" @@ -88,12 +73,7 @@ database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *md struct tm *the_local_time = localtime(&the_time); char year[10]; code = snprintf(year, 10, "%d", the_local_time->tm_year + 1900); - - if (code < 0 || code >= 10) { - fprintf(stderr, " ! database_update_add: Failed to get the year of the current date: %s\n", - sqlite3_errmsg(db)); - goto error_no_sqlite; - } + GOTO_IF(code < 0 || code >= 10, "Failed to get the year of the current date", error_no_sqlite); /* From here we initialize the sqlite stmt. */ @@ -111,8 +91,7 @@ database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *md (sqlite3_bind_int(stmt, 10, id) != SQLITE_OK) || (sqlite3_bind_int(stmt, 11, avail) != SQLITE_OK) ) { - fprintf(stderr, " ! database_update_add: failed to bind argument to stmt statement for kara %s: %s\n", - kara_path, sqlite3_errmsg(db)); + LOG_ERROR_SCT("DB", "Failed to bind argument for kara %s: %s", kara_path, sqlite3_errmsg(db)); goto error; } @@ -130,12 +109,10 @@ database_update(sqlite3 *db, const char *kara_dir) DIR *d; struct dirent *dir; char path[PATH_MAX]; - memset(path, 0, PATH_MAX * sizeof(char)); - d = opendir(kara_dir); - if (!d) { - fprintf(stderr, " ! database_update: Failed to open directory '%s': %s\n", kara_dir, strerror(errno)); + if (!(d = opendir(kara_dir))) { + LOG_ERROR("Failed to open directory '%s': %s", kara_dir, strerror(errno)); return false; } @@ -152,7 +129,7 @@ database_update(sqlite3 *db, const char *kara_dir) database_update(db, path); } - fprintf(stderr, " * database_update: Passed directory '%s'\n", kara_dir); + LOG_INFO("Passed directory '%s'", kara_dir); closedir(d); return true; } diff --git a/src/database/user.c b/src/database/user.c index 38704430d4c7f979ddbff6989446caa320d3612d..b6330b2d3319591a86e21683105afc25d6d88176 100644 --- a/src/database/user.c +++ b/src/database/user.c @@ -13,8 +13,7 @@ database_user_authentificate(sqlite3 *db, const char *password) SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_TEXT(db, stmt, 1, password, error); SQLITE_STEP_ROW(db, stmt, error); - fprintf(stderr, " * User authentification was successfull for user %s\n", - sqlite3_column_text(stmt, 0)); + LOG_INFO_SCT("DB", "User authentification for '%s'", sqlite3_column_text(stmt, 0)); ret = true; error: sqlite3_finalize(stmt); @@ -31,7 +30,7 @@ database_user_add(sqlite3 *db, const char *username, const char *password) SQLITE_BIND_TEXT(db, stmt, 1, username, error); SQLITE_BIND_TEXT(db, stmt, 2, password, error); SQLITE_STEP_OK(db, stmt, error); - fprintf(stderr, " * User %s added successfully\n", username); + LOG_INFO_SCT("DB", "User '%s' successfully added", username); ret = true; error: sqlite3_finalize(stmt); diff --git a/src/main/lkt.c b/src/main/lkt.c index b03a223006539ab4bbd93e7af20d269f739b7dbe..e8820e1a1ee42dc5b73fc94b7d68b4046d2c900b 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -1,7 +1,6 @@ #define _POSIX_C_SOURCE 200809L -#include <lektor/macro.h> -#include <lektor/defines.h> +#include <common/common.h> #include <lektor/net.h> #include <lektor/cmd.h> #include <arpa/inet.h> @@ -58,7 +57,7 @@ help(void) static noreturn inline void fail(const char *message) { - fprintf(stderr, "%s\n", message); + LOG_ERROR("%s", message); exit(EXIT_FAILURE); } diff --git a/src/main/lktadm.c b/src/main/lktadm.c index 41da3dd82a4fb8381d514a7f5ff375b4e91f64e2..5676ad2ec7caaeeb574df389304d6e132722a3cb 100644 --- a/src/main/lktadm.c +++ b/src/main/lktadm.c @@ -1,8 +1,8 @@ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE -#include <lektor/macro.h> -#include <lektor/defines.h> +#include <common/common.h> + #include <lektor/cmd.h> #include <lektor/config.h> #include <lektor/mkv.h> @@ -91,7 +91,7 @@ conf__(struct lkt_cmd_args *args) { (void) args; fprintf(stdout, "%s\n", lkt_default_config_file); - fprintf(stderr, "You may redirect this output to ~/.config/lektor/lektor.ini\n"); + LOG_INFO("%s", "You may redirect this output to ~/.config/lektor/lektor.ini"); exit(EXIT_SUCCESS); } @@ -151,7 +151,7 @@ init_file_prompt__(struct lkt_cmd_args *args) int i, num; struct kara_metadata data; for (i = 0; i < args->argc; ++i) { - fprintf(stdout, "Asking for file '%s':\n", args->argv[i]); + LOG_INFO("Asking for file '%s':", args->argv[i]); if (get_stdin_line(" song_name (TITLE): ", data.song_name, LEKTOR_TAG_MAX)) fail("Input error"); @@ -177,8 +177,8 @@ init_file_prompt__(struct lkt_cmd_args *args) fail("Input error"); kara_metadata_write(&data, args->argv[i], mkvpropedit); - fprintf(stdout, "You may name this kara with the following name: '%s - %s%d - %s'\n", - data.source_name, data.song_type, data.song_number, data.song_name); + LOG_INFO("You may name this kara with the following name: '%s - %s%d - %s'", + data.source_name, data.song_type, data.song_number, data.song_name); } exit(EXIT_SUCCESS); } diff --git a/src/main/server.c b/src/main/server.c index ba4eea5e717579761bc9d1d318948ee9afb2365d..434784e236c647b1bed0f592bff44b040160470e 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -1,14 +1,17 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/config.h> #include <lektor/net.h> #include <lektor/database.h> +#include <mthread/mthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <strings.h> #include <pwd.h> +#include <pthread.h> /* Prints the help of the program */ static void @@ -35,10 +38,9 @@ print_help(void) int main(int argc, char *argv[]) { - /* Variable initialisation */ struct passwd *pw = getpwuid(getuid()); + pthread_t th; - /* Argument handleing */ if (argc <= 1) goto normal_launch; else if (strcasecmp(argv[1], "--help") == 0 || @@ -54,8 +56,8 @@ main(int argc, char *argv[]) return EXIT_FAILURE; normal_launch: - fprintf(stderr, " * Lektor launched by user %s (shell: %s, home: %s)\n", - pw->pw_name, pw->pw_shell, pw->pw_dir); - + LOG_INFO("Lektor launched by user %s (shell: %s, home: %s)", pw->pw_name, pw->pw_shell, pw->pw_dir); + mthread_init(); + pthread_create(&th, NULL, mthread_main, NULL); return lkt_listen(); } diff --git a/src/mkv/write.c b/src/mkv/write.c index 4ebd6b9cc5f84903e83db2c6acb2fab6c366a534..c5caa8c0d45cef00fcfa3e4dc6f709487b249051 100644 --- a/src/mkv/write.c +++ b/src/mkv/write.c @@ -1,8 +1,7 @@ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE -#include <lektor/macro.h> -#include <lektor/defines.h> +#include <common/common.h> #include <lektor/mkv.h> #include <stdbool.h> #include <stdio.h> @@ -66,12 +65,12 @@ mkvpropedit__(const char *const args[]) if ((pid = fork()) == 0) { if ((fd = open("/dev/null", O_WRONLY | O_TRUNC)) < 0) { - fprintf(stderr, " ! call_mkvpropedit: can't to open /dev/null in O_WRONLY O_TRUNC\n"); + LOG_ERROR_SCT("FORK", "%s", "Can't to open /dev/null in O_WRONLY O_TRUNC"); return false; } if (dup2(fd, 1) < 0) { - fprintf(stderr, " ! call_mkvpropedit: failed to duplicate /dev/null to stdout\n"); + LOG_ERROR_SCT("FORK", "%s", "Failed to duplicate /dev/null to stdout"); return false; } @@ -80,21 +79,20 @@ mkvpropedit__(const char *const args[]) } else if (pid < 0) { - fprintf(stderr, " ! metadata_write: failed to fork: %s\n", strerror(errno)); + LOG_ERROR_SCT("FORK", "Failed to fork: %s\n", strerror(errno)); return false; } else { do { if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) { - fprintf(stderr, " ! metadata_write: Failed to wait children: %s\n", - strerror(errno)); + LOG_ERROR_SCT("FORK", "Failed to wait children: %s", strerror(errno)); return false; } } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); if ((status = WEXITSTATUS(wstatus))) { - fprintf(stderr, " ! metadata_write: children failed with status %d", status); + LOG_ERROR_SCT("FORK", "Children failed with status %d", status); return false; } } @@ -116,15 +114,13 @@ kara_metadata_write(struct kara_metadata *mdt, const char *filename, const char strncat(tmpfilepath, "all:/tmp/lektor.metadata.XXXXXX", PATH_MAX - 1); if ((fd = mkstemp(metadafilepath)) < 0) { - fprintf(stderr, " ! metadata_write: failed to create temporary file: %s\n", - strerror(errno)); + LOG_ERROR("Failed to create temporary file: %s", strerror(errno)); goto error; } if (dprintf(fd, METADATA_TEMPLATE, mdt->source_name, mdt->song_name, mdt->category, mdt->language, mdt->author_name, mdt->song_type, mdt->song_number) < 0) { - fprintf(stderr, " ! metadata_write: failed to write to temporary file: %s\n", - metadafilepath); + LOG_ERROR("Failed to write to temporary file: %s", metadafilepath); goto error; } @@ -171,11 +167,11 @@ metadata_from_path(char *const mkvfile, struct kara_metadata *meta) memcpy(msgbuf, mkvfile + pmatch[7].rm_so, pmatch[7].rm_eo - pmatch[7].rm_so); memcpy(meta->song_name, mkvfile + pmatch[8].rm_so, pmatch[8].rm_eo - pmatch[8].rm_so); } else if (REG_NOMATCH == reti) { - fprintf(stderr, "No match for: %s\n", mkvfile); + LOG_ERROR("No match for: %s", mkvfile); goto error; } else { regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); - fprintf(stderr, "Failed to execute regex: %s\n", msgbuf); + LOG_ERROR("Failed to execute regex: %s", msgbuf); goto error; } @@ -185,7 +181,7 @@ metadata_from_path(char *const mkvfile, struct kara_metadata *meta) sta = true; error: - regfree(®ex); + /* regfree(®ex); // Should not be nescessary. */ return sta; } @@ -196,13 +192,10 @@ metadata_set_directory(const char *kara_dir, const char *mkvpropedit) struct dirent *dir; char path[PATH_MAX]; struct kara_metadata meta; - memset(path, 0, PATH_MAX * sizeof(char)); - d = opendir(kara_dir); - if (!d) { - fprintf(stderr, " ! metadata_set_directory: Failed to open directory '%s': %s\n", - kara_dir, strerror(errno)); + if (!(d = opendir(kara_dir))) { + LOG_ERROR("Failed to open directory '%s': %s", kara_dir, strerror(errno)); return 1; } @@ -221,7 +214,7 @@ metadata_set_directory(const char *kara_dir, const char *mkvpropedit) metadata_set_directory(path, mkvpropedit); } - fprintf(stderr, " * metadata_set_directory: Passed directory '%s'\n", kara_dir); + LOG_INFO("Passed directory '%s'", kara_dir); closedir(d); return false; } diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c index 94c2e957e5120a4e9bc81129ee2d42ed961a9f07..6ec3defe8b96ce5667fc47e791bc5cc82ecb62b1 100644 --- a/src/module/module_sdl2.c +++ b/src/module/module_sdl2.c @@ -1,9 +1,9 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/module/module_sdl2.h> #include <lektor/module/mpv.h> -#include <lektor/macro.h> -#include <lektor/defines.h> +#include <mthread/mthread.h> #include <lektor/thread.h> #include <sched.h> @@ -33,8 +33,8 @@ struct module_sdl2_window { volatile int mpv_duration; /* Because don't need to be persistent */ /* Thread related */ - pthread_mutex_t mtx; - struct lkt_thread self; + mthread_mutex_t mtx; + struct poller_thread self; volatile int launched; /* SDL you sucks */ }; @@ -84,7 +84,7 @@ init_mpv_gl__(mpv_handle *mpv, mpv_render_context **mpv_gl, mpv_render_param *pa wakeup_on_mpv_events = SDL_RegisterEvents(1); if (wakeup_on_mpv_render_update == (Uint32) - 1 || wakeup_on_mpv_events == (Uint32) - 1) { - fprintf(stderr, " . init_mpv_gl__: Failed to register events\n"); + LOG_ERROR_SCT("WINDOW", "%s", "Failed to register event"); return 1; } @@ -95,7 +95,7 @@ init_mpv_gl__(mpv_handle *mpv, mpv_render_context **mpv_gl, mpv_render_param *pa /* Thread related functions */ static void * -sdl_thread__(struct lkt_thread_arg *arg) +sdl_thread__(struct poller_thread_arg *arg) { volatile struct lkt_win *const win = arg->args; volatile struct module_sdl2_window *sdl2 = win->window; @@ -118,8 +118,7 @@ sdl_thread__(struct lkt_thread_arg *arg) /* Init mpv here */ - RETURN_IF(init_mpv__((mpv_handle **) & sdl2->mpv), - "Failed to init mpv", false); + RETURN_IF(init_mpv__((mpv_handle **) & sdl2->mpv), "Failed to init mpv", false); mpv_render_param params[] = { { MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL }, @@ -145,11 +144,10 @@ sdl_thread__(struct lkt_thread_arg *arg) while (!sdl2->launched) sched_yield(); - fprintf(stderr, " * Started SDL thread\n"); + LOG_INFO_SCT("WINDOW", "%s", "Started SDL thread"); loop: - if (SDL_PollEvent(&event)) - sched_yield(); + SDL_WaitEvent(&event); switch (event.type) { case SDL_QUIT: @@ -208,6 +206,8 @@ loop: SDL_GL_SwapWindow((SDL_Window *) sdl2->window); redraw = 0; } + + sched_yield(); goto loop; /* A loop without indentation. */ } @@ -244,11 +244,11 @@ module_sdl2_new(struct lkt_win *const win) memset(win->window, 0, sizeof(struct module_sdl2_window)); /* Yeah, this is how it is done. */ - pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + mthread_mutex_t mtx = MTHREAD_MUTEX_INITIALIZER; ((struct module_sdl2_window *) win->window)->mtx = mtx; /* Start the SDL thread */ - struct lkt_thread_arg *arg = calloc(1, sizeof(struct lkt_thread_arg)); + struct poller_thread_arg *arg = calloc(1, sizeof(struct poller_thread_arg)); RETURN_UNLESS(arg, "Out of memory", false); arg->args = win; RETURN_IF(lkt_th_new(&((struct module_sdl2_window *) win->window)->self, diff --git a/src/module/module_x11.c b/src/module/module_x11.c index 36787fd3c6726f4e8e68f26ba0cfa64ebfe5b323..a8f821c53b4a4b1aff0ab9ed6b0e1a86e2473e5d 100644 --- a/src/module/module_x11.c +++ b/src/module/module_x11.c @@ -142,7 +142,7 @@ lx11_handle(struct module_x11_window *win) // Key press if (event.type == KeyRelease) { - fprintf(stderr, " . lx11_handle: released key with keycode: 0x%x\n", event.xkey.keycode); + LOG_INFO_SCT("WINDOW", "Release key: 0x%x", event.xkey.keycode); if (event.xkey.keycode == 0x47) XClearWindow(win->master_display, win->master_win); } @@ -178,7 +178,7 @@ module_x11_new(struct lkt_win *const win) memset(x11_win, 0, sizeof(struct module_x11_window)); RETURN_UNLESS(x11_win, "Out of memory", false); RETURN_UNLESS(lx11_new(x11_win), "Can't create X11 window", false); - fprintf(stderr, " . module_x11_window: successfully created the X11 window\n"); + LOG_INFO_SCT("WINDOW", "%s", "Created the X11 window"); } if (x11_win->mpv == NULL) { diff --git a/src/module/mpv.c b/src/module/mpv.c index c5d5626c4baab06492aa918ea7a8cc975dad6408..bf193417d71e92510491f64c558b4ec03d95edfd 100644 --- a/src/module/mpv.c +++ b/src/module/mpv.c @@ -1,3 +1,6 @@ +#define _POSIX_C_SOURCE 200809L + +#include <common/common.h> #include <lektor/module/mpv.h> #include <lektor/commands.h> #include <lektor/database.h> @@ -15,7 +18,7 @@ lmpv_free(mpv_handle **ctx) mpv_command(*ctx, cmd); mpv_destroy(*ctx); *ctx = NULL; - fprintf(stderr, " * lmpv_free: mpv context destroyed\n"); + LOG_INFO_SCT("WINDOW", "%s", "The mpv context was destroyed"); } mpv_handle * @@ -27,8 +30,8 @@ lmpv_prepare(void) #define MPV_SET_OPTION(opt, value) \ if ((status = mpv_set_option_string(ctx, opt, value)) < 0) { \ - fprintf(stderr, " . %s: Failed to set %s to %s: %s\n", \ - __func__, opt, value, mpv_error_string(status)); \ + LOG_ERROR_SCT("WINDOW", "Failed to set %s to %s: %s", \ + opt, value, mpv_error_string(status)); \ return NULL; \ } @@ -58,23 +61,21 @@ lmpv_new(unsigned long int wid) int status; if ((status = mpv_set_property(ctx, "wid", MPV_FORMAT_INT64, &wid)) < 0) { - fprintf(stderr, " ! lmpv_new: failed to set wid: %s\n", - mpv_error_string(status)); + LOG_ERROR_SCT("WINDOW", "Failed to set wid: %s", mpv_error_string(status)); goto error; } if ((status = mpv_initialize(ctx)) < 0) { - fprintf(stderr, " ! lmpv_new: failed to initialize mpv: %s\n", - mpv_error_string(status)); + LOG_ERROR_SCT("WINDOW", "Failed to init mpv: %s", mpv_error_string(status)); goto error; } if (!lmpv_observe_properties(ctx)) { - fprintf(stderr, " * lmpv_new: failed to observe properties\n"); + LOG_ERROR_SCT("WINDOW", "%s", "Failed to observe properties"); goto error; } - fprintf(stderr, " * lmpv_new: successfully created a mpv context\n"); + LOG_ERROR_SCT("WINDOW", "%s", "Create mpv context"); return ctx; error: lmpv_free(&ctx); @@ -91,8 +92,7 @@ lmpv_set_volume(mpv_handle *ctx, int vol) snprintf(str, 4, "%d", vol); const char *cmd[] = {"set", "ao-volume", str, NULL}; if ((status = mpv_command_async(ctx, 0, cmd)) < 0) { - fprintf(stderr, " ! lmpv_set_volume: Failed to execute command: %s\n", - mpv_error_string(status)); + LOG_ERROR_SCT("WINDOW", "Failed to execute command: %s", mpv_error_string(status)); return 1; } return 0; @@ -106,8 +106,7 @@ lmpv_load_file(mpv_handle *ctx, const char *file) const char *cmd[] = {"loadfile", file, "replace", NULL}; int status; if ((status = mpv_command_async(ctx, 0, cmd)) < 0) { - fprintf(stderr, " ! lmpv_load_file: Failed to add '%s': %s\n", - file, mpv_error_string(status)); + LOG_ERROR_SCT("WINDOW", "Failed to add '%s': %s", file, mpv_error_string(status)); return 1; } return 0; @@ -120,8 +119,7 @@ lmpv_toggle_pause(mpv_handle *ctx) const char *cmd[] = {"cycle", "pause", "up", NULL}; int status; if ((status = mpv_command_async(ctx, 0, cmd)) < 0) { - fprintf(stderr, "lmpv_toggle_pause: Failed issue command: %s\n", - mpv_error_string(status)); + LOG_ERROR_SCT("WINDOW", "Failed issus command: %s", mpv_error_string(status)); return 1; } return 0; @@ -187,7 +185,7 @@ loop: database_queue_set_paused(db, *(bool *) prop->data); break; default: - fprintf(stderr, " ! Unhandled mpv event: %s\n", mpv_event_name(event->event_id)); + LOG_WARN_SCT("WINDOW", "Unhandled mpv event '%s'", mpv_event_name(event->event_id)); break; } goto loop; /* A loop without indentation. */ diff --git a/src/mthread/mthread.c b/src/mthread/mthread.c new file mode 100644 index 0000000000000000000000000000000000000000..4944174f9b70ed5ce3dae073c32d02ec46122b75 --- /dev/null +++ b/src/mthread/mthread.c @@ -0,0 +1,375 @@ +#define _POSIX_C_SOURCE 200809L + +#include <mthread/mthread_internal.h> +#include <sched.h> +#include <string.h> +#include <unistd.h> + +#define MTHREAD_LWP 1 + +static mthread_virtual_processor_t virtual_processors[MTHREAD_MAX_VIRUTAL_PROCESSORS]; +static mthread_list_t joined_list; + +/* Is mthread initialized */ +static volatile int is_mthread_init = 0; + +static void +__mthread_clear_keys(mthread_t *thread) +{ + RETURN_UNLESS(thread, "Invalid argument", NOTHING); + unsigned int i; + struct keys_list *keys = &(*thread)->keys; + + for (i = 0; i < keys->first_avail; ++i) + mthread_key_delete(keys->list[i]); + + keys->first_avail = 0; +} + +static inline void +mthread_list_init(mthread_list_t *list) +{ + mthread_list_t INIT = MTHREAD_LIST_INIT; + *list = INIT; +} + +static inline void +mthread_init_thread(struct mthread_s *thread) +{ + thread->next = NULL; + thread->status = RUNNING; + thread->res = NULL; +} + +void +mthread_insert_first(struct mthread_s *item, mthread_list_t *list) +{ + mthread_spinlock_lock(&(list->lock)); + if (list->first == NULL) { + item->next = NULL; + list->first = item; + list->last = item; + } else { + item ->next = list->first; + list->first = item; + } + mthread_spinlock_unlock(&(list->lock)); +} + +void +mthread_insert_last(struct mthread_s *item, mthread_list_t *list) +{ + mthread_spinlock_lock(&(list->lock)); + if (list->first == NULL) { + item->next = NULL; + list->first = item; + list->last = item; + } else { + item->next = NULL; + list->last->next = item; + list->last = item; + } + mthread_spinlock_unlock(&(list->lock)); +} + +struct mthread_s * +mthread_remove_first(mthread_list_t *list) +{ + struct mthread_s *res = NULL; + mthread_spinlock_lock(&(list->lock)); + if (list->first != NULL) { + res = (struct mthread_s *)list->first; + list->first = res->next; + if (list->first == NULL) + list->last = NULL; + } + mthread_spinlock_unlock(&(list->lock)); + return res; +} + +extern int +mthread_list_test(struct mthread_s *item, mthread_list_t *list) +{ + struct mthread_s *it = (struct mthread_s *) list->last; + + while (it && it != item) + it = (struct mthread_s *) it->next; + + return it == item; +} + +static inline int +mthread_mctx_set(struct mthread_s *mctx, + void (*func) (void *), char *stack, size_t size, + void *arg) +{ + /* fetch current context */ + RETURN_IF(getcontext(&(mctx->uc)) != 0, "Error in getcontext", 1); + + /* remove parent link */ + mctx->uc.uc_link = NULL; + + /* configure new stack */ + mctx->uc.uc_stack.ss_sp = stack; + mctx->uc.uc_stack.ss_size = size; + mctx->uc.uc_stack.ss_flags = 0; + mctx->stack = stack; + + /* configure startup function (with one argument) */ + makecontext(&(mctx->uc), (void (*)(void)) func, 1 + 1, arg); + return 0; +} + +static inline int +mthread_mctx_swap(struct mthread_s *cur_mctx, struct mthread_s *new_mctx) +{ + swapcontext(&(cur_mctx->uc), &(new_mctx->uc)); + return 0; +} + +void +__mthread_yield(mthread_virtual_processor_t *vp) +{ + struct mthread_s *current = (struct mthread_s *)vp->current; + struct mthread_s *next = mthread_remove_first(&(vp->ready_list)); + + if (vp->resched != NULL) { + mthread_insert_last((struct mthread_s *)vp->resched, &(vp->ready_list)); + vp->resched = NULL; + } + + if (current != vp->idle) { + if ((current->status != BLOCKED) && (current->status != ZOMBIE)) { + if (current->status == RUNNING) + vp->resched = current; + + else + not_implemented(); + } + + if (next == NULL) + next = vp->idle; + } + + /* always true at this point - except for idle thread */ + if (next != NULL) { + if (vp->current != next) { + vp->current = next; + mthread_mctx_swap(current, next); + } + } + + vp = mthread_get_vp(); + + if (vp->p != NULL) { + mthread_spinlock_unlock(vp->p); + vp->p = NULL; + } +} + +static void +mthread_idle_task(void *arg) +{ + mthread_virtual_processor_t *vp = arg; + long j; + int done = 0; + + vp->state = 1; + while (done == 0) { + done = 1; + sched_yield(); + for (j = 0; j < MTHREAD_LWP; j++) { + if (virtual_processors[j].state == 0) + done = 0; + } + } + LOG_INFO_SCT("SCHEDULER", "Virtual processor %d started", vp->rank); + while (1) + __mthread_yield(vp); + not_implemented(); +} + +mthread_virtual_processor_t * +mthread_get_vp() +{ + return &(virtual_processors[0]); +} + +int +mthread_get_vp_rank() +{ + return mthread_get_vp()->rank; +} + +static inline void +mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle, + struct mthread_s *current, int rank) +{ + vp->current = current; + vp->idle = idle; + mthread_list_init(&(vp->ready_list)); + vp->rank = rank; + vp->resched = NULL; + vp->p = NULL; +} + +void * +mthread_main(void *arg) +{ + (void)arg; + mthread_virtual_processor_t *vp = mthread_get_vp(); + while (1) { + sched_yield(); + sleep(1); + __mthread_yield(vp); + } + return NULL; +} + +static inline void +mthread_init_lib(long i) +{ + struct mthread_s *current = NULL; + char *stack = (char *) safe_malloc(MTHREAD_DEFAULT_STACK); + struct mthread_s *mctx = (struct mthread_s *) safe_malloc(sizeof(struct mthread_s)); + mthread_init_thread(mctx); + + mthread_list_init(&(joined_list)); + + if (i == 0) { + current = (struct mthread_s *)safe_malloc(sizeof(struct mthread_s)); + mthread_init_thread(current); + current->__start_routine = mthread_main; + current->stack = NULL; + } + + mthread_init_vp(&(virtual_processors[i]), mctx, mctx, i); + mthread_mctx_set(mctx, mthread_idle_task, stack, MTHREAD_DEFAULT_STACK, &(virtual_processors[i])); + if (i != 0) { + virtual_processors[i].current = mctx; + setcontext(&(mctx->uc)); + } else + virtual_processors[i].current = current; +} + +static void +mthread_start_thread(void *arg) +{ + struct mthread_s *mctx = (struct mthread_s *)arg; + LOG_INFO_SCT("THREAD INIT", "Thread %p started", arg); + mthread_virtual_processor_t *vp = mthread_get_vp(); + __mthread_yield(vp); + mctx->res = mctx->__start_routine(mctx->arg); + mctx->status = ZOMBIE; + LOG_INFO_SCT("THREAD END", "Thread %p ended (%d)", arg, vp->rank); + vp = mthread_get_vp(); + __mthread_yield(vp); +} + +/* Function for handling threads. */ + +static inline void +__mthread_lib_init(long i) +{ + mthread_init_lib(i); + virtual_processors[0].state = 1; + LOG_INFO_SCT("THREAD", "%s", "library started"); +} + +void +mthread_init(void) +{ + if (is_mthread_init == 0) { + __mthread_lib_init(0); + is_mthread_init = 1; + } +} + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +int +mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, + void *(*__start_routine) (void *), void *__arg) +{ + if (is_mthread_init == 0) { + __mthread_lib_init(0); + is_mthread_init = 1; + } + + mthread_virtual_processor_t *vp = mthread_get_vp(); + + if (__attr == NULL) { + struct mthread_s *mctx = mthread_remove_first(&(joined_list)); + if (mctx == NULL) { + mctx = safe_malloc(sizeof(struct mthread_s)); + memset(mctx, 0, sizeof(struct mthread_s)); + } + char *stack = mctx->stack ? mctx->stack : safe_malloc(MTHREAD_DEFAULT_STACK); + + mthread_init_thread(mctx); + LOG_INFO_SCT("THREAD INIT", "Create thread %p", (void *) mctx); + mctx->arg = __arg; + mctx->__start_routine = __start_routine; + mthread_mctx_set(mctx, mthread_start_thread, stack, MTHREAD_DEFAULT_STACK, mctx); + mthread_insert_last(mctx, &(vp->ready_list)); + *__threadp = mctx; + } else + not_implemented(); + + return 0; +} + +/* Obtain the identifier of the current thread. */ +mthread_t +mthread_self(void) +{ + return (mthread_t) mthread_get_vp()->current; +} + +/* Compare two thread identifiers. */ +int +mthread_equal(mthread_t __thread1, mthread_t __thread2) +{ + return (__thread1 == __thread2); +} + +/* Terminate calling thread. */ +void +mthread_exit(void *__retval) +{ + mthread_virtual_processor_t *vp = mthread_get_vp(); + struct mthread_s *mctx = (struct mthread_s *) vp->current; + mctx->res = __retval; + mctx->status = ZOMBIE; + LOG_INFO_SCT("THREAD END", "Thread %p exited", (void *) mctx); + __mthread_yield(vp); +} + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +int +mthread_join(mthread_t __th, void **__thread_return) +{ + LOG_INFO_SCT("THREAD END", "Join thread %p", (void *) __th); + + while (__th->status != ZOMBIE) + mthread_yield(); + + if (__thread_return != NULL) + *__thread_return = (void *)__th->res; + + __mthread_clear_keys(&__th); + LOG_INFO_SCT("THREAD END", "Thread %p joined", (void *) __th); + mthread_insert_last(__th, &(joined_list)); + return 0; +} + +void +mthread_yield() +{ + mthread_virtual_processor_t *vp = mthread_get_vp(); + LOG_INFO_SCT("THREAD YIELD", "Thread %p yield", (void *) vp->current); + __mthread_yield(vp); +} diff --git a/src/mthread/mthread_cond.c b/src/mthread/mthread_cond.c new file mode 100644 index 0000000000000000000000000000000000000000..00ebe3098d947dd670f2c56511f250828b9bc2bf --- /dev/null +++ b/src/mthread/mthread_cond.c @@ -0,0 +1,94 @@ +#include <mthread/mthread_internal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +int +mthread_cond_init(mthread_cond_t *__cond, const mthread_condattr_t *__cond_attr) +{ + (void)__cond_attr; + __cond->lock = 0; + __cond->list = safe_malloc(sizeof(struct mthread_list_s)); + memset(__cond->list, 0, sizeof(struct mthread_list_s)); + LOG_INFO("%s", "Successfully created a condition"); + return 0; +} + +/* Destroy condition variable COND. */ +int +mthread_cond_destroy(mthread_cond_t *__cond) +{ + if (__cond->list) + free((void *) __cond->list); + return 0; +} + +/* Wake up one thread waiting for condition variable COND. */ +int +mthread_cond_signal(mthread_cond_t *__cond) +{ + mthread_t first, self = mthread_self(); + mthread_virtual_processor_t *vp; + int ret = 1; + mthread_spinlock_lock(&__cond->lock); + + if (__cond->list->first != NULL) { + first = mthread_remove_first(__cond->list); + vp = mthread_get_vp(); + first->status = RUNNING; + mthread_insert_last(first, &(vp->ready_list)); + LOG_INFO("Wake up the thread %p from the thread %p", (void *) first, (void *) self); + ret = 0; + } else + LOG_INFO("No thread to wake up found from the thread %p", (void *) self); + + mthread_spinlock_unlock(&__cond->lock); + return ret; +} + +/* Wake up all threads waiting for condition variables COND. */ +int +mthread_cond_broadcast(mthread_cond_t *__cond) +{ + mthread_t first, self = mthread_self(); + mthread_virtual_processor_t *vp; + mthread_spinlock_lock(&__cond->lock); + + while (__cond->list->first != NULL) { + first = mthread_remove_first(__cond->list); + vp = mthread_get_vp(); + first->status = RUNNING; + LOG_INFO("Wake up the thread %p from the thread %p", (void *) first, (void *) self); + mthread_insert_last(first, &(vp->ready_list)); + } + + mthread_spinlock_unlock(&__cond->lock); + return 0; +} + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +int +mthread_cond_wait(mthread_cond_t *__cond, mthread_mutex_t *__mutex) +{ + mthread_spinlock_lock(&__cond->lock); + mthread_t self = mthread_self(); + mthread_virtual_processor_t *vp = mthread_get_vp(); + mthread_insert_last(self, __cond->list); + self->status = BLOCKED; + mthread_mutex_unlock(__mutex); + + LOG_ERROR("Waiting in condition for thread %p", (void *) self); + + vp->p = &__cond->lock; + mthread_yield(); + + mthread_mutex_lock(__mutex); + LOG_ERROR("Waike up in condition for thread %p", (void *) self); + + return 0; +} diff --git a/src/mthread/mthread_debug.c b/src/mthread/mthread_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..8adcdc702748a074547bade6992c5654ceae9d2a --- /dev/null +++ b/src/mthread/mthread_debug.c @@ -0,0 +1,11 @@ +#include <mthread/mthread_internal.h> +#include <assert.h> + +void * +safe_malloc(size_t size) +{ + void *tmp; + tmp = malloc(size); + assert(tmp != NULL); + return tmp; +} diff --git a/src/mthread/mthread_key.c b/src/mthread/mthread_key.c new file mode 100644 index 0000000000000000000000000000000000000000..fc9741bc40ce4bff6fc115586a50de65e65ab9ce --- /dev/null +++ b/src/mthread/mthread_key.c @@ -0,0 +1,172 @@ +#include <mthread/mthread_internal.h> +#include <errno.h> +#include <stdlib.h> + +/* TODO -> use binaty trees for better performance in searches. */ +typedef struct cell_s { + mthread_key_t key; + const volatile void *volatile spec; + void (* destr)(void *); + volatile struct cell_s *volatile next; +} cell_t; + +/* Default is 0. Index start at zero. Because of that the vairables hold the + first available slots and not the last used slots in memory. */ +static volatile mthread_key_t first_avail_key = 1; +static volatile cell_t *volatile key_table = NULL; + +/* Protects anything concerning the keys. */ +static mthread_tst_t lock = 0; + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +int +mthread_key_create(mthread_key_t *__key, void (*__destr_function) (void *)) +{ + cell_t *new_cell = (cell_t *) safe_malloc(sizeof(cell_t)); + mthread_spinlock_lock(&lock); + + /* Creation. */ + new_cell->key = first_avail_key; + new_cell->spec = NULL; + new_cell->destr = __destr_function; + new_cell->next = NULL; + + first_avail_key++; + + if (key_table) { + LOG_INFO("Enqueue cell %d into global key list, old head is %d", + new_cell->key, key_table->key); + new_cell->next = key_table; + key_table = new_cell; + LOG_INFO("New head is %d, next is %d", + key_table->key, key_table->next->key); + } else { + LOG_INFO("%s", "Set base cell for global key list"); + key_table = new_cell; + } + + /* Register key into the thread. */ + + struct keys_list *keys = &(mthread_self()->keys); + if (!keys->list) { + keys->list = (mthread_key_t *) safe_malloc(INIT_KEYS_LIST * sizeof(mthread_key_t)); + keys->first_avail = 0; + keys->size = INIT_KEYS_LIST; + LOG_INFO("%s", "Create the key list for thread"); + } + + if (keys->size == keys->first_avail) { + /* Extend size if no space left. */ + void *new = realloc((void *) keys->list, (keys->size + INIT_KEYS_LIST) * sizeof(mthread_key_t)); + GOTO_UNLESS(new, "Could not increase the size of the key list", end); + keys->size += INIT_KEYS_LIST; + keys->list = new; + LOG_INFO("%s", "Increase the size of the key list"); + } + + /* Register the key into the thread. */ + keys->list[keys->first_avail] = new_cell->key; + keys->first_avail++; + + /* Returns. */ + *__key = new_cell->key; + LOG_INFO("Created key %d", *__key); +end: + mthread_spinlock_unlock(&lock); + return errno; +} + +/* Destroy KEY. */ +int +mthread_key_delete(mthread_key_t __key) +{ + mthread_spinlock_lock(&lock); + + cell_t *it = (cell_t *) key_table; + cell_t *last = NULL; + + while (it != NULL && it->key != __key) { + last = it; + it = (cell_t *) it->next; + } + + if (!it) { + errno = EINVAL; + LOG_ERROR("Key %u not found", __key); + goto end; + } + + if (it->destr) { + LOG_INFO("Call function on data at %p", (void *) it->spec); + it->destr((void *) it->spec); + } + + /* Handle deletion in the linked list. */ + + if (last) + last->next = it->next; + else + key_table = it->next; + + free(it); + LOG_INFO("Deleted key %u successfully", __key); + /* End of the function, simply returns. */ +end: + mthread_spinlock_unlock(&lock); + return errno; +} + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +int +mthread_setspecific(mthread_key_t __key, const void *__pointer) +{ + mthread_spinlock_lock(&lock); + + cell_t *it = (cell_t *) key_table; + while (it != NULL && it->key != __key) + it = (cell_t *) it->next; + + if (!it) { + errno = EINVAL; + LOG_ERROR("Key %u not found", __key); + goto end; + } + + it->spec = __pointer; + LOG_INFO("Key %u set to %p", __key, __pointer); + /* End of the function, simply returns. */ +end: + mthread_spinlock_unlock(&lock); + return errno; +} + +/* Return current value of the thread-specific data slot identified by KEY. */ +void * +mthread_getspecific(mthread_key_t __key) +{ + void *ret = NULL; + mthread_spinlock_lock(&lock); + + cell_t *it = (cell_t *) key_table; + while (it != NULL && it->key != __key) + it = (cell_t *) it->next; + + if (!it) { + errno = EINVAL; + LOG_ERROR("Key %u not found", __key); + goto end; + } + + ret = (void *) it->spec; + /* End of the function, simply returns. */ +end: + mthread_spinlock_unlock(&lock); + return (void *) ret; +} diff --git a/src/mthread/mthread_mutex.c b/src/mthread/mthread_mutex.c new file mode 100644 index 0000000000000000000000000000000000000000..b82ec5f1924b9dabcc8996bd3a3185e72aa15ac1 --- /dev/null +++ b/src/mthread/mthread_mutex.c @@ -0,0 +1,119 @@ +#include <errno.h> +#include <string.h> +#include <mthread/mthread_internal.h> + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +int +mthread_mutex_init(mthread_mutex_t *__mutex, const mthread_mutexattr_t *__mutex_attr) +{ + (void) __mutex_attr; + + __mutex->list = safe_malloc(sizeof(mthread_list_t)); + __mutex->list->first = NULL; + __mutex->list->last = NULL; + __mutex->nb_thread = 0; + __mutex->lock = 0; + + LOG_INFO("%s", "MUTEX initialized"); + return 0; +} + +/* Destroy MUTEX. */ +int +mthread_mutex_destroy(mthread_mutex_t *__mutex) +{ + mthread_spinlock_lock(&__mutex->lock); + + if (__mutex->nb_thread != 0) + return EBUSY; + free(__mutex->list); + __mutex->list = NULL; + + mthread_spinlock_unlock(&__mutex->lock); + return 0; +} + +/* Try to lock MUTEX. */ +int +mthread_mutex_trylock(mthread_mutex_t *__mutex) +{ + int retval = EINVAL; + + if (__mutex->list == NULL) { + __mutex->list = safe_malloc(sizeof(mthread_list_t)); + memset(__mutex->list, 0, sizeof(mthread_list_t)); + } + + mthread_spinlock_lock(&__mutex->lock); + + if (__mutex->nb_thread == 0) { + __mutex->nb_thread = 1; + mthread_spinlock_unlock(&__mutex->lock); + retval = 0; + goto end; + } + + mthread_spinlock_unlock(&__mutex->lock); + LOG_WARN("%s", "MUTEX busy"); + retval = EBUSY; + +end: + return retval; +} + +/* Wait until lock for MUTEX becomes available and lock it. */ +int +mthread_mutex_lock(mthread_mutex_t *__mutex) +{ + mthread_t self; + mthread_virtual_processor_t *vp; + + if (__mutex->list == NULL) { + __mutex->list = safe_malloc(sizeof(mthread_list_t)); + memset(__mutex->list, 0, sizeof(mthread_list_t)); + } + + mthread_spinlock_lock(&__mutex->lock); + + if (__mutex->nb_thread == 0) { + __mutex->nb_thread = 1; + mthread_spinlock_unlock(&__mutex->lock); + } else { + self = mthread_self(); + mthread_insert_last(self, __mutex->list); + self->status = BLOCKED; + vp = mthread_get_vp(); + vp->p = &__mutex->lock; + mthread_yield(); + } + + return 0; +} + +/* Unlock MUTEX. */ +int +mthread_mutex_unlock(mthread_mutex_t *__mutex) +{ + mthread_t first; + mthread_virtual_processor_t *vp; + + if (__mutex->list == NULL) { + __mutex->list = safe_malloc(sizeof(mthread_list_t)); + memset(__mutex->list, 0, sizeof(mthread_list_t)); + } + + mthread_spinlock_lock(&__mutex->lock); + if (__mutex->list->first != NULL) { + first = mthread_remove_first(__mutex->list); + vp = mthread_get_vp(); + first->status = RUNNING; + mthread_insert_last(first, &(vp->ready_list)); + } else + __mutex->nb_thread = 0; + + mthread_spinlock_unlock(&__mutex->lock); + return 0; +} diff --git a/src/mthread/mthread_once.c b/src/mthread/mthread_once.c new file mode 100644 index 0000000000000000000000000000000000000000..acab4bcf75aae21aa4fb6314e77fd3e23ef7f3ab --- /dev/null +++ b/src/mthread/mthread_once.c @@ -0,0 +1,19 @@ +#include <mthread/mthread_internal.h> +#include <errno.h> +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if mthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to MTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with . */ +int +mthread_once (mthread_once_t *__once_control, void (*__init_routine) (void)) +{ + if (mthread_test_and_set(__once_control)) + return EAGAIN; + __init_routine(); + return 0; +} diff --git a/src/mthread/mthread_sem.c b/src/mthread/mthread_sem.c new file mode 100644 index 0000000000000000000000000000000000000000..9c5534aea1896b3412f931fae2f0793b85fad2fb --- /dev/null +++ b/src/mthread/mthread_sem.c @@ -0,0 +1,72 @@ +#include <mthread/mthread_internal.h> + +/* Functions for handling semaphore. */ + +int +mthread_sem_init(mthread_sem_t *sem, unsigned int value) +{ + sem->value = value; + mthread_mutex_init(&sem->mutex, NULL); + return 0; +} + +/* P(sem), wait(sem) */ +int +mthread_sem_wait(mthread_sem_t *sem) +{ + /* Here we loop while we can't enter the semaphore because there are already + the maximum number of clients. */ +loop: + mthread_mutex_lock(&sem->mutex); + if (sem->value == 0) { + mthread_mutex_unlock(&sem->mutex); + mthread_yield(); + goto loop; + } + + sem->value --; + mthread_mutex_unlock(&sem->mutex); + return 0; +} + +/* V(sem), signal(sem) */ +int +mthread_sem_post(mthread_sem_t *sem) +{ + mthread_mutex_lock(&sem->mutex); + sem->value ++; + mthread_mutex_unlock(&sem->mutex); + return 0; +} + +int +mthread_sem_getvalue(mthread_sem_t *sem, int *sval) +{ + *sval = sem->value; + return 0; +} + +int +mthread_sem_trywait(mthread_sem_t *sem) +{ + if (mthread_mutex_trylock(&sem->mutex)) + return 1; + + if (sem->value == 0) { + mthread_mutex_unlock(&sem->mutex); + return 1; + } + + sem->value --; + mthread_mutex_unlock(&sem->mutex); + return 0; +} + +/* undo sem_init() */ +int +mthread_sem_destroy(mthread_sem_t *sem) +{ + mthread_mutex_destroy(&sem->mutex); + sem->value = 0; + return 0; +} diff --git a/src/mthread/mthread_tst.c b/src/mthread/mthread_tst.c new file mode 100644 index 0000000000000000000000000000000000000000..35bae1659166ef8c934ebbf7e2671a8bbe1623cf --- /dev/null +++ b/src/mthread/mthread_tst.c @@ -0,0 +1,73 @@ +#include <mthread/mthread_internal.h> +#include <sched.h> + +#if defined(i686_ARCH) || defined(x86_64_ARCH) + +static inline int +__mthread_test_and_set(mthread_tst_t *atomic) +{ + int ret; + __asm__ __volatile__("lock; xchgl %0, %1":"=r"(ret), "=m"(*atomic):"0"(1), "m"(*atomic):"memory"); + return ret; +} + +#elif defined(sparc_ARCH) +static inline int +__mthread_test_and_set(mthread_tst_t *spinlock) +{ + char ret = 0; + __asm__ __volatile__("ldstub [%0], %1": "=r"(spinlock), "=r"(ret): "0"(spinlock), "1" (ret) : "memory"); + return (unsigned) ret; +} + +#elif defined(ia64_ARCH) +static __inline__ int +__mthread_test_and_set(mthread_tst_t *atomic) +{ + int ret; + __asm__ __volatile__("xchg4 %0=%1, %2":"=r"(ret), "=m"(*atomic):"0"(1), "m"(*atomic):"memory"); + return ret; +} +#else +#define USE_GENERIC_ASM +#include <pthread.h> +static pthread_mutex_t tst_mutex = PTHREAD_MUTEX_INITIALIZER; + +static inline int +__mthread_test_and_set(mthread_tst_t *atomic) +{ + int res; + pthread_mutex_lock(&tst_mutex); + res = *atomic; + if (*atomic == 0) + *atomic = 1; + pthread_mutex_unlock(&tst_mutex); + return res; +} +#endif + +int +mthread_test_and_set(mthread_tst_t *atomic) +{ + return __mthread_test_and_set(atomic); +} + +void +mthread_spinlock_lock(mthread_tst_t *atomic) +{ +#ifdef USE_GENERIC_ASM + static pthread_mutex_t spin_tst_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&spin_tst_mutex); +#endif + while (mthread_test_and_set(atomic)) + sched_yield(); +#ifdef USE_GENERIC_ASM + pthread_mutex_unlock(&spin_tst_mutex); +#endif +} + +void +mthread_spinlock_unlock(mthread_tst_t *atomic) +{ + *atomic = 0; +} diff --git a/src/net/command.c b/src/net/command.c index 33df59b7ea8856018480657dc5c2f7e42ab93932..b23744f20595f3ac815365ffbd850c756f666330 100644 --- a/src/net/command.c +++ b/src/net/command.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/net.h> #include <stdlib.h> diff --git a/src/net/listen.c b/src/net/listen.c index 74a2991eb504a08441a072611c22e0881248c07c..9a6a226d9ee4ce6bfc0da82ba0a88919b54afa94 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -2,7 +2,7 @@ #include <lektor/commands.h> #include <lektor/macro.h> -#include <lektor/defines.h> +#include <lektor/define.h> #include <lektor/database.h> #include <lektor/repo.h> #include <lektor/net.h> @@ -10,6 +10,7 @@ #include <sqlite3.h> +#include <sched.h> #include <assert.h> #include <arpa/inet.h> #include <errno.h> @@ -119,13 +120,13 @@ static void send_status(struct lkt_state *srv, size_t c, int status, const char *cmd_name) { if (!status) { - printf(" * Command: %s\n", cmd_name); + LOG_INFO_SCT("COMMAND", " Command: %s", cmd_name); send_ok(srv, c); } else { if (status == 2) - printf(" * Unknown command: %s\n", cmd_name); + LOG_INFO_SCT("COMMAND", " Unknown command: %s", cmd_name); else - printf(" * Command failed: %s\n", cmd_name); + LOG_INFO_SCT("COMMAND", " Command failed: %s", cmd_name); send_ack(srv, c, cmd_name); } } @@ -281,7 +282,7 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) continuation = lkt_get_continuation(srv, c); if (continuation > 0) { - fprintf(stderr, " * Client should continue from %d\n", continuation); + LOG_INFO_SCT("NETWORK", "Client should continue from %d", continuation); send_continue(srv, c, continuation); } send_status(srv, c, err, cmd.name); @@ -329,7 +330,7 @@ handle_command(struct lkt_state *srv, size_t i, struct lkt_command cmd) else err = handle_simple_command(srv, i, cmd); - printf(" * Command result: %s -> %d\n", cmd.name, err); + LOG_INFO_SCT("COMMAND", "Command result: %s -> %d", cmd.name, err); return err; } @@ -467,21 +468,21 @@ failure: if (fd < 0) { if (host) - fprintf(stderr, "Failed to bind to %s:%s\n", host, port); + LOG_ERROR_SCT("NETWORK", "Failed to bind to %s:%s", host, port); else - fprintf(stderr, "Failed to bind to port %s\n", port); + LOG_ERROR_SCT("NETWORK", "Failed to bind to port %s", port); return -1; } if (listen(fd, LKT_BACKLOG) < 0) { - perror("Failed to listen"); + LOG_ERROR_SCT("NETWORK", "Failed to listen: %s", strerror(errno)); return -1; } if (host) - printf(" * Listening on %s:%s\n", host, port); + LOG_INFO_SCT("NETWORK", "Listening on %s:%s", host, port); else - printf(" * Listening on port %s\n", port); + LOG_INFO_SCT("NETWORK", "Listening on port %s", port); return fd; } @@ -506,7 +507,7 @@ accept_all(int listen_fd, struct pollfd *fds, size_t fds_max, size_t *fds_len) } if (*fds_len == fds_max) { - fprintf(stderr, "Maximum number of file descriptors reached.\n"); + LOG_ERROR_SCT("NETWORK", "%s", "Maximum number of file descriptors reached"); break; } @@ -661,8 +662,7 @@ handle_idle_events(struct lkt_state *srv) strncat(msg->data, "message ", LKT_MESSAGE_MAX - 1); msg->data_len = strlen(msg->data); - fprintf(stderr, " * handle_idle_events: sending '%s' (len: %ld) to the client number %ld\n", msg->data, - msg->data_len, i); + LOG_INFO_SCT("COMMAND", "Sending '%s' (len: %ld) to client %ld", msg->data, msg->data_len, i); msg->data[msg->data_len - 1] = '\n'; msg->data[msg->data_len] = '\0'; lkt_state_send(srv, i, msg); @@ -699,26 +699,22 @@ handle_repo_hevents(struct lkt_state *srv) /* Add the downloaded kara to the database. */ case kara_action_add: if (!database_update_add(srv->db, kara->filename, &kara->mdt, kara->id, true)) { - fprintf(stderr, " ! handle_repo_hevents: Failed to add downloaded kara with id %lu and path %s\n", - kara->id, kara->filename); + LOG_ERROR("Failed to add downloaded kara with id %lu and path %s", kara->id, kara->filename); goto get_out; } - fprintf(stderr, " * Added kara %lu with path %s to database\n", - kara->id, kara->filename); + LOG_INFO("Added kara %lu with path %s to database", kara->id, kara->filename); break; /* Add the mdt of the kara to the database. Mark it unavailable. */ case kara_action_unavail: if (!database_update_add(srv->db, kara->filename, &kara->mdt, kara->id, false)) { - fprintf(stderr, " ! handle_repo_hevents: Failed to add kara with id %lu with flag unavailable\n", - kara->id); + LOG_ERROR("Failed to add kara with id %lu with flag unavailable", kara->id); goto get_out; } - fprintf(stderr, " * Added kara %lu to database and set it to unavailable\n", - kara->id); + LOG_INFO("Added kara %lu to database and set it to unavailable", kara->id); break; diff --git a/src/repo/async.c b/src/repo/async.c index 52bc98d0aca2ce260c7e843f0a243642c2feb376..aeeb98a4ed99c217a35448cbf93cdd8aa8d46efb 100644 --- a/src/repo/async.c +++ b/src/repo/async.c @@ -4,13 +4,14 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include <limits.h> +#include <mthread/mthread.h> #include <lektor/macro.h> #include <lektor/repo.h> #include <lektor/thread.h> -#include <limits.h> -static struct lkt_thread repo_thread; +static struct poller_thread repo_thread; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static volatile int init = 0; @@ -22,21 +23,10 @@ repo_join_thread(void) { int ret = 1; RETURN_IF(pthread_mutex_lock(&mtx), "Failed to lock mutex", 3); - - if (!init) { - fprintf(stderr, " ! repo_join_thread: repo thread is not launched, can't join\n"); - goto error; - } - + GOTO_UNLESS(init, "Repo thread no launched, can't join", error); stop = 1; - - if (pthread_join(repo_thread.th, NULL)) { - fprintf(stderr, " ! repo_join_thread: failed to join repo thread\n"); - goto error; - } - - fprintf(stderr, " . repo_join_thread: repo thread joined\n"); - + GOTO_IF(pthread_join(repo_thread.th, NULL), "Failed to join repo thread", error); + LOG_INFO("%s", "repo thread joined"); ret = 0; error: RETURN_IF(pthread_mutex_unlock(&mtx), "Failed to unlock mutex", 3); @@ -50,7 +40,7 @@ extern int safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret); static inline void -__handle_got_json(struct lkt_thread *self, struct lkt_repo *repo, struct json_object *json) +__handle_got_json(struct poller_thread *self, struct lkt_repo *repo, struct json_object *json) { size_t i, len = json_object_array_length(json); struct json_object *kara_json; @@ -78,7 +68,7 @@ __handle_got_json(struct lkt_thread *self, struct lkt_repo *repo, struct json_ob } integer = snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d", integer); kara->filename[PATH_MAX - 1] = 0; - fprintf(stderr, " . __handle_got_json: Crafted filename is '%s'\n", kara->filename); + LOG_INFO("Crafted filename is '%s'", kara->filename); RETURN_UNLESS(kara, "Out of memory", NOTHING); @@ -99,7 +89,7 @@ __handle_got_json(struct lkt_thread *self, struct lkt_repo *repo, struct json_ob /* Append. */ if (lkt_th_append_output(self, kara)) { - fprintf(stderr, " . __handle_got_json: Could not append downloaded kara mdt\n"); + LOG_ERROR("%s", "Could not append downloaded kara mdt"); goto err; } @@ -110,23 +100,20 @@ err: } static void * -__repo_thread_function(struct lkt_thread_arg *arg) +__repo_thread_function(struct poller_thread_arg *arg) { size_t head; struct lkt_repo *repo = arg->args; - struct lkt_thread *self = arg->self; + struct poller_thread *self = arg->self; struct kara *kara; struct json_object *json = NULL; char path[PATH_MAX]; free(arg); - fprintf(stderr, " . __repo_thread_function: Starting the repo thread\n"); + LOG_INFO("%s", "Starting the repo thread"); for (;;) { - if (pthread_mutex_lock(&mtx)) { - fprintf(stderr, " ! __repo_thread_function: Failed to lock mutex\n"); - goto end_loop; - } + GOTO_IF(pthread_mutex_lock(&mtx), "Failed to lock mutex", end_loop); if (all_json) { repo_get_alljson_sync(repo, &json); @@ -136,7 +123,7 @@ __repo_thread_function(struct lkt_thread_arg *arg) if (stop) { if (pthread_mutex_unlock(&mtx)) - fprintf(stderr, " ! __repo_thread_function: Failed to unlock mutex\n"); + LOG_ERROR("Failed to unlock mutex: %s", strerror(errno)); break; } @@ -144,7 +131,7 @@ __repo_thread_function(struct lkt_thread_arg *arg) /* size_t has the size of a pointer (thus of a void *). */ if (lkt_th_pop_input(self, (void **) &head)) { - fprintf(stderr, " * __repo_thread_function: Failed to get the head of the input list\n"); + LOG_ERROR("%s", "Failed to get the head of the input list"); goto end_loop; /* Just skip all the loop to the yield function. */ } @@ -157,12 +144,12 @@ __repo_thread_function(struct lkt_thread_arg *arg) kara = calloc(1, sizeof(struct kara)); if (NULL == kara) { - fprintf(stderr, " ! __repo_thread_function: Out of memory\n"); + LOG_ERROR_SCT("MEMORY", "%s", "Out of memory"); goto end_loop; } if (repo_download_id_sync(repo, NULL, head, path, &kara->mdt)) { - fprintf(stderr, " ! __repo_thread_function: Failed to download kara with id %lu\n", head); + LOG_ERROR("Failed to download kara with id %lu", head); goto try_later; } @@ -172,13 +159,12 @@ __repo_thread_function(struct lkt_thread_arg *arg) memcpy(kara->filename, path, (strlen(path) + 1) * sizeof(char)); if (lkt_th_append_output(self, (void *) kara)) { - fprintf(stderr, " ! __repo_thread_function: Failed to append to output, orphan kara %lu\n", head); + LOG_ERROR("Failed to append to output, orphan kara %lu", head); free(kara); goto end_loop; } - fprintf(stderr, " . __repo_thread_function: Append kara %lu with path %s to out pool\n", - kara->id, kara->filename); + LOG_INFO("Append kara %lu with path %s to out pool", kara->id, kara->filename); kara = NULL; goto end_loop; @@ -189,13 +175,14 @@ try_later: /* Retry later. TODO: Implements a retry counter. */ if (lkt_th_append_input(self, (void *) head)) - fprintf(stderr, " * __repo_thread_function: Failed to get the head of the input list\n"); + LOG_ERROR("%s", "Failed to get the head of the input list"); end_loop: + sched_yield(); sleep(1); } - fprintf(stderr, " . __repo_thread_function: Stopping the repo thread\n"); + LOG_INFO("%s", "Stopping the repo thread"); return NULL; } @@ -203,7 +190,7 @@ int repo_new_thread(struct lkt_repo *const repo) { RETURN_IF(init, "Already running", 1); - struct lkt_thread_arg *arg = calloc(1, sizeof(struct lkt_thread_arg)); + struct poller_thread_arg *arg = calloc(1, sizeof(struct poller_thread_arg)); RETURN_UNLESS(arg, "Out of memory", errno = ENOMEM); arg->args = repo; RETURN_IF(lkt_th_new(&repo_thread, LKT_DEFAULT_LIST_SIZE, __repo_thread_function, arg), "Thread error", 1); @@ -216,7 +203,7 @@ repo_download_id_async(const size_t id) { RETURN_IF(id == 0, "Invalid argument", 1); RETURN_IF(lkt_th_append_input(&repo_thread, (void *) id), "Failed to push downloaded id", id); - fprintf(stderr, " * Asked to download kara with id %lu\n", id); + LOG_INFO("Asked to download kara with id %lu", id); return 0; } diff --git a/src/repo/curl.c b/src/repo/curl.c index d613a7238fcc3368f01ffb85f2e43bdcf928a0a8..03fb6e98d73fd5038a4ab92a53b470792be0ffde 100644 --- a/src/repo/curl.c +++ b/src/repo/curl.c @@ -66,7 +66,7 @@ repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_) uint64_t *calloc2 = calloc(init_size, sizeof(uint64_t)); if (!calloc2) { free(calloc1); - fprintf(stderr, " ! repo_new: Out of memory\n"); + LOG_ERROR_SCT("MEMORY", "%s", "Out of memory"); return ENOMEM; } @@ -143,8 +143,7 @@ repo_get_alljson_sync(struct lkt_repo *const repo, struct json_object **json) res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { - fprintf(stderr, " ! repo_get_alljson_sync: curl_easy_perform failed: %s\n", - curl_easy_strerror(res)); + LOG_ERROR_SCT("CURL", "curl_easy_perform failed: %s", curl_easy_strerror(res)); free(file.mem); goto err; } @@ -184,7 +183,7 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { - fprintf(stderr, " ! repo_get_id: curl_easy_perform failed: %s\n", curl_easy_strerror(res)); + LOG_ERROR_SCT("CURL", "curl_easy_perform failed: %s", curl_easy_strerror(res)); free(url); free(file.mem); curl_easy_cleanup(curl_handle); @@ -198,12 +197,11 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata jobj = json_tokener_parse(file.mem); if (json_object_object_get_ex(jobj, "message", &field)) { - fprintf(stderr, " * repo_get_id: Kara with id %lu not found, message is: %s\n", - id, json_object_get_string(field)); + LOG_ERROR("Kara with id %lu not found, message is: %s", id, json_object_get_string(field)); goto err; } - fprintf(stderr, " . repo_get_id: Got kara with id %lu\n", id); + LOG_INFO("Got kara with id %lu", id); err |= safe_json_get_string(jobj, "song_name", mdt->song_name, LEKTOR_TAG_MAX); err |= safe_json_get_string(jobj, "source_name", mdt->source_name, LEKTOR_TAG_MAX); @@ -215,19 +213,19 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata errno = 0; if (!json_object_object_get_ex(jobj, "song_number", &field)) { - fprintf(stderr, " * repo_get_id: No object with key 'song_number' in json, error\n"); + LOG_ERROR("%s", "No object with key 'song_number' in json, error"); goto err; } mdt->song_number = json_object_get_int(field); if (errno == EINVAL) { - fprintf(stderr, " * repo_get_id: Invalid integer for field with key 'song_number'\n"); + LOG_ERROR("%s", "Invalid integer for field with key 'song_number'"); goto err; } if (mdt->song_number == INT32_MAX || mdt->song_number == INT32_MIN) { - fprintf(stderr, " * repo_get_id: Out of bound integer for field with key 'song_number'\n"); + LOG_ERROR("Out of bound int32_t '%d' for field with key 'song_number'", mdt->song_number); goto err; } @@ -252,7 +250,7 @@ repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t i RETURN_UNLESS(url, "Out of memory", errno = ENOMEM); if (repo_get_id(repo, id, mdt_ret ? mdt_ret : &mdt)) { - fprintf(stderr, " ! repo_download_id_sync: Failed to get kara metadata from kurisu\n"); + LOG_ERROR("%s", "Failed to get kara metadata from kurisu"); goto err_no_curl; } @@ -263,10 +261,10 @@ repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t i if (fd < 0) { if (errno == EEXIST) - fprintf(stderr, " ! repo_download_id_sync: file '%s' already exists\n", kara_path); + LOG_ERROR("File '%s' already exists", kara_path); else - fprintf(stderr, " ! repo_download_id_sync: could not open file '%s'\n", kara_path); + LOG_ERROR("Could not open file '%s'", kara_path); goto err_no_curl; } @@ -289,26 +287,24 @@ repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t i ret = curl_easy_perform(curl_handle); if (ret != CURLE_OK) { - fprintf(stderr, " ! repo_download_id_sync: curl_easy_perform failed: %s\n", - curl_easy_strerror(ret)); + LOG_ERROR_SCT("CURL", "curl_easy_perform failed: %s", curl_easy_strerror(ret)); goto err; } if (CURLE_OK == ( ret = curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_TYPE, &ct))) - fprintf(stderr, " . repo_download_id_sync: Content-Type is '%s'\n", ct); + LOG_INFO_SCT("CURL", "Content-Type is '%s'", ct); else { - fprintf(stderr, " ! repo_download_id_sync: failed to get Content-Type: %s\n", - curl_easy_strerror(ret)); + LOG_ERROR_SCT("CURL", "Failed to get Content-Type: %s", curl_easy_strerror(ret)); goto err; } if (!db) { - fprintf(stderr, " . repo_download_id_sync: Skip database update here\n"); + LOG_INFO("%s", "Skip database update here"); goto no_db_update; } if (! database_update_add(db, kara_path, mdt_ret ? mdt_ret : &mdt, id, true)) { - fprintf(stderr, " ! repo_download_id_sync: Failed to add kara to database\n"); + LOG_ERROR("%s", "Failed to add kara to database"); goto err; } diff --git a/src/thread.c b/src/thread.c index 7d7b1a4666375d762fc01a79dc87f5c49138b905..4969c93320d752211f0c7482bbf487dced727a33 100644 --- a/src/thread.c +++ b/src/thread.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/thread.h> #include <pthread.h> #include <sys/types.h> @@ -10,28 +11,27 @@ #include <string.h> struct __args { - void *(*start)(struct lkt_thread_arg *); - struct lkt_thread_arg *arg; + void *(*start)(struct poller_thread_arg *); + struct poller_thread_arg *arg; }; static void * __start(void *args__) { struct __args *args = (struct __args *) args__; - void *(*start)(struct lkt_thread_arg *) = args->start; - struct lkt_thread_arg *arg = args->arg; + void *(*start)(struct poller_thread_arg *) = args->start; + struct poller_thread_arg *arg = args->arg; free(args__); return start(arg); } int -lkt_th_new(struct lkt_thread *th, unsigned int init_sizes, - void *(*func)(struct lkt_thread_arg *), void *args) +lkt_th_new(struct poller_thread *th, unsigned int init_sizes, + void *(*func)(struct poller_thread_arg *), void *args) { - int ret = 1; pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER; - struct lkt_thread th_ = { + struct poller_thread th_ = { .initial_size = init_sizes, .input_lock = mtx1, .output_lock = mtx2, @@ -52,34 +52,33 @@ lkt_th_new(struct lkt_thread *th, unsigned int init_sizes, __args->arg = args; __args->arg->self = th; - ret = pthread_create(&(th->th), NULL, __start, __args); - - if (ret) - goto end; + if (!pthread_create(&(th->th), NULL, __start, __args)) { + LOG_INFO_SCT("THREAD", "%s", "Create a new poller thread"); + return 0; + } -end: - fprintf(stderr, " %c lkt_th_new: %s\n", - ret ? '!' : '*', - ret ? "Failed to create a new thread" : "Created a new thread"); - return ret; + else { +error: + LOG_ERROR_SCT("THREAD", "%s", "Failed to create a poller thread"); + return 1; + } out_of_memory: - fprintf(stderr, " * lkt_th_new: Out of memory\n"); + LOG_ERROR_SCT("MEMORY", "%s", "Out of memory"); if (th_.input_cells) free((void *) th_.input_cells); if (th_.output_cells) free((void *) th_.output_cells); - ret = errno = ENOMEM; - goto end; + goto error; } int -lkt_th_join(struct lkt_thread *th, void **ret) +lkt_th_join(struct poller_thread *th, void **ret) { int sta = pthread_join(th->th, ret); if (sta) - fprintf(stderr, " ! lkt_th_join: Failed to join thread\n"); + LOG_ERROR("%s", "Failed to join thread"); if (th->input_cells) free((void *) th->input_cells); @@ -87,9 +86,9 @@ lkt_th_join(struct lkt_thread *th, void **ret) free((void *) th->output_cells); if (!sta) - fprintf(stderr, " * lkt_th_join: Thread joined\n"); + LOG_ERROR("%s", "Thread joined"); - memset(th, 0, sizeof(struct lkt_thread)); + memset(th, 0, sizeof(struct poller_thread)); return sta; } @@ -100,16 +99,13 @@ th_append(unsigned int *len, unsigned int *size, void ***cells, void *new; int ret = 0; - if (pthread_mutex_lock(lock)) { - fprintf(stderr, " ! th_append: Failed to lock\n"); - goto end; - } + GOTO_IF(pthread_mutex_lock(lock), "Failed to lock", end); if (*len == *size) { new = realloc((void *) *cells, (*len + *size) * sizeof(void *)); if (new == NULL) { - fprintf(stderr, " ! th_append: Out of memory\n"); + LOG_ERROR_SCT("MEMORY", "%s", "Out of memory"); ret = (errno = ENOMEM); goto end; } @@ -121,11 +117,7 @@ th_append(unsigned int *len, unsigned int *size, void ***cells, (*cells)[(*len)++] = ptr; ret = 0; end: - if (pthread_mutex_unlock(lock)) { - fprintf(stderr, " ! th_append: Failed to lock\n"); - ret = 1; - } - + RETURN_IF(pthread_mutex_unlock(lock), "Failed to lock", 1); return ret; } @@ -134,10 +126,7 @@ th_pop(unsigned int *len, void **cells, pthread_mutex_t *lock, void **ptr) { int ret = 1; - if (pthread_mutex_lock(lock)) { - fprintf(stderr, " ! th_pop: Failed to lock\n"); - goto end; - } + GOTO_IF(pthread_mutex_lock(lock), "Failed to lock", end); if (*len > 0) *ptr = cells[--(*len)]; @@ -146,12 +135,7 @@ th_pop(unsigned int *len, void **cells, pthread_mutex_t *lock, void **ptr) ret = 0; end: - - if (pthread_mutex_unlock(lock)) { - fprintf(stderr, " ! th_pop: Failed to lock\n"); - ret = 1; - } - + RETURN_IF(pthread_mutex_unlock(lock), "Failed to lock", 1); return ret; } @@ -159,11 +143,7 @@ static inline int th_head(unsigned int len, void **cells, pthread_mutex_t *lock, void **ptr) { int ret = 1; - - if (pthread_mutex_lock(lock)) { - fprintf(stderr, " ! th_pop: Failed to lock\n"); - goto end; - } + GOTO_IF(pthread_mutex_lock(lock), "Failed to lock", end); if (len > 0) *ptr = cells[len - 1]; @@ -172,31 +152,26 @@ th_head(unsigned int len, void **cells, pthread_mutex_t *lock, void **ptr) ret = 0; end: - - if (pthread_mutex_unlock(lock)) { - fprintf(stderr, " ! th_pop: Failed to lock\n"); - ret = 1; - } - + RETURN_IF(pthread_mutex_unlock(lock), "Failed to lock", 1); return ret; } int -lkt_th_append_input(struct lkt_thread *th, void *ptr) +lkt_th_append_input(struct poller_thread *th, void *ptr) { return th_append((unsigned int *) &th->input_len, (unsigned int *) &th->input_size, (void ***) &th->input_cells, &th->input_lock, ptr); } int -lkt_th_append_output(struct lkt_thread *th, void *ptr) +lkt_th_append_output(struct poller_thread *th, void *ptr) { return th_append((unsigned int *) &th->output_len, (unsigned int *) &th->output_size, (void ***) &th->output_cells, &th->output_lock, ptr); } int -lkt_th_pop_input(struct lkt_thread *th, void **ptr) +lkt_th_pop_input(struct poller_thread *th, void **ptr) { return th_pop((unsigned int *) &th->input_len, (void **) th->input_cells, &th->input_lock, ptr); @@ -204,20 +179,20 @@ lkt_th_pop_input(struct lkt_thread *th, void **ptr) int -lkt_th_pop_output(struct lkt_thread *th, void **ptr) +lkt_th_pop_output(struct poller_thread *th, void **ptr) { return th_pop((unsigned int *) &th->output_len, (void **) th->output_cells, &th->output_lock, ptr); } int -lkt_th_head_input(struct lkt_thread *th, void **ptr) +lkt_th_head_input(struct poller_thread *th, void **ptr) { return th_head((unsigned int) th->input_len, (void **) th->input_cells, &th->input_lock, ptr); } int -lkt_th_head_output(struct lkt_thread *th, void **ptr) +lkt_th_head_output(struct poller_thread *th, void **ptr) { return th_head((unsigned int) th->output_len, (void **) th->output_cells, &th->output_lock, ptr); }