-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Le 21/12/2010 15:11, Gilles Darold a écrit : > [...] > Regex patch : > > The regex struct array is stored in pool_config struct, it is > dynamically expendable by PATTERN_ARR_SIZE when it reached > NxPATTERN_ARR_SIZE (start with 16 regex max). > > All entries in white_function_list or black_function_list are stored > in this array with a flag to differentiate them. To preserve > backward compatibility and prevent partial matching lists entries > are all prefixed with '^' and ended with '$' if not already done. > This also mean that if we want to match function beginning with > "write_" it has to be written : "write_.*". Indeed "^write_.*$" > works too. >
Not much to say. It applies, it compiles, and it works. I didn't try really big regexp, but I'm quite sure it doesn't aim for big regexps. See attached patch. Thanks Gilles. - -- Guillaume Lelarge Administrateur de bases de données http://dalibo.com - http://dalibo.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk0Uy8YACgkQeWXglSY0snlM3wCguu4b6i2J5p6+00BqziTxypcl 3OYAn04ewYSIwD6GuNX8ezRNzRmgT9VX =hQoP -----END PGP SIGNATURE-----
Index: pool_config.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.c,v
retrieving revision 1.52
diff -c -p -r1.52 pool_config.c
*** pool_config.c 17 Aug 2010 02:09:00 -0000 1.52
--- pool_config.c 24 Dec 2010 15:59:17 -0000
*************** int pool_init_config(void)
*** 1926,1931 ****
--- 1926,1934 ----
pool_config->ssl_ca_cert = "";
pool_config->ssl_ca_cert_dir = "";
pool_config->debug_level = 0;
+ pool_config->lists_patterns = NULL;
+ pool_config->pattc = 0;
+ pool_config->current_pattern_size = 0;
res = gethostname(localhostname,sizeof(localhostname));
if(res !=0 )
*************** int pool_init_config(void)
*** 1941,1946 ****
--- 1944,2041 ----
return 0;
}
+ /*
+ * Add regex expression to patterns array
+ * The supported type are: black_function_list and white_function_list
+ * Return 0 on error, 1 on success
+ */
+ int add_regex_pattern(char *type, char *s)
+ {
+ int regex_flags = REG_NOSUB;
+ RegPattern currItem;
+ /* force case insensitive pattern matching */
+ regex_flags |= REG_ICASE;
+ /* Add extended regex search */
+ regex_flags |= REG_EXTENDED;
+ /* Fill the pattern type */
+ if (strcmp(type, "black_function_list") == 0)
+ {
+ currItem.type = BLACKLIST;
+ }
+ else if (strcmp(type, "white_function_list") == 0)
+ {
+ currItem.type = WHITELIST;
+ }
+ else
+ {
+ pool_error("add_to_patterns: bad pattern type %s", type);
+ return 0;
+ }
+ /* Fill the pattern flag */
+ currItem.flag = regex_flags;
+
+ /* Fill pattern array */
+ currItem.pattern = malloc(sizeof(char)*(strlen(s)+1));
+ if (currItem.pattern == NULL)
+ {
+ pool_error("add_to_patterns: unable to allocate new pattern");
+ return 0;
+ }
+ /* Force exact matching of function name with ^ and $ on the regex
+ if required to prevent partial matching. It also allow backward
+ compatibility.
+ */
+ if (strncmp(s, "^", 1) != 0) {
+ strncpy(currItem.pattern, "^", 2);
+ strncat(currItem.pattern, s, strlen(s) + 1);
+ } else {
+ strncpy(currItem.pattern, s, strlen(s) + 1);
+ }
+ if (s[strlen(s)-1] != '$') {
+ strncat(currItem.pattern, "$", 2);
+ }
+ pool_debug("add_to_patterns: regex pattern: %s", currItem.pattern);
+ /* compile our regex */
+ if (regcomp(&currItem.regexv, currItem.pattern, currItem.flag) != 0)
+ {
+ pool_error("add_to_patterns: invalid regex pattern: %s", currItem.pattern);
+ }
+ else
+ {
+ if (growPatternArray(currItem) < 0)
+ {
+ pool_error("add_to_patterns: unable to allocate new pattern");
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ /*
+ * Dynamically grow the regex pattern array
+ * The array start with PATTERN_ARR_SIZE storage place, if required
+ * it will grow of PATTERN_ARR_SIZE more each time.
+ */
+ int growPatternArray (RegPattern item)
+ {
+ void *_tmp = NULL;
+ if (pool_config->pattc == pool_config->current_pattern_size)
+ {
+ pool_config->current_pattern_size += PATTERN_ARR_SIZE;
+ _tmp = realloc(pool_config->lists_patterns, (pool_config->current_pattern_size * sizeof(RegPattern)));
+ if (!_tmp)
+ {
+ return(-1);
+ }
+
+ pool_config->lists_patterns = (RegPattern*)_tmp;
+ }
+ pool_config->lists_patterns[pool_config->pattc] = item;
+ pool_config->pattc++;
+
+ return(pool_config->pattc);
+ }
+
int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
{
FILE *fd;
Index: pool_config.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.h,v
retrieving revision 1.8
diff -c -p -r1.8 pool_config.h
*** pool_config.h 1 Aug 2010 08:38:17 -0000 1.8
--- pool_config.h 24 Dec 2010 15:59:17 -0000
***************
*** 33,38 ****
--- 33,53 ----
#define MODE_SLONY "slony" /* Slony-I */
/*
+ * Regex support in white and black list function
+ */
+ #include <regex.h>
+ #define BLACKLIST 0
+ #define WHITELIST 1
+ #define PATTERN_ARR_SIZE 16 /* Default length of regex array: 16 patterns */
+ typedef struct {
+ char *pattern;
+ int type;
+ int flag;
+ regex_t regexv;
+ } RegPattern;
+
+
+ /*
* configuration paramters
*/
typedef struct {
*************** typedef struct {
*** 149,154 ****
--- 164,174 ----
char *ssl_key; /* path to ssl key (frontend only) */
char *ssl_ca_cert; /* path to root (CA) certificate */
char *ssl_ca_cert_dir; /* path to directory containing CA certificates */
+
+ /* followings are for regex support and do not exist in the configuration file */
+ RegPattern *lists_patterns; /* Precompiled regex patterns for black/white lists */
+ int pattc; /* number of regexp pattern */
+ int current_pattern_size; /* size of the regex pattern array */
} POOL_CONFIG;
typedef enum {
*************** extern int pool_init_config(void);
*** 162,165 ****
--- 182,190 ----
extern int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context);
extern int eval_logical(char *str);
+ /* methods used for regexp support */
+ extern int add_regex_pattern(char *type, char *s);
+ extern int growPatternArray (RegPattern item);
+ extern int pattern_compare(char *str, const int type);
+
#endif /* POOL_CONFIG_H */
Index: pool_config.l
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.l,v
retrieving revision 1.48
diff -c -p -r1.48 pool_config.l
*** pool_config.l 17 Aug 2010 02:09:00 -0000 1.48
--- pool_config.l 24 Dec 2010 15:59:18 -0000
*************** int pool_init_config(void)
*** 201,206 ****
--- 203,211 ----
pool_config->ssl_ca_cert = "";
pool_config->ssl_ca_cert_dir = "";
pool_config->debug_level = 0;
+ pool_config->lists_patterns = NULL;
+ pool_config->pattc = 0;
+ pool_config->current_pattern_size = 0;
res = gethostname(localhostname,sizeof(localhostname));
if(res !=0 )
*************** int pool_init_config(void)
*** 216,221 ****
--- 221,318 ----
return 0;
}
+ /*
+ * Add regex expression to patterns array
+ * The supported type are: black_function_list and white_function_list
+ * Return 0 on error, 1 on success
+ */
+ int add_regex_pattern(char *type, char *s)
+ {
+ int regex_flags = REG_NOSUB;
+ RegPattern currItem;
+ /* force case insensitive pattern matching */
+ regex_flags |= REG_ICASE;
+ /* Add extended regex search */
+ regex_flags |= REG_EXTENDED;
+ /* Fill the pattern type */
+ if (strcmp(type, "black_function_list") == 0)
+ {
+ currItem.type = BLACKLIST;
+ }
+ else if (strcmp(type, "white_function_list") == 0)
+ {
+ currItem.type = WHITELIST;
+ }
+ else
+ {
+ pool_error("add_to_patterns: bad pattern type %s", type);
+ return 0;
+ }
+ /* Fill the pattern flag */
+ currItem.flag = regex_flags;
+
+ /* Fill pattern array */
+ currItem.pattern = malloc(sizeof(char)*(strlen(s)+1));
+ if (currItem.pattern == NULL)
+ {
+ pool_error("add_to_patterns: unable to allocate new pattern");
+ return 0;
+ }
+ /* Force exact matching of function name with ^ and $ on the regex
+ if required to prevent partial matching. It also allow backward
+ compatibility.
+ */
+ if (strncmp(s, "^", 1) != 0) {
+ strncpy(currItem.pattern, "^", 2);
+ strncat(currItem.pattern, s, strlen(s) + 1);
+ } else {
+ strncpy(currItem.pattern, s, strlen(s) + 1);
+ }
+ if (s[strlen(s)-1] != '$') {
+ strncat(currItem.pattern, "$", 2);
+ }
+ pool_debug("add_to_patterns: regex pattern: %s", currItem.pattern);
+ /* compile our regex */
+ if (regcomp(&currItem.regexv, currItem.pattern, currItem.flag) != 0)
+ {
+ pool_error("add_to_patterns: invalid regex pattern: %s", currItem.pattern);
+ }
+ else
+ {
+ if (growPatternArray(currItem) < 0)
+ {
+ pool_error("add_to_patterns: unable to allocate new pattern");
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ /*
+ * Dynamically grow the regex pattern array
+ * The array start with PATTERN_ARR_SIZE storage place, if required
+ * it will grow of PATTERN_ARR_SIZE more each time.
+ */
+ int growPatternArray (RegPattern item)
+ {
+ void *_tmp = NULL;
+ if (pool_config->pattc == pool_config->current_pattern_size)
+ {
+ pool_config->current_pattern_size += PATTERN_ARR_SIZE;
+ _tmp = realloc(pool_config->lists_patterns, (pool_config->current_pattern_size * sizeof(RegPattern)));
+ if (!_tmp)
+ {
+ return(-1);
+ }
+
+ pool_config->lists_patterns = (RegPattern*)_tmp;
+ }
+ pool_config->lists_patterns[pool_config->pattc] = item;
+ pool_config->pattc++;
+
+ return(pool_config->pattc);
+ }
+
int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
{
FILE *fd;
*************** int pool_get_config(char *confpath, POOL
*** 701,706 ****
--- 798,807 ----
fclose(fd);
return(-1);
}
+ for (i=0;i<pool_config->num_white_function_list;i++)
+ {
+ add_regex_pattern("white_function_list", pool_config->white_function_list[i]);
+ }
}
else if (!strcmp(key, "black_function_list") &&
*************** int pool_get_config(char *confpath, POOL
*** 728,733 ****
--- 829,838 ----
fclose(fd);
return(-1);
}
+ for (i=0;i<pool_config->num_black_function_list;i++)
+ {
+ add_regex_pattern("black_function_list", pool_config->black_function_list[i]);
+ }
}
else if (!strcmp(key, "print_timestamp") && CHECK_CONTEXT(INIT_CONFIG, context))
Index: pool_select_walker.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_select_walker.c,v
retrieving revision 1.6
diff -c -p -r1.6 pool_select_walker.c
*** pool_select_walker.c 6 Sep 2010 05:03:21 -0000 1.6
--- pool_select_walker.c 24 Dec 2010 15:59:18 -0000
*************** bool pool_has_temp_table(Node *node)
*** 97,108 ****
}
/*
* Walker function to find a function call
*/
static bool function_call_walker(Node *node, void *context)
{
SelectContext *ctx = (SelectContext *) context;
- int i;
if (node == NULL)
return false;
--- 97,143 ----
}
/*
+ * Search function name in whilelist or blacklist regex array
+ * Return 1 on success (found in list)
+ * Return 0 when not found in list
+ * Return -1 if the given search type doesn't exist.
+ * Search type supported are: WHITELIST and BLACKLIST
+ */
+ int pattern_compare(char *str, const int type)
+ {
+ int i = 0;
+
+ /* pass througth all regex pattern unless pattern is found */
+ for (i = 0; i < pool_config->pattc; i++) {
+ if ( (pool_config->lists_patterns[i].type == type) && (regexec(&pool_config->lists_patterns[i].regexv, str, 0, 0, 0) == 0) ) {
+ switch(type) {
+ /* return 1 if string matches whitelist pattern */
+ case WHITELIST:
+ if (pool_config->debug_level > 0)
+ pool_debug("pattern_compare: white_function_list (%s) matched: %s", pool_config->lists_patterns[i].pattern, str);
+ return 1;
+ /* return 1 if string matches blacklist pattern */
+ case BLACKLIST:
+ if (pool_config->debug_level > 0)
+ pool_debug("pattern_compare: black_function_list (%s) matched: %s", pool_config->lists_patterns[i].pattern, str);
+ return 1;
+ default:
+ pool_error("pattern_compare: unknown pattern match type: %s", str);
+ return -1;
+ }
+ }
+ }
+
+ /* return 0 otherwise */
+ return 0;
+ }
+
+ /*
* Walker function to find a function call
*/
static bool function_call_walker(Node *node, void *context)
{
SelectContext *ctx = (SelectContext *) context;
if (node == NULL)
return false;
*************** static bool function_call_walker(Node *n
*** 123,135 ****
*/
if (pool_config->num_white_function_list > 0)
{
! for (i=0;i<pool_config->num_white_function_list;i++)
! {
/* If the function is found in the white list, we can ignore it */
! if (!strcasecmp(pool_config->white_function_list[i], fname))
! {
! return raw_expression_tree_walker(node, function_call_walker, context);
! }
}
/*
* Since the function was not found in white list, we
--- 158,167 ----
*/
if (pool_config->num_white_function_list > 0)
{
! /* Search function in the white list regex patterns */
! if (pattern_compare(fname, WHITELIST) == 1) {
/* If the function is found in the white list, we can ignore it */
! return raw_expression_tree_walker(node, function_call_walker, context);
}
/*
* Since the function was not found in white list, we
*************** static bool function_call_walker(Node *n
*** 142,152 ****
/*
* Check black list if any.
*/
! for (i=0;i<pool_config->num_black_function_list;i++)
{
! /* Is the function found in the black list? */
! if (!strcasecmp(pool_config->black_function_list[i], fname))
! {
/* Found. */
ctx->has_function_call = true;
return false;
--- 174,183 ----
/*
* Check black list if any.
*/
! if (pool_config->num_black_function_list > 0)
{
! /* Search function in the black list regex patterns */
! if (pattern_compare(fname, BLACKLIST) == 1) {
/* Found. */
ctx->has_function_call = true;
return false;
regexp.patch.sig
Description: Binary data
_______________________________________________ Pgpool-hackers mailing list [email protected] http://pgfoundry.org/mailman/listinfo/pgpool-hackers
