Re: Support for N synchronous standby servers - take 2
| От | Kyotaro HORIGUCHI |
|---|---|
| Тема | Re: Support for N synchronous standby servers - take 2 |
| Дата | |
| Msg-id | 20160226.105325.168253404.horiguchi.kyotaro@lab.ntt.co.jp обсуждение исходный текст |
| Ответ на | Re: Support for N synchronous standby servers - take 2 (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>) |
| Ответы |
Re: Support for N synchronous standby servers - take 2
|
| Список | pgsql-hackers |
At Fri, 26 Feb 2016 10:38:22 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> wrote in
<20160226.103822.12680005.horiguchi.kyotaro@lab.ntt.co.jp>
> Hello, Thanks for the new patch.
>
>
> At Fri, 26 Feb 2016 08:52:54 +0900, Masahiko Sawada <sawada.mshk@gmail.com> wrote in
<CAD21AoAZKFVu8-MVhkJ3ywAiJmb=P-HSbJTGi=gK1La73KjS6Q@mail.gmail.com>
> > Previous patch could not parse one character standby name correctly.
> > Attached latest patch.
>
> I haven't looked it in detail but it won't work as you
> expected. flex compains as the following for v12 patch.
>
> syncgroup_scanner.l:80: warning, rule cannot be matched
> syncgroup_scanner.l:84: warning, rule cannot be matched
Making it independent from postgres body then compile it with
-DYYDEBUG and set yydebug = 1 would give you valuable information
and make testing of the parser far easier.
| $ flex test2.l; bison -v test2.y; gcc -g -DYYDEBUG -o ltest2 test2.tab.c
| $ echo '1[aa,bb,cc]' | ./ltest2
| Starting parse
| Entering state 0
| Reading a token: Next token is token NAME ()
| Shifting token NAME ()
| ...
| Entering state 4
| Next token is token '[' ()
| syntax error at or near "[" in "(null)
regards,
--
Kyotaro Horiguchi
NTT Open Source Software Center
%{
//#include "postgres.h"
/* No reason to constrain amount of data slurped */
#define YY_READ_BUF_SIZE 16777216
#define BUFSIZE 8192
/* Handles to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle;
/* Functions for handling double quoted string */
static void init_xd_string(void);
static void addlit_xd_string(char *ytext, int yleng);
static void addlitchar_xd_string(unsigned char ychar);
char *scanbuf;
char *xd_string;
int xd_size; /* actual size of xd_string */
int xd_len; /* string length of xd_string */
%}
%option 8bit
/* %option never-interactive*/
/* %option nounput*/
/* %option noinput*/
%option noyywrap
%option warn
/* %option prefix="syncgroup_yy" */
/** <xd> delimited identifiers (double-quoted identifiers)*/
%x xd
space [ \t\n\r\f]
non_newline [^\n\r]
whitespace ({space}+)
self [\[\]\,]
asterisk \*
/** Basically all ascii characteres except for {self} and {whitespace} are allowed* to be used for node name. These
specialcharater could be used by double-quoted.*//* excluding ' ', '\"', '*', ',', '[', ']' */
node_name [\x21\x23-\x29\x29-\x2b\x2d-\x5a\x5c\x5e-\x7e]
/* excluding '\"' */
dquoted_name [\x20\x21\x23-\x7e]
/* Double-quoted string */
dquote \"
xdstart {dquote}
xddouble {dquote}{dquote}
xdstop {dquote}
xdinside {dquoted_name}+
%%
{whitespace} { /* ignore */ }
{xdstart} { init_xd_string(); BEGIN(xd); }
<xd>{xddouble} { addlitchar_xd_string('\"'); }
<xd>{xdinside} { addlit_xd_string(yytext, yyleng); }
<xd>{xdstop} { xd_string[xd_len] = '\0'; yylval.str = xd_string; BEGIN(INITIAL);
return NAME; }
{node_name}+ { yylval.str = strdup(yytext); return NAME; }
[1-9][0-9]* { yylval.str = yytext; return NUM; }
{asterisk} { yylval.str = strdup(yytext); return AST; }
{self} { return yytext[0]; }
. {
// ereport(ERROR,
// (errcode(ERRCODE_SYNTAX_ERROR),
// errmsg("syntax error: unexpected character \"%s\"", yytext))); fprintf(stderr,
"syntaxerror: unexpected character \"%s\"", yytext); exit(1);}
%%
void
yyerror(const char *message)
{
// ereport(ERROR,
// (errcode(ERRCODE_SYNTAX_ERROR),
// errmsg("%s at or near \"%s\" in \"%s\"", message,
// yytext, scanbuf)));fprintf(stderr, "%s at or near \"%s\" in \"%s\"", message, yytext,
scanbuf);exit(1);
}
void
syncgroup_scanner_init(const char *str)
{Size slen = strlen(str);
/* * Might be left over after ereport() */if (YY_CURRENT_BUFFER) yy_delete_buffer(YY_CURRENT_BUFFER);
/* * Make a scan buffer with special termination needed by flex. */scanbuf = (char *) palloc(slen + 2);memcpy(scanbuf,
str,slen);scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
}
void
syncgroup_scanner_finish(void)
{yy_delete_buffer(scanbufhandle);scanbufhandle = NULL;
}
static void
init_xd_string()
{xd_string = palloc(sizeof(char) * BUFSIZE);xd_size = BUFSIZE;xd_len = 0;
}
static void
addlit_xd_string(char *ytext, int yleng)
{/* enlarge buffer if needed */if ((xd_len + yleng) > xd_size) xd_string = repalloc(xd_string, xd_size + BUFSIZE);
memcpy(xd_string + xd_len, ytext, yleng);xd_len += yleng;
}
static void
addlitchar_xd_string(unsigned char ychar)
{/* enlarge buffer if needed */if ((xd_len + 1) > xd_size) xd_string = repalloc(xd_string, xd_size + BUFSIZE);
xd_string[xd_len] = ychar;xd_len += 1;
}
%{
/*-------------------------------------------------------------------------** syncgroup_gram.y - Parser
forsynchronous replication group** Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group* Portions
Copyright(c) 1994, Regents of the University of California*** IDENTIFICATION*
src/backend/replication/syncgroup_gram.y**-------------------------------------------------------------------------*/
//#include "postgres.h"
//#include "replication/syncrep.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define palloc malloc
#define repalloc realloc
#define pfree free
#define SYNC_REP_GROUP_MAIN 0x01
#define SYNC_REP_GROUP_NAME 0x02
#define SYNC_REP_GROUP_GROUP 0x04
#define SYNC_REP_METHOD_PRIORITY 0
struct SyncGroupNode;
typedef struct SyncGroupNode SyncGroupNode;
struct SyncGroupNode
{/* Common information */int type;char *name;SyncGroupNode *next; /* Same group, next name node */
/* For group ndoe */int sync_method; /* priority */int wait_num;SyncGroupNode *members; /* member of its group
*/
};
static SyncGroupNode *create_name_node(char *name);
static SyncGroupNode *add_node(SyncGroupNode *node_list, SyncGroupNode *node);
static SyncGroupNode *create_group_node(char *wait_num, SyncGroupNode *node_list);
static void yyerror(const char *message);typedef int Size;
/** Bison doesn't allocate anything that needs to live across parser calls,* so we can easily have it use palloc
insteadof malloc. This prevents* memory leaks if we error out during parsing. Note this only works with* bison >=
2.0. However, in bison 1.875 the default is to use alloca()* if possible, so there's not really much problem anyhow, at
leastif* you're building with gcc.*/
#define YYMALLOC palloc
#define YYFREE pfreeSyncGroupNode *SyncRepStandbys;
%}
%expect 0/*%name-prefix="syncgroup_yy"*/
%union
{char *str;SyncGroupNode *expr;
}
%token <str> NAME NUM
%token <str> AST
%type <expr> result sync_list sync_list_ast sync_element sync_element_ast sync_node_group sync_group_old
sync_group
%start result
%%
result: sync_node_group { SyncRepStandbys = $1; }
;
sync_node_group: sync_group_old { $$ = $1; } | sync_group { $$ =
$1;}
;
sync_group_old: sync_list { $$ = create_group_node("1", $1); } | sync_list_ast
{ $$ = create_group_node("1", $1); }
;
sync_group: NUM '[' sync_list ']' { $$ = create_group_node($1, $3); } | NUM '[' sync_list_ast ']'
{ $$ = create_group_node($1, $3); }
;
sync_list: sync_element { $$ = $1;} | sync_list ',' sync_element { $$ =
add_node($1,$3);}
;
sync_list_ast: sync_element_ast { $$ = $1;} | sync_list ',' sync_element_ast { $$ =
add_node($1,$3);}
;
sync_element: NAME { $$ = create_name_node($1); } | NUM
{ $$ = create_name_node($1); }
;
sync_element_ast: AST { $$ = create_name_node($1); }
;
%%
static SyncGroupNode *
create_name_node(char *name)
{SyncGroupNode *name_node = (SyncGroupNode *)malloc(sizeof(SyncGroupNode));
/* Common information */name_node->type = SYNC_REP_GROUP_NAME;name_node->name = strdup(name);name_node->next = NULL;
/* For GROUP node */name_node->sync_method = 0;name_node->wait_num = 0;name_node->members = NULL;//
name_node->SyncRepGetSyncedLsnsFn= NULL;// name_node->SyncRepGetSyncStandbysFn = NULL;
return name_node;
}
static SyncGroupNode *
create_group_node(char *wait_num, SyncGroupNode *node_list)
{SyncGroupNode *group_node = (SyncGroupNode *)malloc(sizeof(SyncGroupNode));
/* For NAME node */group_node->type = SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN;group_node->name =
"main";group_node->next= NULL;
/* For GROUP node */group_node->sync_method = SYNC_REP_METHOD_PRIORITY;group_node->wait_num =
atoi(wait_num);group_node->members= node_list;// group_node->SyncRepGetSyncedLsnsFn =
SyncRepGetSyncedLsnsUsingPriority;// group_node->SyncRepGetSyncStandbysFn = SyncRepGetSyncStandbysUsingPriority;
return group_node;
}
static SyncGroupNode *
add_node(SyncGroupNode *node_list, SyncGroupNode *node)
{SyncGroupNode *tmp = node_list;
/* Add node to tailing of node_list */while(tmp->next != NULL) tmp = tmp->next;
tmp->next = node;return node_list;
}
void
indent(int level)
{ int i;
for (i = 0 ; i < level * 2 ; i++) putc(' ', stdout);
}
static void
dump_syncgroupnode(SyncGroupNode *def, int level)
{ char *typelabel[] = {"MAIN", "NAME", "GROUP"}; SyncGroupNode *p;
if (def == NULL) return;
switch(def->type) { case SYNC_REP_GROUP_NAME: indent(level); puts("{"); indent(level+1); printf("NODE_TYPE:
SYNC_REP_GROUP_NAME\n"); indent(level+1); printf("NAME: %s\n", def->name); indent(level); puts("}"); if
(def->next) dump_syncgroupnode(def->next, level); break; case SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN:
indent(level); puts("{"); indent(level+1); printf("NODE_TYPE: SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN\n");
indent(level+1); printf("NAME: %s\n", def->name); indent(level+1); printf("SYNC_METHOD: PRIORITY\n");
indent(level+1); printf("WAIT_NUM: %d\n", def->wait_num); indent(level+1); if (def->members)
dump_syncgroupnode(def->members,level+1); indent(level); puts("}"); if (def->next)
dump_syncgroupnode(def->next,level); break; default: fprintf(stderr, "ERR\n"); exit(1); } level--;
}
int main(void)
{ yydebug = 1; yyparse(); dump_syncgroupnode(SyncRepStandbys, 0);
}
//#include "syncgroup_scanner.c"
#include "lex.yy.c"
В списке pgsql-hackers по дате отправления: