6363#include "parser/analyze.h"
6464#include "parser/parse_relation.h"
6565#include "tcop/pquery.h"
66+ #include "lib/ilist.h"
6667
6768#include "multimaster.h"
6869#include "ddd.h"
@@ -3588,67 +3589,109 @@ static bool MtmTwoPhaseCommit(MtmCurrentTrans* x)
35883589
35893590// XXX: is it defined somewhere?
35903591#define GUC_KEY_MAXLEN 255
3591-
35923592#define MTM_GUC_HASHSIZE 20
35933593
3594- typedef struct MtmGucHashEntry
3594+ typedef struct MtmGucEntry
35953595{
35963596char key [GUC_KEY_MAXLEN ];
3597+ dlist_node list_node ;
35973598char * value ;
3598- }MtmGucHashEntry ;
3599+ }MtmGucEntry ;
35993600
36003601static HTAB * MtmGucHash = NULL ;
3601- static List * MtmGucList = NULL ;
3602+ static dlist_head MtmGucList = DLIST_STATIC_INIT ( MtmGucList ) ;
36023603
3603- static void MtmGucHashInit (void )
3604+ static void MtmGucInit (void )
36043605{
36053606HASHCTL hash_ctl ;
36063607
36073608MemSet (& hash_ctl ,0 ,sizeof (hash_ctl ));
36083609hash_ctl .keysize = GUC_KEY_MAXLEN ;
3609- hash_ctl .entrysize = sizeof (MtmGucHashEntry );
3610+ hash_ctl .entrysize = sizeof (MtmGucEntry );
36103611hash_ctl .hcxt = TopMemoryContext ;
36113612MtmGucHash = hash_create ("MtmGucHash" ,
36123613MTM_GUC_HASHSIZE ,
36133614& hash_ctl ,
36143615HASH_ELEM |HASH_CONTEXT );
36153616}
36163617
3618+ static void MtmGucDiscard ()
3619+ {
3620+ dlist_iter iter ;
3621+
3622+ if (dlist_is_empty (& MtmGucList ))
3623+ return ;
3624+
3625+ dlist_foreach (iter ,& MtmGucList )
3626+ {
3627+ MtmGucEntry * cur_entry = dlist_container (MtmGucEntry ,list_node ,iter .cur );
3628+ pfree (cur_entry -> value );
3629+ }
3630+ dlist_init (& MtmGucList );
3631+
3632+ hash_destroy (MtmGucHash );
3633+ MtmGucInit ();
3634+ }
3635+
3636+ static inline void MtmGucUpdate (const char * key ,char * value )
3637+ {
3638+ MtmGucEntry * hentry ;
3639+ bool found ;
3640+
3641+ hentry = hash_search (MtmGucHash ,key ,HASH_FIND ,& found );
3642+ if (found )
3643+ {
3644+ pfree (hentry -> value );
3645+ dlist_delete (& hentry -> list_node );
3646+ }
3647+
3648+ hentry = hash_search (MtmGucHash ,key ,HASH_ENTER ,NULL );
3649+ hentry -> value = value ;
3650+ dlist_push_tail (& MtmGucList ,& hentry -> list_node );
3651+ }
3652+
3653+ static inline void MtmGucRemove (const char * key )
3654+ {
3655+ MtmGucEntry * hentry ;
3656+ bool found ;
3657+
3658+ hentry = hash_search (MtmGucHash ,key ,HASH_FIND ,& found );
3659+ if (found )
3660+ {
3661+ pfree (hentry -> value );
3662+ dlist_delete (& hentry -> list_node );
3663+ hash_search (MtmGucHash ,key ,HASH_REMOVE ,NULL );
3664+ }
3665+ }
3666+
36173667static void MtmGucSet (VariableSetStmt * stmt ,const char * queryStr )
36183668{
36193669MemoryContext oldcontext ;
3620- MtmGucHashEntry * hentry ;
3621- bool found ;
36223670
36233671if (!MtmGucHash )
3624- MtmGucHashInit ();
3672+ MtmGucInit ();
36253673
36263674oldcontext = MemoryContextSwitchTo (TopMemoryContext );
36273675
36283676switch (stmt -> kind )
36293677{
36303678case VAR_SET_VALUE :
3631- hentry = (MtmGucHashEntry * )hash_search (MtmGucHash ,stmt -> name ,
3632- HASH_ENTER ,& found );
3633- if (found )
3634- pfree (hentry -> value );
3635- hentry -> value = ExtractSetVariableArgs (stmt );
3679+ MtmGucUpdate (stmt -> name ,ExtractSetVariableArgs (stmt ));
36363680break ;
36373681
36383682case VAR_SET_DEFAULT :
3639- hash_search ( MtmGucHash , stmt -> name , HASH_REMOVE , NULL );
3683+ MtmGucRemove ( stmt -> name );
36403684break ;
36413685
36423686case VAR_RESET :
36433687if (strcmp (stmt -> name ,"session_authorization" )== 0 )
3644- hash_search ( MtmGucHash , "role" , HASH_REMOVE , NULL );
3645- hash_search ( MtmGucHash , stmt -> name , HASH_REMOVE , NULL );
3688+ MtmGucRemove ( "role" );
3689+ MtmGucRemove ( stmt -> name );
36463690break ;
36473691
36483692case VAR_RESET_ALL :
36493693/* XXX: shouldn't we keep auth/role here? */
3650- hash_destroy (MtmGucHash );
3651- MtmGucHashInit ();
3694+ MtmGucDiscard ();
36523695break ;
36533696
36543697case VAR_SET_CURRENT :
@@ -3659,46 +3702,36 @@ static void MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
36593702MemoryContextSwitchTo (oldcontext );
36603703}
36613704
3662- static void MtmGucDiscard (DiscardStmt * stmt )
3663- {
3664- if (stmt -> target == DISCARD_ALL )
3665- {
3666- hash_destroy (MtmGucHash );
3667- MtmGucHashInit ();
3668- }
3669- }
3670-
36713705static char * MtmGucSerialize (void )
36723706{
3673- HASH_SEQ_STATUS status ;
3674- MtmGucHashEntry * hentry ;
36753707StringInfo serialized_gucs ;
3708+ dlist_iter iter ;
3709+ int nvars = 0 ;
36763710
36773711serialized_gucs = makeStringInfo ();
36783712appendStringInfoString (serialized_gucs ,"RESET SESSION AUTHORIZATION; reset all; " );
36793713
3680- if ( MtmGucHash )
3714+ dlist_foreach ( iter , & MtmGucList )
36813715{
3682- hash_seq_init (& status ,MtmGucHash );
3683- while ((hentry = (MtmGucHashEntry * )hash_seq_search (& status ))!= NULL )
3684- {
3685- appendStringInfoString (serialized_gucs ,"SET " );
3686- appendStringInfoString (serialized_gucs ,hentry -> key );
3687- appendStringInfoString (serialized_gucs ," TO " );
3716+ MtmGucEntry * cur_entry = dlist_container (MtmGucEntry ,list_node ,iter .cur );
36883717
3689- /* quite a crutch */
3690- if (strcmp (hentry -> key ,"work_mem" )== 0 )
3691- {
3692- appendStringInfoString (serialized_gucs ,"'" );
3693- appendStringInfoString (serialized_gucs ,hentry -> value );
3694- appendStringInfoString (serialized_gucs ,"'" );
3695- }
3696- else
3697- {
3698- appendStringInfoString (serialized_gucs ,hentry -> value );
3699- }
3700- appendStringInfoString (serialized_gucs ,"; " );
3718+ appendStringInfoString (serialized_gucs ,"SET " );
3719+ appendStringInfoString (serialized_gucs ,cur_entry -> key );
3720+ appendStringInfoString (serialized_gucs ," TO " );
3721+
3722+ /* quite a crutch */
3723+ if (strcmp (cur_entry -> key ,"work_mem" )== 0 )
3724+ {
3725+ appendStringInfoString (serialized_gucs ,"'" );
3726+ appendStringInfoString (serialized_gucs ,cur_entry -> value );
3727+ appendStringInfoString (serialized_gucs ,"'" );
37013728}
3729+ else
3730+ {
3731+ appendStringInfoString (serialized_gucs ,cur_entry -> value );
3732+ }
3733+ appendStringInfoString (serialized_gucs ,"; " );
3734+ nvars ++ ;
37023735}
37033736
37043737return serialized_gucs -> data ;
@@ -3846,10 +3879,10 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
38463879{
38473880DiscardStmt * stmt = (DiscardStmt * )parsetree ;
38483881
3849- if (!IsTransactionBlock ())
3882+ if (!IsTransactionBlock ()&& stmt -> target == DISCARD_ALL )
38503883{
38513884skipCommand = true;
3852- MtmGucDiscard (stmt );
3885+ MtmGucDiscard ();
38533886}
38543887}
38553888break ;