Navigation


Changeset 1336:cec0812038bb in freeDiameter


Ignore:
Timestamp:
Apr 9, 2019, 10:46:50 PM (5 years ago)
Author:
Thomas Klausner <tk@giga.or.at>
Branch:
default
Phase:
public
histedit_source:
4e04e2f73d936608db88f0e70d10049fcaf66190
Message:

rt_default: add reload support.

When SIGUSR1 is sent to the freeDiameter process, rt_default reloads
its config file.

Written for Effortel Technologies SA, published with their consent.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • doc/rt_default.conf.sample

    r1197 r1336  
    22#
    33# This extension provides configurable routing properties for freeDiameter.
     4
     5# This extension supports configuration reload at runtime. Send
     6# signal SIGUSR1 to the process to cause the process to reload its
     7# config.
    48
    59# Lines starting with a # are comments and ignored.
  • extensions/rt_default/rt_default.c

    r1235 r1336  
    3838 */
    3939
     40#include <signal.h>
     41
    4042#include "rt_default.h"
     43
     44#define MODULE_NAME "rt_default"
     45
     46#include <pthread.h>
     47
     48static pthread_rwlock_t rtd_lock;
     49
     50static char *rtd_config_file;
    4151
    4252/* The callback called on new messages */
     
    4555        struct msg * msg = *pmsg;
    4656        TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
     57        int ret;
    4758       
    4859        CHECK_PARAMS(msg && candidates);
    49        
     60
     61        if (pthread_rwlock_rdlock(&rtd_lock) != 0) {
     62                fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME);
     63                return 0;
     64        }
    5065        /* Simply pass it to the appropriate function */
    5166        if (FD_IS_LIST_EMPTY(candidates)) {
    52                 return 0;
     67                ret = 0;
    5368        } else {
    54                 return rtd_process( msg, candidates );
     69                ret = rtd_process( msg, candidates );
    5570        }
     71        if (pthread_rwlock_unlock(&rtd_lock) != 0) {
     72                fd_log_notice("%s: read-unlock failed after rtd_out, exiting", MODULE_NAME);
     73                exit(1);
     74        }
     75        return ret;
    5676}
    5777
     
    5979static struct fd_rt_out_hdl * rtd_hdl = NULL;
    6080
     81static volatile int in_signal_handler = 0;
     82
     83/* signal handler */
     84static void sig_hdlr(void)
     85{
     86        if (in_signal_handler) {
     87                fd_log_error("%s: already handling a signal, ignoring new one", MODULE_NAME);
     88                return;
     89        }
     90        in_signal_handler = 1;
     91
     92        if (pthread_rwlock_wrlock(&rtd_lock) != 0) {
     93                fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME);
     94                return;
     95        }
     96        rtd_conf_reload(rtd_config_file);
     97        if (pthread_rwlock_unlock(&rtd_lock) != 0) {
     98                fd_log_error("%s: unlocking failed after config reload, exiting", MODULE_NAME);
     99                exit(1);
     100        }               
     101
     102        fd_log_notice("%s: reloaded configuration", MODULE_NAME);
     103
     104        in_signal_handler = 0;
     105}
     106
     107
    61108/* entry point */
    62109static int rtd_entry(char * conffile)
    63110{
    64111        TRACE_ENTRY("%p", conffile);
    65        
     112
     113        rtd_config_file = conffile;
     114        pthread_rwlock_init(&rtd_lock, NULL);
     115
     116        if (pthread_rwlock_wrlock(&rtd_lock) != 0) {
     117                fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME);
     118                return EDEADLK;
     119        }
     120
    66121        /* Initialize the repo */
    67122        CHECK_FCT( rtd_init() );
     
    69124        /* Parse the configuration file */
    70125        CHECK_FCT( rtd_conf_handle(conffile) );
    71        
     126
     127        if (pthread_rwlock_unlock(&rtd_lock) != 0) {
     128                fd_log_notice("%s: write-unlock failed, aborting", MODULE_NAME);
     129                return EDEADLK;
     130        }
     131
     132        /* Register reload callback */
     133        CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr));
     134
    72135#if 0
    73136        /* Dump the rules */
     
    92155        /* Destroy the data */
    93156        rtd_fini();
    94        
     157
     158        pthread_rwlock_destroy(&rtd_lock);
     159
    95160        /* Done */
    96161        return ;
    97162}
    98163
    99 EXTENSION_ENTRY("rt_default", rtd_entry);
     164EXTENSION_ENTRY(MODULE_NAME, rtd_entry);
  • extensions/rt_default/rt_default.h

    r741 r1336  
    8383int rtd_process( struct msg * msg, struct fd_list * candidates );
    8484
     85/* Reload the config file */
     86void rtd_conf_reload(char *config_file);
     87
    8588/* For debug: dump the rule repository */
    8689void rtd_dump(void);
  • extensions/rt_default/rtd_conf.y

    r1127 r1336  
    5555/* Forward declaration */
    5656int yyparse(char * conffile);
     57void rtd_confrestart(FILE *input_file);
    5758
    5859static int rules_added = 0;
     
    6667        TRACE_ENTRY("%p", conffile);
    6768       
    68         TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
    69        
     69        TRACE_DEBUG (FULL, "rt_default: Parsing configuration file: %s...", conffile);
     70
     71        rules_added = 0;
    7072        rtd_confin = fopen(conffile, "r");
    7173        if (rtd_confin == NULL) {
    7274                ret = errno;
    7375                fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
    74                 TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
     76                TRACE_DEBUG (INFO, "rt_default: Error occurred, message logged -- configuration file.");
    7577                return ret;
    7678        }
    7779
     80        rtd_confrestart(rtd_confin);
    7881        ret = yyparse(conffile);
    7982
     
    8184
    8285        if (ret != 0) {
    83                 TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
     86                TRACE_DEBUG (INFO, "rt_default: Unable to parse the configuration file.");
    8487                return EINVAL;
    8588        } else {
    86                 TRACE_DEBUG(FULL, "Added %d RULES routing entries successfully.", rules_added);
     89                TRACE_DEBUG(INFO, "rt_default: Added %d RULES routing entries successfully.", rules_added);
    8790        }
    8891       
     
    9699void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
    97100{
    98         TRACE_DEBUG(INFO, "Error in configuration parsing");
     101        TRACE_DEBUG(INFO, "rt_default: Error in configuration parsing");
    99102       
    100103        if (ploc->first_line != ploc->last_line)
  • extensions/rt_default/rtd_rules.c

    r1179 r1336  
    4747 *  Under each TARGET element, we have the list of RULES that are defined for this target, ordered by CRITERIA type, then is_regex, then string value.
    4848 *
    49  * Note: Except during configuration parsing and module termination, the lists are only ever accessed read-only, so we do not need a lock.
     49 * Note: Access these only when holding rtd_lock; config reload may change the underlying data.
    5050 */
    5151
     
    390390}
    391391
    392 /* Destroy the module's data */
    393 void rtd_fini(void)
     392static void free_targets(void)
    394393{
    395394        int i;
    396        
    397         TRACE_ENTRY();
    398395
    399396        for (i = 0; i < RTD_TAR_MAX; i++) {
     
    402399                }
    403400        }
    404        
     401}
     402
     403/* Destroy the module's data */
     404void rtd_fini(void)
     405{
     406        TRACE_ENTRY();
     407
     408        free_targets();
    405409}
    406410
     
    493497       
    494498        return 0;
     499}
     500
     501void rtd_conf_reload(char *config_file)
     502{
     503        /* save old config in case reload goes wrong */
     504        struct fd_list old_config[RTD_TAR_MAX];
     505        int i;
     506
     507        for (i = 0; i < RTD_TAR_MAX; i++) {
     508                old_config[i] = TARGETS[i];
     509        }
     510        memset(TARGETS, 0, sizeof(*TARGETS) * RTD_TAR_MAX);
     511        for (i = 0; i < RTD_TAR_MAX; i++) {
     512                fd_list_init(&TARGETS[i], NULL);
     513        }
     514
     515        if (rtd_conf_handle(config_file) != 0) {
     516                fd_log_notice("rt_default: error reloading configuration, restoring previous configuration");
     517                free_targets();
     518                for (i = 0; i < RTD_TAR_MAX; i++) {
     519                        TARGETS[i] = old_config[i];
     520                }
     521        } else {
     522                /* this has to be done in this weird way because the items contain back pointers referencing TARGETS */
     523                struct fd_list save_config[RTD_TAR_MAX];
     524                for (i = 0; i < RTD_TAR_MAX; i++) {
     525                        save_config[i] = TARGETS[i];
     526                        TARGETS[i] = old_config[i];
     527                }
     528                free_targets();
     529                for (i = 0; i < RTD_TAR_MAX; i++) {
     530                        TARGETS[i] = save_config[i];
     531                }
     532        }
    495533}
    496534
Note: See TracChangeset for help on using the changeset viewer.