Skip to content

Commit b093bb1

Browse files
committed
Keep order off assignments in GUC context handlers
1 parent 93becb4 commit b093bb1

File tree

1 file changed

+84
-51
lines changed

1 file changed

+84
-51
lines changed

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"
@@ -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
{
35963596
char key[GUC_KEY_MAXLEN];
3597+
dlist_node list_node;
35973598
char *value;
3598-
} MtmGucHashEntry;
3599+
} MtmGucEntry;
35993600

36003601
static 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
{
36053606
HASHCTL hash_ctl;
36063607

36073608
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
36083609
hash_ctl.keysize = GUC_KEY_MAXLEN;
3609-
hash_ctl.entrysize = sizeof(MtmGucHashEntry);
3610+
hash_ctl.entrysize = sizeof(MtmGucEntry);
36103611
hash_ctl.hcxt = TopMemoryContext;
36113612
MtmGucHash = hash_create("MtmGucHash",
36123613
MTM_GUC_HASHSIZE,
36133614
&hash_ctl,
36143615
HASH_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+
36173667
static void MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
36183668
{
36193669
MemoryContext oldcontext;
3620-
MtmGucHashEntry *hentry;
3621-
bool found;
36223670

36233671
if (!MtmGucHash)
3624-
MtmGucHashInit();
3672+
MtmGucInit();
36253673

36263674
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
36273675

36283676
switch (stmt->kind)
36293677
{
36303678
case 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));
36363680
break;
36373681

36383682
case VAR_SET_DEFAULT:
3639-
hash_search(MtmGucHash, stmt->name, HASH_REMOVE, NULL);
3683+
MtmGucRemove(stmt->name);
36403684
break;
36413685

36423686
case VAR_RESET:
36433687
if (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);
36463690
break;
36473691

36483692
case VAR_RESET_ALL:
36493693
/* XXX: shouldn't we keep auth/role here? */
3650-
hash_destroy(MtmGucHash);
3651-
MtmGucHashInit();
3694+
MtmGucDiscard();
36523695
break;
36533696

36543697
case VAR_SET_CURRENT:
@@ -3659,46 +3702,36 @@ static void MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
36593702
MemoryContextSwitchTo(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-
36713705
static char * MtmGucSerialize(void)
36723706
{
3673-
HASH_SEQ_STATUS status;
3674-
MtmGucHashEntry *hentry;
36753707
StringInfo serialized_gucs;
3708+
dlist_iter iter;
3709+
int nvars = 0;
36763710

36773711
serialized_gucs = makeStringInfo();
36783712
appendStringInfoString(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

37043737
return serialized_gucs->data;
@@ -3846,10 +3879,10 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
38463879
{
38473880
DiscardStmt *stmt = (DiscardStmt *) parsetree;
38483881

3849-
if (!IsTransactionBlock())
3882+
if (!IsTransactionBlock() && stmt->target == DISCARD_ALL)
38503883
{
38513884
skipCommand = true;
3852-
MtmGucDiscard(stmt);
3885+
MtmGucDiscard();
38533886
}
38543887
}
38553888
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