From 2eaf50d19b36f7b00449473d530e5c08d3eb01c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 28 May 2013 00:10:02 +0200 Subject: [PATCH 1/9] Add note about O(n) of uc_timers_count() --- include/ucore/timers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/ucore/timers.h b/include/ucore/timers.h index 8a94131..7182962 100644 --- a/include/ucore/timers.h +++ b/include/ucore/timers.h @@ -113,6 +113,7 @@ void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer); int uc_timers_first(const struct UCTimers *timers, struct timeval *first); /** Get the number of timers the engine is tracking. + * (This function is O(n) ) * * @param timers timer engine to query * @return the number of timers the engine keeps From ecc9218e7cf5312aaec0ce5157b99c684ada9fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 28 May 2013 00:26:12 +0200 Subject: [PATCH 2/9] Add tests for UCTimers --- test/test_runner.c | 4 +- test/test_timers.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 test/test_timers.c diff --git a/test/test_runner.c b/test/test_runner.c index 7799fc2..d85129a 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -18,6 +18,7 @@ extern Suite *buffer_suite(void); extern Suite *clock_suite(void); extern Suite *seq_suite(void); extern Suite *sat_math_suite(void); +extern Suite *timers_suite(void); static suite_func suites[] = { bitvec_suite, @@ -31,7 +32,8 @@ static suite_func suites[] = { buffer_suite, clock_suite, seq_suite, - sat_math_suite + sat_math_suite, + timers_suite }; int diff --git a/test/test_timers.c b/test/test_timers.c new file mode 100644 index 0000000..5ac4b2c --- /dev/null +++ b/test/test_timers.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include + +struct TimerTest { + int cnt; +}; +#define TEST_TIMER_START 1000000 +static void timer_test_cb(struct UCTimers *timers, struct UCTimer *timer) +{ + struct TimerTest *tt = timer->cookie_ptr; + (void)timers; //get rid of unused param warning + tt->cnt++; +} + +static void timer_test_cb_add(struct UCTimers *timers, struct UCTimer *timer) +{ + struct TimerTest *tt = timer->cookie_ptr; + tt->cnt++; + uc_timer_add(timers, timer, 10, 0); +} + +static void timer_test_cb_remove(struct UCTimers *timers, struct UCTimer *timer) +{ + struct UCTimer *timer2 = timer->cookie_ptr; + uc_timer_remove(timers, timer2); +} + +static void common_init(struct UCoreSettableClock *clk, + struct TimerTest *tt, + struct UCTimers *timers, + struct UCTimer *timer) +{ + uc_settable_clock_init(clk); + uc_settable_clock_set(clk, TEST_TIMER_START, 0); + uc_timers_init_ex(timers, &clk->clock); + + + tt->cnt = 0; + memset(timer, 0, sizeof *timer); + timer->cookie_ptr = tt; +} + +START_TEST (test_timers_simple) + struct UCoreSettableClock clk; + struct TimerTest tt; + struct UCTimers timers; + struct UCTimer timer; + int t = TEST_TIMER_START; + int rc; + + common_init(&clk, &tt, &timers, &timer); + + timer.callback = timer_test_cb; + + uc_timer_add(&timers, &timer, 10, 0); + + //5 seconds into the future, no timer should fire + t += 5; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 0); + fail_if(tt.cnt != 0); + fail_if(uc_timer_count(&timers) != 1); + + //10 seconds into the future, our timer should fire + t += 5; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 1); + fail_if(tt.cnt != 1); + + //20 seconds into the future, our oneshot timer shouldn't fire + t += 10; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 0); + fail_if(tt.cnt != 1); + fail_if(uc_timer_count(&timers) != 0); + fail_if(uc_timer_running(&timer) != 0); + +END_TEST + +START_TEST (test_timers_add_from_callback) + struct UCoreSettableClock clk; + struct TimerTest tt; + struct UCTimers timers; + struct UCTimer timer; + int t = TEST_TIMER_START; + int rc; + + common_init(&clk, &tt, &timers, &timer); + + timer.callback = timer_test_cb_add; + + uc_timer_add(&timers, &timer, 10, 0); + + //10 seconds into the future, our timer should fire + t += 10; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 1); + fail_if(tt.cnt != 1); + + + //20 seconds into the future, our timer should fire again + t += 10; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 1); + fail_if(tt.cnt != 2); + + fail_if(uc_timer_running(&timer) == 0); + fail_if(uc_timer_count(&timers) != 1); + +END_TEST + +START_TEST (test_timers_remove_from_callback) + struct UCoreSettableClock clk; + struct TimerTest tt; + struct UCTimers timers; + struct UCTimer timer; + struct UCTimer timer2; + int t = TEST_TIMER_START; + int rc; + struct timeval tv = {0, 0}; + + common_init(&clk, &tt, &timers, &timer); + + timer.callback = timer_test_cb_remove; + timer.cookie_ptr = &timer2; + memset(&timer2, 0, sizeof timer2); + timer2.callback = timer_test_cb; + + uc_timer_add(&timers, &timer, 5, 0); + uc_timer_add(&timers, &timer2, 10, 0); + + fail_if(uc_timer_count(&timers) != 2); + rc = uc_timers_first(&timers, &tv); + fail_if(rc != 0); + fail_if(tv.tv_sec != TEST_TIMER_START + 5); + fail_if(uc_timer_running(&timer) == 0); + fail_if(uc_timer_running(&timer2) == 0); + + //5 seconds into the future, our timer should fire + t += 5; + uc_settable_clock_set(&clk, t, 0); + rc = uc_timers_run(&timers); + fail_if(rc != 1); + fail_if(tt.cnt != 0); + //and our timer2 should be removed, and timer has fired so it + //should be removed too + + fail_if(uc_timer_count(&timers) != 0); + fail_if(uc_timer_running(&timer) != 0); + fail_if(uc_timer_running(&timer2) != 0); + rc = uc_timers_first(&timers, &tv); + fail_if(rc == 0); + +END_TEST + + +Suite *timers_suite(void) +{ + Suite *s = suite_create("timers"); + TCase *tc = tcase_create("timers tests"); + tcase_add_test(tc, test_timers_simple); + tcase_add_test(tc, test_timers_add_from_callback); + tcase_add_test(tc, test_timers_remove_from_callback); + + suite_add_tcase(s, tc); + + return s; +} + From 1e34c1126598986c6868e471c66ab1ecce0383ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 28 May 2013 01:05:38 +0200 Subject: [PATCH 3/9] Name uc_timers_XXX consistently --- include/ucore/timers.h | 10 +++++----- src/timers.c | 18 +++++++++--------- test/iomux_test3.c | 6 +++--- test/test_timers.c | 22 +++++++++++----------- test/timers.c | 12 ++++++------ test/udp_heartbeat.c | 4 ++-- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/ucore/timers.h b/include/ucore/timers.h index 7182962..19c9744 100644 --- a/include/ucore/timers.h +++ b/include/ucore/timers.h @@ -92,17 +92,17 @@ void uc_timers_init_ex(struct UCTimers *t, struct UCoreClock *uclock); * @param sec seconds from now until the timer filres * @param usec microseconds (after the @sec) until the timer fires. */ -void uc_timer_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int usec); +void uc_timers_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int usec); /** Remove a timer. * Note, the timer memory must have been zeroed out or the timer must have been added at least once - * before uc_timer_remove can be called on a UCTimer. - * uc_timer_remove does nothing if the timer has expired. + * before uc_timers_remove can be called on a UCTimer. + * uc_timers_remove does nothing if the timer has expired. * * @param timers timer engine to remove from * @param timer timer to remove */ -void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer); +void uc_timers_remove(struct UCTimers *timers, struct UCTimer *timer); /** Get time of the first timer that will run. * @@ -118,7 +118,7 @@ int uc_timers_first(const struct UCTimers *timers, struct timeval *first); * @param timers timer engine to query * @return the number of timers the engine keeps */ -size_t uc_timer_count(const struct UCTimers *timers); +size_t uc_timers_count(const struct UCTimers *timers); /** Check if a timer is running (i.e. hasn't expired and fired) * diff --git a/src/timers.c b/src/timers.c index 3dd3bb7..0aca525 100644 --- a/src/timers.c +++ b/src/timers.c @@ -26,9 +26,9 @@ static int timers_cmp(const void *a_, const void *b_) return 0; //silence compiler } -static void uc_timer_real_add(struct UCTimers *timers, struct UCTimer *timer) +static void uc_timers_real_add(struct UCTimers *timers, struct UCTimer *timer) { - uc_timer_remove(timers, timer); //re schedule it if it's already running + uc_timers_remove(timers, timer); //re schedule it if it's already running timer->state = UC_TIMER_ACTIVE; timer->seq = timers->seq++; timer->rb_node.data = timer; //point the data in a RBNode back to the timer that contains it. @@ -49,7 +49,7 @@ void uc_timers_init_ex(struct UCTimers *t, struct UCoreClock *uclock) TAILQ_INIT(&t->ready_list); } -void uc_timer_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int usec) +void uc_timers_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int usec) { struct timeval now; struct timeval tmp; @@ -63,10 +63,10 @@ void uc_timer_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int u timers->uclock->now(timers->uclock, &now); timeradd(&now, &tmp, &timer->timeout); - uc_timer_real_add(timers, timer); + uc_timers_real_add(timers, timer); } -void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer) +void uc_timers_remove(struct UCTimers *timers, struct UCTimer *timer) { if (timer->state == UC_TIMER_INACTIVE) { //already removed , or never added. //debugging bandaid @@ -97,7 +97,7 @@ int uc_timers_first(const struct UCTimers *timers, struct timeval *first) return 1; } -size_t uc_timer_count(const struct UCTimers *timers) +size_t uc_timers_count(const struct UCTimers *timers) { struct RBNode *n; size_t count = 0; @@ -134,7 +134,7 @@ int uc_timers_run(struct UCTimers *timers) //Note, timercmp does not work for >= if (!timercmp(&now, &t->timeout, <)) { TAILQ_INSERT_TAIL(&timers->ready_list, t, ready_entry); - t->state = UC_TIMER_PENDING; //so uc_timer_remove knows + t->state = UC_TIMER_PENDING; //so uc_timers_remove knows //it have to remove it from the ready_list } else { break; @@ -147,12 +147,12 @@ int uc_timers_run(struct UCTimers *timers) * Need to always pick the first item in the tail queue * since a timer callback could remove/free a timer * we had in the list. - * uc_timer_remove will unlink the timer from this list. + * uc_timers_remove will unlink the timer from this list. */ while (!TAILQ_EMPTY(&timers->ready_list)) { struct UCTimer *t = TAILQ_FIRST(&timers->ready_list); - uc_timer_remove(timers, t); + uc_timers_remove(timers, t); assert(t->callback != NULL); t->callback(timers, t); //fire // callback might have free'd its timer. diff --git a/test/iomux_test3.c b/test/iomux_test3.c index c81b2e2..3008480 100644 --- a/test/iomux_test3.c +++ b/test/iomux_test3.c @@ -100,11 +100,11 @@ void timer_cb(struct UCTimers *timers, struct UCTimer *timer) struct UCTimer *t = calloc(1, sizeof *t); t->callback = timer_cb; t->cookie_int = timer->cookie_int + 1; - uc_timer_add(timers, t, 5,5); + uc_timers_add(timers, t, 5,5); t = calloc(1, sizeof *t); t->callback = timer_cb; t->cookie_int = timer->cookie_int + 2; - uc_timer_add(timers, t, 5,4); + uc_timers_add(timers, t, 5,4); } @@ -131,7 +131,7 @@ int main(int argc, char *argv[]) struct IOMux *mux = iomux_create(IOMUX_TYPE_EPOLL); iomux_register_fd(mux, ©_ctx.in); - uc_timer_add(iomux_get_timers(mux), &timer, 5, 0); + uc_timers_add(iomux_get_timers(mux), &timer, 5, 0); iomux_run(mux); diff --git a/test/test_timers.c b/test/test_timers.c index 5ac4b2c..a563cd4 100644 --- a/test/test_timers.c +++ b/test/test_timers.c @@ -18,13 +18,13 @@ static void timer_test_cb_add(struct UCTimers *timers, struct UCTimer *timer) { struct TimerTest *tt = timer->cookie_ptr; tt->cnt++; - uc_timer_add(timers, timer, 10, 0); + uc_timers_add(timers, timer, 10, 0); } static void timer_test_cb_remove(struct UCTimers *timers, struct UCTimer *timer) { struct UCTimer *timer2 = timer->cookie_ptr; - uc_timer_remove(timers, timer2); + uc_timers_remove(timers, timer2); } static void common_init(struct UCoreSettableClock *clk, @@ -54,7 +54,7 @@ START_TEST (test_timers_simple) timer.callback = timer_test_cb; - uc_timer_add(&timers, &timer, 10, 0); + uc_timers_add(&timers, &timer, 10, 0); //5 seconds into the future, no timer should fire t += 5; @@ -62,7 +62,7 @@ START_TEST (test_timers_simple) rc = uc_timers_run(&timers); fail_if(rc != 0); fail_if(tt.cnt != 0); - fail_if(uc_timer_count(&timers) != 1); + fail_if(uc_timers_count(&timers) != 1); //10 seconds into the future, our timer should fire t += 5; @@ -77,7 +77,7 @@ START_TEST (test_timers_simple) rc = uc_timers_run(&timers); fail_if(rc != 0); fail_if(tt.cnt != 1); - fail_if(uc_timer_count(&timers) != 0); + fail_if(uc_timers_count(&timers) != 0); fail_if(uc_timer_running(&timer) != 0); END_TEST @@ -94,7 +94,7 @@ START_TEST (test_timers_add_from_callback) timer.callback = timer_test_cb_add; - uc_timer_add(&timers, &timer, 10, 0); + uc_timers_add(&timers, &timer, 10, 0); //10 seconds into the future, our timer should fire t += 10; @@ -112,7 +112,7 @@ START_TEST (test_timers_add_from_callback) fail_if(tt.cnt != 2); fail_if(uc_timer_running(&timer) == 0); - fail_if(uc_timer_count(&timers) != 1); + fail_if(uc_timers_count(&timers) != 1); END_TEST @@ -133,10 +133,10 @@ START_TEST (test_timers_remove_from_callback) memset(&timer2, 0, sizeof timer2); timer2.callback = timer_test_cb; - uc_timer_add(&timers, &timer, 5, 0); - uc_timer_add(&timers, &timer2, 10, 0); + uc_timers_add(&timers, &timer, 5, 0); + uc_timers_add(&timers, &timer2, 10, 0); - fail_if(uc_timer_count(&timers) != 2); + fail_if(uc_timers_count(&timers) != 2); rc = uc_timers_first(&timers, &tv); fail_if(rc != 0); fail_if(tv.tv_sec != TEST_TIMER_START + 5); @@ -152,7 +152,7 @@ START_TEST (test_timers_remove_from_callback) //and our timer2 should be removed, and timer has fired so it //should be removed too - fail_if(uc_timer_count(&timers) != 0); + fail_if(uc_timers_count(&timers) != 0); fail_if(uc_timer_running(&timer) != 0); fail_if(uc_timer_running(&timer2) != 0); rc = uc_timers_first(&timers, &tv); diff --git a/test/timers.c b/test/timers.c index fe37df4..a708b77 100644 --- a/test/timers.c +++ b/test/timers.c @@ -25,7 +25,7 @@ void mystruct1_cb(struct UCTimers *timers, struct UCTimer *timer) struct MyStruct *mystruct = CONTAINER_OF(timer, struct MyStruct, timer); TRACEF("MyStruct1 timer: %s\n", mystruct->str); - uc_timer_add(timers, timer, 1, 0); + uc_timers_add(timers, timer, 1, 0); } void mystruct2_cb(struct UCTimers *timers, struct UCTimer *timer) @@ -33,7 +33,7 @@ void mystruct2_cb(struct UCTimers *timers, struct UCTimer *timer) struct MyStruct *mystruct = timer->cookie_ptr; TRACEF("MyStruct2 timer: %s\n", mystruct->str); - uc_timer_add(timers, timer, 5, 0); + uc_timers_add(timers, timer, 5, 0); } int main(int argc, char *argv[]) @@ -63,10 +63,10 @@ int main(int argc, char *argv[]) }; uc_timers_init(&timers); - uc_timer_add(&timers, &t1, 2, 0); - uc_timer_add(&timers, &t2, 5, 0); - uc_timer_add(&timers, &my_struct1.timer, 10, 0); - uc_timer_add(&timers, &my_struct2.timer, 10, 0); + uc_timers_add(&timers, &t1, 2, 0); + uc_timers_add(&timers, &t2, 5, 0); + uc_timers_add(&timers, &my_struct1.timer, 10, 0); + uc_timers_add(&timers, &my_struct2.timer, 10, 0); for(;;) { uc_timers_run(&timers); diff --git a/test/udp_heartbeat.c b/test/udp_heartbeat.c index 32604f0..18fa205 100644 --- a/test/udp_heartbeat.c +++ b/test/udp_heartbeat.c @@ -74,7 +74,7 @@ void peer_timer_cb(struct UCTimers *timers, struct UCTimer *timer) struct HBContext *ctx = timer->cookie_ptr; time_t now; - uc_timer_add(timers, timer, PEER_HB_MISS , 0); + uc_timers_add(timers, timer, PEER_HB_MISS , 0); now = time(NULL); if (now - peer->last_ok > PEER_HB_MISS * PEER_HB_SEC) { @@ -106,7 +106,7 @@ void peer_add_addr(struct HBContext *ctx, const struct sockaddr_in *addr) sec = rand() % PEER_HB_SEC; usec = rand() % 1000000; - uc_timer_add(iomux_get_timers(ctx->mux), &peer->timer, sec, usec); + uc_timers_add(iomux_get_timers(ctx->mux), &peer->timer, sec, usec); } void peer_add(struct HBContext *ctx, const char *host, uint16_t port) From cfc7cae5c04f9373ab5fc12b6b71d05d92628ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 29 May 2013 22:03:26 +0200 Subject: [PATCH 4/9] Remove erronous UNUSED attribuute --- src/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clock.c b/src/clock.c index 4d52dfb..3e3e309 100644 --- a/src/clock.c +++ b/src/clock.c @@ -28,7 +28,7 @@ struct UCoreClock uc_time_clock = { .now = uc_time_now, }; -static void uc_cached_clock_now(struct UCoreClock *uclock UNUSED, +static void uc_cached_clock_now(struct UCoreClock *uclock, struct timeval *tv) { struct UCoreCachedClock *cached_clock; From 5a427007d658bb5185c3b48169585a55de656e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 30 May 2013 22:38:56 +0200 Subject: [PATCH 5/9] Add fd_utils --- include/ucore/fd_utils.h | 63 +++++++++++++++++++++++++++++++++++++ src/fd_utils.c | 68 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 include/ucore/fd_utils.h create mode 100644 src/fd_utils.c diff --git a/include/ucore/fd_utils.h b/include/ucore/fd_utils.h new file mode 100644 index 0000000..c2145bc --- /dev/null +++ b/include/ucore/fd_utils.h @@ -0,0 +1,63 @@ +#ifndef FD_UTILS_H_ +#define FD_UTILS_H_ +#ifdef __cplusplus +extern "C" { +#endif +// inspect errno if any of these fails + +/** +* set the file descriptor to non-blocking +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_nonblocking(int fd); + +/** +* set the file descriptor to blocking +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_blocking(int fd); + +/** +* set the socket file descriptor to SO_REUSEADDR +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_reuseaddr(int sockfd); + +/** +* enable TCP keepalive on the socket +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_tcp_keepalive(int sockfd); + +/** +* Set the socket send timeout, in miliseconds +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_send_timeout(int sockfd,long timeoutms); + +/** +* Set the socket receive timeout, in miliseconds +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_receive_timeout(int sockfd,long timeoutms); + +/* +* Set the IP DSCP (differnetiated services code point) header value +* The dscp must be < 64 +* @param fd file descriptor +* @return 0 on success -1 on failure +*/ +int set_ip_dscp(int fd, unsigned int dscp); + + +#ifdef __cplusplus +}; +#endif +#endif /* FD_UTILS_H_ */ + diff --git a/src/fd_utils.c b/src/fd_utils.c new file mode 100644 index 0000000..9e7d539 --- /dev/null +++ b/src/fd_utils.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include "ucore/fd_utils.h" + +int set_nonblocking(int fd) +{ + int flags = fcntl(fd,F_GETFL,NULL); + if(flags < 0 ) { + return flags; + } + return fcntl(fd,F_SETFL,flags | O_NONBLOCK); +} + +int set_blocking(int fd) +{ + int flags = fcntl(fd,F_GETFL,NULL); + if(flags < 0 ) { + return flags; + } + + return fcntl(fd,F_SETFL,flags&~O_NONBLOCK); +} + +int set_reuseaddr(int sockfd) +{ + int opt = 1; + return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); + +} + +int set_tcp_keepalive(int sockfd) +{ + int optval = 1; + return setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); +} + + +int set_send_timeout(int sockfd,long timeoutms) +{ + struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000}; + + return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &so_sndtimeo, sizeof(so_sndtimeo)); +} + +int set_receive_timeout(int sockfd,long timeoutms) +{ + struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000}; + + return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &so_sndtimeo, sizeof(so_sndtimeo)); +} +int +set_ip_dscp(int fd, unsigned int dscp) { + int val; + + if (dscp > 63) { + errno = EINVAL; + return -1; + } + + val = dscp << 2; + return setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val); +} + + From af8cab5034fcc518d3b10677116c77f42877dbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 31 May 2013 03:40:33 +0200 Subject: [PATCH 6/9] Prepare for having per destination module log levels --- src/logging.c | 103 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/src/logging.c b/src/logging.c index 2ace73e..d6de280 100644 --- a/src/logging.c +++ b/src/logging.c @@ -9,6 +9,11 @@ #include "ucore/logging.h" +//used to realise per destination settings +struct uc_log_module_setting { + int log_level; +}; + struct uc_log_destination { SLIST_ENTRY(uc_log_destination) entry; enum UC_LOG_DESTINATION dest_type; @@ -16,6 +21,7 @@ struct uc_log_destination { int log_level; //Whether to log the source file name and line number int log_location; + struct uc_log_module_setting *module_settings; union { //for syslog openlog() struct { @@ -95,6 +101,22 @@ static inline int uc_ll_2_syslog(enum UC_LOG_LEVEL l) return LOG_INFO; } +static int uc_log_init_settings(struct uc_log_destination *dest) +{ + int i; + + dest->module_settings = calloc(g_modules.cnt, sizeof *dest->module_settings); + if (dest->module_settings == NULL) { + return -1; + } + + for (i = 0; i < g_modules.cnt; i++) { + dest->module_settings[i].log_level = g_modules.mods[i].log_level; + } + + return 0; +} + struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location) { struct uc_log_destination *dest = calloc(1, sizeof *dest); @@ -102,6 +124,11 @@ struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location) if(dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + dest->dest_type = UC_LDEST_STDERR; dest->type.file.file = stderr; dest->log_level = log_level;; @@ -118,9 +145,15 @@ struct uc_log_destination *uc_log_new_syslog(const char *ident, int facility, in if (dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + //copy the ident - though it's unused inside the struct for now id = strdup(ident); if (id == NULL) { + free(dest->module_settings); free(dest); return NULL; } @@ -145,14 +178,21 @@ struct uc_log_destination *uc_log_new_file(const char *filename, int log_level, if (dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + name = strdup(filename); if (name == NULL) { + free(dest->module_settings); free(dest); return NULL; } f = fopen(filename, "a"); if (f == NULL) { + free(dest->module_settings); free(name); free(dest); return NULL; @@ -245,6 +285,7 @@ void uc_log_delete_destination(struct uc_log_destination *dest) free(dest->type.file.file_name); break; } + free(dest->module_settings); free(dest); @@ -412,43 +453,51 @@ void uc_logf(int log_level, int module, int raw, else log_module = &g_unknown_module; - //Check if the module should not be logged - if (log_level < log_module->log_level) - goto out; - //do logging for each destination SLIST_FOREACH(dest, &g_destinations, entry) { va_list apc; + int module_log_level; - if (log_level >= dest->log_level) { - const struct uc_log_args args = { - .dest = dest, - .module = log_module, - .log_level = log_level, - .file = file, - .line = line, - .raw = raw - }; - //log func will mess with the va_list, - //so make a copy - va_copy(apc, ap); + //destnation level + if (log_level < dest->log_level) + continue; - switch (dest->dest_type) { - case UC_LDEST_SYSLOG: - uc_vlog_syslog(&args, fmt, apc); - break; - case UC_LDEST_STDERR: - case UC_LDEST_FILE: - uc_vlog_file(&args, fmt, apc); - break; - } + //individual module level + if (module >= 0 && module < g_modules.cnt) + module_log_level = dest->module_settings[module].log_level; + else //application bug. use global/unknown module + module_log_level = log_module->log_level; - va_end(apc); + if (log_level < module_log_level) + continue; + + const struct uc_log_args args = { + .dest = dest, + .module = log_module, + .log_level = log_level, + .file = file, + .line = line, + .raw = raw + }; + + //log func will mess with the va_list, + //so make a copy + va_copy(apc, ap); + + switch (dest->dest_type) { + case UC_LDEST_SYSLOG: + uc_vlog_syslog(&args, fmt, apc); + break; + case UC_LDEST_STDERR: + case UC_LDEST_FILE: + uc_vlog_file(&args, fmt, apc); + break; } + + va_end(apc); } -out: pthread_mutex_unlock(&g_log_lock); va_end(ap); } From 1b43ef029957d88fc7f36e28a175dea8a1d9cc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 31 May 2013 03:45:28 +0200 Subject: [PATCH 7/9] Fix test/logging.c --- test/logging.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/logging.c b/test/logging.c index 45d36f2..8305ace 100644 --- a/test/logging.c +++ b/test/logging.c @@ -35,8 +35,9 @@ struct uc_log_modules modules = { int main(int argc, char *argv[]) { - struct uc_log_destination *dest = uc_log_new_stderr(UC_LL_INFO, 0); + struct uc_log_destination *dest; uc_log_init(&modules); + dest = uc_log_new_stderr(UC_LL_INFO, 0); uc_log_add_destination(dest); dest = uc_log_new_file("test.log", UC_LL_INFO, 1); uc_log_add_destination(dest); @@ -55,6 +56,8 @@ int main(int argc, char *argv[]) uc_log_module_set_loglevel(MAIN, UC_LL_WARNING); UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 3\n" ); + uc_log_delete_destination(dest); + return 1; } From 10e717fc7dcb43e75c845e8fd15c266bbaf35425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 31 May 2013 03:49:54 +0200 Subject: [PATCH 8/9] Preserve errno if opening log file fails --- src/logging.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/logging.c b/src/logging.c index d6de280..3970b56 100644 --- a/src/logging.c +++ b/src/logging.c @@ -192,9 +192,11 @@ struct uc_log_destination *uc_log_new_file(const char *filename, int log_level, f = fopen(filename, "a"); if (f == NULL) { + int saved_errno = errno; free(dest->module_settings); free(name); free(dest); + errno = saved_errno; return NULL; } From 032e50e1cda4b299cde391c83e7eeb440d7db3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 1 Jun 2013 23:45:14 +0200 Subject: [PATCH 9/9] Remove setting log level for a module, implement setting log level for a destination --- include/ucore/logging.h | 15 +++++++-------- src/logging.c | 28 +++++++++------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/include/ucore/logging.h b/include/ucore/logging.h index 81d41d3..d523dce 100644 --- a/include/ucore/logging.h +++ b/include/ucore/logging.h @@ -175,6 +175,13 @@ void uc_log_add_destination(struct uc_log_destination *dest); */ void uc_log_remove_destination(struct uc_log_destination *dest); +/** Change the log level of a destination.. + * + * @param dest destination for which to set the log level + * @param level The new log level + */ +void uc_log_destination_set_loglevel(struct uc_log_destination *dest, enum UC_LOG_LEVEL level); + /** Remove and free a destination. * This frees the memory allocated to the destination. For * UC_LDEST_FILE the log file is closed. @@ -187,14 +194,6 @@ void uc_log_remove_destination(struct uc_log_destination *dest); */ void uc_log_delete_destination(struct uc_log_destination *dest); -/** Change the log level of a module. - * - * @param module The module to change, matched against the id member of a struct uc_log_module - * @param level The log level for this module - * - * @return 0 on success, non-zero if the module was not found. - */ -int uc_log_module_set_loglevel(int module, enum UC_LOG_LEVEL level); /** Closes and re-opens all the UC_LDEST_FILE log destinations. * Intended for use when a log file is rotated externally. diff --git a/src/logging.c b/src/logging.c index 3970b56..9e64fce 100644 --- a/src/logging.c +++ b/src/logging.c @@ -294,6 +294,15 @@ void uc_log_delete_destination(struct uc_log_destination *dest) pthread_mutex_unlock(&g_log_lock); } +void uc_log_destination_set_loglevel(struct uc_log_destination *dest, enum UC_LOG_LEVEL level) +{ + pthread_mutex_lock(&g_log_lock); + + dest->log_level = level; + + pthread_mutex_unlock(&g_log_lock); +} + static int uc_log_reopen_file(struct uc_log_destination *dest) { int rc = 0; @@ -337,25 +346,6 @@ void uc_log_init(struct uc_log_modules *user_modules) g_modules = *user_modules; } -int uc_log_module_set_loglevel(int module, enum UC_LOG_LEVEL level) -{ - int rc = -1; - int i; - - pthread_mutex_lock(&g_log_lock); - - for (i = 0; i < g_modules.cnt; i++) { - if (g_modules.mods[i].id == module) { - g_modules.mods[i].log_level = level; - rc = 0; - break; - } - } - - pthread_mutex_unlock(&g_log_lock); - - return rc; -} static inline void uc_vlog_file(const struct uc_log_args *args, const char *fmt, va_list ap) {