Fri Sep 24 19:51:52 PDT 2004
- Previous message: [Slony1-commit] By wieck: unsubscribeSet_int() must delete sl_sequence entries too, or
- Next message: [Slony1-commit] By darcyb: add syslog support, pid file writing and other bells
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Log Message:
-----------
Ok it's finaly here, a slon config file. There are no command line argument chages, so this should be a transparent dropin. I'll be following this up with some documentation and the like RSN(tm).
Modified Files:
--------------
slony1-engine/src/slon:
Makefile (r1.21 -> r1.22)
misc.c (r1.11 -> r1.12)
remote_worker.c (r1.60 -> r1.61)
slon.c (r1.28 -> r1.29)
slon.h (r1.37 -> r1.38)
sync_thread.c (r1.11 -> r1.12)
Added Files:
-----------
slony1-engine/src/slon:
conf-file.l (r1.1)
confoptions.c (r1.1)
confoptions.h (r1.1)
misc.h (r1.1)
-------------- next part --------------
--- /dev/null
+++ src/slon/misc.h
@@ -0,0 +1,26 @@
+#ifndef _MISC_H_
+#define _MISC_H_
+/* ----------
+ * Functions in misc.c
+ * ----------
+ */
+#include "config.h"
+#include "c.h"
+
+typedef enum {
+ SLON_FATAL,
+ SLON_ERROR,
+ SLON_WARN,
+ SLON_CONFIG,
+ SLON_INFO,
+ SLON_DEBUG1,
+ SLON_DEBUG2,
+ SLON_DEBUG3,
+ SLON_DEBUG4
+} SlonLogLevel;
+
+extern void slon_log(SlonLogLevel level, char * fmt, ...);
+
+extern int slon_scanint64(char *str, int64 *result);
+
+#endif
--- /dev/null
+++ src/slon/confoptions.h
@@ -0,0 +1,208 @@
+#ifndef _CONFOPTIONS_H_
+#define _CONFOPTIONS_H_
+
+#include "c.h"
+
+
+void InitializeConfOptions(void);
+
+bool set_config_option(const char *name, const char *value);
+
+extern double real_placeholder;
+extern char *string_placeholder;
+
+
+extern int vac_frequency;
+extern int slon_log_level;
+extern int sync_interval;
+extern int sync_interval_timeout;
+
+extern int sync_group_maxsize;
+
+bool logpid;
+bool logtimestamp;
+
+
+enum config_type
+{
+ SLON_C_BOOL,
+ SLON_C_INT,
+ SLON_C_REAL,
+ SLON_C_STRING
+};
+
+struct config_generic
+{
+ /* constant fields, must be set correctly in initial value: */
+ const char *name;
+ const char *short_desc;
+ const char *long_desc;
+ enum config_type vartype; /* type of variable (set only at startup) */
+};
+
+
+struct config_int
+{
+ struct config_generic gen;
+ /* these fields must be set correctly in initial value: */
+ /* (all but reset_val are constants) */
+ int *variable;
+ int default_val;
+ int min;
+ int max;
+};
+
+struct config_bool
+{
+ struct config_generic gen;
+ /* these fields must be set correctly in initial value: */
+ /* (all but reset_val are constants) */
+ bool *variable;
+ bool default_val;
+};
+
+struct config_real
+{
+ struct config_generic gen;
+ /* these fields must be set correctly in initial value: */
+ /* (all but reset_val are constants) */
+ double *variable;
+ double default_val;
+ double min;
+ double max;
+};
+
+struct config_string
+{
+ struct config_generic gen;
+ /* these fields must be set correctly in initial value: */
+ /* (all are constants) */
+ char **variable;
+ const char *default_val;
+};
+
+
+
+static struct config_int ConfigureNamesInt[] =
+{
+ {
+ {
+ (const char *)"vac_frequency", /* conf name */
+ gettext_noop("Sets how many cleanup cyclse to run before a vacum is done"), /* short desc */
+ gettext_noop("Sets how many cleanup cyclse to run before a vacum is done"), /* long desc */
+ SLON_C_INT /* config type */
+ },
+ &vac_frequency, /* var name */
+ 3, /* default val */
+ 0, /* min val */
+ 100 /* max val */
+ },
+ {
+ {
+ (const char *)"log_level",
+ gettext_noop("debug log level"),
+ gettext_noop("debug log level"),
+ SLON_C_INT
+ },
+ &slon_log_level,
+ 4,
+ 0,
+ 4
+ },
+ {
+ {
+ (const char *)"sync_interval",
+ gettext_noop("sync even interval"),
+ gettext_noop("sync even interval in ms"),
+ SLON_C_INT
+ },
+ &sync_interval,
+ 100,
+ 10,
+ 60000
+ },
+ {
+ {
+ (const char *)"sync_interval_timeout",
+ gettext_noop("sync interval time out"),
+ gettext_noop("sync interval time out"),
+ SLON_C_INT
+ },
+ &sync_interval_timeout,
+ 1000,
+ 0,
+ 120000
+ },
+ {
+ {
+ (const char *)"sync_group_maxsize",
+ gettext_noop("sync group"),
+ gettext_noop("sync group"),
+ SLON_C_INT
+ },
+ &sync_group_maxsize,
+ 6,
+ 0,
+ 100
+ },
+
+ NULL
+};
+static struct config_int ConfigureNamesBool[] =
+{
+ {
+ {
+ (const char *)"log_pid", /* conf name */
+ gettext_noop("place holder"), /* short desc */
+ gettext_noop("place holder"), /* long desc */
+ SLON_C_BOOL /* config type */
+ },
+ &logpid, /* var_name */
+ false /* default_value */
+ },
+ {
+ {
+ (const char *)"log_timestamp",
+ gettext_noop("place holder"),
+ gettext_noop("place holder"),
+ SLON_C_BOOL
+ },
+ &logtimestamp,
+ true
+ },
+ NULL
+};
+
+static struct config_int ConfigureNamesReal[] =
+{
+ {
+ {
+ (const char *)"real_placeholder", /* conf name */
+ gettext_noop("place holder"), /* short desc */
+ gettext_noop("place holder"), /* long desc */
+ SLON_C_REAL /* config type */
+ },
+ &real_placeholder, /* var_name */
+ 0.0, /* default val */
+ 0.0, /* min_value */
+ 1.0 /* max value */
+ },
+ NULL
+};
+
+static struct config_int ConfigureNamesString[] =
+{
+ {
+ {
+ (const char *)"string_placeholder", /* conf name */
+ gettext_noop("place holder"), /* short desc */
+ gettext_noop("place holder"), /* long desc */
+ SLON_C_STRING /* config type */
+ },
+ &string_placeholder, /* var_name */
+ "default" /* default value */
+ },
+ NULL
+};
+
+#endif
Index: remote_worker.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/remote_worker.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -Lsrc/slon/remote_worker.c -Lsrc/slon/remote_worker.c -u -w -r1.60 -r1.61
--- src/slon/remote_worker.c
+++ src/slon/remote_worker.c
@@ -199,7 +199,7 @@
static struct node_confirm_status *node_confirm_tail = NULL;
pthread_mutex_t node_confirm_lock = PTHREAD_MUTEX_INITIALIZER;
-int sync_group_maxsize = 6;
+int sync_group_maxsize;
/* ----------
Index: sync_thread.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/sync_thread.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lsrc/slon/sync_thread.c -Lsrc/slon/sync_thread.c -u -w -r1.11 -r1.12
--- src/slon/sync_thread.c
+++ src/slon/sync_thread.c
@@ -32,8 +32,8 @@
* Global variables
* ----------
*/
-int sync_interval = 10000;
-int sync_interval_timeout = 60000;
+int sync_interval;
+int sync_interval_timeout;
/* ----------
Index: slon.h
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/slon.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -Lsrc/slon/slon.h -Lsrc/slon/slon.h -u -w -r1.37 -r1.38
--- src/slon/slon.h
+++ src/slon/slon.h
@@ -13,7 +13,9 @@
#ifndef SLON_H_INCLUDED
#define SLON_H_INCLUDED
+
#include "config.h"
+#include "misc.h"
#define SLON_MEMDEBUG 1
@@ -52,6 +54,8 @@
} SlonThreadStatus;
+extern bool logpid;
+
/* ----------
* In memory structures for cluster configuration
* ----------
@@ -492,27 +496,5 @@
*/
extern int slon_log_level;
-/* ----------
- * Functions in misc.c
- * ----------
- */
-typedef enum {
- SLON_FATAL,
- SLON_ERROR,
- SLON_WARN,
- SLON_CONFIG,
- SLON_INFO,
- SLON_DEBUG1,
- SLON_DEBUG2,
- SLON_DEBUG3,
- SLON_DEBUG4
-} SlonLogLevel;
-
-extern void slon_log(SlonLogLevel level, char * fmt, ...);
-
-extern int slon_scanint64(char *str, int64 *result);
-
-
-
#endif /* SLON_H_INCLUDED */
Index: misc.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/misc.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lsrc/slon/misc.c -Lsrc/slon/misc.c -u -w -r1.11 -r1.12
--- src/slon/misc.c
+++ src/slon/misc.c
@@ -27,11 +27,14 @@
#include "libpq-fe.h"
#include "c.h"
+#include "confoptions.h"
#include "slon.h"
-int slon_log_level = SLON_INFO;
+extern int slon_log_level;
+extern bool logpid;
+extern bool logtimestamp;
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -88,9 +91,20 @@
}
}
+ sprintf(outbuf, "");
+
+ if (logtimestamp == true)
+ {
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S %Z", localtime(&stamp_time));
+ sprintf(outbuf, "%s ", time_buf);
+ }
+
+ if (logpid == true)
+ {
+ sprintf(outbuf, "%s[%d] ", outbuf, slon_pid);
+ }
+ sprintf(outbuf, "%s%-6.6s ",outbuf, level_c);
- sprintf(outbuf, "%-6.6s [%s] ", level_c, time_buf);
off = strlen(outbuf);
while(vsnprintf(&outbuf[off], outsize - off, fmt, ap) >= outsize - off)
--- /dev/null
+++ src/slon/conf-file.l
@@ -0,0 +1,338 @@
+/* Scanner for slon config file */
+
+%{
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pthread.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "misc.h"
+#include "confoptions.h"
+
+
+#define CONFIG_FILENAME "./slon.conf"
+
+static unsigned ConfigFileLineno;
+
+enum {
+ SLON_ID = 1,
+ SLON_STRING = 2,
+ SLON_INTEGER = 3,
+ SLON_REAL = 4,
+ SLON_EQUALS = 5,
+ SLON_UNQUOTED_STRING = 6,
+ SLON_QUALIFIED_ID = 7,
+ SLON_EOL = 99,
+ SLON_FERROR = 100
+};
+
+#define YY_USER_INIT (ConfigFileLineno = 1)
+
+/* prototype, so compiler is happy with our high warnings setting */
+int SLON_yylex(void);
+char *SLON_scanstr(char *);
+%}
+
+%option 8bit
+%option never-interactive
+%option nodefault
+%option nounput
+%option noyywrap
+
+SIGN ("-"|"+")
+DIGIT [0-9]
+HEXDIGIT [0-9a-fA-F]
+
+INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+)
+
+EXPONENT [Ee]{SIGN}?{DIGIT}+
+REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
+
+LETTER [A-Za-z_\200-\377]
+LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
+
+ID {LETTER}{LETTER_OR_DIGIT}*
+QUALIFIED_ID {ID}"."{ID}
+
+UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
+STRING \'([^'\n]|\\.)*\'
+
+%%
+
+\n ConfigFileLineno++; return SLON_EOL;
+[ \t\r]+ /* eat whitespace */
+#.*$ /* eat comment */
+
+{ID} return SLON_ID;
+{QUALIFIED_ID} return SLON_QUALIFIED_ID;
+{STRING} return SLON_STRING;
+{UNQUOTED_STRING} return SLON_UNQUOTED_STRING;
+{INTEGER} return SLON_INTEGER;
+{REAL} return SLON_REAL;
+= return SLON_EQUALS;
+
+. return SLON_FERROR;
+
+%%
+
+struct name_value_pair
+{
+ char *name;
+ char *value;
+ struct name_value_pair *next;
+};
+
+/*
+ * Free a list of name/value pairs, including the names and the values
+ */
+static void
+free_name_value_list(struct name_value_pair * list)
+{
+ struct name_value_pair *item;
+
+ item = list;
+ while (item)
+ {
+ struct name_value_pair *save;
+
+ save = item->next;
+ free(item->name);
+ free(item->value);
+ free(item);
+ item = save;
+ }
+}
+
+void ProcessConfigFile(const char *filename)
+{
+ int token, parse_state;
+ char *opt_name, *opt_value;
+ int elevel;
+ struct name_value_pair *item, *head, *tail;
+ FILE * fp;
+
+ elevel = SLON_ERROR;
+
+ /*
+ * Open the conf file
+ */
+ if (filename == NULL)
+ {
+ fp = fopen(CONFIG_FILENAME, "r");
+ }
+ else
+ {
+ fp = fopen(filename, "r");
+ }
+ if (!fp)
+ {
+ /* File not found is fine */
+ if (errno != ENOENT)
+ {
+ slon_log(elevel,"could not open configuration file \"%s\"\n", filename);
+
+ }
+ return;
+ }
+
+ /* Ok we have the file, lets parse it */
+
+ yyin = fp;
+ parse_state = 0;
+ head = NULL;
+ tail = head;
+ opt_name = NULL;
+ opt_value = opt_name;
+
+ while (token = yylex())
+ {
+ switch(parse_state)
+ {
+ case 0:
+ if (token == SLON_EOL) /* empty line */
+ {
+ continue;
+ }
+ if (token != SLON_ID && token != SLON_QUALIFIED_ID)
+ {
+ goto parse_error;
+ }
+ opt_name = strdup(yytext);
+ parse_state = 1;
+ break;
+ case 1:
+ /* ignore equals sign */
+ if (token == SLON_EQUALS)
+ {
+ token = yylex();
+ }
+ if (token != SLON_ID && token != SLON_STRING && token != SLON_INTEGER && token != SLON_REAL && token != SLON_UNQUOTED_STRING)
+ {
+ goto parse_error;
+ }
+ opt_value = strdup(yytext);
+ if (token == SLON_STRING)
+ {
+ memmove(opt_value,opt_value+1,strlen(opt_value)-1);
+ opt_value[strlen(opt_value)-2]='\0';
+ opt_value=SLON_scanstr(opt_value);
+ }
+ parse_state = 2;
+ break;
+ case 2: /* OEL ? */
+ if (token != SLON_EOL)
+ {
+ goto parse_error;
+ }
+ item = malloc(sizeof *item);
+ item->name = opt_name;
+ item->value = opt_value;
+
+ if (strcmp(opt_name, "custom_variable_classes") == 0)
+ {
+ item->next = head;
+ head = item;
+ if (!tail)
+ {
+ tail = item;
+ }
+ }
+ else
+ {
+ /* append to list */
+ item->next = NULL;
+ if (!head)
+ {
+ head = item;
+ }
+ else
+ {
+ tail->next = item;
+ }
+ tail = item;
+ }
+ parse_state = 0;
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ for (item = head; item; item=item->next)
+ {
+ if (!set_config_option(item->name, item->value))
+ {
+ goto cleanup_exit;
+ }
+ }
+ for(item = head; item; item=item->next)
+ {
+ set_config_option(item->name, item->value);
+ }
+
+ cleanup_exit:
+ free_name_value_list(head);
+ return;
+
+ parse_error:
+ fclose(fp);
+ free_name_value_list(head);
+ if (token == SLON_EOL)
+ {
+ slon_log(elevel, "syntax error in file \"%s\" line %u, near end of line", filename, ConfigFileLineno - 1);
+ }
+ else
+ {
+ slon_log(elevel, "syntax error in file \"%s\" line %u, near end of line", filename, ConfigFileLineno - 1);
+ }
+}
+
+
+
+
+
+
+
+char *SLON_scanstr(char *s)
+{
+ char *newStr;
+ int len,
+ i,
+ j;
+
+ if (s == NULL || s[0] == '\0')
+ {
+ if (s != NULL)
+ free(s);
+ return strdup("");
+ }
+ len = strlen(s);
+
+ newStr = malloc(len + 1); /* string cannot get longer */
+ if (newStr == NULL)
+ slon_log(SLON_FATAL, "out of memory");
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (s[i] == '\\')
+ {
+ i++;
+ switch (s[i])
+ {
+ case 'b':
+ newStr[j] = '\b';
+ break;
+ case 'f':
+ newStr[j] = '\f';
+ break;
+ case 'n':
+ newStr[j] = '\n';
+ break;
+ case 'r':
+ newStr[j] = '\r';
+ break;
+ case 't':
+ newStr[j] = '\t';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int k;
+ long octVal = 0;
+
+ for (k = 0;
+ s[i + k] >= '0' && s[i
++ k] <= '7' && k < 3;
+ k++)
+ octVal = (octVal << 3) +
+ (s[i + k] - '0');
+ i += k - 1;
+ newStr[j] = ((char) octVal);
+ }
+ break;
+ default:
+ newStr[j] = s[i];
+ break;
+ }
+ } /* switch */
+ else
+ newStr[j] = s[i];
+ j++;
+ }
+ newStr[j] = '\0';
+ free(s);
+ return newStr;
+}
+
--- /dev/null
+++ src/slon/confoptions.c
@@ -0,0 +1,472 @@
+#include <pthread.h>
+#include "libpq-fe.h"
+#include "confoptions.h"
+#include "postgres.h"
+#include "misc.h"
+
+
+static struct config_generic **conf_variables;
+static int size_conf_variables;
+static int num_conf_variables;
+
+static int conf_var_compare(const void *a, const void *b);
+static int conf_name_compare(const char *namea, const char *nameb);
+
+bool set_config_option(const char *name, const char *value);
+
+
+bool bool_placeholder;
+double real_placeholder;
+char *string_placeholder;
+
+
+
+void build_conf_variables(void)
+{
+ int size_vars;
+ int num_vars=0;
+ struct config_generic **conf_vars;
+ int i;
+
+ for (i = 0; ConfigureNamesBool[i].gen.name; i++)
+ {
+ struct config_bool *conf = &ConfigureNamesBool[i];
+
+ /* Rather than requiring vartype to be filled in by hand, do this: */
+ conf->gen.vartype = SLON_C_BOOL;
+ num_vars++;
+ }
+
+ for (i = 0; ConfigureNamesInt[i].gen.name; i++)
+ {
+ struct config_int *conf = &ConfigureNamesInt[i];
+ conf->gen.vartype = SLON_C_INT;
+ num_vars++;
+ }
+
+ for (i = 0; ConfigureNamesReal[i].gen.name; i++)
+ {
+ struct config_real *conf = &ConfigureNamesReal[i];
+ conf->gen.vartype = SLON_C_REAL;
+ num_vars++;
+ }
+
+ for (i = 0; ConfigureNamesString[i].gen.name; i++)
+ {
+ struct config_string *conf = &ConfigureNamesString[i];
+ conf->gen.vartype = SLON_C_STRING;
+ num_vars++;
+ }
+
+ size_vars = num_vars + num_vars / 4;
+
+ conf_vars = (struct config_generic **) malloc(size_vars * sizeof(struct config_generic *));
+ if (conf_vars == NULL)
+ {
+ slon_log(FATAL, "malloc failed");
+ return;
+ }
+
+ num_vars = 0;
+
+ for (i = 0; ConfigureNamesBool[i].gen.name; i++)
+ {
+ conf_vars[num_vars++] = &ConfigureNamesBool[i].gen;
+ }
+ for (i = 0; ConfigureNamesInt[i].gen.name; i++)
+ {
+ conf_vars[num_vars++] = &ConfigureNamesInt[i].gen;
+ }
+ for (i = 0; ConfigureNamesReal[i].gen.name; i++)
+ {
+ conf_vars[num_vars++] = &ConfigureNamesReal[i].gen;
+ }
+ for (i = 0; ConfigureNamesString[i].gen.name; i++)
+ {
+ conf_vars[num_vars++] = &ConfigureNamesString[i].gen;
+ }
+
+ if (conf_variables)
+ {
+ free(conf_variables);
+ }
+ conf_variables = conf_vars;
+ num_conf_variables = num_vars;
+ size_conf_variables = size_vars;
+ qsort((void *) conf_variables, num_conf_variables, sizeof(struct config_generic *), conf_var_compare);
+}
+
+
+static bool
+add_conf_variable(struct config_generic * var, int elevel)
+{
+ if (num_conf_variables + 1 >= size_conf_variables)
+ {
+ /*
+ * Increase the vector by 25%
+ */
+ int size_vars = size_conf_variables + size_conf_variables / 4;
+ struct config_generic **conf_vars;
+
+ if (size_vars == 0)
+ {
+ size_vars = 100;
+ conf_vars = (struct config_generic **)
+ malloc(size_vars * sizeof(struct config_generic *));
+ }
+ else
+ {
+ conf_vars = (struct config_generic **)
+ realloc(conf_variables, size_vars * sizeof(struct config_generic *));
+ }
+
+ if (conf_vars == NULL)
+ {
+ slon_log(elevel,"malloc failed");
+ return false; /* out of memory */
+ }
+
+ conf_variables = conf_vars;
+ size_conf_variables = size_vars;
+ }
+ conf_variables[num_conf_variables++] = var;
+ qsort((void *) conf_variables, num_conf_variables,
+ sizeof(struct config_generic *), conf_var_compare);
+ return true;
+}
+
+void InitializeConfOptions(void)
+{
+ int i;
+ char *env;
+
+ build_conf_variables();
+
+ for (i = 0; i < num_conf_variables; i++)
+ {
+ struct config_generic *gconf = conf_variables[i];
+
+ switch (gconf->vartype)
+ {
+ case SLON_C_BOOL:
+ {
+ struct config_bool *conf = (struct config_bool *) gconf;
+ *conf->variable = conf->default_val;
+ break;
+ }
+ case SLON_C_INT:
+ {
+ struct config_int *conf = (struct config_int *) gconf;
+ *conf->variable = conf->default_val;
+ break;
+ }
+ case SLON_C_REAL:
+ {
+ struct config_int *conf = (struct config_int *) gconf;
+ *conf->variable = conf->default_val;
+ break;
+ }
+ case SLON_C_STRING:
+ {
+ char *str;
+ struct config_int *conf = (struct config_int *) gconf;
+ *conf->variable = NULL;
+ str = strdup(conf->default_val);
+ *conf->variable = str;
+ break;
+ }
+ }
+ }
+
+ env = getenv("CLUSTER");
+ if (env != NULL)
+ {
+ set_config_option("cluster_name", env);
+ }
+}
+
+static bool
+parse_bool(const char *value, bool *result)
+{
+ size_t len = strlen(value);
+
+ if (strncasecmp(value, "true", len) == 0)
+ {
+ if (result)
+ {
+ *result = true;
+ }
+ }
+ else if (strncasecmp(value, "false", len) == 0)
+ {
+ if (result)
+ {
+ *result = false;
+ }
+ }
+ else if (strncasecmp(value, "yes", len) == 0)
+ {
+ if (result)
+ {
+ *result = true;
+ }
+ }
+ else if (strncasecmp(value, "no", len) == 0)
+ {
+ if (result)
+ {
+ *result = false;
+ }
+ }
+ else if (strncasecmp(value, "on", len) == 0)
+ {
+ if (result)
+ {
+ *result = true;
+ }
+ }
+ else if (strncasecmp(value, "off", len) == 0)
+ {
+ if (result)
+ {
+ *result = false;
+ }
+ }
+ else if (strncasecmp(value, "1", len) == 0)
+ {
+ if (result)
+ {
+ *result = true;
+ }
+ }
+ else if (strncasecmp(value, "o", len) == 0)
+ {
+ if (result)
+ {
+ *result = false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Try to parse value as an integer. The accepted formats are the
+ * usual decimal, octal, or hexadecimal formats. If the string parses
+ * okay, return true, else false. If result is not NULL, return the
+ * value there.
+ */
+static bool
+parse_int(const char *value, int *result)
+{
+ long val;
+ char *endptr;
+
+ errno = 0;
+ val = strtol(value, &endptr, 0);
+
+ if (endptr == value || *endptr != '\0' || errno == ERANGE
+#ifdef HAVE_LONG_INT_64
+ /* if long > 32 bits, check for overflow of int4 */
+ || val != (long) ((int32) val)
+#endif
+ )
+ return false;
+ if (result)
+ *result = (int) val;
+ return true;
+}
+
+/*
+ * Try to parse value as a floating point constant in the usual
+ * format. If the value parsed okay return true, else false. If
+ * result is not NULL, return the semantic value there.
+ */
+static bool
+parse_real(const char *value, double *result)
+{
+ double val;
+ char *endptr;
+
+ errno = 0;
+ val = strtod(value, &endptr);
+ if (endptr == value || *endptr != '\0' || errno == ERANGE)
+ return false;
+ if (result)
+ *result = val;
+ return true;
+}
+
+
+static struct config_generic *find_option(const char *name, int elevel)
+{
+ const char *dot;
+ const char **key = &name;
+ struct config_generic **res;
+ int i;
+
+ res = (struct config_generic **)
+ bsearch((void *) &key,
+ (void *) conf_variables,
+ num_conf_variables,
+ sizeof(struct config_generic *),
+ conf_var_compare);
+ if (res)
+ return *res;
+}
+
+static int
+conf_var_compare(const void *a, const void *b)
+{
+ struct config_generic *confa = *(struct config_generic **) a;
+ struct config_generic *confb = *(struct config_generic **) b;
+
+ return conf_name_compare(confa->name, confb->name);
+}
+
+static int
+conf_name_compare(const char *namea, const char *nameb)
+{
+ /*
+ * The temptation to use strcasecmp() here must be resisted, because
+ * the array ordering has to remain stable across setlocale() calls.
+ * So, build our own with a simple ASCII-only downcasing.
+ */
+ while (*namea && *nameb)
+ {
+ char cha = *namea++;
+ char chb = *nameb++;
+
+ if (cha >= 'A' && cha <= 'Z')
+ cha += 'a' - 'A';
+ if (chb >= 'A' && chb <= 'Z')
+ chb += 'a' - 'A';
+ if (cha != chb)
+ return cha - chb;
+ }
+ if (*namea)
+ return 1; /* a is longer */
+ if (*nameb)
+ return -1; /* b is longer */
+ return 0;
+}
+
+
+bool set_config_option(const char *name, const char *value)
+{
+ struct config_generic *record;
+ int elevel;
+
+ elevel = SLON_WARN;
+
+ record = find_option(name, elevel);
+
+ if (record == NULL)
+ {
+ slon_log(elevel, "unrecognized configuration parameter \"%s\"\n", name);
+ return false;
+ }
+
+ switch (record->vartype)
+ {
+ case SLON_C_BOOL:
+ {
+ struct config_bool *conf = (struct config_bool *) record;
+ bool newval;
+ if (value)
+ {
+ if (!parse_bool(value, &newval))
+ {
+ slon_log(elevel, "parameter \"%s\" requires a Boolean value\n", name);
+ return false;
+ }
+ }
+ else
+ {
+ slon_log(elevel, "parameter \"%s\"\n", name );
+ }
+
+ *conf->variable = newval;
+
+ break;
+ }
+ case SLON_C_INT:
+ {
+ struct config_int *conf = (struct config_int *) record;
+ int newval;
+ if (value)
+ {
+ if (!parse_int(value, &newval))
+ {
+ slon_log(elevel, "parameter \"%s\" requires a integer value\n", name);
+ return false;
+ }
+ if (newval < conf->min || newval > conf->max)
+ {
+ slon_log(elevel, "%d is outside the valid range for parameter \"%s\" (%d .. %d)\n",
+ newval, name, conf->min, conf->max);
+ return false;
+ }
+ }
+ else
+ {
+ slon_log(elevel, "parameter \"%s\"\n", name );
+ }
+ *conf->variable = newval;
+ break;
+ }
+ case SLON_C_REAL:
+ {
+ struct config_real *conf = (struct config_real *) record;
+ double newval;
+
+ if (value)
+ {
+ if (!parse_real(value, &newval))
+ {
+ slon_log(elevel, "parameter \"%s\" requires a numeric value\n", name);
+ return false;
+ }
+ if (newval < conf->min || newval > conf->max)
+ {
+ slon_log(elevel, "%g is outside the valid range for parameter \"%s\" (%g .. %g)\n",
+ newval, name, conf->min, conf->max);
+ return false;
+ }
+ }
+ else
+ {
+ slon_log(elevel, "parameter \"%s\"\n", name );
+ }
+ *conf->variable = newval;
+ break;
+ }
+ case SLON_C_STRING:
+ {
+ struct config_string *conf = (struct config_string *) record;
+ char *newval;
+
+ if (value)
+ {
+ newval = strdup(value);
+ if (newval == NULL)
+ {
+ return false;
+ }
+
+ }
+ else
+ {
+ slon_log(elevel, "parameter \"%s\"\n", name );
+ free(newval);
+ }
+ *conf->variable = newval;
+ break;
+ }
+ }
+ return true;
+}
+
Index: slon.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/slon.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -Lsrc/slon/slon.c -Lsrc/slon/slon.c -u -w -r1.28 -r1.29
--- src/slon/slon.c
+++ src/slon/slon.c
@@ -27,7 +27,7 @@
#include "c.h"
#include "slon.h"
-
+#include "confoptions.h"
/* ----------
* Global data
@@ -52,6 +52,8 @@
static char *const *main_argv;
static void sigalrmhandler(int signo);
+int slon_log_level;
+
/* ----------
* main
@@ -73,62 +75,39 @@
int group_size_set = 0;
- while ((c = getopt(argc, argv, "d:s:t:g:c:h")) != EOF)
+ InitializeConfOptions();
+
+
+ while ((c = getopt(argc, argv, "f:d:s:t:g:c:f:h")) != EOF)
{
switch(c)
{
- case 'd': slon_log_level = strtol(optarg, NULL, 10);
- if (slon_log_level < 0 || slon_log_level > 4)
- {
- fprintf(stderr, "illegal debug level %d\n",
- slon_log_level);
- errors++;
- }
- slon_log_level += SLON_INFO;
+ case 'f':
+ ProcessConfigFile(optarg);
break;
- case 's': sync_interval = strtol(optarg, NULL, 10);
- if (sync_interval < 100 || sync_interval > 60000)
- {
- fprintf(stderr, "sync interval must be between 100 and 60000 ms\n");
- errors++;
- }
- else if (!group_size_set)
- {
- sync_group_maxsize = 60000 / sync_interval;
- if (sync_group_maxsize > 100)
- sync_group_maxsize = 100;
- }
-
+ case 'd':
+ set_config_option("log_level", optarg);
break;
- case 't': sync_interval_timeout = strtol(optarg, NULL, 10);
- if (sync_interval < 0)
- {
- fprintf(stderr, "sync interval must be >= 0\n");
- errors++;
- }
+ case 's':
+ set_config_option("sync_group_maxsize", optarg);
+ break;
+ case 't':
+ set_config_option("sync_interval_timeout", optarg);
break;
- case 'g': sync_group_maxsize = strtol(optarg, NULL, 10);
- if (sync_group_maxsize < 1 || sync_group_maxsize > 100)
- {
- fprintf(stderr, "sync group size must be between 1 and 100 ms\n");
- errors++;
- }
- group_size_set = 1;
+ case 'g':
+ set_config_option("sync_group_maxsize", optarg);
break;
- case 'c': vac_frequency = strtol(optarg, NULL, 10);
- if (vac_frequency < 0 || vac_frequency > 10)
- {
- fprintf(stderr, "Vaccum frequency must be between 0 (disable) and 10\n");
- errors++;
- }
+ case 'c':
+ set_config_option("vac_frequency", optarg);
break;
- case 'h': errors++;
+ case 'h':
+ errors++;
break;
default: fprintf(stderr, "unknown option '%c'\n", c);
@@ -136,7 +115,18 @@
break;
}
}
-
+#if 0
+fprintf( stderr, "config: vac_frequency %d\n"
+ " sync_group_maxsize %d\n"
+ " sync_interval_timeout %d\n"
+ " sync_interval %d\n"
+ " slon_log_level %d\n"
+ " log_pid %d\n"
+ " log_timestamp %d\n",
+ vac_frequency, sync_group_maxsize, sync_interval_timeout,
+ sync_interval, slon_log_level, logpid, logtimestamp);
+fflush(NULL);
+#endif
if (argc - optind != 2)
errors++;
@@ -150,6 +140,7 @@
fprintf(stderr, " -t <milliseconds> SYNC interval timeout (default 60000)\n");
fprintf(stderr, " -g <num> maximum SYNC group size (default 6)\n");
fprintf(stderr, " -c <num> how often to vaccum in cleanup cycles\n");
+ fprintf(stderr, " -f <filename> slon configuration file\n");
return 1;
}
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/Makefile,v
retrieving revision 1.21
retrieving revision 1.22
diff -Lsrc/slon/Makefile -Lsrc/slon/Makefile -u -w -r1.21 -r1.22
--- src/slon/Makefile
+++ src/slon/Makefile
@@ -36,6 +36,8 @@
cleanup_thread.o \
scheduler.o \
dbutils.o \
+ conf-file.o \
+ confoptions.o \
misc.o
DISTFILES = Makefile README $(wildcard *.c) $(wildcard *.h)
@@ -59,6 +61,11 @@
scheduler.o: scheduler.c slon.h
slon.o: slon.c slon.h
sync_thread.o: sync_thread.c slon.h
+conf-file.o: conf-file.c slon.h confoptions.h
+confoptions.o: confoptions.c slon.h confoptions.h
+
+conf-file.c: conf-file.l
+ $(FLEX) -o$(@) $<
clean distclean maintainer-clean:
rm -f $(ALL) $(OBJS)
- Previous message: [Slony1-commit] By wieck: unsubscribeSet_int() must delete sl_sequence entries too, or
- Next message: [Slony1-commit] By darcyb: add syslog support, pid file writing and other bells
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list