@@ -166,6 +166,7 @@ int MtmConnectAttempts;
166166int MtmConnectTimeout ;
167167int MtmKeepaliveTimeout ;
168168int MtmReconnectAttempts ;
169+ MtmConnectionInfo * MtmConnections ;
169170
170171static char * MtmConnStrs ;
171172static int MtmQueueSize ;
@@ -420,8 +421,13 @@ MtmAdjustOldestXid(TransactionId xid)
420421oldestSnapshot = Mtm -> nodes [i ].oldestSnapshot ;
421422}
422423}
423- for (ts = Mtm -> transListHead ;ts != NULL && ts -> csn < oldestSnapshot ;prev = ts ,ts = ts -> next ) {
424- Assert (ts -> status == TRANSACTION_STATUS_COMMITTED || ts -> status == TRANSACTION_STATUS_ABORTED || ts -> status == TRANSACTION_STATUS_IN_PROGRESS );
424+ for (ts = Mtm -> transListHead ;
425+ ts != NULL
426+ && ts -> csn < oldestSnapshot
427+ && (ts -> status == TRANSACTION_STATUS_COMMITTED || ts -> status == TRANSACTION_STATUS_ABORTED )
428+ && TransactionIdPrecedes (ts -> xid ,xid );
429+ prev = ts ,ts = ts -> next )
430+ {
425431if (prev != NULL ) {
426432/* Remove information about too old transactions */
427433hash_search (MtmXid2State ,& prev -> xid ,HASH_REMOVE ,NULL );
@@ -989,7 +995,7 @@ MtmBuildConnectivityMatrix(nodemask_t* matrix, bool nowait)
989995for (i = 0 ;i < n ;i ++ ) {
990996if (i + 1 != MtmNodeId ) {
991997void * data = PaxosGet (psprintf ("node-mask-%d" ,i + 1 ),NULL ,NULL ,nowait );
992- matrix [i ]= * (nodemask_t * )data ;
998+ matrix [i ]= data ? * (nodemask_t * )data : 0 ;
993999}else {
9941000matrix [i ]= Mtm -> connectivityMask ;
9951001}
@@ -1153,6 +1159,7 @@ static void MtmInitialize()
11531159for (i = 0 ;i < MtmNodes ;i ++ ) {
11541160Mtm -> nodes [i ].oldestSnapshot = 0 ;
11551161Mtm -> nodes [i ].transDelay = 0 ;
1162+ Mtm -> nodes [i ].con = MtmConnections [i ];
11561163}
11571164PGSemaphoreCreate (& Mtm -> votingSemaphore );
11581165PGSemaphoreReset (& Mtm -> votingSemaphore );
@@ -1178,17 +1185,17 @@ MtmShmemStartup(void)
11781185MtmInitialize ();
11791186}
11801187
1181- void MtmUpdateNodeConnStr ( int nodeId ,char const * connStr )
1188+ void MtmUpdateNodeConnectionInfo ( MtmConnectionInfo * conn ,char const * connStr )
11821189{
11831190char const * host ;
11841191char const * end ;
11851192int hostLen ;
11861193
11871194if (strlen (connStr ) >=MULTIMASTER_MAX_CONN_STR_SIZE ) {
1188- elog (ERROR ,"Too long (%d) connection string '%s' for node %d, limit is %d" ,
1189- (int )strlen (connStr ),connStr ,nodeId , MULTIMASTER_MAX_CONN_STR_SIZE - 1 );
1195+ elog (ERROR ,"Too long (%d) connection string '%s': limit is %d" ,
1196+ (int )strlen (connStr ),connStr ,MULTIMASTER_MAX_CONN_STR_SIZE - 1 );
11901197}
1191- strcpy (Mtm -> nodes [ nodeId - 1 ]. connStr ,connStr );
1198+ strcpy (conn -> connStr ,connStr );
11921199
11931200host = strstr (connStr ,"host=" );
11941201if (host == NULL ) {
@@ -1198,30 +1205,46 @@ void MtmUpdateNodeConnStr(int nodeId, char const* connStr)
11981205for (end = host ;* end != ' ' && * end != '\0' ;end ++ );
11991206hostLen = end - host ;
12001207if (hostLen >=MULTIMASTER_MAX_HOST_NAME_SIZE ) {
1201- elog (ERROR ,"Too long (%d) host name '%.*s' for node %d, limit is %d" ,
1202- hostLen ,hostLen ,host ,nodeId , MULTIMASTER_MAX_HOST_NAME_SIZE - 1 );
1208+ elog (ERROR ,"Too long (%d) host name '%.*s': limit is %d" ,
1209+ hostLen ,hostLen ,host ,MULTIMASTER_MAX_HOST_NAME_SIZE - 1 );
12031210}
1204- memcpy (Mtm -> nodes [ nodeId - 1 ]. hostName ,host ,hostLen );
1205- Mtm -> nodes [ nodeId - 1 ]. hostName [hostLen ]= '\0' ;
1211+ memcpy (conn -> hostName ,host ,hostLen );
1212+ conn -> hostName [hostLen ]= '\0' ;
12061213}
12071214
12081215static void MtmSplitConnStrs (void )
12091216{
12101217int i ;
1211- char * copy = strdup (MtmConnStrs );
1218+ char * copy = pstrdup (MtmConnStrs );
12121219char * connStr = copy ;
12131220char * connStrEnd = connStr + strlen (connStr );
12141221
1222+ for (i = 0 ;connStr < connStrEnd ;i ++ ) {
1223+ char * p = strchr (connStr ,',' );
1224+ if (p == NULL ) {
1225+ p = connStrEnd ;
1226+ }
1227+ connStr = p + 1 ;
1228+ }
1229+ if (i > MAX_NODES ) {
1230+ elog (ERROR ,"Multimaster with more than %d nodes is not currently supported" ,MAX_NODES );
1231+ }
1232+ if (i < 2 ) {
1233+ elog (ERROR ,"Multimaster should have at least two nodes" );
1234+ }
1235+ MtmNodes = i ;
1236+ MtmConnections = (MtmConnectionInfo * )palloc (i * sizeof (MtmConnectionInfo ));
1237+ connStr = copy ;
1238+
12151239for (i = 0 ;connStr < connStrEnd ;i ++ ) {
12161240char * p = strchr (connStr ,',' );
12171241if (p == NULL ) {
12181242p = connStrEnd ;
12191243 }
1220- if (i == MAX_NODES ) {
1221- elog (ERROR ,"Multimaster with more than %d nodes is not currently supported" ,MAX_NODES );
1222- }
12231244* p = '\0' ;
1224- MtmUpdateNodeConnStr (i + 1 ,connStr );
1245+
1246+ MtmUpdateNodeConnectionInfo (& MtmConnections [i ],connStr );
1247+
12251248if (i + 1 == MtmNodeId ) {
12261249char * dbName = strstr (connStr ,"dbname=" );
12271250char * end ;
@@ -1232,20 +1255,13 @@ static void MtmSplitConnStrs(void)
12321255dbName += 7 ;
12331256for (end = dbName ;* end != ' ' && * end != '\0' ;end ++ );
12341257len = end - dbName ;
1235- MtmDatabaseName = (char * )malloc (len + 1 );
1258+ MtmDatabaseName = (char * )palloc (len + 1 );
12361259memcpy (MtmDatabaseName ,dbName ,len );
12371260MtmDatabaseName [len ]= '\0' ;
12381261}
12391262connStr = p + 1 ;
12401263 }
1241- free (copy );
1242- if (i < 2 ) {
1243- elog (ERROR ,"Multimaster should have at least two nodes" );
1244- }
1245- MtmNodes = i ;
1246- if (MtmNodeId > MtmNodes ) {
1247- elog (ERROR ,"Invalid node id %d for specified nubmer of nodes %d" ,MtmNodeId ,MtmNodes );
1248- }
1264+ pfree (copy );
12491265}
12501266
12511267void