@@ -67,78 +67,81 @@ term_cmp(GlobalTxTerm t1, GlobalTxTerm t2)
67
67
return 1 ;
68
68
}
69
69
70
+ #define XStateVersion 1
70
71
71
72
char *
72
- serialize_gtx_state ( GlobalTxStatus status , GlobalTxTerm term_prop , GlobalTxTerm term_acc )
73
+ serialize_xstate ( XactInfo * xinfo , GTxState * gtx_state )
73
74
{
74
75
char * state ;
75
76
char * status_abbr ;
76
77
77
- if (status == GTXInvalid )
78
+ if (gtx_state -> status == GTXInvalid )
78
79
status_abbr = "in" ;
79
- else if (status == GTXPreCommitted )
80
+ else if (gtx_state -> status == GTXPreCommitted )
80
81
status_abbr = "pc" ;
81
- else if (status == GTXPreAborted )
82
+ else if (gtx_state -> status == GTXPreAborted )
82
83
status_abbr = "pa" ;
83
- else if (status == GTXCommitted )
84
+ else if (gtx_state -> status == GTXCommitted )
84
85
status_abbr = "cm" ;
85
86
else
86
87
{
87
- Assert (status == GTXAborted );
88
+ Assert (gtx_state -> status == GTXAborted );
88
89
status_abbr = "ab" ;
89
90
}
90
91
91
- state = psprintf ("%s-%d:%d-%d:%d" ,
92
+ state = psprintf ("%d-%d-" XID_FMT "-%" INT64_MODIFIER "X-%" INT64_MODIFIER "X-%s-%d:%d-%d:%d" ,
93
+ XStateVersion ,
94
+ xinfo -> coordinator ,
95
+ xinfo -> xid ,
96
+ xinfo -> gen_num ,
97
+ xinfo -> configured ,
92
98
status_abbr ,
93
- term_prop .ballot , term_prop .node_id ,
94
- term_acc .ballot , term_acc .node_id );
99
+ gtx_state -> proposal .ballot , gtx_state -> proposal .node_id ,
100
+ gtx_state -> accepted .ballot , gtx_state -> accepted .node_id );
95
101
return state ;
96
102
}
97
103
98
- void
99
- parse_gtx_state (const char * state , GlobalTxStatus * status ,
100
- GlobalTxTerm * term_prop , GlobalTxTerm * term_acc )
104
+ /* returns 0 on success */
105
+ int
106
+ deserialize_xstate (const char * state , XactInfo * xinfo , GTxState * gtx_state ,
107
+ int elevel )
101
108
{
102
109
int n_parsed = 0 ;
110
+ char status_abbr [3 ]; /* must be big enough for '\0' */
103
111
104
112
Assert (state );
105
113
106
- /*
107
- * Might be immediately after PrepareTransaction. It would be better to
108
- * also pass state_3pc to it, but...
109
- */
110
- if (state [0 ] == '\0' )
114
+ n_parsed = sscanf (state , "%*d-%d-" XID_FMT "-%" INT64_MODIFIER "X-%" INT64_MODIFIER "X-%2s-%d:%d-%d:%d" ,
115
+ & xinfo -> coordinator ,
116
+ & xinfo -> xid ,
117
+ & xinfo -> gen_num ,
118
+ & xinfo -> configured ,
119
+ status_abbr ,
120
+ & gtx_state -> proposal .ballot ,
121
+ & gtx_state -> proposal .node_id ,
122
+ & gtx_state -> accepted .ballot ,
123
+ & gtx_state -> accepted .node_id );
124
+ if (n_parsed != 9 )
111
125
{
112
- * status = GTXInvalid ;
113
- * term_prop = InitialGTxTerm ;
114
- * term_acc = InvalidGTxTerm ;
126
+ mtm_log ( elevel , "GlobalTxLoadAll: failed to deparse state_3pc %s, ignoring it (res=%d)" ,
127
+ state , n_parsed ) ;
128
+ return n_parsed ;
115
129
}
130
+
131
+ if (strncmp (status_abbr , "in" , 2 ) == 0 )
132
+ gtx_state -> status = GTXInvalid ;
133
+ else if (strncmp (status_abbr , "pc" , 2 ) == 0 )
134
+ gtx_state -> status = GTXPreCommitted ;
135
+ else if (strncmp (status_abbr , "pa" , 2 ) == 0 )
136
+ gtx_state -> status = GTXPreAborted ;
137
+ else if (strncmp (status_abbr , "cm" , 3 ) == 0 )
138
+ gtx_state -> status = GTXCommitted ;
116
139
else
117
140
{
118
- if (strncmp (state , "in-" , 3 ) == 0 )
119
- * status = GTXInvalid ;
120
- else if (strncmp (state , "pc-" , 3 ) == 0 )
121
- * status = GTXPreCommitted ;
122
- else if (strncmp (state , "pa-" , 3 ) == 0 )
123
- * status = GTXPreAborted ;
124
- else if (strncmp (state , "cm-" , 3 ) == 0 )
125
- * status = GTXCommitted ;
126
- else
127
- {
128
- Assert ((strncmp (state , "ab-" , 3 ) == 0 ));
129
- * status = GTXAborted ;
130
- }
131
-
132
- n_parsed = sscanf (state + 3 , "%d:%d-%d:%d" ,
133
- & term_prop -> ballot , & term_prop -> node_id ,
134
- & term_acc -> ballot , & term_acc -> node_id );
135
-
136
- if (n_parsed != 4 )
137
- {
138
- Assert (false);
139
- mtm_log (PANIC , "wrong state_3pc format: %s" , state );
140
- }
141
+ Assert ((strncmp (status_abbr , "ab" , 2 ) == 0 ));
142
+ gtx_state -> status = GTXAborted ;
141
143
}
144
+ return 0 ;
142
145
}
143
146
144
147
void
@@ -219,10 +222,11 @@ GlobalTxEnsureBeforeShmemExitHook(void)
219
222
* If nowait_own_live is true, gtx is already locked, I am the coordinator and
220
223
* gtx is not orphaned, don't wait for release -- backend is still working on
221
224
* xact, which may be very long. *busy (if provided) is set to true in this
222
- * case.
225
+ * case. coordinator must be passed for this to work.
223
226
*/
224
227
GlobalTx *
225
- GlobalTxAcquire (const char * gid , bool create , bool nowait_own_live , bool * busy )
228
+ GlobalTxAcquire (const char * gid , bool create , bool nowait_own_live , bool * busy ,
229
+ int coordinator )
226
230
{
227
231
GlobalTx * gtx = NULL ;
228
232
bool found ;
@@ -274,9 +278,7 @@ GlobalTxAcquire(const char *gid, bool create, bool nowait_own_live, bool *busy)
274
278
275
279
if (nowait_own_live )
276
280
{
277
- int tx_node_id = MtmGidParseNodeId (gid );
278
-
279
- if (tx_node_id == Mtm -> my_node_id && !gtx -> orphaned )
281
+ if (coordinator == Mtm -> my_node_id && !gtx -> orphaned )
280
282
{
281
283
if (busy )
282
284
* busy = true;
@@ -374,8 +376,15 @@ GlobalTxLoadAll()
374
376
Assert (!found );
375
377
376
378
gtx -> acquired_by = InvalidBackendId ;
377
- parse_gtx_state (pxacts [i ].state_3pc , & gtx -> state .status ,
378
- & gtx -> state .proposal , & gtx -> state .accepted );
379
+ /*
380
+ * Allow instance to start even if we have problems parsing xstate...
381
+ */
382
+ if (deserialize_xstate (pxacts [i ].state_3pc , & gtx -> xinfo , & gtx -> state ,
383
+ WARNING ) != 0 )
384
+ {
385
+ hash_search (gtx_shared -> gid2gtx , pxacts [i ].gid , HASH_REMOVE , & found );
386
+ continue ;
387
+ }
379
388
gtx -> prepared = true;
380
389
gtx -> orphaned = true;
381
390
gtx -> resolver_stage = GTRS_AwaitStatus ;
@@ -420,8 +429,7 @@ GlobalTxMarkOrphaned(int node_id)
420
429
hash_seq_init (& hash_seq , gtx_shared -> gid2gtx );
421
430
while ((gtx = hash_seq_search (& hash_seq )) != NULL )
422
431
{
423
- int tx_node_id = MtmGidParseNodeId (gtx -> gid );
424
- if (tx_node_id == node_id )
432
+ if (gtx -> xinfo .coordinator == node_id )
425
433
{
426
434
gtx -> orphaned = true;
427
435
mtm_log (MtmTxTrace , "%s is orphaned" , gtx -> gid );
0 commit comments