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  (Masahiko Sawada <sawada.mshk@gmail.com>)
Список 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 по дате отправления:

Предыдущее
От: Kyotaro HORIGUCHI
Дата:
Сообщение: Re: Support for N synchronous standby servers - take 2
Следующее
От: Amit Kapila
Дата:
Сообщение: Re: Performance degradation in commit 6150a1b0