Merge branch 'dev' of ssh://box.fiane.intra/var/lib/git/libucore into dev
This commit is contained in:
@@ -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_ */
|
||||||
|
|
||||||
@@ -175,6 +175,13 @@ void uc_log_add_destination(struct uc_log_destination *dest);
|
|||||||
*/
|
*/
|
||||||
void uc_log_remove_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.
|
/** Remove and free a destination.
|
||||||
* This frees the memory allocated to the destination. For
|
* This frees the memory allocated to the destination. For
|
||||||
* UC_LDEST_FILE the log file is closed.
|
* 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);
|
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.
|
/** Closes and re-opens all the UC_LDEST_FILE log destinations.
|
||||||
* Intended for use when a log file is rotated externally.
|
* Intended for use when a log file is rotated externally.
|
||||||
|
|||||||
@@ -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 sec seconds from now until the timer filres
|
||||||
* @param usec microseconds (after the @sec) until the timer fires.
|
* @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.
|
/** Remove a timer.
|
||||||
* Note, the timer memory must have been zeroed out or the timer must have been added at least once
|
* 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.
|
* before uc_timers_remove can be called on a UCTimer.
|
||||||
* uc_timer_remove does nothing if the timer has expired.
|
* uc_timers_remove does nothing if the timer has expired.
|
||||||
*
|
*
|
||||||
* @param timers timer engine to remove from
|
* @param timers timer engine to remove from
|
||||||
* @param timer timer to remove
|
* @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.
|
/** Get time of the first timer that will run.
|
||||||
*
|
*
|
||||||
@@ -113,11 +113,12 @@ void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer);
|
|||||||
int uc_timers_first(const struct UCTimers *timers, struct timeval *first);
|
int uc_timers_first(const struct UCTimers *timers, struct timeval *first);
|
||||||
|
|
||||||
/** Get the number of timers the engine is tracking.
|
/** Get the number of timers the engine is tracking.
|
||||||
|
* (This function is O(n) )
|
||||||
*
|
*
|
||||||
* @param timers timer engine to query
|
* @param timers timer engine to query
|
||||||
* @return the number of timers the engine keeps
|
* @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)
|
/** Check if a timer is running (i.e. hasn't expired and fired)
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ struct UCoreClock uc_time_clock = {
|
|||||||
.now = uc_time_now,
|
.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 timeval *tv)
|
||||||
{
|
{
|
||||||
struct UCoreCachedClock *cached_clock;
|
struct UCoreCachedClock *cached_clock;
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+67
-26
@@ -10,6 +10,11 @@
|
|||||||
#include "ucore/utils.h"
|
#include "ucore/utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
//used to realise per destination settings
|
||||||
|
struct uc_log_module_setting {
|
||||||
|
int log_level;
|
||||||
|
};
|
||||||
|
|
||||||
struct uc_log_destination {
|
struct uc_log_destination {
|
||||||
SLIST_ENTRY(uc_log_destination) entry;
|
SLIST_ENTRY(uc_log_destination) entry;
|
||||||
enum UC_LOG_DESTINATION dest_type;
|
enum UC_LOG_DESTINATION dest_type;
|
||||||
@@ -17,6 +22,7 @@ struct uc_log_destination {
|
|||||||
int log_level;
|
int log_level;
|
||||||
//Whether to log the source file name and line number
|
//Whether to log the source file name and line number
|
||||||
int log_location;
|
int log_location;
|
||||||
|
struct uc_log_module_setting *module_settings;
|
||||||
union {
|
union {
|
||||||
//for syslog openlog()
|
//for syslog openlog()
|
||||||
struct {
|
struct {
|
||||||
@@ -112,6 +118,22 @@ static inline int uc_ll_2_syslog(enum UC_LOG_LEVEL l)
|
|||||||
return LOG_INFO;
|
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 *uc_log_new_stderr(int log_level, int log_location)
|
||||||
{
|
{
|
||||||
struct uc_log_destination *dest = calloc(1, sizeof *dest);
|
struct uc_log_destination *dest = calloc(1, sizeof *dest);
|
||||||
@@ -119,6 +141,11 @@ struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location)
|
|||||||
if(dest == NULL)
|
if(dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (uc_log_init_settings(dest) != 0) {
|
||||||
|
free(dest);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dest->dest_type = UC_LDEST_STDERR;
|
dest->dest_type = UC_LDEST_STDERR;
|
||||||
dest->type.file.file = stderr;
|
dest->type.file.file = stderr;
|
||||||
dest->log_level = log_level;;
|
dest->log_level = log_level;;
|
||||||
@@ -135,9 +162,15 @@ struct uc_log_destination *uc_log_new_syslog(const char *ident, int facility, in
|
|||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return 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
|
//copy the ident - though it's unused inside the struct for now
|
||||||
id = strdup(ident);
|
id = strdup(ident);
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
|
free(dest->module_settings);
|
||||||
free(dest);
|
free(dest);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -162,16 +195,25 @@ struct uc_log_destination *uc_log_new_file(const char *filename, int log_level,
|
|||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (uc_log_init_settings(dest) != 0) {
|
||||||
|
free(dest);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
name = strdup(filename);
|
name = strdup(filename);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
|
free(dest->module_settings);
|
||||||
free(dest);
|
free(dest);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(filename, "a");
|
f = fopen(filename, "a");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
free(dest->module_settings);
|
||||||
free(name);
|
free(name);
|
||||||
free(dest);
|
free(dest);
|
||||||
|
errno = saved_errno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,12 +304,22 @@ void uc_log_delete_destination(struct uc_log_destination *dest)
|
|||||||
free(dest->type.file.file_name);
|
free(dest->type.file.file_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
free(dest->module_settings);
|
||||||
|
|
||||||
free(dest);
|
free(dest);
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_log_lock);
|
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)
|
static int uc_log_reopen_file(struct uc_log_destination *dest)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -311,25 +363,6 @@ void uc_log_init(struct uc_log_modules *user_modules)
|
|||||||
g_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)
|
static inline void uc_vlog_file(const struct uc_log_args *args, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
@@ -429,15 +462,25 @@ void uc_logf(int log_level, int module, int raw,
|
|||||||
else
|
else
|
||||||
log_module = &g_unknown_module;
|
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
|
//do logging for each destination
|
||||||
SLIST_FOREACH(dest, &g_destinations, entry) {
|
SLIST_FOREACH(dest, &g_destinations, entry) {
|
||||||
va_list apc;
|
va_list apc;
|
||||||
|
int module_log_level;
|
||||||
|
|
||||||
|
|
||||||
|
//destnation level
|
||||||
|
if (log_level < dest->log_level)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
if (log_level < module_log_level)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (log_level >= dest->log_level) {
|
|
||||||
const struct uc_log_args args = {
|
const struct uc_log_args args = {
|
||||||
.dest = dest,
|
.dest = dest,
|
||||||
.module = log_module,
|
.module = log_module,
|
||||||
@@ -463,9 +506,7 @@ void uc_logf(int log_level, int module, int raw,
|
|||||||
|
|
||||||
va_end(apc);
|
va_end(apc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
pthread_mutex_unlock(&g_log_lock);
|
pthread_mutex_unlock(&g_log_lock);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -26,9 +26,9 @@ static int timers_cmp(const void *a_, const void *b_)
|
|||||||
return 0; //silence compiler
|
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->state = UC_TIMER_ACTIVE;
|
||||||
timer->seq = timers->seq++;
|
timer->seq = timers->seq++;
|
||||||
timer->rb_node.data = timer; //point the data in a RBNode back to the timer that contains it.
|
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);
|
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 now;
|
||||||
struct timeval tmp;
|
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);
|
timers->uclock->now(timers->uclock, &now);
|
||||||
timeradd(&now, &tmp, &timer->timeout);
|
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.
|
if (timer->state == UC_TIMER_INACTIVE) { //already removed , or never added.
|
||||||
//debugging bandaid
|
//debugging bandaid
|
||||||
@@ -97,7 +97,7 @@ int uc_timers_first(const struct UCTimers *timers, struct timeval *first)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t uc_timer_count(const struct UCTimers *timers)
|
size_t uc_timers_count(const struct UCTimers *timers)
|
||||||
{
|
{
|
||||||
struct RBNode *n;
|
struct RBNode *n;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@@ -134,7 +134,7 @@ int uc_timers_run(struct UCTimers *timers)
|
|||||||
//Note, timercmp does not work for >=
|
//Note, timercmp does not work for >=
|
||||||
if (!timercmp(&now, &t->timeout, <)) {
|
if (!timercmp(&now, &t->timeout, <)) {
|
||||||
TAILQ_INSERT_TAIL(&timers->ready_list, t, ready_entry);
|
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
|
//it have to remove it from the ready_list
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -147,12 +147,12 @@ int uc_timers_run(struct UCTimers *timers)
|
|||||||
* Need to always pick the first item in the tail queue
|
* Need to always pick the first item in the tail queue
|
||||||
* since a timer callback could remove/free a timer
|
* since a timer callback could remove/free a timer
|
||||||
* we had in the list.
|
* 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)) {
|
while (!TAILQ_EMPTY(&timers->ready_list)) {
|
||||||
struct UCTimer *t = TAILQ_FIRST(&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);
|
assert(t->callback != NULL);
|
||||||
t->callback(timers, t); //fire
|
t->callback(timers, t); //fire
|
||||||
// callback might have free'd its timer.
|
// callback might have free'd its timer.
|
||||||
|
|||||||
+3
-3
@@ -100,11 +100,11 @@ void timer_cb(struct UCTimers *timers, struct UCTimer *timer)
|
|||||||
struct UCTimer *t = calloc(1, sizeof *t);
|
struct UCTimer *t = calloc(1, sizeof *t);
|
||||||
t->callback = timer_cb;
|
t->callback = timer_cb;
|
||||||
t->cookie_int = timer->cookie_int + 1;
|
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 = calloc(1, sizeof *t);
|
||||||
t->callback = timer_cb;
|
t->callback = timer_cb;
|
||||||
t->cookie_int = timer->cookie_int + 2;
|
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);
|
struct IOMux *mux = iomux_create(IOMUX_TYPE_EPOLL);
|
||||||
iomux_register_fd(mux, ©_ctx.in);
|
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);
|
iomux_run(mux);
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -35,8 +35,9 @@ struct uc_log_modules modules = {
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
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);
|
uc_log_init(&modules);
|
||||||
|
dest = uc_log_new_stderr(UC_LL_INFO, 0);
|
||||||
uc_log_add_destination(dest);
|
uc_log_add_destination(dest);
|
||||||
dest = uc_log_new_file("test.log", UC_LL_INFO, 1);
|
dest = uc_log_new_file("test.log", UC_LL_INFO, 1);
|
||||||
uc_log_add_destination(dest);
|
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_log_module_set_loglevel(MAIN, UC_LL_WARNING);
|
||||||
UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 3\n" );
|
UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 3\n" );
|
||||||
|
|
||||||
|
uc_log_delete_destination(dest);
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -18,6 +18,7 @@ extern Suite *buffer_suite(void);
|
|||||||
extern Suite *clock_suite(void);
|
extern Suite *clock_suite(void);
|
||||||
extern Suite *seq_suite(void);
|
extern Suite *seq_suite(void);
|
||||||
extern Suite *sat_math_suite(void);
|
extern Suite *sat_math_suite(void);
|
||||||
|
extern Suite *timers_suite(void);
|
||||||
|
|
||||||
static suite_func suites[] = {
|
static suite_func suites[] = {
|
||||||
bitvec_suite,
|
bitvec_suite,
|
||||||
@@ -31,7 +32,8 @@ static suite_func suites[] = {
|
|||||||
buffer_suite,
|
buffer_suite,
|
||||||
clock_suite,
|
clock_suite,
|
||||||
seq_suite,
|
seq_suite,
|
||||||
sat_math_suite
|
sat_math_suite,
|
||||||
|
timers_suite
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
#include <check.h>
|
||||||
|
#include <ucore/timers.h>
|
||||||
|
#include <ucore/timers.h>
|
||||||
|
#include <ucore/clock.h>
|
||||||
|
|
||||||
|
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_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_timers_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_timers_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_timers_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_timers_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_timers_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_timers_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_timers_add(&timers, &timer, 5, 0);
|
||||||
|
uc_timers_add(&timers, &timer2, 10, 0);
|
||||||
|
|
||||||
|
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);
|
||||||
|
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_timers_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;
|
||||||
|
}
|
||||||
|
|
||||||
+6
-6
@@ -25,7 +25,7 @@ void mystruct1_cb(struct UCTimers *timers, struct UCTimer *timer)
|
|||||||
struct MyStruct *mystruct = CONTAINER_OF(timer, struct MyStruct, timer);
|
struct MyStruct *mystruct = CONTAINER_OF(timer, struct MyStruct, timer);
|
||||||
|
|
||||||
TRACEF("MyStruct1 timer: %s\n", mystruct->str);
|
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)
|
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;
|
struct MyStruct *mystruct = timer->cookie_ptr;
|
||||||
|
|
||||||
TRACEF("MyStruct2 timer: %s\n", mystruct->str);
|
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[])
|
int main(int argc, char *argv[])
|
||||||
@@ -63,10 +63,10 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
uc_timers_init(&timers);
|
uc_timers_init(&timers);
|
||||||
uc_timer_add(&timers, &t1, 2, 0);
|
uc_timers_add(&timers, &t1, 2, 0);
|
||||||
uc_timer_add(&timers, &t2, 5, 0);
|
uc_timers_add(&timers, &t2, 5, 0);
|
||||||
uc_timer_add(&timers, &my_struct1.timer, 10, 0);
|
uc_timers_add(&timers, &my_struct1.timer, 10, 0);
|
||||||
uc_timer_add(&timers, &my_struct2.timer, 10, 0);
|
uc_timers_add(&timers, &my_struct2.timer, 10, 0);
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uc_timers_run(&timers);
|
uc_timers_run(&timers);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ void peer_timer_cb(struct UCTimers *timers, struct UCTimer *timer)
|
|||||||
struct HBContext *ctx = timer->cookie_ptr;
|
struct HBContext *ctx = timer->cookie_ptr;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
|
||||||
uc_timer_add(timers, timer, PEER_HB_MISS , 0);
|
uc_timers_add(timers, timer, PEER_HB_MISS , 0);
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
|
|
||||||
if (now - peer->last_ok > PEER_HB_MISS * PEER_HB_SEC) {
|
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;
|
sec = rand() % PEER_HB_SEC;
|
||||||
usec = rand() % 1000000;
|
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)
|
void peer_add(struct HBContext *ctx, const char *host, uint16_t port)
|
||||||
|
|||||||
Reference in New Issue
Block a user