mirror of
https://github.com/falk-werner/webfuse-provider
synced 2024-10-27 20:44:10 +00:00
added timeout handling
This commit is contained in:
parent
aec60d194e
commit
083ebbefe3
@ -44,6 +44,9 @@ add_library(fuse-wsfs
|
|||||||
src/wsfs/server.c
|
src/wsfs/server.c
|
||||||
src/wsfs/message.c
|
src/wsfs/message.c
|
||||||
src/wsfs/message_queue.c
|
src/wsfs/message_queue.c
|
||||||
|
src/wsfs/time/timepoint.c
|
||||||
|
src/wsfs/time/timer.c
|
||||||
|
src/wsfs/time/timeout_manager.c
|
||||||
src/wsfs/operation/lookup.c
|
src/wsfs/operation/lookup.c
|
||||||
src/wsfs/operation/getattr.c
|
src/wsfs/operation/getattr.c
|
||||||
src/wsfs/operation/readdir.c
|
src/wsfs/operation/readdir.c
|
||||||
@ -81,6 +84,8 @@ pkg_check_modules(GTEST gtest_main)
|
|||||||
add_executable(alltests
|
add_executable(alltests
|
||||||
test-src/test_response_parser.cc
|
test-src/test_response_parser.cc
|
||||||
test-src/test_server.cc
|
test-src/test_server.cc
|
||||||
|
test-src/test_timepoint.cc
|
||||||
|
test-src/test_timer.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(alltests PUBLIC fuse-wsfs ${EXTRA_LIBS} ${GTEST_LIBRARIES})
|
target_link_libraries(alltests PUBLIC fuse-wsfs ${EXTRA_LIBS} ${GTEST_LIBRARIES})
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "wsfs/jsonrpc/request.h"
|
#include "wsfs/jsonrpc/request.h"
|
||||||
#include "wsfs/jsonrpc/response.h"
|
#include "wsfs/jsonrpc/response.h"
|
||||||
|
|
||||||
|
#define WSFS_DEFAULT_TIMEOUT (10 * 1000)
|
||||||
|
|
||||||
static struct wsfs_jsonrpc_method const * wsfs_jsonrpc_server_getmethod(
|
static struct wsfs_jsonrpc_method const * wsfs_jsonrpc_server_getmethod(
|
||||||
struct wsfs_jsonrpc_server * server,
|
struct wsfs_jsonrpc_server * server,
|
||||||
char const * name)
|
char const * name)
|
||||||
@ -18,16 +20,41 @@ static struct wsfs_jsonrpc_method const * wsfs_jsonrpc_server_getmethod(
|
|||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wsfs_jsonrpc_server_timeout(
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
struct wsfs_jsonrpc_server * server = timer->user_data;
|
||||||
|
|
||||||
|
if (server->request.is_pending)
|
||||||
|
{
|
||||||
|
wsfs_jsonrpc_method_finished_fn * finished = server->request.finished;
|
||||||
|
void * user_data = server->request.user_data;
|
||||||
|
|
||||||
|
server->request.is_pending = false;
|
||||||
|
server->request.id = 0;
|
||||||
|
server->request.user_data = NULL;
|
||||||
|
server->request.finished = NULL;
|
||||||
|
wsfs_timer_cancel(&server->request.timer);
|
||||||
|
|
||||||
|
finished(user_data, WSFS_BAD_TIMEOUT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wsfs_jsonrpc_server_init(
|
void wsfs_jsonrpc_server_init(
|
||||||
struct wsfs_jsonrpc_server * server)
|
struct wsfs_jsonrpc_server * server,
|
||||||
|
struct wsfs_timeout_manager * timeout_manager)
|
||||||
{
|
{
|
||||||
server->methods = NULL;
|
server->methods = NULL;
|
||||||
server->request.is_pending = false;
|
server->request.is_pending = false;
|
||||||
|
|
||||||
|
wsfs_timer_init(&server->request.timer, timeout_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsfs_jsonrpc_server_cleanup(
|
void wsfs_jsonrpc_server_cleanup(
|
||||||
struct wsfs_jsonrpc_server * server)
|
struct wsfs_jsonrpc_server * server)
|
||||||
{
|
{
|
||||||
|
wsfs_timer_cleanup(&server->request.timer);
|
||||||
|
|
||||||
if (server->request.is_pending)
|
if (server->request.is_pending)
|
||||||
{
|
{
|
||||||
server->request.finished(server->request.user_data, WSFS_BAD, NULL);
|
server->request.finished(server->request.user_data, WSFS_BAD, NULL);
|
||||||
@ -74,6 +101,8 @@ void wsfs_jsonrpc_server_invoke(
|
|||||||
server->request.finished = finished;
|
server->request.finished = finished;
|
||||||
server->request.user_data = user_data;
|
server->request.user_data = user_data;
|
||||||
server->request.id = 42;
|
server->request.id = 42;
|
||||||
|
wsfs_timer_start(&server->request.timer, wsfs_timepoint_in_msec(WSFS_DEFAULT_TIMEOUT),
|
||||||
|
&wsfs_jsonrpc_server_timeout, server);
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, param_info);
|
va_start(args, param_info);
|
||||||
@ -87,6 +116,7 @@ void wsfs_jsonrpc_server_invoke(
|
|||||||
server->request.finished = NULL;
|
server->request.finished = NULL;
|
||||||
server->request.user_data = NULL;
|
server->request.user_data = NULL;
|
||||||
server->request.id = 0;
|
server->request.id = 0;
|
||||||
|
wsfs_timer_cancel(&server->request.timer);
|
||||||
|
|
||||||
finished(user_data, WSFS_BAD, NULL);
|
finished(user_data, WSFS_BAD, NULL);
|
||||||
}
|
}
|
||||||
@ -146,6 +176,7 @@ void wsfs_jsonrpc_server_onresult(
|
|||||||
server->request.id = 0;
|
server->request.id = 0;
|
||||||
server->request.user_data = NULL;
|
server->request.user_data = NULL;
|
||||||
server->request.finished = NULL;
|
server->request.finished = NULL;
|
||||||
|
wsfs_timer_cancel(&server->request.timer);
|
||||||
|
|
||||||
finished(user_data, response.status, response.result);
|
finished(user_data, response.status, response.result);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@ using std::size_t;
|
|||||||
|
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include "wsfs/jsonrpc/method.h"
|
#include "wsfs/jsonrpc/method.h"
|
||||||
|
#include "wsfs/time/timeout_manager.h"
|
||||||
|
#include "wsfs/time/timer.h"
|
||||||
|
|
||||||
|
|
||||||
struct wsfs_jsonrpc_request
|
struct wsfs_jsonrpc_request
|
||||||
{
|
{
|
||||||
@ -20,6 +23,7 @@ struct wsfs_jsonrpc_request
|
|||||||
wsfs_jsonrpc_method_finished_fn * finished;
|
wsfs_jsonrpc_method_finished_fn * finished;
|
||||||
void * user_data;
|
void * user_data;
|
||||||
int id;
|
int id;
|
||||||
|
struct wsfs_timer timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wsfs_jsonrpc_server
|
struct wsfs_jsonrpc_server
|
||||||
@ -35,7 +39,8 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void wsfs_jsonrpc_server_init(
|
extern void wsfs_jsonrpc_server_init(
|
||||||
struct wsfs_jsonrpc_server * server);
|
struct wsfs_jsonrpc_server * server,
|
||||||
|
struct wsfs_timeout_manager * manager);
|
||||||
|
|
||||||
extern void wsfs_jsonrpc_server_cleanup(
|
extern void wsfs_jsonrpc_server_cleanup(
|
||||||
struct wsfs_jsonrpc_server * server);
|
struct wsfs_jsonrpc_server * server);
|
||||||
|
@ -39,7 +39,7 @@ static void wsfs_operation_read_finished(void * user_data, wsfs_status status, j
|
|||||||
fuse_req_t request = user_data;
|
fuse_req_t request = user_data;
|
||||||
|
|
||||||
char * buffer = NULL;
|
char * buffer = NULL;
|
||||||
size_t length;
|
size_t length = 0;
|
||||||
if (NULL != data)
|
if (NULL != data)
|
||||||
{
|
{
|
||||||
json_t * data_holder = json_object_get(data, "data");
|
json_t * data_holder = json_object_get(data, "data");
|
||||||
|
@ -17,6 +17,8 @@ static int wsfs_server_protocol_callback(
|
|||||||
struct lws_protocols const * ws_protocol = lws_get_protocol(wsi);
|
struct lws_protocols const * ws_protocol = lws_get_protocol(wsi);
|
||||||
struct wsfs_server_protocol * protocol = ws_protocol->user;
|
struct wsfs_server_protocol * protocol = ws_protocol->user;
|
||||||
|
|
||||||
|
wsfs_timeout_manager_check(&protocol->timeout_manager);
|
||||||
|
|
||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||||
@ -146,7 +148,9 @@ bool wsfs_server_protocol_init(
|
|||||||
protocol->wsi = NULL;
|
protocol->wsi = NULL;
|
||||||
wsfs_message_queue_init(&protocol->queue);
|
wsfs_message_queue_init(&protocol->queue);
|
||||||
|
|
||||||
wsfs_jsonrpc_server_init(&protocol->rpc);
|
wsfs_timeout_manager_init(&protocol->timeout_manager);
|
||||||
|
|
||||||
|
wsfs_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager);
|
||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "lookup", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "lookup", &wsfs_server_protocol_invoke, protocol);
|
||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "getattr", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "getattr", &wsfs_server_protocol_invoke, protocol);
|
||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "readdir", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "readdir", &wsfs_server_protocol_invoke, protocol);
|
||||||
@ -154,7 +158,17 @@ bool wsfs_server_protocol_init(
|
|||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "close", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "close", &wsfs_server_protocol_invoke, protocol);
|
||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "read", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "read", &wsfs_server_protocol_invoke, protocol);
|
||||||
|
|
||||||
return wsfs_filesystem_init(&protocol->filesystem, &protocol->rpc, mount_point);
|
bool const success = wsfs_filesystem_init(&protocol->filesystem, &protocol->rpc, mount_point);
|
||||||
|
|
||||||
|
// cleanup on error
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
||||||
|
wsfs_timeout_manager_cleanup(&protocol->timeout_manager);
|
||||||
|
wsfs_message_queue_cleanup(&protocol->queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsfs_server_protocol_cleanup(
|
void wsfs_server_protocol_cleanup(
|
||||||
@ -162,6 +176,7 @@ void wsfs_server_protocol_cleanup(
|
|||||||
{
|
{
|
||||||
wsfs_filesystem_cleanup(&protocol->filesystem);
|
wsfs_filesystem_cleanup(&protocol->filesystem);
|
||||||
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
||||||
|
wsfs_timeout_manager_cleanup(&protocol->timeout_manager);
|
||||||
wsfs_message_queue_cleanup(&protocol->queue);
|
wsfs_message_queue_cleanup(&protocol->queue);
|
||||||
protocol->wsi = NULL;
|
protocol->wsi = NULL;
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
#include "wsfs/filesystem.h"
|
#include "wsfs/filesystem.h"
|
||||||
#include "wsfs/message_queue.h"
|
#include "wsfs/message_queue.h"
|
||||||
#include "wsfs/jsonrpc/server.h"
|
#include "wsfs/jsonrpc/server.h"
|
||||||
|
#include "wsfs/time/timeout_manager.h"
|
||||||
|
|
||||||
struct wsfs_server_protocol
|
struct wsfs_server_protocol
|
||||||
{
|
{
|
||||||
|
struct wsfs_timeout_manager timeout_manager;
|
||||||
struct wsfs_filesystem filesystem;
|
struct wsfs_filesystem filesystem;
|
||||||
struct wsfs_jsonrpc_server rpc;
|
struct wsfs_jsonrpc_server rpc;
|
||||||
struct wsfs_message_queue queue;
|
struct wsfs_message_queue queue;
|
||||||
|
84
src/wsfs/time/timeout_manager.c
Normal file
84
src/wsfs/time/timeout_manager.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "wsfs/time/timeout_manager_intern.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "wsfs/time/timer_intern.h"
|
||||||
|
#include "wsfs/time/timepoint.h"
|
||||||
|
|
||||||
|
void wsfs_timeout_manager_init(
|
||||||
|
struct wsfs_timeout_manager * manager)
|
||||||
|
{
|
||||||
|
manager->timers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timeout_manager_cleanup(
|
||||||
|
struct wsfs_timeout_manager * manager)
|
||||||
|
{
|
||||||
|
struct wsfs_timer * timer = manager->timers;
|
||||||
|
while (NULL != timer)
|
||||||
|
{
|
||||||
|
struct wsfs_timer * next = timer->next;
|
||||||
|
|
||||||
|
wsfs_timer_trigger(timer);
|
||||||
|
|
||||||
|
timer = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
manager->timers = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timeout_manager_check(
|
||||||
|
struct wsfs_timeout_manager * manager)
|
||||||
|
{
|
||||||
|
struct wsfs_timer * timer = manager->timers;
|
||||||
|
while (NULL != timer)
|
||||||
|
{
|
||||||
|
struct wsfs_timer * next = timer->next;
|
||||||
|
|
||||||
|
if (wsfs_timer_is_timeout(timer))
|
||||||
|
{
|
||||||
|
wsfs_timeout_manager_removetimer(manager, timer);
|
||||||
|
wsfs_timer_trigger(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timeout_manager_addtimer(
|
||||||
|
struct wsfs_timeout_manager * manager,
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
if (NULL != manager->timers)
|
||||||
|
{
|
||||||
|
manager->timers->prev = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer->next = manager->timers;
|
||||||
|
timer->prev = NULL;
|
||||||
|
manager->timers = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timeout_manager_removetimer(
|
||||||
|
struct wsfs_timeout_manager * manager,
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
struct wsfs_timer * prev = timer->prev;
|
||||||
|
struct wsfs_timer * next = timer->next;
|
||||||
|
|
||||||
|
if (NULL != prev)
|
||||||
|
{
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager->timers == timer)
|
||||||
|
{
|
||||||
|
manager->timers = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
src/wsfs/time/timeout_manager.h
Normal file
29
src/wsfs/time/timeout_manager.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _WSFS_TIME_TIMEOUT_MANAGER_H
|
||||||
|
#define _WSFS_TIME_TIMEOUT_MANAGER_H
|
||||||
|
|
||||||
|
struct wsfs_timer;
|
||||||
|
struct wsfs_timeout_manager
|
||||||
|
{
|
||||||
|
struct wsfs_timer * timers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void wsfs_timeout_manager_init(
|
||||||
|
struct wsfs_timeout_manager * manager);
|
||||||
|
|
||||||
|
extern void wsfs_timeout_manager_cleanup(
|
||||||
|
struct wsfs_timeout_manager * manager);
|
||||||
|
|
||||||
|
extern void wsfs_timeout_manager_check(
|
||||||
|
struct wsfs_timeout_manager * manager);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
24
src/wsfs/time/timeout_manager_intern.h
Normal file
24
src/wsfs/time/timeout_manager_intern.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _WSFS_TIME_TIMEOUT_MANAGER_INTERN_H
|
||||||
|
#define _WSFS_TIME_TIMEOUT_MANAGER_INTERN_H
|
||||||
|
|
||||||
|
#include "wsfs/time/timeout_manager.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void wsfs_timeout_manager_addtimer(
|
||||||
|
struct wsfs_timeout_manager * manager,
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
extern void wsfs_timeout_manager_removetimer(
|
||||||
|
struct wsfs_timeout_manager * manager,
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
31
src/wsfs/time/timepoint.c
Normal file
31
src/wsfs/time/timepoint.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "wsfs/time/timepoint.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define WSFS_MSEC_PER_SEC ((wsfs_timepoint) 1000)
|
||||||
|
#define WSFS_NSEC_PER_MSEC ((wsfs_timepoint) 1000 * 1000)
|
||||||
|
|
||||||
|
wsfs_timepoint wsfs_timepoint_now(void)
|
||||||
|
{
|
||||||
|
struct timespec timepoint;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &timepoint);
|
||||||
|
|
||||||
|
wsfs_timepoint const now = (timepoint.tv_sec * WSFS_MSEC_PER_SEC) + (timepoint.tv_nsec / WSFS_NSEC_PER_MSEC);
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsfs_timepoint wsfs_timepoint_in_msec(wsfs_timediff value)
|
||||||
|
{
|
||||||
|
wsfs_timepoint const now = wsfs_timepoint_now();
|
||||||
|
wsfs_timepoint result = now + ((wsfs_timepoint) value);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wsfs_timepoint_is_elapsed(wsfs_timepoint timepoint)
|
||||||
|
{
|
||||||
|
wsfs_timepoint const now = wsfs_timepoint_now();
|
||||||
|
wsfs_timediff const diff = (wsfs_timediff) (timepoint - now);
|
||||||
|
|
||||||
|
return (0 > diff);
|
||||||
|
}
|
31
src/wsfs/time/timepoint.h
Normal file
31
src/wsfs/time/timepoint.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _WSFS_TIME_TIMEPOINT_H
|
||||||
|
#define _WSFS_TIME_TIMEPOINT_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#else
|
||||||
|
#include <cinttypes>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef uint64_t wsfs_timepoint;
|
||||||
|
typedef int64_t wsfs_timediff;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern wsfs_timepoint wsfs_timepoint_now(void);
|
||||||
|
|
||||||
|
extern wsfs_timepoint wsfs_timepoint_in_msec(
|
||||||
|
wsfs_timediff value);
|
||||||
|
|
||||||
|
extern bool wsfs_timepoint_is_elapsed(
|
||||||
|
wsfs_timepoint timepoint);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
65
src/wsfs/time/timer.c
Normal file
65
src/wsfs/time/timer.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "wsfs/time/timer_intern.h"
|
||||||
|
#include "wsfs/time/timeout_manager_intern.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void wsfs_timer_init(
|
||||||
|
struct wsfs_timer * timer,
|
||||||
|
struct wsfs_timeout_manager * manager)
|
||||||
|
{
|
||||||
|
timer->manager = manager;
|
||||||
|
timer->timeout = 0;
|
||||||
|
timer->timeout_handler = NULL;
|
||||||
|
timer->user_data = NULL;
|
||||||
|
timer->prev = NULL;
|
||||||
|
timer->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timer_cleanup(
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
memset(timer, 0, sizeof(struct wsfs_timer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timer_start(
|
||||||
|
struct wsfs_timer * timer,
|
||||||
|
wsfs_timepoint absolute_timeout,
|
||||||
|
wsfs_timer_timeout_fn * handler,
|
||||||
|
void * user_data)
|
||||||
|
{
|
||||||
|
timer->timeout = absolute_timeout;
|
||||||
|
timer->timeout_handler = handler;
|
||||||
|
timer->user_data = user_data;
|
||||||
|
|
||||||
|
wsfs_timeout_manager_addtimer(timer->manager, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_timer_cancel(
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
wsfs_timeout_manager_removetimer(timer->manager, timer);
|
||||||
|
|
||||||
|
timer->timeout = 0;
|
||||||
|
timer->timeout_handler = NULL;
|
||||||
|
timer->user_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wsfs_timer_is_timeout(
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
return wsfs_timepoint_is_elapsed(timer->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wsfs_timer_trigger(
|
||||||
|
struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
if (NULL != timer->timeout_handler)
|
||||||
|
{
|
||||||
|
timer->prev = NULL;
|
||||||
|
timer->next = NULL;
|
||||||
|
|
||||||
|
timer->timeout_handler(timer);
|
||||||
|
}
|
||||||
|
}
|
48
src/wsfs/time/timer.h
Normal file
48
src/wsfs/time/timer.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef _WSFS_TIMER_H
|
||||||
|
#define _WSFS_TIMER_H
|
||||||
|
|
||||||
|
#include "wsfs/time/timepoint.h"
|
||||||
|
|
||||||
|
struct wsfs_timer;
|
||||||
|
struct wsfs_timeout_manager;
|
||||||
|
|
||||||
|
typedef void wsfs_timer_timeout_fn(struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
struct wsfs_timer
|
||||||
|
{
|
||||||
|
struct wsfs_timeout_manager * manager;
|
||||||
|
wsfs_timepoint timeout;
|
||||||
|
wsfs_timer_timeout_fn * timeout_handler;
|
||||||
|
void * user_data;
|
||||||
|
struct wsfs_timer * next;
|
||||||
|
struct wsfs_timer * prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void wsfs_timer_init(
|
||||||
|
struct wsfs_timer * timer,
|
||||||
|
struct wsfs_timeout_manager * manager);
|
||||||
|
|
||||||
|
extern void wsfs_timer_cleanup(
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
extern void wsfs_timer_start(
|
||||||
|
struct wsfs_timer * timer,
|
||||||
|
wsfs_timepoint absolute_timeout,
|
||||||
|
wsfs_timer_timeout_fn * handler,
|
||||||
|
void * user_data);
|
||||||
|
|
||||||
|
extern void wsfs_timer_cancel(
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
25
src/wsfs/time/timer_intern.h
Normal file
25
src/wsfs/time/timer_intern.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef _WSFS_TIME_TIMER_INTERN_H
|
||||||
|
#define _WSFS_TIME_TIMER_INTERN_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wsfs/time/timer.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern bool wsfs_timer_is_timeout(
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
extern void wsfs_timer_trigger(
|
||||||
|
struct wsfs_timer * timer);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
34
test-src/test_timepoint.cc
Normal file
34
test-src/test_timepoint.cc
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "wsfs/time/timepoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
TEST(timepoint, now)
|
||||||
|
{
|
||||||
|
wsfs_timepoint start = wsfs_timepoint_now();
|
||||||
|
usleep(42 * 1000);
|
||||||
|
wsfs_timepoint end = wsfs_timepoint_now();
|
||||||
|
|
||||||
|
ASSERT_LT(start, end);
|
||||||
|
ASSERT_LT(end, start + 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timepoint, in_msec)
|
||||||
|
{
|
||||||
|
wsfs_timepoint now = wsfs_timepoint_now();
|
||||||
|
wsfs_timepoint later = wsfs_timepoint_in_msec(42);
|
||||||
|
|
||||||
|
ASSERT_LT(now, later);
|
||||||
|
ASSERT_LT(later, now + 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timepoint, elapsed)
|
||||||
|
{
|
||||||
|
wsfs_timepoint now;
|
||||||
|
|
||||||
|
now = wsfs_timepoint_now();
|
||||||
|
ASSERT_TRUE(wsfs_timepoint_is_elapsed(now - 1));
|
||||||
|
|
||||||
|
now = wsfs_timepoint_now();
|
||||||
|
ASSERT_FALSE(wsfs_timepoint_is_elapsed(now + 500));
|
||||||
|
}
|
100
test-src/test_timer.cc
Normal file
100
test-src/test_timer.cc
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "wsfs/time/timer.h"
|
||||||
|
#include "wsfs/time/timeout_manager.h"
|
||||||
|
|
||||||
|
using std::size_t;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void on_timeout(struct wsfs_timer * timer)
|
||||||
|
{
|
||||||
|
bool * triggered = reinterpret_cast<bool*>(timer->user_data);
|
||||||
|
*triggered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timer, init)
|
||||||
|
{
|
||||||
|
struct wsfs_timeout_manager manager;
|
||||||
|
struct wsfs_timer timer;
|
||||||
|
|
||||||
|
wsfs_timeout_manager_init(&manager);
|
||||||
|
wsfs_timer_init(&timer, &manager);
|
||||||
|
|
||||||
|
wsfs_timer_cleanup(&timer);
|
||||||
|
wsfs_timeout_manager_cleanup(&manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timer, trigger)
|
||||||
|
{
|
||||||
|
struct wsfs_timeout_manager manager;
|
||||||
|
struct wsfs_timer timer;
|
||||||
|
|
||||||
|
wsfs_timeout_manager_init(&manager);
|
||||||
|
wsfs_timer_init(&timer, &manager);
|
||||||
|
|
||||||
|
bool triggered = false;
|
||||||
|
wsfs_timer_start(&timer, wsfs_timepoint_in_msec(250), &on_timeout, reinterpret_cast<void*>(&triggered));
|
||||||
|
usleep(500 * 1000);
|
||||||
|
wsfs_timeout_manager_check(&manager);
|
||||||
|
|
||||||
|
ASSERT_TRUE(triggered);
|
||||||
|
|
||||||
|
wsfs_timer_cleanup(&timer);
|
||||||
|
wsfs_timeout_manager_cleanup(&manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timer, cancel)
|
||||||
|
{
|
||||||
|
struct wsfs_timeout_manager manager;
|
||||||
|
struct wsfs_timer timer;
|
||||||
|
|
||||||
|
wsfs_timeout_manager_init(&manager);
|
||||||
|
wsfs_timer_init(&timer, &manager);
|
||||||
|
|
||||||
|
bool triggered = false;
|
||||||
|
wsfs_timer_start(&timer, wsfs_timepoint_in_msec(250), &on_timeout, &triggered);
|
||||||
|
usleep(500 * 1000);
|
||||||
|
wsfs_timer_cancel(&timer);
|
||||||
|
wsfs_timeout_manager_check(&manager);
|
||||||
|
|
||||||
|
ASSERT_FALSE(triggered);
|
||||||
|
|
||||||
|
wsfs_timer_cleanup(&timer);
|
||||||
|
wsfs_timeout_manager_cleanup(&manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(timer, multiple_timers)
|
||||||
|
{
|
||||||
|
static size_t const count = 5;
|
||||||
|
struct wsfs_timeout_manager manager;
|
||||||
|
struct wsfs_timer timer[count];
|
||||||
|
bool triggered[count];
|
||||||
|
|
||||||
|
wsfs_timeout_manager_init(&manager);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
wsfs_timer_init(&timer[i], &manager);
|
||||||
|
triggered[i] = false;
|
||||||
|
wsfs_timer_start(&timer[i], wsfs_timepoint_in_msec(300 - (50 * i)), &on_timeout, &triggered[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
usleep(100 * 1000);
|
||||||
|
wsfs_timeout_manager_check(&manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(triggered[i]);
|
||||||
|
wsfs_timer_cleanup(&timer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wsfs_timeout_manager_cleanup(&manager);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user