Mercurial > louis > mq > lightsd
changeset 256:b4a0f4dcee32
Use the new timer interface on the gateway refresh loop and speed-up bulb discovery
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 16 Aug 2015 18:37:31 -0700 |
parents | f0ae1e79c4b0 |
children | bd1132c0f8cf |
files | add_start_stop_timer.patch expose_a_bunch_of_metadata_in_get_light_state.patch series use_timer_interface_for_the_gateway_refresh_loop.patch |
diffstat | 4 files changed, 243 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/add_start_stop_timer.patch Sun Aug 16 16:55:02 2015 -0700 +++ b/add_start_stop_timer.patch Sun Aug 16 18:37:31 2015 -0700 @@ -1,7 +1,21 @@ # HG changeset patch -# Parent e9bbea56e55f41d6bf2f774208408c8f7e9395bd +# Parent e65d8e17050df8f3b7265c06bc44e9b32558db7f Add an interface to start and stop standalone timers +diff --git a/core/lightsd.c b/core/lightsd.c +--- a/core/lightsd.c ++++ b/core/lightsd.c +@@ -65,9 +65,9 @@ + lgtd_listen_close_all(); + lgtd_command_pipe_close_all(); + lgtd_client_close_all(); +- lgtd_lifx_timer_close(); + lgtd_lifx_broadcast_close(); + lgtd_lifx_gateway_close_all(); ++ lgtd_lifx_timer_close(); + event_base_free(lgtd_ev_base); + #if LIBEVENT_VERSION_NUMBER >= 0x02010100 + libevent_global_shutdown(); diff --git a/lifx/timer.c b/lifx/timer.c --- a/lifx/timer.c +++ b/lifx/timer.c @@ -34,7 +48,7 @@ if (lgtd_lifx_timer_context.discovery_timeout_ev) { event_del(lgtd_lifx_timer_context.discovery_timeout_ev); event_free(lgtd_lifx_timer_context.discovery_timeout_ev); -@@ -207,3 +215,55 @@ +@@ -207,3 +215,67 @@ lgtd_lifx_timer_discovery_timeout_event_callback(-1, 0, NULL); lgtd_debug("starting discovery timer"); } @@ -51,8 +65,9 @@ + timer->callback(timer, timer->ctx); +} + -+bool -+lgtd_lifx_timer_start_timer(int ms, ++struct lgtd_lifx_timer * ++lgtd_lifx_timer_start_timer(int flags, ++ int ms, + void (*cb)(struct lgtd_lifx_timer *, + union lgtd_lifx_timer_ctx), + union lgtd_lifx_timer_ctx ctx) @@ -69,15 +84,26 @@ + LIST_INSERT_HEAD(&lgtd_lifx_timers, timer, link); + + struct timeval tv = LGTD_MSECS_TO_TIMEVAL(ms); -+ timer->event = evtimer_new(lgtd_ev_base, lgtd_lifx_timer_callback, timer); ++ timer->event = event_new( ++ lgtd_ev_base, ++ -1, ++ flags & LGTD_LIFX_TIMER_PERSISTENT ? EV_PERSIST : 0, ++ lgtd_lifx_timer_callback, ++ timer ++ ); + if (!timer->event || evtimer_add(timer->event, &tv)) { + LIST_REMOVE(timer, link); ++ if (timer->event) { ++ event_free(timer->event); ++ } + free(timer); -+ return false; ++ return NULL; + } + -+ event_active(timer->event, 0, 0); -+ return true; ++ if (flags & LGTD_LIFX_TIMER_ACTIVATE_NOW) { ++ lgtd_lifx_timer_activate_timer(timer); ++ } ++ return timer; +} + +void @@ -93,7 +119,7 @@ diff --git a/lifx/timer.h b/lifx/timer.h --- a/lifx/timer.h +++ b/lifx/timer.h -@@ -17,13 +17,36 @@ +@@ -17,13 +17,77 @@ #pragma once @@ -110,6 +136,7 @@ + LGTD_LIFX_TIMER_DEVICE_FORCE_REFRESH_MSECS = 2000 +}; + ++struct timeval; +struct event; + +union lgtd_lifx_timer_ctx { @@ -117,6 +144,8 @@ + void *as_ptr; +}; + ++// NOTE: the timer utility isn't really lifx specific, we should move it back ++// to core, that will make naming suck less too: +struct lgtd_lifx_timer { + LIST_ENTRY(lgtd_lifx_timer) link; + void (*callback)(struct lgtd_lifx_timer *, @@ -125,15 +154,53 @@ + struct event *event; +}; +LIST_HEAD(lgtd_lifx_timer_list, lgtd_lifx_timer); ++ ++// Activate the timer now, in other words make the callback pending: ++static inline void ++lgtd_lifx_timer_activate_timer(struct lgtd_lifx_timer *timer) ++{ ++ assert(timer); ++ ++ event_active(timer->event, 0, 0); ++} ++ ++// Re-schedule a non-persistent timer with the given timeout: ++static inline bool ++lgtd_lifx_timer_reschedule_timer(struct lgtd_lifx_timer *timer, ++ struct timeval *tv) ++{ ++ assert(timer); ++ assert(tv); ++ ++ return !evtimer_add(timer->event, tv); ++} ++ ++static inline bool ++lgtd_lifx_timer_ispending_timer(struct lgtd_lifx_timer *timer) ++{ ++ assert(timer); ++ ++ return evtimer_pending(timer->event, NULL); ++} ++ ++enum lgtd_lifx_timer_flags { ++ LGTD_LIFX_TIMER_DEFAULT_FLAGS = 0, ++ LGTD_LIFX_TIMER_ACTIVATE_NOW = 1, ++ LGTD_LIFX_TIMER_PERSISTENT = 1 << 1, ++}; bool lgtd_lifx_timer_setup(void); void lgtd_lifx_timer_close(void); void lgtd_lifx_timer_start_watchdog(void); void lgtd_lifx_timer_start_discovery(void); -+bool lgtd_lifx_timer_start_timer(int, // ms, & the timer is activated right away -+ void (*)(struct lgtd_lifx_timer *, -+ union lgtd_lifx_timer_ctx), -+ union lgtd_lifx_timer_ctx); ++ ++// Create a new timer and schedule it: ++struct lgtd_lifx_timer *lgtd_lifx_timer_start_timer(int, ++ int, // ms, & the timer is activated right away ++ void (*)(struct lgtd_lifx_timer *, ++ union lgtd_lifx_timer_ctx), ++ union lgtd_lifx_timer_ctx); ++// Un-schedule and free the given timer: +void lgtd_lifx_timer_stop_timer(struct lgtd_lifx_timer *); diff --git a/tests/core/daemon/test_daemon_update_proctitle.c b/tests/core/daemon/test_daemon_update_proctitle.c --- a/tests/core/daemon/test_daemon_update_proctitle.c @@ -762,26 +829,30 @@ new file mode 100644 --- /dev/null +++ b/tests/lifx/mock_timer.h -@@ -0,0 +1,23 @@ +@@ -0,0 +1,27 @@ +#pragma once + +#include "lifx/timer.h" // to pull the union definition + +#ifndef MOCKED_LGTD_LIFX_TIMER_START_TIMER -+bool lgtd_lifx_timer_start_timer(int ms, -+ void (*cb)(struct lgtd_lifx_timer *, -+ union lgtd_lifx_timer_ctx), -+ union lgtd_lifx_timer_ctx ctx) ++struct lgtd_lifx_timer * ++lgtd_lifx_timer_start_timer(int flags, ++ int ms, ++ void (*cb)(struct lgtd_lifx_timer *, ++ union lgtd_lifx_timer_ctx), ++ union lgtd_lifx_timer_ctx ctx) +{ ++ (void)flags; + (void)ms; + (void)cb; + (void)ctx; -+ return true; ++ return NULL; +} +#endif + +#ifndef MOCKED_LGTD_LIFX_TIMER_START_TIMER -+void lgtd_lifx_timer_stop_timer(struct lgtd_lifx_timer *timer) ++void ++lgtd_lifx_timer_stop_timer(struct lgtd_lifx_timer *timer) +{ + (void)timer; +}
--- a/expose_a_bunch_of_metadata_in_get_light_state.patch Sun Aug 16 16:55:02 2015 -0700 +++ b/expose_a_bunch_of_metadata_in_get_light_state.patch Sun Aug 16 18:37:31 2015 -0700 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 2cfd0a561bb72156459fc8a9dde5bfbb5613724a +# Parent 7027549920d48dc2320bb80ab1b9439474f6d7e1 diff --git a/core/daemon.c b/core/daemon.c --- a/core/daemon.c @@ -320,8 +320,8 @@ + } + + switch (product_id) { -+ case 1: -+ case 2: ++ case 0x1: ++ case 0x2: + return "Original"; + case 0xa: + return "White 800"; @@ -381,22 +381,26 @@ struct lgtd_lifx_bulb * lgtd_lifx_bulb_get(const uint8_t *addr) { -@@ -68,6 +142,14 @@ +@@ -68,6 +142,18 @@ bulb->last_light_state_at = lgtd_time_monotonic_msecs(); + union lgtd_lifx_timer_ctx ctx = { .as_uint = 0 }; + memcpy(&ctx.as_uint, addr, LGTD_LIFX_ADDR_LENGTH); -+ lgtd_lifx_timer_start_timer( ++ struct lgtd_lifx_timer *timer = lgtd_lifx_timer_start_timer( ++ LGTD_LIFX_TIMER_ACTIVATE_NOW|LGTD_LIFX_TIMER_PERSISTENT, + LGTD_LIFX_BULB_FETCH_HARDWARE_INFO_TIMER_MSECS, + lgtd_lifx_bulb_fetch_hardware_info, + ctx + ); ++ if (!timer) { ++ lgtd_warn("can't start a timer to fetch the bulb hardware specs"); ++ } + return bulb; } -@@ -124,6 +206,7 @@ +@@ -124,6 +210,7 @@ LGTD_STATS_ADD_AND_UPDATE_PROCTITLE( bulbs_powered_on, state->power == LGTD_LIFX_POWER_ON ? 1 : -1 ); @@ -404,7 +408,7 @@ } lgtd_lifx_gateway_update_tag_refcounts(bulb->gw, bulb->state.tags, state->tags); -@@ -141,6 +224,7 @@ +@@ -141,6 +228,7 @@ LGTD_STATS_ADD_AND_UPDATE_PROCTITLE( bulbs_powered_on, power == LGTD_LIFX_POWER_ON ? 1 : -1 ); @@ -412,7 +416,7 @@ } bulb->state.power = power; -@@ -155,3 +239,57 @@ +@@ -155,3 +243,57 @@ bulb->state.tags = tags; } @@ -586,7 +590,7 @@ - int latency = gw->last_pkt_at - gw->last_req_at; + int latency = LGTD_LIFX_GATEWAY_LATENCY(gw); if (latency < LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS) { - if (!event_pending(gw->refresh_ev, EV_TIMEOUT, NULL)) { + if (!lgtd_lifx_timer_ispending_timer(gw->refresh_timer)) { int timeout = LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS - latency; @@ -573,14 +569,9 @@ LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr), pkt->power
--- a/series Sun Aug 16 16:55:02 2015 -0700 +++ b/series Sun Aug 16 18:37:31 2015 -0700 @@ -2,5 +2,6 @@ make_device_timeout_2_5x_force_refresh.patch ignore_sigpipe.patch add_start_stop_timer.patch +use_timer_interface_for_the_gateway_refresh_loop.patch expose_a_bunch_of_metadata_in_get_light_state.patch add_ipv4_to_ieee8023mac.patch #+future #+linux
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/use_timer_interface_for_the_gateway_refresh_loop.patch Sun Aug 16 18:37:31 2015 -0700 @@ -0,0 +1,138 @@ +# HG changeset patch +# Parent 8321e57f9a3eb3935e3710c1ab68a1d08495d4cb +Speed-up bulbs discovery + +By querying a gateway's bulbs as soon as it's discovered. + +This is the exact same optimization done earlier with the gateway +discovery timer. + +This changeset also updates the gateway code to use the new timer +interface. + +diff --git a/lifx/gateway.c b/lifx/gateway.c +--- a/lifx/gateway.c ++++ b/lifx/gateway.c +@@ -57,13 +57,12 @@ + assert(gw); + + LGTD_STATS_ADD_AND_UPDATE_PROCTITLE(gateways, -1); +- event_del(gw->refresh_ev); ++ lgtd_lifx_timer_stop_timer(gw->refresh_timer); + event_del(gw->write_ev); + if (gw->socket != -1) { + evutil_closesocket(gw->socket); + LIST_REMOVE(gw, link); + } +- event_free(gw->refresh_ev); + event_free(gw->write_ev); + evbuffer_free(gw->write_buf); + for (int i = 0; i != LGTD_LIFX_GATEWAY_MAX_TAGS; i++) { +@@ -240,13 +239,12 @@ + } + + static void +-lgtd_lifx_gateway_refresh_callback(evutil_socket_t socket, +- short events, +- void *ctx) ++lgtd_lifx_gateway_refresh_callback(struct lgtd_lifx_timer *timer, ++ union lgtd_lifx_timer_ctx ctx) + { +- (void)socket; +- (void)events; +- lgtd_lifx_gateway_send_get_all_light_state((struct lgtd_lifx_gateway *)ctx); ++ (void)timer; ++ struct lgtd_lifx_gateway *gw = ctx.as_ptr; ++ lgtd_lifx_gateway_send_get_all_light_state(gw); + } + + void +@@ -254,7 +252,7 @@ + { + assert(gw); + +- event_active(gw->refresh_ev, 0, 0); ++ lgtd_lifx_timer_activate_timer(gw->refresh_timer); + } + + static struct lgtd_lifx_bulb * +@@ -303,6 +301,7 @@ + lgtd_warn("can't open a new socket"); + goto error_connect; + } ++ + gw->write_ev = event_new( + lgtd_ev_base, + gw->socket, +@@ -311,9 +310,11 @@ + gw + ); + gw->write_buf = evbuffer_new(); +- gw->refresh_ev = evtimer_new( +- lgtd_ev_base, lgtd_lifx_gateway_refresh_callback, gw +- ); ++ if (!gw->write_ev || !gw->write_buf) { ++ lgtd_warn("can't allocate a new gateway bulb"); ++ goto error_allocate; ++ } ++ + memcpy(&gw->peer, peer, sizeof(gw->peer)); + lgtd_sockaddrtoa(peer, gw->ip_addr, sizeof(gw->ip_addr)); + gw->port = lgtd_sockaddrport(peer); +@@ -322,13 +323,15 @@ + gw->next_req_at = received_at; + gw->last_pkt_at = received_at; + +- struct timeval refresh_interval = LGTD_MSECS_TO_TIMEVAL( +- LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS ++ union lgtd_lifx_timer_ctx ctx = { .as_ptr = gw }; ++ gw->refresh_timer = lgtd_lifx_timer_start_timer( ++ LGTD_LIFX_TIMER_ACTIVATE_NOW, ++ LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS, ++ lgtd_lifx_gateway_refresh_callback, ++ ctx + ); +- +- if (!gw->write_ev || !gw->write_buf || !gw->refresh_ev +- || event_add(gw->refresh_ev, &refresh_interval) != 0) { +- lgtd_warn("can't allocate a new gateway bulb"); ++ if (!gw->refresh_timer) { ++ lgtd_warn("can't allocate a new timer"); + goto error_allocate; + } + +@@ -355,9 +358,6 @@ + if (gw->write_buf) { + evbuffer_free(gw->write_buf); + } +- if (gw->refresh_ev) { +- event_free(gw->refresh_ev); +- } + error_connect: + evutil_closesocket(gw->socket); + error_socket: +@@ -529,10 +529,10 @@ + + int latency = LGTD_LIFX_GATEWAY_LATENCY(gw); + if (latency < LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS) { +- if (!event_pending(gw->refresh_ev, EV_TIMEOUT, NULL)) { ++ if (!lgtd_lifx_timer_ispending_timer(gw->refresh_timer)) { + int timeout = LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS - latency; + struct timeval tv = LGTD_MSECS_TO_TIMEVAL(timeout); +- evtimer_add(gw->refresh_ev, &tv); ++ lgtd_lifx_timer_reschedule_timer(gw->refresh_timer, &tv); + lgtd_debug( + "[%s]:%hu latency is %dms, scheduling next GET_LIGHT_STATE in %dms", + gw->ip_addr, gw->port, latency, timeout +diff --git a/lifx/gateway.h b/lifx/gateway.h +--- a/lifx/gateway.h ++++ b/lifx/gateway.h +@@ -79,7 +79,7 @@ + struct event *write_ev; + struct evbuffer *write_buf; + bool pending_refresh_req; +- struct event *refresh_ev; ++ struct lgtd_lifx_timer *refresh_timer; + }; + LIST_HEAD(lgtd_lifx_gateway_list, lgtd_lifx_gateway); +