Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5be559f

Browse files
committed
dmq integration: use xid-based channel names to support deadlock detection
1 parent 865c45f commit 5be559f

File tree

8 files changed

+247
-124
lines changed

8 files changed

+247
-124
lines changed

commit.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ MtmPrePrepareTransaction(MtmCurrentTrans* x)
8282
MtmDatabaseName);
8383

8484
Assert(TransactionIdIsValid(GetCurrentTransactionId()));
85-
Assert(*x->gid != '\0');
8685
}
8786

8887
bool // XXX: do we need that bool?
@@ -91,21 +90,21 @@ MtmTwoPhaseCommit(MtmCurrentTrans* x)
9190
nodemask_t participantsMask;
9291
bool ret;
9392
int failed_at;
93+
TransactionId xid;
94+
char stream[DMQ_NAME_MAXLEN];
95+
pgid_t gid;
9496

9597
if (!x->isDistributed || !x->containsDML)
9698
return false;
9799

98100
if (!DmqSubscribed)
99101
{
100102
int i, sender_id = 0;
101-
102103
for (i = 0; i < Mtm->nAllNodes; i++)
103104
{
104105
if (i + 1 != MtmNodeId)
105106
{
106-
dmq_stream_subscribe(psprintf("node%d", i + 1),
107-
psprintf("be%d", MyProc->pgprocno),
108-
i);
107+
dmq_attach_receiver(psprintf("node%d", i + 1), i);
109108
sender_to_node[sender_id++] = i + 1;
110109
}
111110
}
@@ -120,32 +119,40 @@ MtmTwoPhaseCommit(MtmCurrentTrans* x)
120119
StartTransactionCommand();
121120
}
122121

123-
MtmGenerateGid(x->gid);
122+
xid = GetCurrentTransactionId();
123+
sprintf(stream, "xid" XID_FMT, xid);
124+
dmq_stream_subscribe(stream);
125+
x->xid = xid;
126+
127+
MtmGenerateGid(gid, xid);
124128
participantsMask = (((nodemask_t)1 << Mtm->nAllNodes) - 1) &
125129
~Mtm->disabledNodeMask &
126130
~((nodemask_t)1 << (MtmNodeId-1));
127131

128-
ret = PrepareTransactionBlock(x->gid);
132+
ret = PrepareTransactionBlock(gid);
129133
if (!ret)
130134
{
131-
MTM_ELOG(WARNING, "Failed to prepare transaction %s (%llu)", x->gid, (long64)x->xid);
135+
MTM_ELOG(WARNING, "Failed to prepare transaction %s (%llu)", gid, (long64)x->xid);
132136
return false;
133137
}
134138
CommitTransactionCommand();
135139

136140
ret = GatherPrepares(x, participantsMask, &failed_at);
137141
if (!ret)
138142
{
139-
FinishPreparedTransaction(x->gid, false, false);
143+
dmq_stream_unsubscribe(stream);
144+
FinishPreparedTransaction(gid, false, false);
140145
MTM_ELOG(ERROR, "Failed to prepare transaction %s at node %d",
141-
x->gid, failed_at);
146+
gid, failed_at);
142147
}
143148

144-
SetPreparedTransactionState(x->gid, MULTIMASTER_PRECOMMITTED);
149+
SetPreparedTransactionState(gid, MULTIMASTER_PRECOMMITTED);
145150
GatherPrecommits(x, participantsMask);
146151

147152
StartTransactionCommand();
148-
FinishPreparedTransaction(x->gid, true, false);
153+
FinishPreparedTransaction(gid, true, false);
154+
155+
dmq_stream_unsubscribe(stream);
149156

150157
return true;
151158
}
@@ -167,14 +174,14 @@ GatherPrepares(MtmCurrentTrans* x, nodemask_t participantsMask, int *failed_at)
167174
msg = (MtmArbiterMessage *) buffer.data;
168175

169176
// elog(LOG, "GatherPrepares: got %s from node%d", msg->gid, sender_to_node[sender_id]);
170-
ereport(LOG,
171-
(errmsg("GatherPrepares: got %s from node%d",
172-
msg->gid, sender_to_node[sender_id]),
173-
errhidestmt(true)));
177+
// ereport(LOG,
178+
// (errmsg("GatherPrepares: got %s from node%d",
179+
// msg->gid, sender_to_node[sender_id]),
180+
// errhidestmt(true)));
174181

175182
Assert(msg->node == sender_to_node[sender_id]);
176183
Assert(msg->code == MSG_PREPARED || msg->code == MSG_ABORTED);
177-
Assert(strcmp(msg->gid, x->gid) == 0);
184+
Assert(msg->dxid == x->xid);
178185
Assert(BIT_CHECK(participantsMask, sender_to_node[sender_id] - 1));
179186

180187
BIT_CLEAR(participantsMask, sender_to_node[sender_id] - 1);
@@ -203,11 +210,11 @@ GatherPrecommits(MtmCurrentTrans* x, nodemask_t participantsMask)
203210
dmq_pop(&sender_id, &buffer, participantsMask);
204211
msg = (MtmArbiterMessage *) buffer.data;
205212

206-
elog(LOG, "GatherPrecommits: got %s from node%d", msg->gid, sender_to_node[sender_id]);
213+
// elog(LOG, "GatherPrecommits: got %s from node%d", msg->gid, sender_to_node[sender_id]);
207214

208215
Assert(msg->node == sender_to_node[sender_id]);
209216
Assert(msg->code == MSG_PRECOMMITTED);
210-
Assert(strcmp(msg->gid, x->gid) == 0);
217+
Assert(msg->dxid == x->xid);
211218
Assert(BIT_CHECK(participantsMask, sender_to_node[sender_id] - 1));
212219

213220
BIT_CLEAR(participantsMask, sender_to_node[sender_id] - 1);

dmq.c

Lines changed: 81 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
* size limits, but now it doesn't seems to be worth of troubles.
5252
*/
5353

54-
#define DMQ_NAME_MAXLEN 32
5554
#define DMQ_CONNSTR_MAX_LEN 150
5655

5756
#define DMQ_MAX_SUBS_PER_BACKEND 10
@@ -83,38 +82,42 @@ typedef struct
8382
int procno;
8483
} DmqStreamSubscription;
8584

86-
typedef struct DmqSharedState
85+
86+
/* Global state for dmq */
87+
struct DmqSharedState
8788
{
8889
LWLock *lock;
8990
dsm_handle out_dsm;
9091
DmqDestination destinations[DMQ_MAX_DESTINATIONS];
9192

9293
HTAB *subscriptions;
94+
95+
// XXX: change to nested struct
9396
char receiver[DMQ_MAX_RECEIVERS][DMQ_NAME_MAXLEN];
9497
dsm_handle receiver_dsm[DMQ_MAX_RECEIVERS];
9598
int receiver_procno[DMQ_MAX_RECEIVERS];
9699
int nreceivers;
97100

98101
pid_t sender_pid;
99-
} DmqSharedState;
102+
} *dmq_state;
100103

101-
static DmqSharedState *dmq_state;
102104

103105
/* Backend-local i/o queues. */
104-
typedef struct DmqBackendState
106+
struct
105107
{
106-
shm_mq_handle *mq_outh;
107-
shm_mq_handle *mq_inh[DMQ_MAX_RECEIVERS];
108+
shm_mq_handle *mq_outh;
108109
int n_inhandles;
109-
char receiver_names[DMQ_MAX_RECEIVERS][DMQ_NAME_MAXLEN];
110-
int mask_pos[DMQ_MAX_RECEIVERS];
111-
} DmqBackendState;
110+
struct
111+
{
112+
shm_mq_handle *mqh;
113+
char name[DMQ_NAME_MAXLEN];
114+
int mask_pos;
115+
} inhandles[DMQ_MAX_RECEIVERS];
116+
} dmq_local;
112117

113118
/* Flags set by signal handlers */
114119
static volatile sig_atomic_t got_SIGHUP = false;
115120

116-
static DmqBackendState dmq_local;
117-
118121
static shmem_startup_hook_type PreviousShmemStartupHook;
119122

120123
dmq_receiver_hook_type dmq_receiver_start_hook;
@@ -177,7 +180,7 @@ dmq_shmem_startup_hook(void)
177180
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
178181

179182
dmq_state = ShmemInitStruct("dmq",
180-
sizeof(DmqSharedState),
183+
sizeof(struct DmqSharedState),
181184
&found);
182185
if (!found)
183186
{
@@ -211,7 +214,7 @@ dmq_shmem_size(void)
211214
{
212215
Size size = 0;
213216

214-
size = add_size(size, sizeof(DmqSharedState));
217+
size = add_size(size, sizeof(struct DmqSharedState));
215218
size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND*MaxBackends,
216219
sizeof(DmqStreamSubscription)));
217220
return MAXALIGN(size);
@@ -612,7 +615,6 @@ dmq_handle_message(StringInfo msg, shm_mq_handle **mq_handles, dsm_segment *seg)
612615
bool found;
613616
DmqStreamSubscription *sub;
614617
shm_mq_result res;
615-
shm_mq *mq;
616618

617619
/*
618620
* Consume stream_name packed as a string and interpret rest of the data
@@ -653,7 +655,7 @@ dmq_handle_message(StringInfo msg, shm_mq_handle **mq_handles, dsm_segment *seg)
653655
return;
654656
}
655657

656-
elog(LOG, "got message %s.%s, passing to %d", stream_name, body, sub->procno);
658+
// elog(LOG, "got message %s.%s, passing to %d", stream_name, body, sub->procno);
657659

658660
/* and send it */
659661
res = shm_mq_send(mq_handles[sub->procno], body_len, body, false);
@@ -1046,13 +1048,43 @@ dmq_push(DmqDestinationId dest_id, char *stream_name, char *msg)
10461048

10471049
// elog(LOG, "pushing l=%d '%.*s'", buf.len, buf.len, buf.data);
10481050

1051+
// XXX: use sendv instead
10491052
res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false);
10501053
if (res != SHM_MQ_SUCCESS)
10511054
elog(ERROR, "dmq_push: can't send to queue");
10521055

10531056
resetStringInfo(&buf);
10541057
}
10551058

1059+
1060+
void
1061+
dmq_push_buffer(DmqDestinationId dest_id, char *stream_name, const void *payload, size_t len)
1062+
{
1063+
StringInfoData buf;
1064+
shm_mq_result res;
1065+
1066+
ensure_outq_handle();
1067+
1068+
initStringInfo(&buf);
1069+
pq_sendbyte(&buf, dest_id);
1070+
pq_send_ascii_string(&buf, stream_name);
1071+
pq_sendbytes(&buf, payload, len);
1072+
1073+
// elog(LOG, "pushing l=%d '%.*s'", buf.len, buf.len, buf.data);
1074+
1075+
// XXX: use sendv instead
1076+
res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false);
1077+
if (res != SHM_MQ_SUCCESS)
1078+
elog(ERROR, "dmq_push: can't send to queue");
1079+
}
1080+
1081+
1082+
1083+
1084+
1085+
1086+
1087+
10561088
static bool
10571089
dmq_reattach_shm_mq(int handle_id)
10581090
{
@@ -1065,12 +1097,11 @@ dmq_reattach_shm_mq(int handle_id)
10651097
int receiver_procno;
10661098
int i;
10671099

1068-
/* await for sender to connect */
10691100
LWLockAcquire(dmq_state->lock, LW_SHARED);
10701101
for (i = 0; i < DMQ_MAX_RECEIVERS; i++)
10711102
{
1072-
// XXX: change to hash
1073-
if (strcmp(dmq_state->receiver[i], dmq_local.receiver_names[handle_id]) == 0)
1103+
// XXX: change to hash maybe
1104+
if (strcmp(dmq_state->receiver[i], dmq_local.inhandles[handle_id].name) == 0)
10741105
{
10751106
receiver_id = i;
10761107
receiver_procno = dmq_state->receiver_procno[i];
@@ -1098,9 +1129,9 @@ dmq_reattach_shm_mq(int handle_id)
10981129
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10991130
errmsg("bad magic number in dynamic shared memory segment")));
11001131

1101-
if (dmq_local.mq_inh[handle_id])
1132+
if (dmq_local.inhandles[handle_id].mqh)
11021133
{
1103-
shm_mq_detach(dmq_local.mq_inh[handle_id]);
1134+
shm_mq_detach(dmq_local.inhandles[handle_id].mqh);
11041135
}
11051136

11061137
inq = shm_toc_lookup(toc, MyProc->pgprocno, false);
@@ -1111,15 +1142,28 @@ dmq_reattach_shm_mq(int handle_id)
11111142
shm_mq_set_sender(inq, &ProcGlobal->allProcs[receiver_procno]);
11121143

11131144
oldctx = MemoryContextSwitchTo(TopMemoryContext);
1114-
dmq_local.mq_inh[handle_id] = shm_mq_attach(inq, seg, NULL);
1145+
dmq_local.inhandles[handle_id].mqh = shm_mq_attach(inq, seg, NULL);
11151146
MemoryContextSwitchTo(oldctx);
11161147

11171148
return true;
11181149
}
11191150

1151+
void
1152+
dmq_attach_receiver(char *sender_name, int mask_pos)
1153+
{
1154+
int handle_id = dmq_local.n_inhandles;
1155+
1156+
dmq_local.inhandles[handle_id].mqh = NULL;
1157+
dmq_local.inhandles[handle_id].mask_pos = mask_pos;
1158+
strncpy(dmq_local.inhandles[handle_id].name, sender_name, DMQ_NAME_MAXLEN);
1159+
1160+
dmq_reattach_shm_mq(handle_id);
1161+
1162+
dmq_local.n_inhandles++;
1163+
}
11201164

11211165
void
1122-
dmq_stream_subscribe(char *sender_name, char *stream_name, int mask_pos)
1166+
dmq_stream_subscribe(char *stream_name)
11231167
{
11241168
bool found;
11251169
DmqStreamSubscription *sub;
@@ -1133,17 +1177,19 @@ dmq_stream_subscribe(char *sender_name, char *stream_name, int mask_pos)
11331177
MyProc->pgprocno, stream_name, sub->procno, sub->stream_name);
11341178
}
11351179
sub->procno = MyProc->pgprocno;
1136-
sub->mask_pos = mask_pos;
11371180
LWLockRelease(dmq_state->lock);
1181+
}
11381182

1139-
dmq_local.mq_inh[dmq_local.n_inhandles] = NULL;
1140-
strncpy(dmq_local.receiver_names[dmq_local.n_inhandles], sender_name,
1141-
DMQ_NAME_MAXLEN);
1142-
dmq_local.mask_pos[dmq_local.n_inhandles] = mask_pos;
1183+
void
1184+
dmq_stream_unsubscribe(char *stream_name)
1185+
{
1186+
bool found;
11431187

1144-
dmq_reattach_shm_mq(dmq_local.n_inhandles);
1188+
LWLockAcquire(dmq_state->lock, LW_EXCLUSIVE);
1189+
hash_search(dmq_state->subscriptions, stream_name, HASH_REMOVE, &found);
1190+
LWLockRelease(dmq_state->lock);
11451191

1146-
dmq_local.n_inhandles++;
1192+
Assert(found);
11471193
}
11481194

11491195
void
@@ -1163,10 +1209,10 @@ dmq_pop(DmqSenderId *sender_id, StringInfo msg, int64 mask)
11631209
Size len;
11641210
void *data;
11651211

1166-
if (!BIT_CHECK(mask, dmq_local.mask_pos[i]))
1212+
if (!BIT_CHECK(mask, dmq_local.inhandles[i].mask_pos))
11671213
continue;
11681214

1169-
res = shm_mq_receive(dmq_local.mq_inh[i], &len, &data, true);
1215+
res = shm_mq_receive(dmq_local.inhandles[i].mqh, &len, &data, true);
11701216
if (res == SHM_MQ_SUCCESS)
11711217
{
11721218
msg->data = data;
@@ -1201,12 +1247,14 @@ dmq_pop_nb(DmqSenderId *sender_id, StringInfo msg)
12011247
shm_mq_result res;
12021248
int i;
12031249

1250+
return false;
1251+
12041252
for (i = 0; i < dmq_local.n_inhandles; i++)
12051253
{
12061254
Size len;
12071255
void *data;
12081256

1209-
res = shm_mq_receive(dmq_local.mq_inh[i], &len, &data, true);
1257+
res = shm_mq_receive(dmq_local.inhandles[i].mqh, &len, &data, true);
12101258
if (res == SHM_MQ_SUCCESS)
12111259
{
12121260
msg->data = data;
@@ -1258,23 +1306,3 @@ dmq_destination_add(char *connstr, char *sender_name, int ping_period)
12581306
}
12591307

12601308

1261-
void
1262-
dmq_push_buffer(DmqDestinationId dest_id, char *stream_name, const void *payload, size_t len)
1263-
{
1264-
StringInfoData buf;
1265-
shm_mq_result res;
1266-
1267-
ensure_outq_handle();
1268-
1269-
initStringInfo(&buf);
1270-
pq_sendbyte(&buf, dest_id);
1271-
pq_send_ascii_string(&buf, stream_name);
1272-
pq_sendbytes(&buf, payload, len);
1273-
1274-
// elog(LOG, "pushing l=%d '%.*s'", buf.len, buf.len, buf.data);
1275-
1276-
res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false);
1277-
if (res != SHM_MQ_SUCCESS)
1278-
elog(ERROR, "dmq_push: can't send to queue");
1279-
}
1280-

0 commit comments

Comments
 (0)