Skip to content

Commit 9958c15

Browse files
committed
Keep order off assignments in GUC context handlers
1 parent 869aefc commit 9958c15

File tree

1 file changed

+84
-51
lines changed

1 file changed

+84
-51
lines changed

contrib/mmts/multimaster.c

Lines changed: 84 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
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"
@@ -3589,67 +3590,109 @@ static bool MtmTwoPhaseCommit(MtmCurrentTrans* x)
35893590

35903591
// XXX: is it defined somewhere?
35913592
#define GUC_KEY_MAXLEN 255
3592-
35933593
#define MTM_GUC_HASHSIZE 20
35943594

3595-
typedef struct MtmGucHashEntry
3595+
typedef struct MtmGucEntry
35963596
{
35973597
char key[GUC_KEY_MAXLEN];
3598+
dlist_node list_node;
35983599
char *value;
3599-
} MtmGucHashEntry;
3600+
} MtmGucEntry;
36003601

36013602
static HTAB *MtmGucHash = NULL;
3602-
static List *MtmGucList = NULL;
3603+
static dlist_head MtmGucList = DLIST_STATIC_INIT(MtmGucList);
36033604

3604-
static void MtmGucHashInit(void)
3605+
static void MtmGucInit(void)
36053606
{
36063607
HASHCTL hash_ctl;
36073608

36083609
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
36093610
hash_ctl.keysize = GUC_KEY_MAXLEN;
3610-
hash_ctl.entrysize = sizeof(MtmGucHashEntry);
3611+
hash_ctl.entrysize = sizeof(MtmGucEntry);
36113612
hash_ctl.hcxt = TopMemoryContext;
36123613
MtmGucHash = hash_create("MtmGucHash",
36133614
MTM_GUC_HASHSIZE,
36143615
&hash_ctl,
36153616
HASH_ELEM | HASH_CONTEXT);
36163617
}
36173618

3619+
static void MtmGucDiscard()
3620+
{
3621+
dlist_iter iter;
3622+
3623+
if (dlist_is_empty(&MtmGucList))
3624+
return;
3625+
3626+
dlist_foreach(iter, &MtmGucList)
3627+
{
3628+
MtmGucEntry *cur_entry = dlist_container(MtmGucEntry, list_node, iter.cur);
3629+
pfree(cur_entry->value);
3630+
}
3631+
dlist_init(&MtmGucList);
3632+
3633+
hash_destroy(MtmGucHash);
3634+
MtmGucInit();
3635+
}
3636+
3637+
static inline void MtmGucUpdate(const char *key, char *value)
3638+
{
3639+
MtmGucEntry *hentry;
3640+
bool found;
3641+
3642+
hentry = hash_search(MtmGucHash, key, HASH_FIND, &found);
3643+
if (found)
3644+
{
3645+
pfree(hentry->value);
3646+
dlist_delete(&hentry->list_node);
3647+
}
3648+
3649+
hentry = hash_search(MtmGucHash, key, HASH_ENTER, NULL);
3650+
hentry->value = value;
3651+
dlist_push_tail(&MtmGucList, &hentry->list_node);
3652+
}
3653+
3654+
static inline void MtmGucRemove(const char *key)
3655+
{
3656+
MtmGucEntry *hentry;
3657+
bool found;
3658+
3659+
hentry = hash_search(MtmGucHash, key, HASH_FIND, &found);
3660+
if (found)
3661+
{
3662+
pfree(hentry->value);
3663+
dlist_delete(&hentry->list_node);
3664+
hash_search(MtmGucHash, key, HASH_REMOVE, NULL);
3665+
}
3666+
}
3667+
36183668
static void MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
36193669
{
36203670
MemoryContext oldcontext;
3621-
MtmGucHashEntry *hentry;
3622-
bool found;
36233671

36243672
if (!MtmGucHash)
3625-
MtmGucHashInit();
3673+
MtmGucInit();
36263674

36273675
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
36283676

36293677
switch (stmt->kind)
36303678
{
36313679
case VAR_SET_VALUE:
3632-
hentry = (MtmGucHashEntry *) hash_search(MtmGucHash, stmt->name,
3633-
HASH_ENTER, &found);
3634-
if (found)
3635-
pfree(hentry->value);
3636-
hentry->value = ExtractSetVariableArgs(stmt);
3680+
MtmGucUpdate(stmt->name, ExtractSetVariableArgs(stmt));
36373681
break;
36383682

36393683
case VAR_SET_DEFAULT:
3640-
hash_search(MtmGucHash, stmt->name, HASH_REMOVE, NULL);
3684+
MtmGucRemove(stmt->name);
36413685
break;
36423686

36433687
case VAR_RESET:
36443688
if (strcmp(stmt->name, "session_authorization") == 0)
3645-
hash_search(MtmGucHash, "role", HASH_REMOVE, NULL);
3646-
hash_search(MtmGucHash, stmt->name, HASH_REMOVE, NULL);
3689+
MtmGucRemove("role");
3690+
MtmGucRemove(stmt->name);
36473691
break;
36483692

36493693
case VAR_RESET_ALL:
36503694
/* XXX: shouldn't we keep auth/role here? */
3651-
hash_destroy(MtmGucHash);
3652-
MtmGucHashInit();
3695+
MtmGucDiscard();
36533696
break;
36543697

36553698
case VAR_SET_CURRENT:
@@ -3660,46 +3703,36 @@ static void MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
36603703
MemoryContextSwitchTo(oldcontext);
36613704
}
36623705

3663-
static void MtmGucDiscard(DiscardStmt *stmt)
3664-
{
3665-
if (stmt->target == DISCARD_ALL)
3666-
{
3667-
hash_destroy(MtmGucHash);
3668-
MtmGucHashInit();
3669-
}
3670-
}
3671-
36723706
static char * MtmGucSerialize(void)
36733707
{
3674-
HASH_SEQ_STATUS status;
3675-
MtmGucHashEntry *hentry;
36763708
StringInfo serialized_gucs;
3709+
dlist_iter iter;
3710+
int nvars = 0;
36773711

36783712
serialized_gucs = makeStringInfo();
36793713
appendStringInfoString(serialized_gucs, "RESET SESSION AUTHORIZATION; reset all; ");
36803714

3681-
if (MtmGucHash)
3715+
dlist_foreach(iter, &MtmGucList)
36823716
{
3683-
hash_seq_init(&status, MtmGucHash);
3684-
while ((hentry = (MtmGucHashEntry *) hash_seq_search(&status)) != NULL)
3685-
{
3686-
appendStringInfoString(serialized_gucs, "SET ");
3687-
appendStringInfoString(serialized_gucs, hentry->key);
3688-
appendStringInfoString(serialized_gucs, " TO ");
3717+
MtmGucEntry *cur_entry = dlist_container(MtmGucEntry, list_node, iter.cur);
36893718

3690-
/* quite a crutch */
3691-
if (strcmp(hentry->key, "work_mem") == 0)
3692-
{
3693-
appendStringInfoString(serialized_gucs, "'");
3694-
appendStringInfoString(serialized_gucs, hentry->value);
3695-
appendStringInfoString(serialized_gucs, "'");
3696-
}
3697-
else
3698-
{
3699-
appendStringInfoString(serialized_gucs, hentry->value);
3700-
}
3701-
appendStringInfoString(serialized_gucs, "; ");
3719+
appendStringInfoString(serialized_gucs, "SET ");
3720+
appendStringInfoString(serialized_gucs, cur_entry->key);
3721+
appendStringInfoString(serialized_gucs, " TO ");
3722+
3723+
/* quite a crutch */
3724+
if (strcmp(cur_entry->key, "work_mem") == 0)
3725+
{
3726+
appendStringInfoString(serialized_gucs, "'");
3727+
appendStringInfoString(serialized_gucs, cur_entry->value);
3728+
appendStringInfoString(serialized_gucs, "'");
37023729
}
3730+
else
3731+
{
3732+
appendStringInfoString(serialized_gucs, cur_entry->value);
3733+
}
3734+
appendStringInfoString(serialized_gucs, "; ");
3735+
nvars++;
37033736
}
37043737

37053738
return serialized_gucs->data;
@@ -3847,10 +3880,10 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
38473880
{
38483881
DiscardStmt *stmt = (DiscardStmt *) parsetree;
38493882

3850-
if (!IsTransactionBlock())
3883+
if (!IsTransactionBlock() && stmt->target == DISCARD_ALL)
38513884
{
38523885
skipCommand = true;
3853-
MtmGucDiscard(stmt);
3886+
MtmGucDiscard();
38543887
}
38553888
}
38563889
break;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy