From 7e1a00669c5fb37cb69583366147b4e3e707706b Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Thu, 25 Apr 2024 14:49:06 +0200 Subject: [PATCH] Event priority. Backend socket has higher prio. --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 6 +- apps/backend/backend_socket.c | 7 +- apps/restconf/restconf_stream_fcgi.c | 2 +- lib/clixon/clixon_event.h | 13 +--- lib/src/clixon_event.c | 94 ++++++++++++++++------- yang/clixon/clixon-config@2024-04-01.yang | 13 ++++ 7 files changed, 89 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df128ad7..af8c90b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: branches: - master - - datastore-split + - test-actions pull_request: branches: [ master ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c05100..93af25a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,15 +15,17 @@ Expected: June 2024 ### Features +* New: Event priority. Backend socket has higher prio * New: Split configure datastore multiple sub-files on mount-point boundaries - * Avoid writung sub-files without new data (dirty cache) + * Avoid writing sub-files without new data (dirty cache) * Added: Code for SHA digests. * New: [Autolock](https://github.com/clicon/clixon/issues/508) * CLI configurable format: [Default format should be configurable](https://github.com/clicon/clixon-controller/issues/87) * CLI support for multiple inline commands separated by semi-colon * New `clixon-config@2024-04-01.yang` revision * Added options: - - `CLICON_XMLDB_MULTIPLE`: Split datastore into multiple sub files + - `CLICON_SOCK_PRIO`: Enable socket event priority + - `CLICON_XMLDB_MULTI`: Split datastore into multiple sub files - `CLICON_NETCONF_DUPLICATE_ALLOW`: Disable duplicate check in NETCONF messages - `CLICON_CLI_OUTPUT_FORMAT`: Default CLI output format - `CLICON_AUTOLOCK`: Implicit locks diff --git a/apps/backend/backend_socket.c b/apps/backend/backend_socket.c index a63d4f9e..79fe59fc 100644 --- a/apps/backend/backend_socket.c +++ b/apps/backend/backend_socket.c @@ -253,7 +253,6 @@ backend_accept_client(int fd, } if ((ce = backend_client_add(h, &from)) == NULL) goto done; - /* * Get credentials of connected peer - only for unix socket */ @@ -291,11 +290,11 @@ backend_accept_client(int fd, break; } ce->ce_s = s; - /* - * Here we register callbacks for actual data socket + * Register callback for actual data socket */ - if (clixon_event_reg_fd(s, from_client, (void*)ce, "local netconf client socket") < 0) + if (clixon_event_reg_fd_prio(s, from_client, (void*)ce, "local netconf client socket", + clicon_option_bool(h, "CLICON_SOCK_PRIO")) < 0) goto done; s = -1; retval = 0; diff --git a/apps/restconf/restconf_stream_fcgi.c b/apps/restconf/restconf_stream_fcgi.c index 58c2aa36..63ff7b78 100644 --- a/apps/restconf/restconf_stream_fcgi.c +++ b/apps/restconf/restconf_stream_fcgi.c @@ -170,7 +170,7 @@ stream_child_free(clixon_handle h, goto done; } sc = NEXTQ(struct stream_child *, sc); - } while (sc && sc != STREAM_CHILD); + } while (sc && sc != STREAM_CHILD); } done: return 0; diff --git a/lib/clixon/clixon_event.h b/lib/clixon/clixon_event.h index 4ca7b11e..2f36d112 100644 --- a/lib/clixon/clixon_event.h +++ b/lib/clixon/clixon_event.h @@ -44,30 +44,19 @@ * Prototypes */ int clixon_exit_set(int nr); - int clixon_exit_get(void); - int clicon_sig_child_set(int val); - int clicon_sig_child_get(void); - int clicon_sig_ignore_set(int val); - int clicon_sig_ignore_get(void); - int clixon_event_reg_fd(int fd, int (*fn)(int, void*), void *arg, char *str); - +int clixon_event_reg_fd_prio(int fd, int (*fn)(int, void*), void *arg, char *str, int prio); int clixon_event_unreg_fd(int s, int (*fn)(int, void*)); - int clixon_event_reg_timeout(struct timeval t, int (*fn)(int, void*), void *arg, char *str); - int clixon_event_unreg_timeout(int (*fn)(int, void*), void *arg); - int clixon_event_poll(int fd); - int clixon_event_loop(clixon_handle h); - int clixon_event_exit(void); #endif /* _CLIXON_EVENT_H_ */ diff --git a/lib/src/clixon_event.c b/lib/src/clixon_event.c index a01db725..2e6b4f96 100644 --- a/lib/src/clixon_event.c +++ b/lib/src/clixon_event.c @@ -66,6 +66,7 @@ #include "clixon_err.h" #include "clixon_sig.h" #include "clixon_proc.h" +#include "clixon_options.h" #include "clixon_event.h" /* @@ -77,13 +78,14 @@ * Types */ struct event_data{ - struct event_data *e_next; /* next in list */ - int (*e_fn)(int, void*); /* function */ - enum {EVENT_FD, EVENT_TIME} e_type; /* type of event */ - int e_fd; /* File descriptor */ - struct timeval e_time; /* Timeout */ - void *e_arg; /* function argument */ - char e_string[EVENT_STRLEN]; /* string for debugging */ + struct event_data *e_next; /* Next in list */ + int (*e_fn)(int, void*); /* Callback function */ + enum {EVENT_FD, EVENT_TIME} e_type; /* Type of event */ + int e_fd; /* File descriptor */ + int e_prio; /* 1: high-prio FD:s only*/ + struct timeval e_time; /* Timeout */ + void *e_arg; /* Function argument */ + char e_string[EVENT_STRLEN]; /* String for debugging */ }; /* @@ -168,10 +170,11 @@ clicon_sig_ignore_get(void) /*! Register a callback function to be called on input on a file descriptor. * - * @param[in] fd File descriptor - * @param[in] fn Function to call when input available on fd - * @param[in] arg Argument to function fn - * @param[in] str Describing string for logging + * @param[in] fd File descriptor + * @param[in] fn Function to call when input available on fd + * @param[in] arg Argument to function fn + * @param[in] str Describing string for logging + * @param[in] prio Priority (0 or 1) * @code * int fn(int fd, void *arg){ * } @@ -180,10 +183,11 @@ clicon_sig_ignore_get(void) * @see clixon_event_unreg_fd */ int -clixon_event_reg_fd(int fd, - int (*fn)(int, void*), - void *arg, - char *str) +clixon_event_reg_fd_prio(int fd, + int (*fn)(int, void*), + void *arg, + char *str, + int prio) { struct event_data *e; @@ -197,12 +201,22 @@ clixon_event_reg_fd(int fd, e->e_fn = fn; e->e_arg = arg; e->e_type = EVENT_FD; + e->e_prio = prio; e->e_next = ee; ee = e; - clixon_debug(CLIXON_DBG_EVENT | CLIXON_DBG_DETAIL, "registering %s", e->e_string); + clixon_debug(CLIXON_DBG_EVENT, "registering %s", e->e_string); return 0; } +int +clixon_event_reg_fd(int fd, + int (*fn)(int, void*), + void *arg, + char *str) +{ + return clixon_event_reg_fd_prio(fd, fn, arg, str, 0); +} + /*! Deregister a file descriptor callback * * @param[in] s File descriptor @@ -217,9 +231,9 @@ int clixon_event_unreg_fd(int s, int (*fn)(int, void*)) { - struct event_data *e; - struct event_data **e_prev; + struct event_data *e; int found = 0; + struct event_data **e_prev; e_prev = ⅇ for (e = ee; e; e = e->e_next){ @@ -315,8 +329,9 @@ int clixon_event_unreg_timeout(int (*fn)(int, void*), void *arg) { - struct event_data *e, **e_prev; - int found = 0; + struct event_data *e; + int found = 0; + struct event_data **e_prev; e_prev = &ee_timers; for (e = ee_timers; e; e = e->e_next){ @@ -365,13 +380,13 @@ int clixon_event_loop(clixon_handle h) { struct event_data *e; - struct event_data *e_next; int n; struct timeval t; struct timeval t0; struct timeval tnull = {0,}; fd_set fdset; int retval = -1; + struct event_data *e_next; while (clixon_exit_get() != 1){ FD_ZERO(&fdset); @@ -409,7 +424,7 @@ clixon_event_loop(clixon_handle h) * New select loop is called * (3) Other signals result in an error and return -1. */ - clixon_debug(CLIXON_DBG_EVENT | CLIXON_DBG_DETAIL, "select: %s", strerror(errno)); + clixon_debug(CLIXON_DBG_EVENT, "select: %s", strerror(errno)); if (clixon_exit_get() == 1){ clixon_err(OE_EVENTS, errno, "select"); retval = 0; @@ -443,13 +458,33 @@ clixon_event_loop(clixon_handle h) free(e); } _ee_unreg = 0; - for (e=ee; e; e=e_next){ - if (clixon_exit_get() == 1){ - break; + if (clicon_option_bool(h, "CLICON_SOCK_PRIO")){ + for (e=ee; e; e=e_next) { + if (clixon_exit_get() == 1) + break; + e_next = e->e_next; + if (e->e_type == EVENT_FD && FD_ISSET(e->e_fd, &fdset) && e->e_prio){ + clixon_debug(CLIXON_DBG_EVENT, "FD_ISSET: %s prio:%d", e->e_string, e->e_prio); + if ((*e->e_fn)(e->e_fd, e->e_arg) < 0){ + clixon_debug(CLIXON_DBG_EVENT, "Error in: %s", e->e_string); + goto err; + } + if (_ee_unreg){ + _ee_unreg = 0; + break; + } + } } + } + + /* Unprio + * Note that without prio, round-robin fairness is ensured, not with prio */ + for (e=ee; e; e=e_next){ + if (clixon_exit_get() == 1) + break; e_next = e->e_next; - if(e->e_type == EVENT_FD && FD_ISSET(e->e_fd, &fdset)){ - clixon_debug(CLIXON_DBG_EVENT | CLIXON_DBG_DETAIL, "FD_ISSET: %s", e->e_string); + if (e->e_type == EVENT_FD && FD_ISSET(e->e_fd, &fdset) && e->e_prio==0){ + clixon_debug(CLIXON_DBG_EVENT, "FD_ISSET: %s", e->e_string); if ((*e->e_fn)(e->e_fd, e->e_arg) < 0){ clixon_debug(CLIXON_DBG_EVENT, "Error in: %s", e->e_string); goto err; @@ -458,6 +493,8 @@ clixon_event_loop(clixon_handle h) _ee_unreg = 0; break; } + if (clicon_option_bool(h, "CLICON_SOCK_PRIO")) + break; } } clixon_exit_decr(); /* If exit is set and > 1, decrement it (and exit when 1) */ @@ -475,7 +512,8 @@ clixon_event_loop(clixon_handle h) int clixon_event_exit(void) { - struct event_data *e, *e_next; + struct event_data *e; + struct event_data *e_next; e_next = ee; while ((e = e_next) != NULL){ diff --git a/yang/clixon/clixon-config@2024-04-01.yang b/yang/clixon/clixon-config@2024-04-01.yang index c958433c..efe65808 100644 --- a/yang/clixon/clixon-config@2024-04-01.yang +++ b/yang/clixon/clixon-config@2024-04-01.yang @@ -52,6 +52,7 @@ module clixon-config { revision 2024-04-01 { description "Added options: + CLICON_SOCK_PRIO: Enable socket event priority CLICON_XMLDB_MULTI: Split datastore into multiple sub files CLICON_NETCONF_DUPLICATE_ALLOW: Disable duplicate check in NETCONF messages. CLICON_CLI_OUTPUT_FORMAT: Default CLI output format @@ -927,6 +928,18 @@ module clixon-config { "Group membership to access clixon_backend unix socket and gid for deamon"; } + leaf CLICON_SOCK_PRIO { + type boolean; + default false; + description + "Enable socket event priority. + If enabled, a file-descriptor can be registered as high prio. + Presently, the backend socket has higher prio than others. + (should be made more generic) + Note that a side-effect of enabling this option is that fairness of + non-prio events is disabled + This is useful if the backend opens other sockets, such as the controller"; + } leaf CLICON_BACKEND_USER { type string; description