Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: doc/userguide/userguide.xml
- ===================================================================
- --- doc/userguide/userguide.xml (revision 5009)
- +++ doc/userguide/userguide.xml (working copy)
- @@ -2007,11 +2007,26 @@
- </entry></row>
- <row><entry><literal>restart</literal></entry>
- - <entry valign="bottom">
- + <entry valign="bottom">
- Re-start whole bearerbox, hence all SMSC links. Password required.
- - Beware that you loose the smsbox connections in such a case.
- - </entry></row>
- + This is the hard restarting version, where we fully stop the
- + bearerbox and then initiate from ground up.
- + Beware that you loose the smsbox connections in such a case.
- + </entry></row>
- + <row><entry><literal>graceful-restart</literal></entry>
- + <entry valign="bottom">
- + Re-start bearerbox gracefully, hence only the changes in the
- + configuration for the SMSC connections are performed. I.e.
- + an added SMSC group will be start, and a removed SMSC group
- + will be shutdown and destroyed. Any unchanged SMSC connection
- + keeps on running without interruption. Password required.
- + This is the soft restarting version, where we keep all internal
- + parts of the bearebox running, including the smsbox connections.
- + The same graceful restart can be initiated by sending a SIGHUP
- + signal to the bearerbox daemon process.
- + </entry></row>
- +
- <row><entry><literal>loglevel</literal></entry>
- <entry valign="bottom">
- Set Kannel log-level of log-files while running. This allows
- @@ -10429,9 +10444,12 @@
- to /etc/logrotate.d) is shown below. In this example the Kannel log files found
- in /var/log/kannel are rotated and compressed daily over 365 days. See the
- documentation for logrotate for more details. Of particular note however is the
- - postrotate command, this killall -HUP issues a HUP command to each Kannel
- - box running. The HUP signal has the effect of reopening the log file, without this
- - command Kannel will continue to write to the rotated log file.
- + postrotate command, this killall -HUP issues a SIGHUP signal to each Kannel
- + box process running. The SIGHUP signal has the effect of reopening the log file,
- + and performing graceful restart of SMSC connections. Without this command Kannel
- + will continue to write to the rotated log file. Kannel bearerbox has can use the
- + SIGUSR2 to reopen the logs only, without performing the graceful restart. This
- + may be more applicable for logrotate usage.
- </para>
- <screen><userinput>
- @@ -10445,7 +10463,7 @@
- create 640 kannel adm
- sharedscripts
- postrotate
- - killall -HUP bearerbox smsbox wapbox || true > /dev/null 2> /dev/null
- + killall -USR2 bearerbox && killall -HUP smsbox wapbox || true > /dev/null 2> /dev/null
- endscript
- }
- </userinput></screen>
- Index: gw/bb_http.c
- ===================================================================
- --- gw/bb_http.c (revision 4986)
- +++ gw/bb_http.c (working copy)
- @@ -236,6 +236,21 @@
- return octstr_create("Restarting.....");
- }
- +static Octstr *httpd_graceful_restart(List *cgivars, int status_type)
- +{
- + Octstr *reply;
- + if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
- + if ((reply = httpd_check_status())!= NULL) return reply;
- +
- + if (bb_status == BB_SHUTDOWN) {
- + bb_status = BB_DEAD;
- + bb_restart();
- + return octstr_create("Already in shutdown phase, restarting hard...");
- + }
- + bb_graceful_restart();
- + return octstr_create("Restarting gracefully.....");
- +}
- +
- static Octstr *httpd_flush_dlr(List *cgivars, int status_type)
- {
- Octstr *reply;
- @@ -345,6 +360,7 @@
- { "isolate", httpd_isolate },
- { "resume", httpd_resume },
- { "restart", httpd_restart },
- + { "graceful-restart", httpd_graceful_restart },
- { "flush-dlr", httpd_flush_dlr },
- { "stop-smsc", httpd_stop_smsc },
- { "start-smsc", httpd_restart_smsc },
- Index: gw/bb_smscconn.c
- ===================================================================
- --- gw/bb_smscconn.c (revision 5002)
- +++ gw/bb_smscconn.c (working copy)
- @@ -127,6 +127,7 @@
- static volatile sig_atomic_t smsc_running;
- static List *smsc_list;
- static RWLock smsc_list_lock;
- +static Cfg *cfg_reloaded;
- static List *smsc_groups;
- static Octstr *unified_prefix;
- @@ -554,17 +555,16 @@
- int bb_reload_smsc_groups()
- {
- - Cfg *cfg;
- -
- - debug("bb.sms", 0, "Reloading groups list from disk");
- - cfg = cfg_create(cfg_filename);
- - if (cfg_read(cfg) == -1) {
- + debug("bb.sms", 0, "Reloading smsc groups list from config resource");
- + cfg_destroy(cfg_reloaded);
- + cfg_reloaded = cfg_create(cfg_filename);
- + if (cfg_read(cfg_reloaded) == -1) {
- warning(0, "Error opening configuration file %s", octstr_get_cstr(cfg_filename));
- return -1;
- }
- - if (smsc_groups != NULL)
- - gwlist_destroy(smsc_groups, NULL);
- - smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
- + gwlist_destroy(smsc_groups, NULL);
- + smsc_groups = cfg_get_multi_group(cfg_reloaded, octstr_imm("smsc"));
- +
- return 0;
- }
- @@ -573,8 +573,6 @@
- * Other functions
- */
- -
- -
- /* function to route outgoing SMS'es from delay-list
- * use some nice magics to route them to proper SMSC
- */
- @@ -653,8 +651,68 @@
- }
- +static int cmp_conn_grp_checksum(void *a, void *b)
- +{
- + int ret;
- + SMSCConn *conn = a;
- + Octstr *os = cfg_get_group_checksum((CfgGroup*)b, NULL);
- + ret = (octstr_compare(conn->chksum, os) == 0);
- + octstr_destroy(os);
- + return ret;
- +}
- +
- +
- +static int cmp_rout_grp_checksum(void *a, void *b)
- +{
- + int ret;
- + SMSCConn *conn = a;
- + Octstr *os;
- +
- +#define OCTSTR(os) octstr_imm(#os)
- +
- + os = cfg_get_group_checksum((CfgGroup*)b,
- + OCTSTR(denied-smsc-id),
- + OCTSTR(allowed-smsc-id),
- + OCTSTR(preferred-smsc-id),
- + OCTSTR(allowed-prefix),
- + OCTSTR(denied-prefix),
- + OCTSTR(preferred-prefix),
- + OCTSTR(unified-prefix),
- + OCTSTR(reroute),
- + OCTSTR(reroute-smsc-id),
- + OCTSTR(reroute-receiver),
- + OCTSTR(reroute-dlr),
- + OCTSTR(allowed-smsc-id-regex),
- + OCTSTR(denied-smsc-id-regex),
- + OCTSTR(preferred-smsc-id-regex),
- + OCTSTR(allowed-prefix-regex),
- + OCTSTR(denied-prefix-regex),
- + OCTSTR(preferred-prefix-regex),
- + NULL
- + );
- +
- + ret = (octstr_compare(conn->chksum_conn, os) == 0);
- + octstr_destroy(os);
- +
- + return ret;
- +}
- +
- +
- +static int cmp_conn_grp_id(void *a, void *b)
- +{
- + int ret;
- + SMSCConn *conn = a;
- + Octstr *os = cfg_get((CfgGroup*)b, octstr_imm("smsc-id"));
- +
- + ret = (os && octstr_compare(conn->id, os) == 0);
- + octstr_destroy(os);
- +
- + return ret;
- +}
- +
- +
- /*-------------------------------------------------------------
- * public functions
- *
- @@ -669,6 +727,9 @@
- if (smsc_running) return -1;
- + /* at start-up time there is no reloaded config */
- + cfg_reloaded = NULL;
- +
- /* create split sms counter */
- split_msg_counter = counter_create();
- @@ -1236,6 +1297,7 @@
- break;
- default:
- sprintf(tmp3, "unknown");
- + break;
- }
- if (status_type == BBSTATUS_XML)
- @@ -1278,9 +1340,6 @@
- lb);
- }
- -
- -
- -
- gw_rwlock_unlock(&smsc_list_lock);
- if (para)
- @@ -1293,6 +1352,156 @@
- }
- +int smsc2_graceful_restart(void)
- +{
- + CfgGroup *grp;
- + SMSCConn *conn;
- + List *keep, *add, *remove;
- + List *l;
- + int i;
- +
- + if (!smsc_running)
- + return -1;
- +
- + gw_rwlock_wrlock(&smsc_list_lock);
- +
- + /* load the smsc groups from the config resource */
- + if (bb_reload_smsc_groups() != 0) {
- + gw_rwlock_unlock(&smsc_list_lock);
- + return -1;
- + }
- +
- + /* List of SMSCConn that we keep running */
- + keep = gwlist_create();
- +
- + /* List of CfgGroup that we will add */
- + add = gwlist_create();
- +
- + /* List of SMSCConnn that we will shutdown */
- + remove = gwlist_create();
- +
- + /*
- + * Loop through the loaded smsc groups
- + */
- + for (i = 0; i < gwlist_len(smsc_groups) &&
- + (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
- + /*
- + * 1st check: Search for the same md5 hash of the whole group.
- + * If we find it, then this group is already running, and no
- + * routing information has changed, bail out.
- + */
- + if ((conn = gwlist_search(smsc_list, grp, cmp_conn_grp_checksum)) != NULL) {
- + gwlist_append(keep, conn);
- + continue;
- + }
- + /*
- + * 2nd check: Search for the same md5 hash minus the routing
- + * information. If we find it, then this group is already running
- + * and the routing information changed, we'll apply only the new
- + * routing information.
- + */
- + if ((conn = gwlist_search(smsc_list, grp, cmp_rout_grp_checksum)) != NULL) {
- + gwlist_append(keep, conn);
- + smscconn_reconfig(conn, grp);
- + info(0, "Re-configured routing for smsc-id `%s'.", octstr_get_cstr(conn->id));
- + continue;
- + }
- + /*
- + * 3nd check: if the smsc-id is NOT in the running list, then
- + * this is a new group, add it. If the smsc-id IS found, then
- + * mark it/them to be removed, and add the new group.
- + */
- + if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_id)) == NULL) {
- + gwlist_append(add, grp);
- + continue;
- + } else {
- + while ((conn = gwlist_extract_first(l)) != NULL) {
- + /* add them to the remove list only
- + * if they are not yet present inside. */
- + if (gwlist_search_equal(remove, conn) != -1)
- + gwlist_append(remove, conn);
- + }
- + gwlist_destroy(l, NULL);
- + gwlist_append(add, grp);
- + continue;
- + }
- + }
- +
- + /*
- + * We may have running smsc-ids now, that haven't been
- + * re-loaded from the new config, hence add them to be removed.
- + */
- + for (i = 0; i < gwlist_len(smsc_list) &&
- + (conn = gwlist_get(smsc_list, i)) != NULL; i++) {
- + /* if this is already in the remove list, bail out. */
- + if (gwlist_search_equal(remove, conn) != -1)
- + continue;
- + /* if this is in the keep list, bail out. */
- + if (gwlist_search_equal(keep, conn) != -1)
- + continue;
- + /* mark it to be removed */
- + gwlist_append(remove, conn);
- + }
- + gwlist_destroy(keep, NULL);
- +
- + /*
- + * Stop any connections from the remove list.
- + *
- + * The smscconn_shutdown() only initiates the shutdown,
- + * it is not guaranteed that the SMSC connection is stopped
- + * and the status is SMSCCONN_DEAD when we return from the
- + * function call. Therefore we pass the connection to a
- + * retry list, in order to cleanly destroy all connection
- + * structures that have been stopped and reached SMSSCONN_DEAD.
- + */
- + l = gwlist_create();
- + gwlist_add_producer(smsc_list);
- + while ((conn = gwlist_extract_first(remove)) != NULL) {
- + if ((i = gwlist_search_equal(smsc_list, conn)) != -1) {
- + gwlist_delete(smsc_list, i, 1);
- + smscconn_shutdown(conn, 0);
- + /* if smsc is still in shutdown, then add to retry list */
- + if (smscconn_destroy(conn) == -1)
- + gwlist_append(l, conn);
- + }
- + }
- + gwlist_remove_producer(smsc_list);
- + gwlist_destroy(remove, NULL);
- +
- + /*
- + * Start any connections from the add list.
- + */
- + gwlist_add_producer(smsc_list);
- + while ((grp = gwlist_extract_first(add)) != NULL) {
- + conn = smscconn_create(grp, 1);
- + if (conn != NULL)
- + gwlist_append(smsc_list, conn);
- + }
- + gwlist_remove_producer(smsc_list);
- + gwlist_destroy(add, NULL);
- +
- + gw_rwlock_unlock(&smsc_list_lock);
- +
- + /* wake-up the router */
- + if (router_thread >= 0)
- + gwthread_wakeup(router_thread);
- +
- + /*
- + * We may still have pending connections in the retry list
- + * that haven't been destroyed yet.
- + */
- + while ((conn = gwlist_extract_first(l)) != NULL) {
- + if (smscconn_destroy(conn) == -1) {
- + gwlist_append(l, conn);
- + gwthread_sleep(2);
- + }
- + }
- + gwlist_destroy(l, NULL);
- +
- + return 0;
- +}
- +
- +
- /* function to route outgoing SMS'es
- *
- * If finds a good one, puts into it and returns SMSCCONN_SUCCESS
- Index: gw/bearerbox.c
- ===================================================================
- --- gw/bearerbox.c (revision 5002)
- +++ gw/bearerbox.c (working copy)
- @@ -135,8 +135,9 @@
- * Flags for main thread to check what is to do.
- */
- enum {
- - BB_LOGREOPEN = 1,
- - BB_CHECKLEAKS = 2
- + BB_GRACEFUL_RESTART = 1,
- + BB_CHECKLEAKS = 2,
- + BB_LOGREOPEN = 3
- };
- /* Here we will set above flags */
- static volatile sig_atomic_t bb_todo = 0;
- @@ -191,6 +192,10 @@
- break;
- case SIGHUP:
- + bb_todo |= BB_GRACEFUL_RESTART;
- + break;
- +
- + case SIGUSR2:
- bb_todo |= BB_LOGREOPEN;
- break;
- @@ -216,6 +221,7 @@
- sigaction(SIGQUIT, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGPIPE, &act, NULL);
- + sigaction(SIGUSR2, &act, NULL);
- }
- @@ -749,8 +755,16 @@
- continue;
- }
- + if (bb_todo & BB_GRACEFUL_RESTART) {
- + warning(0, "SIGHUP received, re-opening logs and gracefully restarting.");
- + log_reopen();
- + alog_reopen();
- + bb_graceful_restart();
- + bb_todo = bb_todo & ~BB_GRACEFUL_RESTART;
- + }
- +
- if (bb_todo & BB_LOGREOPEN) {
- - warning(0, "SIGHUP received, catching and re-opening logs");
- + warning(0, "SIGUSR2 received, re-opening logs.");
- log_reopen();
- alog_reopen();
- bb_todo = bb_todo & ~BB_LOGREOPEN;
- @@ -928,6 +942,11 @@
- return bb_shutdown();
- }
- +int bb_graceful_restart(void)
- +{
- + return smsc2_graceful_restart();
- +}
- +
- int bb_reload_lists(void)
- {
- return smsc2_reload_lists();
- Index: gw/bearerbox.h
- ===================================================================
- --- gw/bearerbox.h (revision 5002)
- +++ gw/bearerbox.h (working copy)
- @@ -150,6 +150,7 @@
- int smsc2_start(Cfg *config);
- int smsc2_restart(Cfg *config);
- +int smsc2_graceful_restart(void);
- void smsc2_suspend(void); /* suspend (can still send but not receive) */
- void smsc2_resume(int is_init); /* resume */
- @@ -212,6 +213,7 @@
- int bb_suspend(void);
- int bb_resume(void);
- int bb_restart(void);
- +int bb_graceful_restart(void);
- int bb_flush_dlr(void);
- int bb_stop_smsc(Octstr *id);
- int bb_add_smsc(Octstr *id);
- Index: gw/smscconn.c
- ===================================================================
- --- gw/smscconn.c (revision 5003)
- +++ gw/smscconn.c (working copy)
- @@ -109,7 +109,7 @@
- if ((rule = cfg_get(grp, octstr_imm("reroute-receiver"))) != NULL) {
- List *routes;
- - /* create hash disctionary for this smsc-id */
- + /* create hash dictionary for this smsc-id */
- conn->reroute_by_receiver = dict_create(100, (void(*)(void *)) octstr_destroy);
- routes = octstr_split(rule, octstr_imm(";"));
- @@ -169,6 +169,33 @@
- conn->connect_time = -1;
- conn->is_stopped = start_as_stopped;
- +#define OCTSTR(os) octstr_imm(#os)
- +
- + /* checksum of the whole config */
- + conn->chksum = cfg_get_group_checksum(grp, NULL);
- +
- + /* checksum of the connection related part, without routing */
- + conn->chksum_conn = cfg_get_group_checksum(grp,
- + OCTSTR(denied-smsc-id),
- + OCTSTR(allowed-smsc-id),
- + OCTSTR(preferred-smsc-id),
- + OCTSTR(allowed-prefix),
- + OCTSTR(denied-prefix),
- + OCTSTR(preferred-prefix),
- + OCTSTR(unified-prefix),
- + OCTSTR(reroute),
- + OCTSTR(reroute-smsc-id),
- + OCTSTR(reroute-receiver),
- + OCTSTR(reroute-dlr),
- + OCTSTR(allowed-smsc-id-regex),
- + OCTSTR(denied-smsc-id-regex),
- + OCTSTR(preferred-smsc-id-regex),
- + OCTSTR(allowed-prefix-regex),
- + OCTSTR(denied-prefix-regex),
- + OCTSTR(preferred-prefix-regex),
- + NULL
- + );
- +
- conn->received = counter_create();
- conn->received_dlr = counter_create();
- conn->sent = counter_create();
- @@ -335,10 +362,11 @@
- void smscconn_shutdown(SMSCConn *conn, int finish_sending)
- {
- gw_assert(conn != NULL);
- +
- mutex_lock(conn->flow_mutex);
- if (conn->status == SMSCCONN_DEAD) {
- - mutex_unlock(conn->flow_mutex);
- - return;
- + mutex_unlock(conn->flow_mutex);
- + return;
- }
- /* Call SMSC specific destroyer */
- @@ -348,10 +376,10 @@
- * and will try to lock this mutex.Otherwise we have deadlock!
- */
- mutex_unlock(conn->flow_mutex);
- - conn->shutdown(conn, finish_sending);
- + conn->shutdown(conn, finish_sending);
- }
- else {
- - conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
- + conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
- mutex_unlock(conn->flow_mutex);
- }
- @@ -390,6 +418,8 @@
- octstr_destroy(conn->unified_prefix);
- octstr_destroy(conn->our_host);
- octstr_destroy(conn->log_file);
- + octstr_destroy(conn->chksum);
- + octstr_destroy(conn->chksum_conn);
- if (conn->denied_smsc_id_regex != NULL) gw_regex_destroy(conn->denied_smsc_id_regex);
- if (conn->allowed_smsc_id_regex != NULL) gw_regex_destroy(conn->allowed_smsc_id_regex);
- @@ -658,3 +688,57 @@
- }
- +void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp)
- +{
- + Octstr *tmp;
- +
- + gw_assert(conn != NULL);
- +
- + if (grp == NULL)
- + return;
- +
- +#define GET_OPTIONAL_VAL(x, n) \
- + octstr_destroy(x); \
- + x = cfg_get(grp, octstr_imm(n))
- +#define SPLIT_OPTIONAL_VAL(x, n) \
- + gwlist_destroy(x, octstr_destroy_item); \
- + if ((tmp = cfg_get(grp, octstr_imm(n))) != NULL) \
- + x = octstr_split(tmp, octstr_imm(";")); \
- + else \
- + x = NULL; \
- + octstr_destroy(tmp);
- +#define GET_OPTIONAL_REGEX(x, n) \
- + gw_regex_destroy(x); \
- + if ((tmp = cfg_get(grp, octstr_imm(n))) != NULL) { \
- + if ((x = gw_regex_comp(tmp, REG_EXTENDED)) == NULL) \
- + error(0, "Could not compile pattern '%s'", octstr_get_cstr(tmp)); \
- + octstr_destroy(tmp); \
- + }
- +
- + SPLIT_OPTIONAL_VAL(conn->allowed_smsc_id, "allowed-smsc-id");
- + SPLIT_OPTIONAL_VAL(conn->denied_smsc_id, "denied-smsc-id");
- + SPLIT_OPTIONAL_VAL(conn->preferred_smsc_id, "preferred-smsc-id");
- + GET_OPTIONAL_VAL(conn->allowed_prefix, "allowed-prefix");
- + GET_OPTIONAL_VAL(conn->denied_prefix, "denied-prefix");
- + GET_OPTIONAL_VAL(conn->preferred_prefix, "preferred-prefix");
- + GET_OPTIONAL_VAL(conn->unified_prefix, "unified-prefix");
- + GET_OPTIONAL_REGEX(conn->allowed_smsc_id_regex, "allowed-smsc-id-regex");
- + GET_OPTIONAL_REGEX(conn->denied_smsc_id_regex, "denied-smsc-id-regex");
- + GET_OPTIONAL_REGEX(conn->preferred_smsc_id_regex, "preferred-smsc-id-regex");
- + GET_OPTIONAL_REGEX(conn->allowed_prefix_regex, "allowed-prefix-regex");
- + GET_OPTIONAL_REGEX(conn->denied_prefix_regex, "denied-prefix-regex");
- + GET_OPTIONAL_REGEX(conn->preferred_prefix_regex, "preferred-prefix-regex");
- +
- + octstr_destroy(conn->reroute_to_smsc);
- + dict_destroy(conn->reroute_by_receiver);
- + init_reroute(conn, grp);
- +
- + /*
- + * Since we applied changes, we need to re-compute
- + * at least the overall checksum. The other one
- + * is not changed as the routing values are excluded.
- + * also the checksum hash values.
- + */
- + octstr_destroy(conn->chksum);
- + conn->chksum = cfg_get_group_checksum(grp, NULL);
- +}
- Index: gw/smscconn.h
- ===================================================================
- --- gw/smscconn.h (revision 4986)
- +++ gw/smscconn.h (working copy)
- @@ -199,5 +199,9 @@
- */
- int smscconn_info(SMSCConn *smscconn, StatusInfo *infotable);
- +/* Reconfigure the running SMSC for any routing relevant
- + * information from the configuration group.
- + */
- +void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp);
- #endif
- Index: gw/smscconn_p.h
- ===================================================================
- --- gw/smscconn_p.h (revision 5003)
- +++ gw/smscconn_p.h (working copy)
- @@ -168,6 +168,8 @@
- /* SMSCConn variables set in smscconn.c */
- volatile sig_atomic_t is_stopped;
- + Octstr *chksum; /* MD5 hash of the whole configuration */
- + Octstr *chksum_conn; /* MD5 hash minus the routing configuration */
- Octstr *name; /* Descriptive name filled from connection info */
- Octstr *id; /* Abstract name specified in configuration and
- used for logging and routing */
- Index: gwlib/cfg.c
- ===================================================================
- --- gwlib/cfg.c (revision 4986)
- +++ gwlib/cfg.c (working copy)
- @@ -146,6 +146,21 @@
- }
- +static int octstr_sort_cb(const void *a, const void *b)
- +{
- + const Octstr *fa = a;
- + const Octstr *fb = b;
- +
- + return octstr_compare(fa, fb);
- +}
- +
- +
- +static int octstr_cmp_cb(void *a, void *b)
- +{
- + return (octstr_compare((Octstr*)a, (Octstr*)b) == 0);
- +}
- +
- +
- struct Cfg {
- Octstr *filename;
- Dict *single_groups;
- @@ -647,6 +662,56 @@
- return octstr_duplicate(grp->name);
- }
- +Octstr *cfg_get_group_checksum(CfgGroup *grp, ...)
- +{
- + va_list args;
- + Octstr *ret, *os, *key, *val;
- + List *exclude, *keys;
- +
- + exclude = gwlist_create();
- +
- + /*
- + * Variadic Octstr* arguments may contain the
- + * config key names that DO NOT go into the
- + * checksum computation. This allows differential
- + * compares and detection of single changes.
- + */
- + va_start(args, grp);
- + while ((os = va_arg(args, Octstr*)) != NULL) {
- + gwlist_append(exclude, os);
- + }
- + va_end(args);
- +
- + /* all configured config names of this group */
- + keys = dict_keys(grp->vars);
- +
- + /* remove all excluded configs names */
- + while ((os = gwlist_extract_first(exclude)) != NULL) {
- + if ((key = gwlist_search(keys, os, octstr_cmp_cb)) != NULL) {
- + if (gwlist_delete_equal(keys, key) != 1)
- + panic(0, "%s: multiple config variables with same name `%s'?!", __func__,
- + octstr_get_cstr(key));
- + octstr_destroy(key);
- + }
- + }
- + gwlist_destroy(exclude, NULL);
- +
- + os = octstr_duplicate(grp->name);
- + gwlist_sort(keys, octstr_sort_cb);
- + while ((key = gwlist_extract_first(keys)) != NULL) {
- + octstr_append(os, key);
- + if ((val = dict_get(grp->vars, key)) != NULL)
- + octstr_append(os, val);
- + octstr_destroy(key);
- + }
- + gwlist_destroy(keys, NULL);
- +
- + ret = md5(os);
- + octstr_destroy(os);
- +
- + return ret;
- +}
- +
- Octstr *cfg_get_configfile(CfgGroup *grp)
- {
- return octstr_duplicate(grp->configfile);
- Index: gwlib/cfg.h
- ===================================================================
- --- gwlib/cfg.h (revision 4986)
- +++ gwlib/cfg.h (working copy)
- @@ -78,6 +78,7 @@
- CfgGroup *cfg_get_single_group(Cfg *cfg, Octstr *name);
- List *cfg_get_multi_group(Cfg *cfg, Octstr *name);
- Octstr *cfg_get_group_name(CfgGroup *grp);
- +Octstr *cfg_get_group_checksum(CfgGroup *grp, ...);
- Octstr *cfg_get_configfile(CfgGroup *grp);
- Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file,
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement