You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
(28) |
Jun
(12) |
Jul
(11) |
Aug
(12) |
Sep
(5) |
Oct
(19) |
Nov
(14) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(18) |
Feb
(30) |
Mar
(115) |
Apr
(89) |
May
(50) |
Jun
(44) |
Jul
(22) |
Aug
(13) |
Sep
(11) |
Oct
(30) |
Nov
(28) |
Dec
(39) |
2012 |
Jan
(38) |
Feb
(18) |
Mar
(43) |
Apr
(91) |
May
(108) |
Jun
(46) |
Jul
(37) |
Aug
(44) |
Sep
(33) |
Oct
(29) |
Nov
(36) |
Dec
(15) |
2013 |
Jan
(35) |
Feb
(611) |
Mar
(5) |
Apr
(55) |
May
(30) |
Jun
(28) |
Jul
(458) |
Aug
(34) |
Sep
(9) |
Oct
(39) |
Nov
(22) |
Dec
(32) |
2014 |
Jan
(16) |
Feb
(16) |
Mar
(42) |
Apr
(179) |
May
(7) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(4) |
Oct
|
Nov
(3) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Koichi S. <koi...@us...> - 2011-04-05 09:40:42
|
Project "Postgres-XC". The branch, ha_support has been updated via c811d7f4a755154cdf9f4b5e0353aad56fa16331 (commit) from 79263d24f7768522f238b7be0b8c07fc162fb742 (commit) - Log ----------------------------------------------------------------- commit c811d7f4a755154cdf9f4b5e0353aad56fa16331 Author: Koichi Suzuki <koi...@gm...> Date: Tue Apr 5 18:38:43 2011 +0900 This commit is a tweak to gtm_txn.c to avoid warning messages at the time of make. This code is not complete yet and actually is not used from any other code. To avoid any problems in the future, I added some of the lines so that the variable is properly initialized and we will have assert message when incomplete codes are accidentally reached. diff --git a/src/gtm/main/gtm_txn.c b/src/gtm/main/gtm_txn.c index 9cfbeb6..0c6c238 100644 --- a/src/gtm/main/gtm_txn.c +++ b/src/gtm/main/gtm_txn.c @@ -101,7 +101,7 @@ GTM_InitTxnManager(void) static XidStatus GlobalTransactionIdGetStatus(GlobalTransactionId transactionId) { - XidStatus xidstatus; + XidStatus xidstatus = TRANSACTION_STATUS_IN_PROGRESS; /* * Also, check to see if the transaction ID is a permanent one. @@ -117,7 +117,10 @@ GlobalTransactionIdGetStatus(GlobalTransactionId transactionId) /* * TODO To be implemeneted + * + * This code is not completed yet and the latter code must not be reached. */ + Assert(0); return xidstatus; } ----------------------------------------------------------------------- Summary of changes: src/gtm/main/gtm_txn.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-04-05 05:14:15
|
Project "Postgres-XC". The branch, ha_support has been updated via 79263d24f7768522f238b7be0b8c07fc162fb742 (commit) from 1fc12bd8cc427393ad4c0597a85c35060e1b1a2b (commit) - Log ----------------------------------------------------------------- commit 79263d24f7768522f238b7be0b8c07fc162fb742 Author: Koichi Suzuki <koi...@gm...> Date: Tue Apr 5 14:12:24 2011 +0900 This commit is to fix wrong commit done last. It was to fix xcm_telhowto behavior where it should have told to shutdown the cluster when no coordinator is running. Code correction was wrong and was corrected. Thanks Sudo-san for findding this. diff --git a/src/include/pgxc/xcm/node_membership_struct.h b/src/include/pgxc/xcm/node_membership_struct.h index 754e472..affad93 100644 --- a/src/include/pgxc/xcm/node_membership_struct.h +++ b/src/include/pgxc/xcm/node_membership_struct.h @@ -460,13 +460,13 @@ typedef struct xcm_fault_comps { */ #define XCM_OK 0 /* Successful */ #define XCM_OTHER_UPDATE 1 /* Shared memory updated for some reason */ +#define XCM_ERR_COMP_FAILED 2 /* Specified component is not running */ #define XCM_ERR_NOT_INITIALIZED -1 /* Shared memory not built yet */ #define XCM_ERR_OUT_OF_RANGE -2 /* Specified component does not exist */ -#define XCM_ERR_COMP_FAILED -3 /* Specified component is not running */ -#define XCM_ERR_MISC -4 /* Other system call error */ -#define XCM_ERR_PARM -5 /* Invalid parameters specified */ -#define XCM_ERR_STATUS -6 /* Cluster status cannot accept the operation */ -#define XCM_NOT_FOUND -7 /* Indicates that the specified object not found */ +#define XCM_ERR_MISC -3 /* Other system call error */ +#define XCM_ERR_PARM -4 /* Invalid parameters specified */ +#define XCM_ERR_STATUS -5 /* Cluster status cannot accept the operation */ +#define XCM_NOT_FOUND -6 /* Indicates that the specified object not found */ /* * Misc. magic numbers/values. diff --git a/src/pgxc/xcm/xcm_telhowto.c b/src/pgxc/xcm/xcm_telhowto.c index 41e736f..c53d257 100644 --- a/src/pgxc/xcm/xcm_telhowto.c +++ b/src/pgxc/xcm/xcm_telhowto.c @@ -514,7 +514,7 @@ static void handle_coordinator_failure(int ac, char *av[]) rv, __LINE__); end_and_exit(1); } - for (ii = 1, live_coord_count = 0; ii <= rv; ii++) + for (ii = 1, live_coord_count = 0; ii <= coord_count; ii++) { rv = get_xcm_coordinator_status(ii, &coord_status); if (rv < 0) @@ -530,7 +530,7 @@ static void handle_coordinator_failure(int ac, char *av[]) } if (live_coord_count <= 0) { - printf("shutdonw\n"); + printf("shutdown\n"); end_and_exit(0); } fflush(stdout); ----------------------------------------------------------------------- Summary of changes: src/include/pgxc/xcm/node_membership_struct.h | 10 +++++----- src/pgxc/xcm/xcm_telhowto.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-04-04 06:18:22
|
Project "Postgres-XC". The branch, ha_support has been updated via 1fc12bd8cc427393ad4c0597a85c35060e1b1a2b (commit) from 066fb159d1008f869bd396bb4be4d966bb0a74cf (commit) - Log ----------------------------------------------------------------- commit 1fc12bd8cc427393ad4c0597a85c35060e1b1a2b Author: Koichi Suzuki <koi...@gm...> Date: Mon Apr 4 15:17:08 2011 +0900 This commit is to fix the bug #3266463 in the track. Now xcm_telhowto tells to shutdown the whole cluster if no coordinators are running. diff --git a/src/pgxc/xcm/xcm_telhowto.c b/src/pgxc/xcm/xcm_telhowto.c index 8488cfb..41e736f 100644 --- a/src/pgxc/xcm/xcm_telhowto.c +++ b/src/pgxc/xcm/xcm_telhowto.c @@ -476,6 +476,9 @@ static void handle_coordinator_failure(int ac, char *av[]) int coord_id; /* Failed one */ int coord_count; int rv; + int ii; + unsigned coord_status; + int live_coord_count; rv = str_toi(&coord_id, av[3]); if (rv) @@ -501,6 +504,35 @@ static void handle_coordinator_failure(int ac, char *av[]) * Clean outstanding 2PCs */ printf("cleanup coordinator %d\n", coord_id); + /* + * Check if we can continue XCM cluster operation + */ + rv = get_xcm_coordinator_count(&coord_count); + if (rv < 0) + { + printf("ERR: Coundn't get coordinator count (%d, %d)\n", + rv, __LINE__); + end_and_exit(1); + } + for (ii = 1, live_coord_count = 0; ii <= rv; ii++) + { + rv = get_xcm_coordinator_status(ii, &coord_status); + if (rv < 0) + { + printf("ERR: Couldn't get coordinator %d status (%d, %d)\n", + ii, rv, __LINE__); + end_and_exit(1); + } + if (XCM_IS_RUNNING(coord_status)) + { + live_coord_count++; + } + } + if (live_coord_count <= 0) + { + printf("shutdonw\n"); + end_and_exit(0); + } fflush(stdout); return; } ----------------------------------------------------------------------- Summary of changes: src/pgxc/xcm/xcm_telhowto.c | 32 ++++++++++++++++++++++++++++++++ 1 files changed, 32 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-04-04 02:49:59
|
Project "Postgres-XC". The branch, ha_support has been updated via 066fb159d1008f869bd396bb4be4d966bb0a74cf (commit) from 263fffdb2d9865eac2d6780b2ac7edb6d4c0b857 (commit) - Log ----------------------------------------------------------------- commit 066fb159d1008f869bd396bb4be4d966bb0a74cf Author: Koichi Suzuki <koi...@gm...> Date: Mon Apr 4 11:45:24 2011 +0900 This commit resolves conflict to build pgxc_clean and gtm-standby. Gtm-standby introduced more module from Postgres-XC core and it introduced some conflicts to build pgxc_clean. They're resolved by this commit, which changed conflicted indentifiers. diff --git a/src/gtm/common/gtm_serialize.c b/src/gtm/common/gtm_serialize.c new file mode 100644 index 0000000..cdd9cdd --- /dev/null +++ b/src/gtm/common/gtm_serialize.c @@ -0,0 +1,864 @@ + + +#include "gtm/gtm_c.h" +#include "gtm/elog.h" +#include "gtm/palloc.h" +#include "gtm/gtm.h" +#include "gtm/gtm_txn.h" +#include "gtm/gtm_seq.h" +#include "gtm/assert.h" +#include "gtm/register.h" +#include "gtm/stringinfo.h" +#include "gtm/libpq.h" +#include "gtm/pqformat.h" +#include "gtm/gtm_msg.h" + +#include "gtm/gtm_serialize.h" + +//#include "gtm/gtm_list.h" +//#include "gtm/memutils.h" + +/* ----------------------------------------------------- + * Get a serialized size of GTM_SnapshotData structure + * ----------------------------------------------------- + */ +size_t +gtm_get_snapshotdata_size(GTM_SnapshotData *data) +{ + size_t len = 0; + + len += sizeof(GlobalTransactionId); + len += sizeof(GlobalTransactionId); + len += sizeof(GlobalTransactionId); + len += sizeof(uint32); + len += sizeof(GlobalTransactionId); + + return len; +} + +/* ----------------------------------------------------- + * Serialize a GTM_SnapshotData structure + * ----------------------------------------------------- + */ +size_t +gtm_serialize_snapshotdata(GTM_SnapshotData *data, char *buf, size_t buflen) +{ + int len = 0; + + memset(buf, 0, buflen); + + /* size check */ + if ( gtm_get_snapshotdata_size(data) > buflen ) + return 0; + + /* GTM_SnapshotData.sn_xmin */ + memcpy(buf+len, &(data->sn_xmin), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_xmax */ + memcpy(buf+len, &(data->sn_xmax), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_recent_global_xmin */ + memcpy(buf+len, &(data->sn_recent_global_xmin), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_xcnt */ + memcpy(buf+len, &(data->sn_xcnt), sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_SnapshotData.sn_xip */ + memcpy(buf+len, &(data->sn_xip), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + return len; +} + +/* ----------------------------------------------------- + * Deserialize a GTM_SnapshotData structure + * ----------------------------------------------------- + */ +size_t +gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buflen) +{ + size_t len = 0; + + /* GTM_SnapshotData.sn_xmin */ + memcpy(&(data->sn_xmin), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_xmax */ + memcpy(&(data->sn_xmax), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_recent_global_xmin */ + memcpy(&(data->sn_recent_global_xmin), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_SnapshotData.sn_xcnt */ + memcpy(&(data->sn_xcnt), buf+len, sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_SnapshotData.sn_xip */ + memcpy(&(data->sn_xip), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + return len; +} + + +/* ----------------------------------------------------- + * Get a serialized size ofGTM_TransactionInfo structure + * ----------------------------------------------------- + */ +size_t +gtm_get_transactioninfo_size(GTM_TransactionInfo *data) +{ + size_t len = 0; + + if ( data==NULL ) + return len; + + len += sizeof(GTM_TransactionHandle); /* gti_handle */ + len += sizeof(GTM_ThreadID); /* gti_thread_id */ + len += sizeof(bool); /* gti_in_use */ + len += sizeof(GlobalTransactionId); /* gti_gxid */ + len += sizeof(GTM_TransactionStates); /* gti_state */ + len += sizeof(PGXC_NodeId); /* gti_coordid */ + len += sizeof(GlobalTransactionId); /* gti_xmin */ + len += sizeof(GTM_IsolationLevel); /* gti_isolevel */ + len += sizeof(bool); /* gti_readonly */ + len += sizeof(GTMProxy_ConnID); /* gti_backend_id */ + len += sizeof(uint32); /* gti_datanodecount */ + len += sizeof(PGXC_NodeId) * data->gti_datanodecount; + /* gti_datanodes */ + len += sizeof(uint32); /* gti_coordcount */ + len += sizeof(PGXC_NodeId) * data->gti_coordcount; + /* gti_coordinators */ + + if ( data->gti_gid != NULL ) + len += strlen(data->gti_gid) + 1; /* gti_gid */ + else + len += 1; + + len += gtm_get_snapshotdata_size( &(data->gti_current_snapshot) ); + /* gti_current_snapshot */ + len += sizeof(bool); /* gti_snapshot_set */ + /* NOTE: nothing to be done for gti_lock */ + len += sizeof(bool); /* gti_vacuum */ + + return len; +} + + +/* ----------------------------------------------------- + * Serialize a GTM_TransactionInfo structure + * ----------------------------------------------------- + */ +size_t +gtm_serialize_transactioninfo(GTM_TransactionInfo *data, char *buf, size_t buflen) +{ + int len = 0; + char *buf2; + int i; + + /* size check */ + if ( gtm_get_transactioninfo_size(data) > buflen ) + return 0; + + memset(buf, 0, buflen); + + /* GTM_TransactionInfo.gti_handle */ + memcpy(buf+len, &(data->gti_handle), sizeof(GTM_TransactionHandle)); + len += sizeof(GTM_TransactionHandle); + + /* GTM_TransactionInfo.gti_thread_id */ + memcpy(buf+len, &(data->gti_thread_id), sizeof(GTM_ThreadID)); + len += sizeof(GTM_ThreadID); + + /* GTM_TransactionInfo.gti_in_use */ + memcpy(buf+len, &(data->gti_in_use), sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_gxid */ + memcpy(buf+len, &(data->gti_gxid), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_TransactionInfo.gti_state */ + memcpy(buf+len, &(data->gti_state), sizeof(GTM_TransactionStates)); + len += sizeof(GTM_TransactionStates); + + /* GTM_TransactionInfo.gti_coordid */ + memcpy(buf+len, &(data->gti_coordid), sizeof(PGXC_NodeId)); + len += sizeof(PGXC_NodeId); + + /* GTM_TransactionInfo.gti_xmin */ + memcpy(buf+len, &(data->gti_xmin), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_TransactionInfo.gti_isolevel */ + memcpy(buf+len, &(data->gti_isolevel), sizeof(GTM_IsolationLevel)); + len += sizeof(GTM_IsolationLevel); + + /* GTM_TransactionInfo.gti_readonly */ + memcpy(buf+len, &(data->gti_readonly), sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_backend_id */ + memcpy(buf+len, &(data->gti_backend_id), sizeof(GTMProxy_ConnID)); + len += sizeof(GTMProxy_ConnID); + + /* GTM_TransactionInfo.gti_datanodecount */ + memcpy(buf+len, &(data->gti_datanodecount), sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_TransactionInfo.gti_datanodes */ + for (i=0 ; i<data->gti_datanodecount ; i++) + { + memcpy(buf+len, &(data->gti_datanodes[i]), sizeof(PGXC_NodeId)); + len += sizeof(PGXC_NodeId); + } + + /* GTM_TransactionInfo.gti_coordcount */ + memcpy(buf+len, &(data->gti_coordcount), sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_TransactionInfo.gti_coordinators */ + for (i=0 ; i<data->gti_coordcount ; i++) + { + memcpy(buf+len, &(data->gti_coordinators[i]), sizeof(PGXC_NodeId)); + len += sizeof(PGXC_NodeId); + } + + /* GTM_TransactionInfo.gti_gid */ + if ( data->gti_gid!=NULL ) + { + memcpy(buf+len, data->gti_gid, strlen(data->gti_gid)); + len += strlen(data->gti_gid) + 1; /* null-terminated */ + } + else + { + *(buf+len) = '\0'; + len += 1; + } + + /* GTM_TransactionInfo.gti_current_snapshot */ + buf2 = malloc( gtm_get_snapshotdata_size( &(data->gti_current_snapshot) ) ); + i = gtm_serialize_snapshotdata( &(data->gti_current_snapshot), + buf2, + gtm_get_snapshotdata_size( &(data->gti_current_snapshot) )); + memcpy(buf+len, buf2, i); + free(buf2); + len += i; + + /* GTM_TransactionInfo.gti_snapshot_set */ + memcpy(buf+len, &(data->gti_snapshot_set), sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_lock would not be serialized. */ + + /* GTM_TransactionInfo.gti_vacuum */ + memcpy(buf+len, &(data->gti_vacuum), sizeof(bool)); + len += sizeof(bool); + + return len; +} + +/* ----------------------------------------------------- + * Deserialize a GTM_TransactionInfo structure + * ----------------------------------------------------- + */ +size_t +gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size_t maxlen) +{ + int len = 0; + int i; + + memset(data, 0, sizeof(GTM_TransactionInfo)); + + /* GTM_TransactionInfo.gti_handle */ + memcpy(&(data->gti_handle), buf+len, sizeof(GTM_TransactionHandle)); + len += sizeof(GTM_TransactionHandle); + + /* GTM_TransactionInfo.gti_thread_id */ + memcpy(&(data->gti_thread_id), buf+len, sizeof(GTM_ThreadID)); + len += sizeof(GTM_ThreadID); + + /* GTM_TransactionInfo.gti_in_use */ + memcpy(&(data->gti_in_use), buf+len, sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_gxid */ + memcpy(&(data->gti_gxid), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_TransactionInfo.gti_state */ + memcpy(&(data->gti_state), buf+len, sizeof(GTM_TransactionStates)); + len += sizeof(GTM_TransactionStates); + + /* GTM_TransactionInfo.gti_coordid */ + memcpy(&(data->gti_coordid), buf+len, sizeof(PGXC_NodeId)); + len += sizeof(PGXC_NodeId); + + /* GTM_TransactionInfo.gti_xmin */ + memcpy(&(data->gti_xmin), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_TransactionInfo.gti_isolevel */ + memcpy(&(data->gti_isolevel), buf+len, sizeof(GTM_IsolationLevel)); + len += sizeof(GTM_IsolationLevel); + + /* GTM_TransactionInfo.gti_readonly */ + memcpy(&(data->gti_readonly), buf+len, sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_backend_id */ + memcpy(&(data->gti_backend_id), buf+len, sizeof(GTMProxy_ConnID)); + len += sizeof(GTMProxy_ConnID); + + /* GTM_TransactionInfo.gti_datanodecount */ + memcpy(&(data->gti_datanodecount), buf+len, sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_TransactionInfo.gti_datanodes */ + data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); + + for (i=0 ; i<data->gti_datanodecount ; i++) + { + memcpy(&(data->gti_datanodes[i]), buf+len, sizeof(PGXC_NodeId)); + len += sizeof(PGXC_NodeId); + } + + /* GTM_TransactionInfo.gti_coordcount */ + memcpy(&(data->gti_coordcount), buf+len, sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_TransactionInfo.gti_coordinators */ + data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); + + for (i=0 ; i<data->gti_coordcount ; i++) + { + PGXC_NodeId *cur = data->gti_coordinators; + + memcpy(cur, buf+len, sizeof(PGXC_NodeId)); + + len += sizeof(PGXC_NodeId); + cur++; + } + + /* GTM_TransactionInfo.gti_gid */ + if ( *(buf+len) != '\0' ) + { + data->gti_gid = (char *)malloc( strlen(buf+len)+1); + strncpy(data->gti_gid, buf+len, strlen(buf+len) ); + len += strlen(buf+len) + 1; /* null-terminated */ + } + else + { + data->gti_gid = NULL; + len += 1; + } + + /* GTM_TransactionInfo.gti_current_snapshot */ + i = gtm_deserialize_snapshotdata( &(data->gti_current_snapshot), + buf+len, + sizeof(GTM_SnapshotData) ); + len += i; + + /* GTM_TransactionInfo.gti_snapshot_set */ + memcpy(&(data->gti_snapshot_set), buf+len, sizeof(bool)); + len += sizeof(bool); + + /* GTM_TransactionInfo.gti_lock would not be serialized. */ + + /* GTM_TransactionInfo.gti_vacuum */ + memcpy(&(data->gti_vacuum), buf+len, sizeof(bool)); + len += sizeof(bool); + + return len; +} + + +size_t +gtm_get_transactions_size(GTM_Transactions *data) +{ + size_t len = 0; + int i; + + len += sizeof(uint32); /* gt_txn_count */ + len += sizeof(GTM_States); /* gt_gtm_state */ + + /* NOTE: nothing to be done for gt_XidGenLock */ + + len += sizeof(GlobalTransactionId); /* gt_nextXid */ + len += sizeof(GlobalTransactionId); /* gt_oldestXid */ + len += sizeof(GlobalTransactionId); /* gt_xidVacLimit */ + len += sizeof(GlobalTransactionId); /* gt_xidWarnLimit */ + len += sizeof(GlobalTransactionId); /* gt_xidStopLimit */ + len += sizeof(GlobalTransactionId); /* gt_xidWrapLimit */ + + len += sizeof(GlobalTransactionId); /* gt_latestCompletedXid */ + len += sizeof(GlobalTransactionId); /* gt_recent_global_xmin */ + + len += sizeof(int32); /* gt_lastslot */ + + len += sizeof(int32); /* txn_count */ + + for (i=0 ; i<GTM_MAX_GLOBAL_TRANSACTIONS ; i++) + { + len += sizeof(size_t); /* length */ + len += gtm_get_transactioninfo_size(&data->gt_transactions_array[i]); + } + + /* NOTE: nothing to be done for gt_open_transactions */ + /* NOTE: nothing to be done for gt_TransArrayLock */ + + return len; +} + +size_t +gtm_serialize_transactions(GTM_Transactions *data, char *buf, size_t buflen) +{ + int len = 0; + int i; + uint32 txn_count; + + /* size check */ + if ( gtm_get_transactions_size(data) > buflen ) + return 0; + + memset(buf, 0, buflen); + + /* GTM_Transactions.gt_txn_count */ + memcpy(buf+len, &(data->gt_txn_count), sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_Transactions.gt_gtm_state */ + memcpy(buf+len, &(data->gt_gtm_state), sizeof(GTM_States)); + len += sizeof(GTM_States); + + /* NOTE: nothing to be done for gt_XidGenLock */ + + /* GTM_Transactions.gt_nextXid */ + memcpy(buf+len, &(data->gt_nextXid), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_oldestXid */ + memcpy(buf+len, &(data->gt_oldestXid), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidVacLimit */ + memcpy(buf+len, &(data->gt_xidVacLimit), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidWarnLimit */ + memcpy(buf+len, &(data->gt_xidWarnLimit), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidStopLimit */ + memcpy(buf+len, &(data->gt_xidStopLimit), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidWrapLimit */ + memcpy(buf+len, &(data->gt_xidWrapLimit), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_latestCompletedXid */ + memcpy(buf+len, &(data->gt_latestCompletedXid), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_recent_global_xmin */ + memcpy(buf+len, &(data->gt_recent_global_xmin), sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_lastslot */ + memcpy(buf+len, &(data->gt_lastslot), sizeof(int32)); + len += sizeof(int32); + + /* Count up for valid transactions. */ + txn_count = 0; + + for (i=0 ; i<GTM_MAX_GLOBAL_TRANSACTIONS ; i++) + { + if ( data->gt_transactions_array[i].gti_gxid != InvalidGlobalTransactionId ) + txn_count++; + } + + memcpy(buf+len, &txn_count, sizeof(int32)); + len += sizeof(int32); + + /* + * GTM_Transactions.gt_transactions_array + */ + for (i=0 ; i<txn_count ; i++) + { + char *buf2; + size_t buflen2, len2; + + /* + * Not to include invalid global transactions. + */ + if ( data->gt_transactions_array[i].gti_gxid == InvalidGlobalTransactionId ) + continue; + + buflen2 = gtm_get_transactioninfo_size( &data->gt_transactions_array[i] ); + + /* store a length of following data. */ + memcpy(buf+len, &buflen2, sizeof(size_t)); + len += sizeof(size_t); + + buf2 = (char *)malloc( buflen2 ); + + len2 = gtm_serialize_transactioninfo( &data->gt_transactions_array[i], + buf2, + buflen2); + + /* store a serialized GTM_TransactionInfo structure. */ + memcpy(buf+len, buf2, len2); + len += len2; + + free(buf2); + } + + // dump_transactions_elog(data, txn_count); + + /* NOTE: nothing to be done for gt_TransArrayLock */ + + return len; +} + + +/* + * Return a number of deserialized transactions. + */ +size_t +gtm_deserialize_transactions(GTM_Transactions *data, const char *buf, size_t maxlen) +{ + int len = 0; + int i; + uint32 txn_count; + + /* GTM_Transactions.gt_txn_count */ + memcpy(&(data->gt_txn_count), buf+len, sizeof(uint32)); + len += sizeof(uint32); + + /* GTM_Transactions.gt_gtm_state */ + memcpy(&(data->gt_gtm_state), buf+len, sizeof(GTM_States)); + len += sizeof(GTM_States); + + /* NOTE: nothing to be done for gt_XidGenLock */ + + /* GTM_Transactions.gt_nextXid */ + memcpy(&(data->gt_nextXid), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_oldestXid */ + memcpy(&(data->gt_oldestXid), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidVacLimit */ + memcpy(&(data->gt_xidVacLimit), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidWarnLimit */ + memcpy(&(data->gt_xidWarnLimit), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidStopLimit */ + memcpy(&(data->gt_xidStopLimit), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_xidWrapLimit */ + memcpy(&(data->gt_xidWrapLimit), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_latestCompletedXid */ + memcpy(&(data->gt_latestCompletedXid), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_recent_global_xmin */ + memcpy(&(data->gt_recent_global_xmin), buf+len, sizeof(GlobalTransactionId)); + len += sizeof(GlobalTransactionId); + + /* GTM_Transactions.gt_lastslot */ + memcpy(&(data->gt_lastslot), buf+len, sizeof(int32)); + len += sizeof(int32); + + /* A number of valid transactions */ + memcpy(&txn_count, buf+len, sizeof(int32)); + len += sizeof(int32); + + /* GTM_Transactions.gt_transactions_array */ + for (i=0 ; i<txn_count ; i++) + { + size_t buflen2, len2; + + /* read a length of following data. */ + memcpy(&buflen2, buf+len, sizeof(size_t)); + len += sizeof(size_t); + + /* reada serialized GTM_TransactionInfo structure. */ + len2 = gtm_deserialize_transactioninfo( &(data->gt_transactions_array[i]), + buf+len, + buflen2); + + len += len2; + } + + /* NOTE: nothing to be done for gt_TransArrayLock */ + + return txn_count; +} + +size_t +gtm_get_pgxcnodeinfo_size(GTM_PGXCNodeInfo *data) +{ + size_t len = 0; + + len += sizeof(GTM_PGXCNodeType); /* type */ + len += sizeof(GTM_PGXCNodeId); /* nodenum */ + len += sizeof(GTM_PGXCNodeId); /* proxynum */ + len += sizeof(GTM_PGXCNodePort); /* port */ + + if ( data->ipaddress == NULL ) /* ipaddress */ + len += 1; + else + len += strlen(data->ipaddress) + 1; + + if ( data->datafolder == NULL ) /* datafolder */ + len += 1; + else + len += strlen(data->datafolder) + 1; + + len += sizeof(GTM_PGXCNodeStatus); /* status */ + + return len; +} + +size_t +gtm_serialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, char *buf, size_t buflen) +{ + size_t len = 0; + + /* size check */ + if ( gtm_get_pgxcnodeinfo_size(data) > buflen ) + return 0; + + memset(buf, 0, buflen); + + /* GTM_PGXCNodeInfo.type */ + memcpy(buf+len, &(data->type), sizeof(GTM_PGXCNodeType)); + len += sizeof(GTM_PGXCNodeType); + + /* GTM_PGXCNodeInfo.nodenum */ + memcpy(buf+len, &(data->nodenum), sizeof(GTM_PGXCNodeId)); + len += sizeof(GTM_PGXCNodeId); + + /* GTM_PGXCNodeInfo.proxynum */ + memcpy(buf+len, &(data->proxynum), sizeof(GTM_PGXCNodeId)); + len += sizeof(GTM_PGXCNodeId); + + /* GTM_PGXCNodeInfo.port */ + memcpy(buf+len, &(data->port), sizeof(GTM_PGXCNodePort)); + len += sizeof(GTM_PGXCNodePort); + + /* GTM_PGXCNodeInfo.ipaddress */ + if ( data->ipaddress == NULL ) + { + len += 1; + } + else + { + strncpy(buf+len, data->ipaddress, strlen(data->ipaddress)); + len += strlen(data->ipaddress) + 1; + } + + /* GTM_PGXCNodeInfo.datafolder */ + if ( data->datafolder == NULL ) + { + len += 1; + } + else + { + strncpy(buf+len, data->datafolder, strlen(data->datafolder)); + len += strlen(data->datafolder) + 1; + } + + /* GTM_PGXCNodeInfo.status */ + memcpy(buf+len, &(data->status), sizeof(GTM_PGXCNodeStatus)); + len += sizeof(GTM_PGXCNodeStatus); + + /* NOTE: nothing to be done for node_lock */ + + return len; +} + +size_t +gtm_deserialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, const char *buf, size_t buflen) +{ + size_t len = 0; + + /* GTM_PGXCNodeInfo.type */ + memcpy(&(data->type), buf+len, sizeof(GTM_PGXCNodeType)); + len += sizeof(GTM_PGXCNodeType); + + /* GTM_PGXCNodeInfo.nodenum */ + memcpy(&(data->nodenum), buf+len, sizeof(GTM_PGXCNodeId)); + len += sizeof(GTM_PGXCNodeId); + + /* GTM_PGXCNodeInfo.proxynum */ + memcpy(&(data->proxynum), buf+len, sizeof(GTM_PGXCNodeId)); + len += sizeof(GTM_PGXCNodeId); + + /* GTM_PGXCNodeInfo.port */ + memcpy(&(data->port), buf+len, sizeof(GTM_PGXCNodePort)); + len += sizeof(GTM_PGXCNodePort); + + /* GTM_PGXCNodeInfo.ipaddress */ + if ( *(buf+len) == '\0' ) + { + len += 1; + data->ipaddress = NULL; + } + else + { + data->ipaddress = (char *)malloc( strlen(buf+len) ) + 1; + strncpy(data->ipaddress, buf+len, strlen(buf+len)); + len += strlen(buf+len) + 1; + } + + /* GTM_PGXCNodeInfo.datafolder */ + if ( *(buf+len) == '\0' ) + { + len += 1; + data->datafolder = NULL; + } + else + { + data->datafolder = (char *)malloc( strlen(buf+len) ) + 1; + strncpy(data->datafolder, buf+len, strlen(buf+len)); + len += strlen(buf+len) + 1; + } + + /* GTM_PGXCNodeInfo.status */ + memcpy(&(data->status), buf+len, sizeof(GTM_PGXCNodeStatus)); + len += sizeof(GTM_PGXCNodeStatus); + + /* NOTE: nothing to be done for node_lock */ + + return len; +} + +size_t +gtm_get_sequence_size(GTM_SeqInfo *seq) +{ + size_t len = 0; + + len += sizeof(uint32); /* gs_key.gsk_keylen */ + len += seq->gs_key->gsk_keylen; /* gs_key.gsk_key */ + len += sizeof(GTM_SequenceKeyType); /* gs_key.gsk_type */ + len += sizeof(GTM_Sequence); /* gs_value */ + len += sizeof(GTM_Sequence); /* gs_init_value */ + len += sizeof(GTM_Sequence); /* gs_last_value */ + len += sizeof(GTM_Sequence); /* gs_increment_by */ + len += sizeof(GTM_Sequence); /* gs_min_value */ + len += sizeof(GTM_Sequence); /* gs_max_value */ + len += sizeof(bool); /* gs_cycle */ + len += sizeof(bool); /* gs_called */ + + return len; +} + +size_t +gtm_serialize_sequence(GTM_SeqInfo *s, char *buf, size_t buflen) +{ + size_t len = 0; + + /* size check */ + if ( gtm_get_sequence_size(s) > buflen ) + return 0; + + memset(buf, 0, buflen); + + memcpy(buf+len, &s->gs_key->gsk_keylen, sizeof(uint32)); + len += sizeof(uint32); /* gs_key.gsk_keylen */ + + memcpy(buf+len, s->gs_key->gsk_key, s->gs_key->gsk_keylen); + len += s->gs_key->gsk_keylen; /* gs_key.gsk_key */ + + memcpy(buf+len, &s->gs_key->gsk_type, sizeof(GTM_SequenceKeyType)); + len += sizeof(GTM_SequenceKeyType); /* gs_key.gsk_type */ + + memcpy(buf+len, &s->gs_value, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_value */ + + memcpy(buf+len, &s->gs_init_value, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_init_value */ + + memcpy(buf+len, &s->gs_last_value, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_last_value */ + + memcpy(buf+len, &s->gs_increment_by, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_increment_by */ + + memcpy(buf+len, &s->gs_min_value, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_min_value */ + + memcpy(buf+len, &s->gs_max_value, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_max_value */ + + memcpy(buf+len, &s->gs_cycle, sizeof(bool)); + len += sizeof(bool); /* gs_cycle */ + + memcpy(buf+len, &s->gs_called, sizeof(bool)); + len += sizeof(bool); /* gs_called */ + + return len; +} + +GTM_SeqInfo * +gtm_deserialize_sequence(const char *buf, size_t buflen) +{ + size_t len = 0; + GTM_SeqInfo *seq; + + seq = (GTM_SeqInfo *)malloc( sizeof(GTM_SeqInfo) ); + seq->gs_key = (GTM_SequenceKeyData *)malloc( sizeof(GTM_SequenceKeyData) ); + + memcpy(&seq->gs_key->gsk_keylen, buf+len, sizeof(uint32)); + len += sizeof(uint32); /* gs_key.gsk_keylen */ + + seq->gs_key->gsk_key = (char *)malloc(seq->gs_key->gsk_keylen+1); + memset(seq->gs_key->gsk_key, 0, seq->gs_key->gsk_keylen+1); + memcpy(seq->gs_key->gsk_key, buf+len, seq->gs_key->gsk_keylen); + len += seq->gs_key->gsk_keylen; /* gs_key.gsk_key */ + + memcpy(&seq->gs_key->gsk_type, buf+len, sizeof(GTM_SequenceKeyType)); + len += sizeof(GTM_SequenceKeyType); /* gs_key.gsk_type */ + + memcpy(&seq->gs_value, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_value */ + + memcpy(&seq->gs_init_value, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_init_value */ + + memcpy(&seq->gs_last_value, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_last_value */ + + memcpy(&seq->gs_increment_by, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_increment_by */ + + memcpy(&seq->gs_min_value, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_min_value */ + + memcpy(&seq->gs_max_value, buf+len, sizeof(GTM_Sequence)); + len += sizeof(GTM_Sequence); /* gs_max_value */ + + memcpy(&seq->gs_cycle, buf+len, sizeof(bool)); + len += sizeof(bool); /* gs_cycle */ + + memcpy(&seq->gs_called, buf+len, sizeof(bool)); + len += sizeof(bool); /* gs_called */ + + return seq; +} diff --git a/src/gtm/common/gtm_serialize_debug.c b/src/gtm/common/gtm_serialize_debug.c new file mode 100644 index 0000000..d9d689e --- /dev/null +++ b/src/gtm/common/gtm_serialize_debug.c @@ -0,0 +1,76 @@ + +#include "gtm/gtm_c.h" +#include "gtm/elog.h" +#include "gtm/palloc.h" +#include "gtm/gtm.h" +#include "gtm/gtm_txn.h" +#include "gtm/gtm_seq.h" +#include "gtm/assert.h" +#include "gtm/register.h" +#include "gtm/stringinfo.h" +#include "gtm/libpq.h" +#include "gtm/pqformat.h" +#include "gtm/gtm_msg.h" + +#include "gtm/gtm_serialize.h" + +void +dump_transactioninfo_elog(GTM_TransactionInfo *txn) +{ + elog(LOG, " ========= GTM_TransactionInfo ========="); + elog(LOG, " gti_handle: %d", txn->gti_handle); + elog(LOG, " gti_thread_id: %ld", txn->gti_thread_id); + elog(LOG, " gti_in_use: %d", txn->gti_in_use); + elog(LOG, " gti_gxid: %d", txn->gti_gxid); + elog(LOG, " gti_state: %d", txn->gti_state); + elog(LOG, " gti_coordid: %d", txn->gti_coordid); + elog(LOG, " gti_xmin: %d", txn->gti_xmin); + elog(LOG, " gti_isolevel: %d", txn->gti_isolevel); + elog(LOG, " gti_readonly: %d", txn->gti_readonly); + elog(LOG, " gti_backend_id: %d", txn->gti_backend_id); + elog(LOG, " gti_datanodecount: %d", txn->gti_datanodecount); + // PGXC_NodeId *gti_datanodes; + elog(LOG, " gti_coordcount: %d", txn->gti_coordcount); + // PGXC_NodeId *gti_coordinators; + elog(LOG, " gti_gid: %s", txn->gti_gid); + + elog(LOG, " sn_xmin: %d", txn->gti_current_snapshot.sn_xmin); + elog(LOG, " sn_xmax: %d", txn->gti_current_snapshot.sn_xmax); + elog(LOG, " sn_recent_global_xmin: %d", txn->gti_current_snapshot.sn_recent_global_xmin); + elog(LOG, " sn_xcnt: %d", txn->gti_current_snapshot.sn_xcnt); + elog(LOG, " sn_xip: %d", *(txn->gti_current_snapshot.sn_xip)); + + elog(LOG, " gti_snapshot_set: %d", txn->gti_snapshot_set); + elog(LOG, " gti_vacuum: %d", txn->gti_vacuum); + elog(LOG, " ========================================"); +} + +void +dump_transactions_elog(GTM_Transactions *txn, int num_txn) +{ + int i; + + elog(LOG, "============ GTM_Transactions ============"); + elog(LOG, " gt_txn_count: %d", txn->gt_txn_count); + elog(LOG, " gt_XidGenLock: %p", &txn->gt_XidGenLock); + elog(LOG, " gt_nextXid: %d", txn->gt_nextXid); + elog(LOG, " gt_oldestXid: %d", txn->gt_oldestXid); + elog(LOG, " gt_xidVacLimit: %d", txn->gt_xidVacLimit); + elog(LOG, " gt_xidWarnLimit: %d", txn->gt_xidWarnLimit); + elog(LOG, " gt_xidStopLimit: %d", txn->gt_xidStopLimit); + elog(LOG, " gt_xidWrapLimit: %d", txn->gt_xidWrapLimit); + elog(LOG, " gt_latestCompletedXid: %d", txn->gt_latestCompletedXid); + elog(LOG, " gt_recent_global_xmin: %d", txn->gt_recent_global_xmin); + elog(LOG, " gt_lastslot: %d", txn->gt_lastslot); + + for (i=0 ; i<num_txn ; i++) + { + if ( txn->gt_transactions_array[i].gti_gxid != InvalidGlobalTransactionId ) + dump_transactioninfo_elog(&txn->gt_transactions_array[i]); + } + // gtm_List *gt_open_transactions; + elog(LOG, " gt_TransArrayLock: %p", &txn->gt_TransArrayLock); + elog(LOG, "=========================================="); +} + + diff --git a/src/gtm/common/gtm_utils.c b/src/gtm/common/gtm_utils.c new file mode 100644 index 0000000..a25ae6a --- /dev/null +++ b/src/gtm/common/gtm_utils.c @@ -0,0 +1,19 @@ +#include "gtm/gtm_utils.h" + +#include "gtm/elog.h" +#include "gtm/gtm.h" + +/* + * gtm_report_failure() is an utility function to report fatal failure + * which occureed inside GTM to XCM, especially communication errors. + * + * `failed_conn' is null-able when failed to establish a connection + * with other node. + */ +void +gtm_report_failure(GTM_Conn *failed_conn) +{ + /* FIXME: report_xcwatch_gtm_failure() */ + elog(LOG, "Calling report_xcwatch_gtm_failure()..."); + return; +} diff --git a/src/gtm/main/gtm_standby.c b/src/gtm/main/gtm_standby.c new file mode 100644 index 0000000..bca82f7 --- /dev/null +++ b/src/gtm/main/gtm_standby.c @@ -0,0 +1,489 @@ +#include "gtm/gtm_standby.h" + +#include "gtm/elog.h" +#include "gtm/gtm.h" +#include "gtm/gtm_c.h" +#include "gtm/gtm_client.h" +#include "gtm/gtm_seq.h" +#include "gtm/gtm_serialize.h" +#include "gtm/gtm_utils.h" +#include "gtm/register.h" + +/* + * Variables to interact with GTM active under GTM standby mode. + * + * FIXME: need to protect these values with mutex lock for thread safe. + */ +static bool GTM_StandbyMode = false; +static char *GTM_ActiveAddress; +static int GTM_ActivePort; +static GTM_Conn *GTM_ActiveConn = NULL; + +static char standbyNodeName[NI_MAXHOST]; +static GTM_PGXCNodeId standbyNodeNum; +static int standbyPortNumber; +static char *standbyDataDir; + +static GTM_Conn *gtm_standby_connect_to_standby_int(int *); + +bool +gtm_is_standby() +{ + return GTM_StandbyMode; +} + +void +gtm_set_standby(bool standby) +{ + GTM_StandbyMode = standby; +} + +void +gtm_set_active_conninfo(const char *addr, int port) +{ + GTM_ActiveAddress = strdup(addr); + GTM_ActivePort = port; +} + +int +gtm_standby_start_startup() +{ + char connect_string[1024]; + + elog(LOG, "Connecting the GTM active on %s:%d...", GTM_ActiveAddress, GTM_ActivePort); + + sprintf(connect_string, "host=%s port=%d pgxc_node_id=1 remote_type=%d", + GTM_ActiveAddress, GTM_ActivePort, PGXC_NODE_GTM); + + GTM_ActiveConn = PQconnectGTM(connect_string); + if (GTM_ActiveConn == NULL) + { + elog(DEBUG3, "Error in connection"); + return 0; + } + elog(LOG, "Connection established to the GTM active."); + + return 1; +} + +int +gtm_standby_finish_startup() +{ + elog(LOG, "Closing a startup connection..."); + + GTMPQfinish(GTM_ActiveConn); + + elog(LOG, "A startup connection closed."); + + return 1; +} + +int +gtm_standby_restore_next_gxid() +{ + GlobalTransactionId next_gxid = InvalidGlobalTransactionId; + + next_gxid = get_next_gxid(GTM_ActiveConn); + GTM_RestoreTxnInfo(-1, next_gxid); + + elog(LOG, "Restoring the next GXID done."); + + return 1; +} + +int +gtm_standby_restore_sequence() +{ + GTM_SeqInfo *seq_list[1024]; + int num_seq; + int i; + + /* + * Restore sequence data. + */ + num_seq = get_sequence_list(GTM_ActiveConn, seq_list, 1024); + + for (i=0 ; i<num_seq ; i++) + { + GTM_SeqRestore(seq_list[i]->gs_key, + seq_list[i]->gs_increment_by, + seq_list[i]->gs_min_value, + seq_list[i]->gs_max_value, + seq_list[i]->gs_init_value, + seq_list[i]->gs_value, + seq_list[i]->gs_state, + seq_list[i]->gs_cycle, + seq_list[i]->gs_called); + } + + elog(LOG, "Restoring sequences done."); + + return 1; +} + +int +gtm_standby_restore_gxid() +{ + int num_txn; + GTM_Transactions txn; + int i; + + /* + * Restore gxid data. + */ + num_txn = get_txn_gxid_list(GTM_ActiveConn, &txn); + + GTM_RWLockAcquire(>MTransactions.gt_XidGenLock, GTM_LOCKMODE_WRITE); + + GTMTransactions.gt_txn_count = txn.gt_txn_count; + GTMTransactions.gt_gtm_state = txn.gt_gtm_state; + GTMTransactions.gt_nextXid = txn.gt_nextXid; + GTMTransactions.gt_oldestXid = txn.gt_oldestXid; + GTMTransactions.gt_xidVacLimit = txn.gt_xidVacLimit; + GTMTransactions.gt_xidWarnLimit = txn.gt_xidWarnLimit; + GTMTransactions.gt_xidStopLimit = txn.gt_xidStopLimit; + GTMTransactions.gt_xidWrapLimit = txn.gt_xidWrapLimit; + GTMTransactions.gt_latestCompletedXid = txn.gt_latestCompletedXid; + GTMTransactions.gt_recent_global_xmin = txn.gt_recent_global_xmin; + GTMTransactions.gt_lastslot = txn.gt_lastslot; + + for (i=0 ; i<num_txn ; i++) + { + GTMTransactions.gt_transactions_array[i].gti_handle = txn.gt_transactions_array[i].gti_handle; + GTMTransactions.gt_transactions_array[i].gti_thread_id = txn.gt_transactions_array[i].gti_thread_id; + GTMTransactions.gt_transactions_array[i].gti_in_use = txn.gt_transactions_array[i].gti_in_use; + GTMTransactions.gt_transactions_array[i].gti_gxid = txn.gt_transactions_array[i].gti_gxid; + GTMTransactions.gt_transactions_array[i].gti_state = txn.gt_transactions_array[i].gti_state; + GTMTransactions.gt_transactions_array[i].gti_coordid = txn.gt_transactions_array[i].gti_coordid; + GTMTransactions.gt_transactions_array[i].gti_xmin = txn.gt_transactions_array[i].gti_xmin; + GTMTransactions.gt_transactions_array[i].gti_isolevel = txn.gt_transactions_array[i].gti_isolevel; + GTMTransactions.gt_transactions_array[i].gti_readonly = txn.gt_transactions_array[i].gti_readonly; + GTMTransactions.gt_transactions_array[i].gti_backend_id = txn.gt_transactions_array[i].gti_backend_id; + + /* data node */ + GTMTransactions.gt_transactions_array[i].gti_datanodecount + = txn.gt_transactions_array[i].gti_datanodecount; + GTMTransactions.gt_transactions_array[i].gti_datanodes + = palloc(sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_datanodecount); + memcpy(GTMTransactions.gt_transactions_array[i].gti_datanodes, + txn.gt_transactions_array[i].gti_datanodes, + sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_datanodecount); + + /* coordinator node */ + GTMTransactions.gt_transactions_array[i].gti_coordcount + = txn.gt_transactions_array[i].gti_coordcount; + GTMTransactions.gt_transactions_array[i].gti_coordinators + = palloc(sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_coordcount); + memcpy(GTMTransactions.gt_transactions_array[i].gti_coordinators, + txn.gt_transactions_array[i].gti_coordinators, + sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_coordcount); + + if (txn.gt_transactions_array[i].gti_gid==NULL ) + GTMTransactions.gt_transactions_array[i].gti_gid = NULL; + else + GTMTransactions.gt_transactions_array[i].gti_gid = strdup(txn.gt_transactions_array[i].gti_gid); + + /* copy GTM_SnapshotData */ + GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_xmin + = txn.gt_transactions_array[i].gti_current_snapshot.sn_xmin; + GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_xmax + = txn.gt_transactions_array[i].gti_current_snapshot.sn_xmax; + GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_recent_global_xmin + = txn.gt_transactions_array[i].gti_current_snapshot.sn_recent_global_xmin; + GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_xcnt + = txn.gt_transactions_array[i].gti_current_snapshot.sn_xcnt; + GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_xip + = txn.gt_transactions_array[i].gti_current_snapshot.sn_xip; + /* end of copying GTM_SnapshotData */ + + GTMTransactions.gt_transactions_array[i].gti_snapshot_set + = txn.gt_transactions_array[i].gti_snapshot_set; + GTMTransactions.gt_transactions_array[i].gti_vacuum + = txn.gt_transactions_array[i].gti_vacuum; + + if ( GTMTransactions.gt_transactions_array[i].gti_state != GTM_TXN_ABORTED ) + { + GTMTransactions.gt_open_transactions = gtm_lappend(GTMTransactions.gt_open_transactions, + >MTransactions.gt_transactions_array[i]); + } + } + + dump_transactions_elog(>MTransactions, num_txn); + + GTM_RWLockRelease(>MTransactions.gt_XidGenLock); + + elog(LOG, "Restoring %d gxid(s) done.", num_txn); + + return 1; +} + +int +gtm_standby_restore_node() +{ + GTM_PGXCNodeInfo *data; + int rc, i; + int num_node; + + elog(LOG, "Copying node information from the GTM active..."); + + data = (GTM_PGXCNodeInfo *)malloc( sizeof(GTM_PGXCNodeInfo)*128 ); + memset(data, 0, sizeof(GTM_PGXCNodeInfo)*128); + + rc = get_node_list(GTM_ActiveConn, data, 128); + if ( rc<0 ) + { + elog(DEBUG3, "get_node_list() failed."); + rc = 0; + goto finished; + } + + num_node = rc; + + for (i=0 ; i<num_node ; i++) + { + elog(LOG, "get_node_list: nodetype=%d, nodenum=%d, datafolder=%s", + data[i].type, data[i].nodenum, data[i].datafolder); + + if ( Recovery_PGXCNodeRegister(data[i].type, data[i].nodenum, data[i].port, + data[i].proxynum, data[i].status, + data[i].ipaddress, data[i].datafolder, true, + -1 /* dummy socket */) != 0 ) + { + rc = 0; + goto finished; + } + } + + elog(LOG, "Copying node information from GTM active done."); + + finished: + free(data); + return rc; +} + +/* + * Regiter myself to the GTM (active) as a "disconnected" node. + * + * This status would be updated later after restoring completion. + * See gtm_standby_update_self(). + * + * Returns 1 on success, 0 on failure. + */ +int +gtm_standby_register_self(GTM_PGXCNodeId nodenum, int port, const char *datadir) +{ + int rc; + + elog(LOG, "Registering standby-GTM status..."); + + node_get_local_addr(GTM_ActiveConn, standbyNodeName, sizeof(standbyNodeName), &rc); + if ( rc!=0 ) + return 0; + + standbyNodeNum = nodenum; + standbyPortNumber = port; + standbyDataDir = (char *)datadir; + + rc = node_register2(GTM_ActiveConn, PGXC_NODE_GTM, standbyNodeName, standbyPortNumber, + standbyNodeNum, standbyDataDir, NODE_DISCONNECTED); + if ( rc<0 ) + { + elog(LOG, "Failed to register a standby-GTM status."); + return 0; + } + + elog(LOG, "Registering standby-GTM done."); + + return 1; +} + +/* + * Update my node status from "disconnected" to "connected" in GTM by myself. + * + * Returns 1 on success, 0 on failure. + */ +int +gtm_standby_activate_self() +{ + int rc; + + elog(LOG, "Updating the standby-GTM status to \"CONNECTED\"..."); + + rc = node_unregister(GTM_ActiveConn, PGXC_NODE_GTM, standbyNodeNum); + if ( rc<0 ) + { + elog(LOG, "Failed to unregister old standby-GTM status."); + return 0; + } + + rc = node_register2(GTM_ActiveConn, PGXC_NODE_GTM, standbyNodeName, standbyPortNumber, + standbyNodeNum, standbyDataDir, NODE_CONNECTED); + if ( rc<0 ) + { + elog(LOG, "Failed to register a new standby-GTM status."); + return 0; + } + + elog(LOG, "Updating the standby-GTM status done."); + + return 1; +} + + +/* + * Find "one" GTM standby node info. + * + * Returns a pointer to GTM_PGXCNodeInfo on success, + * or returns NULL on failure. + */ +static GTM_PGXCNodeInfo * +find_standby_node_info() +{ + GTM_PGXCNodeInfo *node[1024]; + size_t n; + int i; + + n = pgxcnode_find_by_type(PGXC_NODE_GTM, node, 1024); + + for (i=0 ; i<n ; i++) + { + elog(LOG, "pgxcnode_find_by_type: nodenum=%d, type=%d, ipaddress=%s, port=%d, status=%d", + node[i]->nodenum, + node[i]->type, + node[i]->ipaddress, + node[i]->port, + node[i]->status); + + if ( node[i]->nodenum!=standbyNodeNum && node[i]->status==NODE_CONNECTED ) + return node[i]; + } + + return NULL; +} + + +/* + * Make a connection to the GTM standby node when getting connected + * from the client. + * + * Returns a pointer to a GTM_Conn object on success, or NULL on failure. + */ +GTM_Conn * +gtm_standby_connect_to_standby() +{ + GTM_Conn *conn; + int report; + + conn = gtm_standby_connect_to_standby_int(&report); + if ( !conn && report ) + gtm_report_failure(NULL); + + return conn; +} + +static GTM_Conn * +gtm_standby_connect_to_standby_int(int *report_needed) +{ + GTM_Conn *standby = NULL; + GTM_PGXCNodeInfo *n; + char conn_string[1024]; + + *report_needed = 0; + + if ( GTM_StandbyMode ) + return NULL; + + n = find_standby_node_info(); + + if ( !n ) + { + elog(LOG, "Any GTM standby node not found in registered node(s)."); + return NULL; + } + + elog(LOG, "GTM standby is active. Going to connect."); + *report_needed = 1; + + snprintf(conn_string, sizeof(conn_string), + "host=%s port=%d pgxc_node_id=1 remote_type=4", + n->ipaddress, n->port); + + standby = PQconnectGTM(conn_string); + + if ( !standby ) + { + elog(LOG, "Failed to establish a connection with GTM standby. - %p", n); + return NULL; + } + + elog(LOG, "Connection established with GTM standby. - %p", n); + + return standby; +} + +void +gtm_standby_disconnect_from_standby(GTM_Conn *conn) +{ + if ( GTM_StandbyMode ) + return; + + GTMPQfinish(conn); +} + + +GTM_Conn * +gtm_standby_reconnect_to_standby(GTM_Conn *old_conn, int retry_max) +{ + GTM_Conn *newconn; + int report; + int i; + + if ( GTM_StandbyMode ) + return NULL; + + if ( old_conn!=NULL ) + gtm_standby_disconnect_from_standby(old_conn); + + for (i=0 ; i<retry_max ; i++) + { + elog(LOG, "gtm_standby_reconnect_to_standby(): going to re-connect. retry=%d", i); + + newconn = gtm_standby_connect_to_standby_int(&report); + if ( newconn!=NULL ) + break; + + elog(LOG, "gtm_standby_reconnect_to_standby(): re-connect failed. retry=%d", i); + } + + if ( newconn ) + gtm_report_failure(NULL); + + return newconn; +} + + +#define GTM_STANDBY_RETRY_MAX 3 + +bool +gtm_standby_check_communication_error(int *retry_count, GTM_Conn *oldconn) +{ + if ( GetMyThreadInfo->thr_conn->standby->result->gr_status == GTM_RESULT_COMM_ERROR ) + { + if ( *retry_count==0 ) + { + (*retry_count)++; + + GetMyThreadInfo->thr_conn->standby + = gtm_standby_reconnect_to_standby(GetMyThreadInfo->thr_conn->standby, + GTM_STANDBY_RETRY_MAX); + + if ( GetMyThreadInfo->thr_conn->standby ) + return true; + } + + elog(LOG, "communication error with standby."); + gtm_report_failure(oldconn); + } + return false; +} + diff --git a/src/gtm/main/main2.c b/src/gtm/main/main2.c new file mode 100644 index 0000000..b8d7287 --- /dev/null +++ b/src/gtm/main/main2.c @@ -0,0 +1,58 @@ + if ( GTM_StandbyMode ) + { + /* initialize standby */ + char connstr[1024]; + + /* FIXME: node id must be suppied. */ + int node_id = 1; + + snprintf(connstr, sizeof(connstr), "host=%s port=%d pgxc_node_id=%d remote_type=%d", + GTM_ActiveAddress, GTM_ActivePort, node_id, PGXC_NODE_GTM_PROXY_POSTMASTER); + + GTM_ActiveConn = PQconnectGTM(connstr); + + if ( GTMPQstatus(GTM_ActiveConn)!=CONNECTION_OK ) + { + /* failed to connect GTM-active. */ + elog(ERROR, "Failed to connect to GTM-active."); + exit(1); + } + + elog(LOG, "Connected to GTM active running on %s:%d.", GTM_ActiveAddress, GTM_ActivePort); + +#ifdef NOT_USED + elog(LOG, "Starting GTM standby on %s:%d /w control file %s.", ListenAddresses, GTMPortNumber, GTMControlFile); + + /* FIXME: how can I generate GTM_PGXCNodeId? */ + GTM_PGXCNodeId nodenum = 1; + + node_register(GTM_ActiveConn, PGXC_NODE_GTM, GTM_ActivePort, nodenum, GTMDataDir); + + begin_replication_initial_sync(GTM_ActiveConn); + end_replication_initial_sync(GTM_ActiveConn); + + node_unregister(GTM_ActiveConn, PGXC_NODE_GTM, nodenum); +#endif /* NOT_USED */ + + GTMPQfinish(GTM_ActiveConn); + + GTM_ActiveConn = NULL; + + exit(0); + } + else + { + /* + * Read the last GXID and start from there + */ + ctlfd = open(GTMControlFile, O_RDONLY); + + GTM_RestoreTxnInfo(ctlfd, next_gxid); + GTM_RestoreSeqInfo(ctlfd); + + close(ctlfd); + + /* Recover Data of Registered nodes. */ + Recovery_RestoreRegisterInfo(); + } + diff --git a/src/gtm/proxy/proxy_utils.c b/src/gtm/proxy/proxy_utils.c new file mode 100644 index 0000000..077afbe --- /dev/null +++ b/src/gtm/proxy/proxy_utils.c @@ -0,0 +1,36 @@ +#include "gtm/proxy_utils.h" + +#include "gtm/elog.h" +#include "gtm/gtm.h" +#include "gtm/gtm_c.h" +#include "gtm/gtm_client.h" +#include "gtm/gtm_seq.h" +#include "gtm/register.h" + +/* + * This function is a dummy function of gtm_proxy mobule to avoid + * object link problem. + * + * Most of command processing functions are existing only in GTM main + * module, but a few are both in GTM main and GTM proxy modules, which + * consist of same binary objects. And all the command processing + * functions require calling gtm_standby_check_communication_error() + * for GTM main. + * + * Two options should be considered here: (1) Moving all command + * processing functions into the common modules, or (2) Creating a + * dummy function in GTM proxy module. + * + * (1) may cause another hard thing because of object and variable + * referencing issue. + * + * This is the reason why this dummy function needed. So this is here. + * + * The object and module structure of GTM/GTM Proxy needs review, and + * fix to remove this kind of tricks. + */ +bool +gtm_standby_check_communication_error(int *retry_count, GTM_Conn *oldconn) +{ + return false; +} diff --git a/src/gtm/recovery/replication.c b/src/gtm/recovery/replication.c new file mode 100644 index 0000000..46d29a5 --- /dev/null +++ b/src/gtm/recovery/replication.c @@ -0,0 +1,123 @@ +/*------------------------------------------------------------------------- + * + * register.c + * PGXC Node Register on GTM and GTM Proxy, node registering functions + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation + * + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#include "gtm/replication.h" + +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "gtm/gtm_c.h" +#include "gtm/gtm.h" +#include "gtm/gtm_txn.h" +#include "gtm/gtm_standby.h" +#include "gtm/register.h" +#include "gtm/assert.h" +#include <stdio.h> +#include "gtm/libpq.h" +#include "gtm/pqformat.h" +#include "gtm/gtm_msg.h" +#include "gtm/gtm_ip.h" + +/* + * Process MSG_NODE_BEGIN_REPlCATION_INIT + */ +void +ProcessBeginReplicationInitialSyncRequest(Port *myport, StringInfo message) +{ + StringInfoData buf; + MemoryContext oldContext; + + pq_getmsgend(message); + + if ( gtm_is_standby() ) + ereport(ERROR, + (EPERM, + errmsg("Operation not permitted under the standby mode."))); + + oldContext = MemoryContextSwitchTo(TopMemoryContext); + + /* + * Acquire global locks to copy resource data to the standby. + */ + GTM_RWLockAcquire(>MTransactions.gt_XidGenLock, GTM_LOCKMODE_WRITE); + GTM_RWLockAcquire(>MTransactions.gt_TransArrayLock, GTM_LOCKMODE_WRITE); + elog(LOG, "Prepared for copying data with holding XidGenLock and TransArrayLock."); + + MemoryContextSwitchTo(oldContext); + + pq_beginmessage(&buf, 'S'); + pq_sendint(&buf, NODE_BEGIN_REPLICATION_INIT_RESULT, 4); + if (myport->remote_type == PGXC_NODE_GTM_PROXY) + { + GTM_ProxyMsgHeader proxyhdr; + proxyhdr.ph_conid = myport->conn_id; + pq_sendbytes(&buf, (char *)&proxyhdr, sizeof (GTM_ProxyMsgHeader)); + } + pq_endmessage(myport, &buf); + + if (myport->remote_type != PGXC_NODE_GTM_PROXY) + pq_flush(myport); + + elog(LOG, "ProcessBeginReplicationInitialSyncRequest() ok."); + + return; +} + +/* + * Process MSG_NODE_END_REPlCATION_INIT + */ +void +ProcessEndReplicationInitialSyncRequest(Port *myport, StringInfo message) +{ + StringInfoData buf; + MemoryContext oldContext; + + pq_getmsgend(message); + + if ( gtm_is_standby() ) + ereport(ERROR, + (EPERM, + errmsg("Operation not permitted under the standby mode."))); + + oldContext = MemoryContextSwitchTo(TopMemoryContext); + + /* + * Release global locks after copying resource data to the standby. + */ + GTM_RWLockRelease(>MTransactions.gt_TransArrayLock); + GTM_RWLockRelease(>MTransactions.gt_XidGenLock); + elog(LOG, "XidGenLock and TransArrayLock released."); + + MemoryContextSwitchTo(oldContext); + + pq_beginmessage(&buf, 'S'); + pq_sendint(&buf, NODE_END_REPLICATION_INIT_RESULT, 4); + if (myport->remote_type == PGXC_NODE_GTM_PROXY) + { + GTM_ProxyMsgHeader proxyhdr; + proxyhdr.ph_conid = myport->conn_id; + pq_sendbytes(&buf, (char *)&proxyhdr, sizeof (GTM_ProxyMsgHeader)); + } + pq_endmessage(myport, &buf); + + if (myport->remote_type != PGXC_NODE_GTM_PROXY) + pq_flush(myport); + + elog(LOG, "ProcessEndReplicationInitialSyncRequest() ok."); + + return; +} + diff --git a/src/gtm/test/Makefile b/src/gtm/test/Makefile new file mode 100644 index 0000000..e6155ea --- /dev/null +++ b/src/gtm/test/Makefile @@ -0,0 +1,53 @@ +# Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation + +top_build_dir=../.. +include $(top_build_dir)/gtm/Makefile.global + +override CPPFLAGS := -I$(top_build_dir)/gtm/client $(CPPFLAGS) + +SRCS=test_serialize.c test_connect.c test_node.c test_node5.c test_txn.c test_txn4.c test_txn5.c test_repli.c test_repli2.c test_seq.c test_seq4.c test_seq5.c test_scenario.c test_startup.c test_standby.c test_common.c + +PROGS=test_serialize test_connect test_txn test_txn4 test_txn5 test_repli test_repli2 test_seq test_seq4 test_seq5 test_scenario test_startup test_node test_node5 test_standby + +OBJS=$(SRCS:.c=.o) +LIBS=$(top_build_dir)/gtm/client/libgtmclient.a \ + $(top_build_dir)/gtm/common/libgtm.a \ + $(top_build_dir)/gtm/libpq/libpqcomm.a + +LOADLIBES=-lpthread +CFLAGS=-g -O0 + +all: $(PROGS) + +test_serialize: test_serialize.o test_common.o $(LIBS) + +test_connect: test_connect.o test_common.o $(LIBS) +test_startup: test_startup.o test_common.o $(LIBS) + +test_node: test_node.o test_common.o $(LIBS) +test_node5: test_node5.o test_common.o $(LIBS) + +test_txn: test_txn.o test_common.o $(LIBS) + +test_txn4: test_txn4.o test_common.o $(LIBS) +test_txn5: test_txn5.o test_common.o $(LIBS) + +test_repli: test_repli.o test_common.o $(LIBS) + +test_standby: test_standby.o test_common.o $(LIBS) + +test_repli2: test_repli2.o test_common.o $(LIBS) + +test_seq: test_seq.o test_common.o $(LIBS) +test_seq4: test_seq4.o test_common.o $(LIBS) +test_seq5: test_seq5.o test_common.o $(LIBS) + +test_scenario: test_scenario.o test_common.o $(LIBS) + +clean: + rm -f $(OBJS) *~ + rm -f $(PROGS) + +distclean: clean + +maintainer-clean: distclean diff --git a/src/gtm/test/clean.sh b/src/gtm/test/clean.sh new file mode 100755 index 0000000..87c452b --- /dev/null +++ b/src/gtm/test/clean.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +export PATH=/tmp/pgxc/bin:$PATH + +# ------------------------------- +# starting standby... +# ------------------------------- +echo "cleaning standby..." +export DATA=/tmp/pgxc/data/gtm_standby + +pushd $DATA +rm -rf gtm.control gtm.opts gtm.pid register.node +cat /dev/null > gtm.log +popd + +# ------------------------------- +# starting active... +# ------------------------------- +echo "cleaning active..." +export DATA=/tmp/pgxc/data/gtm + +pushd $DATA +rm -rf gtm.control gtm.opts gtm.pid register.node +cat /dev/null > gtm.log +popd diff --git a/src/gtm/test/promote.sh b/src/gtm/test/promote.sh new file mode 100755 index 0000000..ae60e9c --- /dev/null +++ b/src/gtm/test/promote.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +export PATH=/tmp/pgxc/bin:$PATH + +# ------------------------------- +# promoting standby... +# ------------------------------- +echo "promoting standby..." +export DATA=/tmp/pgxc/data/gtm_standby + +gtm_ctl -D ${DATA} -S gtm_standby promote + +# ------------------------------- +# process check +# ------------------------------- +echo "checking process..." +ps -aef |grep gtm diff --git a/src/gtm/test/regress.sh b/src/gtm/test/regress.sh new file mode 100755 index 0000000..314d17c --- /dev/null +++ b/src/gtm/test/regress.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +cat /dev/null>regress.log + +./test_serialize | tee -a regress.log 2>&1 + +./stop.sh +./start_a.sh +./test_connect 2>&1 | tee -a regress.log +./test_node 2>&1 | tee -a regress.log +./test_txn 2>&1 | tee -a regress.log +./test_seq 2>&1 | tee -a regress.log + +echo "" +echo "=========== SUMMARY ============" +date +echo -n "Assert: " +grep -c ASSERT regress.log diff --git a/src/gtm/test/start.sh b/src/gtm/test/start.sh new file mode 100755 index 0000000..24951ff --- /dev/null +++ b/src/gtm/test/start.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +./start_a.sh + +echo "sleeping 3 seconds..." +sleep 3; + +./start_s.sh diff --git a/src/gtm/test/start_a.sh b/src/gtm/test/start_a.sh new file mode 100755 index 0000000..4a6c1c1 --- /dev/null +++ b/src/gtm/test/start_a.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +export PATH=/tmp/pgxc/bin:$PATH +export DATA=/tmp/pgxc/data/gtm + +# ------------------------------- +# starting active... +# ------------------------------- +echo "starting active..." + +gtm_ctl -D ${DATA} -S gtm stop +rm -rf ${DATA}/gtm.opts ${DATA}/gtm.pid ${DATA}/register.node + +gtm_ctl -D ${DATA} -S gtm -o "-n 101" start + +# ------------------------------- +# process check +# ------------------------------- +echo "checking process..." +ps -aef |grep gtm diff --git a/src/gtm/test/start_s.sh b/src/gtm/test/start_s.sh new file mode 100755 index 0000000..b016bce --- /dev/null +++ b/src/gtm/test/start_s.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +export PATH=/tmp/pgxc/bin:$PATH + +# ------------------------------- +# starting standby... +# ------------------------------- +echo "starting standby..." + +export DATA=/tmp/pgxc/data/gtm_standby + +gtm_ctl -D ${DATA} -S gtm stop +rm -rf ${DATA}/gtm.opts ${DATA}/gtm.pid ${DATA}/register.node + +gtm_ctl -D ${DATA} -S gtm_standby -o "-n 102 -s -p 6667 -i 127.0.0.1 -q 6666" start + +# ------------------------------- +# process check +# ------------------------------- +echo "checking process..." +ps -aef |grep gtm diff --git a/src/gtm/test/stop.sh b/src/gtm/test/stop.sh new file mode 100755 index 0000000..4660ecc --- /dev/null +++ b/src/gtm/test/stop.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# GTM start script for test + +pushd /tmp/pgxc/bin; ln -fs gtm gtm_standby; popd + +export PATH=/tmp/pgxc/bin:$PATH + +# ------------------------------- +# starting standby... +# ------------------------------- +echo "stopping standby..." +export DATA=/tmp/pgxc/data/gtm_standby + +gtm_ctl -D ${DATA} -S gtm stop + +# ------------------------------- +# starting active... +# ------------------------------- +echo "stopping active..." +export DATA=/tmp/pgxc/data/gtm + +gtm_ctl -D ${DATA} -S gtm stop + +killall -9 gtm gtm_standby + +# ------------------------------- +# process check +# ------------------------------- +echo "checking process..." +ps -aef |grep gtm diff --git a/src/gtm/test/test_common.c b/src/gtm/test/test_common.c new file mode 100644 index 0000000..df8b581 --- /dev/null +++ b/src/gtm/test/test_common.c @@ -0,0 +1,80 @@ +#include "test_common.h" + +pthread_key_t threadinfo_key; + +GTM_ThreadID TopMostThreadID; + +GTM_Conn *conn = NULL; +GTM_Conn *conn2 = NULL; +GTM_Timestamp *timestamp = NULL; +char connect_string[100]; + +void +print_nodeinfo(GTM_PGXCNodeInfo d) +{ + client_log(("type=%d, nodenum=%d, proxynum=%d, ipaddress=%s, port=%d, datafolder=%s, status=%d\n", + d.type, + d.nodenum, + d.proxynum, + d.ipaddress, + d.port, + d.datafolder, + d.status)); +} + + +/* + * Connect to active GTM. + */ +void +connect1() +{ + sprintf(connect_string, "host=localhost port=6666 pgxc_node_id=101 remote_type=%d", + PGXC_NODE_GTM); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); +} + +/* + * Connect to standby GTM. + */ +void +connect2() +{ + sprintf(connect_string, "host=localhost port=6667 pgxc_node_id=102 remote_type=%d", + PGXC_NODE_GTM); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); +} + + +/* + * Get a word count with using grep command in a log file. + */ +int +grep_count(const char *file, const char *key) +{ + FILE *fp; + int count; + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), "grep -c '%s' %s", key, file); + + fp = popen(cmd, "r"); + fscanf(fp, "%d", &count); + pclose(fp); + + return count; +} diff --git a/src/gtm/test/test_connect.c b/src/gtm/test/test_connect.c new file mode 100644 index 0000000..cb25378 --- /dev/null +++ b/src/gtm/test/test_connect.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation + */ + +#include <sys/types.h> +#include <unistd.h> + +#include "gtm/libpq-fe.h" +#include "gtm/gtm_c.h" +#include "gtm/gtm_client.h" + +#include "test_common.h" + +#define client_log(x) printf x + +void +setUp() +{ +} + +void +tearDown() +{ +} + +void +test01() +{ + GTM_Conn *conn; + char connect_string[100]; + + SETUP(); + + sprintf(connect_string, "host=localhost port=6666 pgxc_node_id=1 remote_type=%d", + PGXC_NODE_GTM_PROXY); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); + + GTMPQfinish(conn); + + TEARDOWN(); +} + +void +test02() +{ + GTM_Conn *conn; + char connect_string[100]; + + SETUP(); + + sprintf(connect_string, "host=localhost port=6666 pgxc_node_id=1 remote_type=%d", + PGXC_NODE_GTM_PROXY_POSTMASTER); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); + + GTMPQfinish(conn); + + TEARDOWN(); +} + +void +test03() +{ + GTM_Conn *conn; + char connect_string[100]; + + SETUP(); + + sprintf(connect_string, "host=localhost port=6666 pgxc_node_id=1 remote_type=%d", + PGXC_NODE_COORDINATOR); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); + + GTMPQfinish(conn); + + TEARDOWN(); +} + +void +test04() +{ + GTM_Conn *conn; + char connect_string[100]; + + SETUP(); + + sprintf(connect_string, "host=localhost port=6666 pgxc_node_id=1 remote_type=%d", + PGXC_NODE_DATANODE); + + conn = PQconnectGTM(connect_string); + if (conn == NULL) + { + client_log(("Error in connection\n")); + exit(1); + } + client_log(("PGconnectGTM() ok.\n")); + + GTMPQfinish(c... [truncated message content] |
From: Michael P. <mic...@us...> - 2011-04-02 17:28:23
|
Project "Postgres-XC". The branch, master has been updated via e1946160fe64042e76b5252c66b6f6fb5da6b85d (commit) from 098a076729929a8ecf2c6eecd5cc6de63628e882 (commit) - Log ----------------------------------------------------------------- commit e1946160fe64042e76b5252c66b6f6fb5da6b85d Author: Michael P <mic...@us...> Date: Sun Apr 3 02:27:21 2011 +0900 Support for COMMENT Depending on the object type, COMMENT is treated on Coordinators or on all nodes. diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index a184b89..1ffeead 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -804,6 +804,24 @@ standard_ProcessUtility(Node *parsetree, case T_CommentStmt: CommentObject((CommentStmt *) parsetree); + +#ifdef PGXC + /* + * We need to check details of the object being dropped and + * run command on correct nodes + */ + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + CommentStmt *stmt = (CommentStmt *) parsetree; + + /* Sequence and views exists only on Coordinators */ + if (stmt->objtype == OBJECT_SEQUENCE || + stmt->objtype == OBJECT_VIEW) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); + else + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + } +#endif break; case T_CopyStmt: ----------------------------------------------------------------------- Summary of changes: src/backend/tcop/utility.c | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-04-02 16:48:55
|
Project "Postgres-XC". The branch, master has been updated via 098a076729929a8ecf2c6eecd5cc6de63628e882 (commit) from 894ec20ad348f6230e1a796b7435d62f6867eab8 (commit) - Log ----------------------------------------------------------------- commit 098a076729929a8ecf2c6eecd5cc6de63628e882 Author: Michael P <mic...@us...> Date: Sun Apr 3 01:46:20 2011 +0900 Fix for bug 3237724: CREATE/DROP TABLE in test join The origin of this bug was a query in inherit. This query dropped a dozen of tables at once but some tables did not exist due to Postgres-XC's SQL restrictions. It was resulting in diff about tables already existing for test cases create_view and join. diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index 4babd68..d735a73 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -333,7 +333,16 @@ SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_clas CREATE TABLE inh_error1 () INHERITS (t1, t4); CREATE TABLE inh_error2 (LIKE t4 INCLUDING STORAGE) INHERITS (t1); -DROP TABLE t1, t2, t3, t4, t12_storage, t12_comments, t1_inh, t13_inh, t13_like, t_all; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +DROP TABLE t12_storage; +DROP TABLE t12_comments; +DROP TABLE t1_inh; +DROP TABLE t13_inh; +DROP TABLE t13_like; +DROP TABLE t_all; -- Test for renaming in simple multiple inheritance CREATE TABLE t1 (a int, b int); ----------------------------------------------------------------------- Summary of changes: src/test/regress/sql/inherit.sql | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-04-02 16:33:25
|
Project "Postgres-XC". The branch, master has been updated via 894ec20ad348f6230e1a796b7435d62f6867eab8 (commit) from f738280c29b0e50348a8b0940679595534220e24 (commit) - Log ----------------------------------------------------------------- commit 894ec20ad348f6230e1a796b7435d62f6867eab8 Author: Michael P <mic...@us...> Date: Sun Apr 3 01:32:35 2011 +0900 Fix for bug 3269392: GRANT for VIEW and SEQUENCE GRANT was launched on all the nodes, but for views and sequence objects it is only necessary to launch it on Coordinators. When multiple objects are granted at the same time, XC checks their types and returns an error in case Coordinator-only objects are mixed with normal relations. There is also a fix for regression test privileges. diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 49c018b..a184b89 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1007,12 +1007,58 @@ standard_ProcessUtility(Node *parsetree, break; case T_GrantStmt: - ExecuteGrantStmt((GrantStmt *) parsetree); - #ifdef PGXC - if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; + GrantStmt *stmt = (GrantStmt *) parsetree; + + /* Launch GRANT on Coordinator if object is a sequence */ + if (stmt->objtype == ACL_OBJECT_SEQUENCE) + remoteExecType = EXEC_ON_COORDS; + else if (stmt->objtype == ACL_OBJECT_RELATION && + stmt->targtype == ACL_TARGET_OBJECT) + { + /* + * In case object is a relation, differenciate the case + * of a sequence, a view and a table + */ + ListCell *cell; + /* Check the list of objects */ + bool first = true; + RemoteQueryExecType type_local = remoteExecType; + + foreach (cell, stmt->objects) + { + RangeVar *relvar = (RangeVar *) lfirst(cell); + Oid relid = RangeVarGetRelid(relvar, false); + + if (get_rel_relkind(relid) == RELKIND_SEQUENCE || + get_rel_relkind(relid) == RELKIND_VIEW) + remoteExecType = EXEC_ON_COORDS; + else + remoteExecType = EXEC_ON_ALL_NODES; + + /* Check if objects can be launched at the same place as 1st one */ + if (first) + { + type_local = remoteExecType; + first = false; + } + else + { + if (type_local != remoteExecType) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("PGXC does not support GRANT on multiple object types"), + errdetail("Grant VIEW/SEQUENCE and relations on separate queries"))); + } + } + } + ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType); + } #endif + ExecuteGrantStmt((GrantStmt *) parsetree); break; case T_GrantRoleStmt: diff --git a/src/test/regress/expected/privileges_1.out b/src/test/regress/expected/privileges_1.out index 94b9267..d71fd34 100644 --- a/src/test/regress/expected/privileges_1.out +++ b/src/test/regress/expected/privileges_1.out @@ -457,7 +457,6 @@ REVOKE ALL PRIVILEGES ON LANGUAGE sql FROM PUBLIC; GRANT USAGE ON LANGUAGE sql TO regressuser1; -- ok GRANT USAGE ON LANGUAGE c TO PUBLIC; -- fail ERROR: language "c" is not trusted -HINT: Only superusers can use untrusted languages. SET SESSION AUTHORIZATION regressuser1; GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail WARNING: no privileges were granted for "sql" @@ -893,14 +892,19 @@ SELECT lo_create(1005); (1 row) GRANT ALL ON LARGE OBJECT 1001 TO PUBLIC; +ERROR: large object 1001 does not exist GRANT SELECT ON LARGE OBJECT 1003 TO regressuser2; +ERROR: large object 1003 does not exist GRANT SELECT,UPDATE ON LARGE OBJECT 1004 TO regressuser2; +ERROR: large object 1004 does not exist GRANT ALL ON LARGE OBJECT 1005 TO regressuser2; +ERROR: large object 1005 does not exist GRANT SELECT ON LARGE OBJECT 1005 TO regressuser2 WITH GRANT OPTION; +ERROR: large object 1005 does not exist GRANT SELECT, INSERT ON LARGE OBJECT 1001 TO PUBLIC; -- to be failed -ERROR: invalid privilege type INSERT for large object +ERROR: large object 1001 does not exist GRANT SELECT, UPDATE ON LARGE OBJECT 1001 TO nosuchuser; -- to be failed -ERROR: role "nosuchuser" does not exist +ERROR: large object 1001 does not exist GRANT SELECT, UPDATE ON LARGE OBJECT 999 TO PUBLIC; -- to be failed ERROR: large object 999 does not exist \c - @@ -918,46 +922,29 @@ SELECT lo_create(2002); (1 row) SELECT loread(lo_open(1001, x'40000'::int), 32); - loread --------- - \x -(1 row) - +ERROR: permission denied for large object 1001 SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied ERROR: permission denied for large object 1002 SELECT loread(lo_open(1003, x'40000'::int), 32); - loread --------- - \x -(1 row) - +ERROR: permission denied for large object 1003 SELECT loread(lo_open(1004, x'40000'::int), 32); - loread --------- - \x -(1 row) - +ERROR: permission denied for large object 1004 SELECT lowrite(lo_open(1001, x'20000'::int), 'abcd'); - lowrite ---------- - 4 -(1 row) - +ERROR: permission denied for large object 1001 SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied ERROR: permission denied for large object 1002 SELECT lowrite(lo_open(1003, x'20000'::int), 'abcd'); -- to be denied ERROR: permission denied for large object 1003 SELECT lowrite(lo_open(1004, x'20000'::int), 'abcd'); - lowrite ---------- - 4 -(1 row) - +ERROR: permission denied for large object 1004 GRANT SELECT ON LARGE OBJECT 1005 TO regressuser3; +ERROR: large object 1005 does not exist GRANT UPDATE ON LARGE OBJECT 1006 TO regressuser3; -- to be denied ERROR: large object 1006 does not exist REVOKE ALL ON LARGE OBJECT 2001, 2002 FROM PUBLIC; +ERROR: large object 2001 does not exist GRANT ALL ON LARGE OBJECT 2001 TO regressuser3; +ERROR: large object 2001 does not exist SELECT lo_unlink(1001); -- to be denied ERROR: must be owner of large object 1001 SELECT lo_unlink(2002); @@ -969,39 +956,27 @@ SELECT lo_unlink(2002); \c - -- confirm ACL setting SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata; - oid | ownername | lomacl -------+--------------+------------------------------------------------------------------------------------------ + oid | ownername | lomacl +------+--------------+-------- + 1001 | regressuser1 | 1002 | regressuser1 | - 1001 | regressuser1 | {regressuser1=rw/regressuser1,=rw/regressuser1} - 1003 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r/regressuser1} - 1004 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=rw/regressuser1} - 1005 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r*w/regressuser1,regressuser3=r/regressuser2} - 2001 | regressuser2 | {regressuser2=rw/regressuser2,regressuser3=rw/regressuser2} + 1003 | regressuser1 | + 1004 | regressuser1 | + 1005 | regressuser1 | + 2001 | regressuser2 | (6 rows) SET SESSION AUTHORIZATION regressuser3; SELECT loread(lo_open(1001, x'40000'::int), 32); - loread ------------- - \x61626364 -(1 row) - +ERROR: permission denied for large object 1001 SELECT loread(lo_open(1003, x'40000'::int), 32); -- to be denied ERROR: permission denied for large object 1003 SELECT loread(lo_open(1005, x'40000'::int), 32); - loread --------- - \x -(1 row) - +ERROR: permission denied for large object 1005 SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied ERROR: permission denied for large object 1005 SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); - lo_truncate -------------- - 0 -(1 row) - +ERROR: permission denied for large object 2001 -- compatibility mode in largeobject permission \c - SET lo_compat_privileges = false; -- default setting @@ -1260,6 +1235,8 @@ REVOKE USAGE ON LANGUAGE sql FROM regressuser1; DROP OWNED BY regressuser1; DROP USER regressuser1; DROP USER regressuser2; +ERROR: role "regressuser2" cannot be dropped because some objects depend on it +DETAIL: privileges for language sql DROP USER regressuser3; DROP USER regressuser4; DROP USER regressuser5; ----------------------------------------------------------------------- Summary of changes: src/backend/tcop/utility.c | 54 ++++++++++++++++++-- src/test/regress/expected/privileges_1.out | 77 ++++++++++------------------ 2 files changed, 77 insertions(+), 54 deletions(-) hooks/post-receive -- Postgres-XC |
From: Abbas B. <ga...@us...> - 2011-04-01 18:17:46
|
Project "Postgres-XC". The branch, master has been updated via f738280c29b0e50348a8b0940679595534220e24 (commit) from 91466a5b79ebd8aea0b6313704654b0a1b7818ac (commit) - Log ----------------------------------------------------------------- commit f738280c29b0e50348a8b0940679595534220e24 Author: Abbas <abb...@en...> Date: Fri Apr 1 22:40:29 2011 +0500 This patch fixes bug ID 3136257. The test case was trying to prepare a transaction after a fetch from a cursor inside a transaction. The way cursors are handled in XC, a FETCH can leave one of the datanodes in DN_CONNECTION_STATE_QUERY. This fact was being ignored by pgxc_all_handles_send_query, which would error out if any of the data nodes is in any state other than DN_CONNECTION_STATE_IDLE, where as the correct handling in this case is to call BufferConnection and continue. Next there was an error in ExecEndRemoteQuery. PGXCNodePrepare called in response to PREPARE TRANSACTION would call release_handles to release all data node connections and coordinator connections back to pool. Later when ExecEndRemoteQuery would try to close cursors, it would find a -1 in sock of all data node connections and hence the system would report that it was unable to close cursors. This patch adds correct handling while closing cursors in ExecEndRemoteQuery. diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 7c9ec5b..cf38041 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -3470,9 +3470,17 @@ do_query(RemoteQueryState *node) int i = 0; if (pgxc_node_receive(regular_conn_count, connections, NULL)) + { + pfree(connections); + if (primaryconnection) + pfree(primaryconnection); + if (node->cursor_connections) + pfree(node->cursor_connections); + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Failed to read response from data nodes"))); + } /* * Handle input from the data nodes. * If we got a RESPONSE_DATAROW we can break handling to wrap @@ -3631,6 +3639,7 @@ ExecRemoteQuery(RemoteQueryState *node) node->update_cursor); pfree(node->update_cursor); node->update_cursor = NULL; + pfree_pgxc_all_handles(all_dn_handles); } handle_results: @@ -3878,17 +3887,45 @@ ExecEndRemoteQuery(RemoteQueryState *node) /* * If there are active cursors close them */ - if (node->cursor) - close_node_cursors(node->cursor_connections, node->cursor_count, node->cursor); - - if (node->update_cursor) + if (node->cursor || node->update_cursor) { - PGXCNodeAllHandles *all_dn_handles = get_exec_connections(node, NULL, EXEC_ON_DATANODES); - close_node_cursors(all_dn_handles->datanode_handles, - all_dn_handles->dn_conn_count, - node->update_cursor); - pfree(node->update_cursor); - node->update_cursor = NULL; + PGXCNodeAllHandles *all_handles = NULL; + PGXCNodeHandle **cur_handles; + bool bFree = false; + int nCount; + int i; + + cur_handles = node->cursor_connections; + nCount = node->cursor_count; + + for(i=0;i<node->cursor_count;i++) + { + if (node->cursor_connections == NULL || node->cursor_connections[i]->sock == -1) + { + bFree = true; + all_handles = get_exec_connections(node, NULL, EXEC_ON_DATANODES); + cur_handles = all_handles->datanode_handles; + nCount = all_handles->dn_conn_count; + break; + } + } + + if (node->cursor) + { + close_node_cursors(cur_handles, nCount, node->cursor); + pfree(node->cursor); + node->cursor = NULL; + } + + if (node->update_cursor) + { + close_node_cursors(cur_handles, nCount, node->update_cursor); + pfree(node->update_cursor); + node->update_cursor = NULL; + } + + if (bFree) + pfree_pgxc_all_handles(all_handles); } /* diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c index 8c1de08..dcd721d 100644 --- a/src/backend/pgxc/pool/pgxcnode.c +++ b/src/backend/pgxc/pool/pgxcnode.c @@ -1832,13 +1832,12 @@ pgxc_all_handles_send_query(PGXCNodeAllHandles *pgxc_handles, const char *buffer if (pgxc_handles->primary_handle) dn_conn_count--; - /* Send to Datanodes */ - for (i = 0; i < dn_conn_count; i++) + /* Send to Datanodes */ + for (i = 0; i < dn_conn_count; i++) { if (pgxc_handles->datanode_handles[i]->state != DN_CONNECTION_STATE_IDLE) { - pgxc_handles->datanode_handles[i]->state = DN_CONNECTION_STATE_ERROR_FATAL; - continue; + BufferConnection(pgxc_handles->datanode_handles[i]); } if (pgxc_node_send_query(pgxc_handles->datanode_handles[i], buffer)) { @@ -1848,8 +1847,8 @@ pgxc_all_handles_send_query(PGXCNodeAllHandles *pgxc_handles, const char *buffer goto finish; } } - /* Send to Coordinators */ - for (i = 0; i < co_conn_count; i++) + /* Send to Coordinators */ + for (i = 0; i < co_conn_count; i++) { if (pgxc_node_send_query(pgxc_handles->coord_handles[i], buffer)) { ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/pool/execRemote.c | 57 +++++++++++++++++++++++++++++------ src/backend/pgxc/pool/pgxcnode.c | 11 +++---- 2 files changed, 52 insertions(+), 16 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-04-01 07:32:06
|
Project "Postgres-XC". The branch, master has been updated via 91466a5b79ebd8aea0b6313704654b0a1b7818ac (commit) from 0429a889372c6db0b4b1253624601c42410cc108 (commit) - Log ----------------------------------------------------------------- commit 91466a5b79ebd8aea0b6313704654b0a1b7818ac Author: Michael P <mic...@us...> Date: Fri Apr 1 16:21:34 2011 +0900 Fix for bug 3234421: multiple user support for pooler This commit extends pooler functionalities for multiple users. Now user name used for connection string is built directly from the user name got on port of postmaster at a user connection on Coordinator. This also solves a serious security issue with passwords parameters in postgresql.conf and when building the connection string of pooler. It also avoids that passwords are written by pooler logging system. In consequence, the following GUC parameters are deleted: data_node_users, data_node_passwords, coordinator_users, coordinator_passwords. This commit is a first step for the support of session parameters. diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c index e93ee7f..8c1de08 100644 --- a/src/backend/pgxc/pool/pgxcnode.c +++ b/src/backend/pgxc/pool/pgxcnode.c @@ -144,7 +144,7 @@ InitMultinodeExecutor(void) */ char * PGXCNodeConnStr(char *host, char *port, char *dbname, - char *user, char *password, char *remote_type) + char *user, char *remote_type) { char *out, connstr[256]; @@ -155,8 +155,8 @@ PGXCNodeConnStr(char *host, char *port, char *dbname, * remote type can be coordinator, datanode or application. */ num = snprintf(connstr, sizeof(connstr), - "host=%s port=%s dbname=%s user=%s password=%s options='-c remotetype=%s'", - host, port, dbname, user, password, remote_type); + "host=%s port=%s dbname=%s user=%s options='-c remotetype=%s'", + host, port, dbname, user, remote_type); /* Check for overflow */ if (num > 0 && num < sizeof(connstr)) diff --git a/src/backend/pgxc/pool/poolmgr.c b/src/backend/pgxc/pool/poolmgr.c index 28e9dce..478ba42 100644 --- a/src/backend/pgxc/pool/poolmgr.c +++ b/src/backend/pgxc/pool/poolmgr.c @@ -68,14 +68,10 @@ static MemoryContext PoolerMemoryContext = NULL; /* Connection info of Datanodes */ char *DataNodeHosts = NULL; char *DataNodePorts = NULL; -char *DataNodeUsers = NULL; -char *DataNodePwds = NULL; /* Connection info of Coordinators */ char *CoordinatorHosts = NULL; char *CoordinatorPorts = NULL; -char *CoordinatorUsers = NULL; -char *CoordinatorPwds = NULL; /* PGXC Nodes info list */ static PGXCNodeConnectionInfo *datanode_connInfos; @@ -93,15 +89,16 @@ static PoolHandle *Handle = NULL; static int is_pool_cleaning = false; static int server_fd = -1; -static void agent_init(PoolAgent *agent, const char *database); +static void agent_init(PoolAgent *agent, const char *database, const char *user_name); static void agent_destroy(PoolAgent *agent); static void agent_create(void); static void agent_handle_input(PoolAgent *agent, StringInfo s); -static DatabasePool *create_database_pool(const char *database); +static DatabasePool *create_database_pool(const char *database, const char *user_name); static void insert_database_pool(DatabasePool *pool); -static int destroy_database_pool(const char *database); -static DatabasePool *find_database_pool(const char *database); -static DatabasePool *remove_database_pool(const char *database); +static int destroy_database_pool(const char *database, const char *user_name); +static DatabasePool *find_database_pool(const char *database, const char *user_name); +static DatabasePool *find_database_pool_to_clean(const char *database, List *dn_list, List *co_list); +static DatabasePool *remove_database_pool(const char *database, const char *user_name); static int *agent_acquire_connections(PoolAgent *agent, List *datanodelist, List *coordlist); static PGXCNodePoolSlot *acquire_connection(DatabasePool *dbPool, int node, char client_conn_type); static void agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard); @@ -352,164 +349,8 @@ PoolManagerInit() (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid list syntax for \"coordinator_ports\""))); } - - if (count == 0) - rawstring = pstrdup(DataNodeUsers); - if (count == 1) - rawstring = pstrdup(CoordinatorUsers); - - /* Parse string into list of identifiers */ - if (!SplitIdentifierString(rawstring, ',', &elemlist)) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_users\""))); - else - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_users\""))); - } - - i = 0; - foreach(l, elemlist) - { - char *curuser = (char *) lfirst(l); - - connectionInfos[i].uname = pstrdup(curuser); - if (connectionInfos[i].uname == NULL) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } - /* Ignore extra entries, if any */ - if (++i == num_nodes) - break; - } - list_free(elemlist); - pfree(rawstring); - - /* Validate */ - if (i == 0) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_users\""))); - else - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_users\""))); - } - else if (i == 1) - { - /* Copy all values from first */ - for (; i < num_nodes; i++) - { - connectionInfos[i].uname = pstrdup(connectionInfos[0].uname); - if (connectionInfos[i].uname == NULL) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } - } - } - else if (i < num_nodes) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_users\""))); - else - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_users\""))); - } - - if (count == 0) - rawstring = pstrdup(DataNodePwds); - if (count == 1) - rawstring = pstrdup(CoordinatorPwds); - - /* Parse string into list of identifiers */ - if (!SplitIdentifierString(rawstring, ',', &elemlist)) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_passwords\""))); - else - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_passwords\""))); - } - - i = 0; - foreach(l, elemlist) - { - char *curpassword = (char *) lfirst(l); - - connectionInfos[i].password = pstrdup(curpassword); - if (connectionInfos[i].password == NULL) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } - /* Ignore extra entries, if any */ - if (++i == num_nodes) - break; - } - list_free(elemlist); - pfree(rawstring); - - /* Validate */ - if (i == 0) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_passwords\""))); - else - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_passwords\""))); - } - else if (i == 1) - { - /* Copy all values from first */ - for (; i < num_nodes; i++) - { - connectionInfos[i].password = pstrdup(connectionInfos[0].password); - if (connectionInfos[i].password == NULL) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } - } - } - else if (i < num_nodes) - { - if (count == 0) - /* syntax error in list */ - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"data_node_passwords\""))); - else - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid list syntax for \"coordinator_passwords\""))); - } } + /* End of Parsing for Datanode and Coordinator Data */ PoolerLoop(); @@ -647,13 +488,14 @@ agent_create(void) * Invoked from Session process */ void -PoolManagerConnect(PoolHandle *handle, const char *database) +PoolManagerConnect(PoolHandle *handle, const char *database, const char *user_name) { int n32; char msgtype = 'c'; Assert(handle); Assert(database); + Assert(user_name); /* Save the handle */ Handle = handle; @@ -662,7 +504,7 @@ PoolManagerConnect(PoolHandle *handle, const char *database) pool_putbytes(&handle->port, &msgtype, 1); /* Message length */ - n32 = htonl(strlen(database) + 13); + n32 = htonl(strlen(database) + strlen(user_name) + 18); pool_putbytes(&handle->port, (char *) &n32, 4); /* PID number */ @@ -676,28 +518,37 @@ PoolManagerConnect(PoolHandle *handle, const char *database) /* Send database name followed by \0 terminator */ pool_putbytes(&handle->port, database, strlen(database) + 1); pool_flush(&handle->port); + + /* Length of user name string */ + n32 = htonl(strlen(user_name) + 1); + pool_putbytes(&handle->port, (char *) &n32, 4); + + /* Send user name followed by \0 terminator */ + pool_putbytes(&handle->port, user_name, strlen(user_name) + 1); + pool_flush(&handle->port); } /* * Init PoolAgent -*/ + */ static void -agent_init(PoolAgent *agent, const char *database) +agent_init(PoolAgent *agent, const char *database, const char *user_name) { Assert(agent); Assert(database); + Assert(user_name); /* disconnect if we are still connected */ if (agent->pool) agent_release_connections(agent, NULL, NULL); /* find database */ - agent->pool = find_database_pool(database); + agent->pool = find_database_pool(database, user_name); /* create if not found */ if (agent->pool == NULL) - agent->pool = create_database_pool(database); + agent->pool = create_database_pool(database, user_name); } @@ -932,6 +783,7 @@ agent_handle_input(PoolAgent * agent, StringInfo s) for (;;) { const char *database; + const char *user_name; int datanodecount; int coordcount; List *datanodelist = NIL; @@ -969,11 +821,13 @@ agent_handle_input(PoolAgent * agent, StringInfo s) agent->pid = pq_getmsgint(s, 4); len = pq_getmsgint(s, 4); database = pq_getmsgbytes(s, len); + len = pq_getmsgint(s, 4); + user_name = pq_getmsgbytes(s, len); /* * Coordinator pool is not initialized. * With that it would be impossible to create a Database by default. */ - agent_init(agent, database); + agent_init(agent, database, user_name); pq_getmsgend(s); break; case 'd': /* DISCONNECT */ @@ -1312,13 +1166,13 @@ agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard) * error and POOL_WEXIST if poll for this database already exist. */ static DatabasePool * -create_database_pool(const char *database) +create_database_pool(const char *database, const char *user_name) { DatabasePool *databasePool; int i; /* check if exist */ - databasePool = find_database_pool(database); + databasePool = find_database_pool(database, user_name); if (databasePool) { /* already exist */ @@ -1336,8 +1190,10 @@ create_database_pool(const char *database) return NULL; } - /* Copy the database name */ ; + /* Copy the database name */ databasePool->database = pstrdup(database); + /* Copy the user name */ + databasePool->user_name = pstrdup(user_name); if (!databasePool->database) { /* out of memory */ @@ -1361,6 +1217,7 @@ create_database_pool(const char *database) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); pfree(databasePool->database); + pfree(databasePool->user_name); pfree(databasePool); return NULL; } @@ -1378,6 +1235,7 @@ create_database_pool(const char *database) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); pfree(databasePool->database); + pfree(databasePool->user_name); pfree(databasePool); return NULL; } @@ -1396,13 +1254,13 @@ create_database_pool(const char *database) * Destroy the pool and free memory */ static int -destroy_database_pool(const char *database) +destroy_database_pool(const char *database, const char *user_name) { DatabasePool *databasePool; int i; /* Delete from the list */ - databasePool = remove_database_pool(database); + databasePool = remove_database_pool(database, user_name); if (databasePool) { if (databasePool->dataNodePools) @@ -1421,6 +1279,7 @@ destroy_database_pool(const char *database) } /* free allocated memory */ pfree(databasePool->database); + pfree(databasePool->user_name); pfree(databasePool); return 1; } @@ -1448,10 +1307,10 @@ insert_database_pool(DatabasePool *databasePool) /* - * Find pool for specified database in the list + * Find pool for specified database and username in the list */ static DatabasePool * -find_database_pool(const char *database) +find_database_pool(const char *database, const char *user_name) { DatabasePool *databasePool; @@ -1459,8 +1318,8 @@ find_database_pool(const char *database) databasePool = databasePools; while (databasePool) { - /* if match break the loop and return */ - if (strcmp(database, databasePool->database) == 0) + if (strcmp(database, databasePool->database) == 0 && + strcmp(user_name, databasePool->user_name) == 0) break; databasePool = databasePool->next; @@ -1468,12 +1327,55 @@ find_database_pool(const char *database) return databasePool; } +/* + * Find pool to be cleaned for specified database in the list + */ +static DatabasePool * +find_database_pool_to_clean(const char *database, List *dn_list, List *co_list) +{ + DatabasePool *databasePool; + + /* Scan the list */ + databasePool = databasePools; + while (databasePool) + { + /* Check for given database name */ + if (strcmp(database, databasePool->database) == 0) + { + ListCell *nodelist_item; + + /* Check if this database pool is clean for given coordinator list */ + foreach (nodelist_item, co_list) + { + int nodenum = lfirst_int(nodelist_item); + + if (databasePool->coordNodePools && + databasePool->coordNodePools[nodenum - 1] && + databasePool->coordNodePools[nodenum - 1]->freeSize != 0) + return databasePool; + } + + /* Check if this database pool is clean for given datanode list */ + foreach (nodelist_item, dn_list) + { + int nodenum = lfirst_int(nodelist_item); + + if (databasePool->dataNodePools && + databasePool->dataNodePools[nodenum - 1] && + databasePool->dataNodePools[nodenum - 1]->freeSize != 0) + return databasePool; + } + } + databasePool = databasePool->next; + } + return databasePool; +} /* * Remove pool for specified database from the list */ static DatabasePool * -remove_database_pool(const char *database) +remove_database_pool(const char *database, const char *user_name) { DatabasePool *databasePool, *prev; @@ -1485,7 +1387,8 @@ remove_database_pool(const char *database) { /* if match break the loop and return */ - if (strcmp(database, databasePool->database) == 0) + if (strcmp(database, databasePool->database) == 0 && + strcmp(user_name, databasePool->user_name) == 0) break; prev = databasePool; databasePool = databasePool->next; @@ -1680,7 +1583,6 @@ grow_pool(DatabasePool * dbPool, int index, char client_conn_type) if (IS_PGXC_COORDINATOR) { remote_type = pstrdup("coordinator"); - } else if (IS_PGXC_DATANODE) { @@ -1692,18 +1594,15 @@ grow_pool(DatabasePool * dbPool, int index, char client_conn_type) nodePool->connstr = PGXCNodeConnStr(datanode_connInfos[index].host, datanode_connInfos[index].port, dbPool->database, - datanode_connInfos[index].uname, - datanode_connInfos[index].password, + dbPool->user_name, remote_type); else if (client_conn_type == REMOTE_CONN_COORD) nodePool->connstr = PGXCNodeConnStr(coord_connInfos[index].host, coord_connInfos[index].port, dbPool->database, - coord_connInfos[index].uname, - coord_connInfos[index].password, + dbPool->user_name, remote_type); - if (!nodePool->connstr) { pfree(nodePool); @@ -1864,7 +1763,8 @@ PoolerLoop(void) agent_destroy(agent); } while (databasePools) - if (destroy_database_pool(databasePools->database) == 0) + if (destroy_database_pool(databasePools->database, + databasePools->user_name) == 0) break; close(server_fd); exit(0); @@ -1918,74 +1818,79 @@ clean_connection(List *dn_discard, List *co_discard, const char *database) co_list[count++] = lfirst_int(nodelist_item); /* Find correct Database pool to clean */ - databasePool = find_database_pool(database); + databasePool = find_database_pool_to_clean(database, dn_discard, co_discard); - /* Database pool has not been found, it is already clean */ - if (!databasePool) - return CLEAN_CONNECTION_COMPLETED; - - /* - * Clean each Pool Correctly - * First for Datanode Pool - */ - for (count = 0; count < dn_len; count++) + while (databasePool) { - int node_num = dn_list[count]; - nodePool = databasePool->dataNodePools[node_num - 1]; + databasePool = find_database_pool_to_clean(database, dn_discard, co_discard); + + /* Database pool has not been found, cleaning is over */ + if (!databasePool) + break; - if (nodePool) + /* + * Clean each Pool Correctly + * First for Datanode Pool + */ + for (count = 0; count < dn_len; count++) { - /* Check if connections are in use */ - if (nodePool->freeSize != nodePool->size) - { - elog(WARNING, "Pool of Database %s is using Datanode %d connections", - databasePool->database, node_num); - res = CLEAN_CONNECTION_NOT_COMPLETED; - } + int node_num = dn_list[count]; + nodePool = databasePool->dataNodePools[node_num - 1]; - /* Destroy connections currently in Node Pool */ - if (nodePool->slot) + if (nodePool) { - for (i = 0; i < nodePool->freeSize; i++) - destroy_slot(nodePool->slot[i]); + /* Check if connections are in use */ + if (nodePool->freeSize != nodePool->size) + { + elog(WARNING, "Pool of Database %s is using Datanode %d connections", + databasePool->database, node_num); + res = CLEAN_CONNECTION_NOT_COMPLETED; + } + + /* Destroy connections currently in Node Pool */ + if (nodePool->slot) + { + for (i = 0; i < nodePool->freeSize; i++) + destroy_slot(nodePool->slot[i]); - /* Move slots in use at the beginning of Node Pool array */ - for (i = nodePool->freeSize; i < nodePool->size; i++ ) - nodePool->slot[i - nodePool->freeSize] = nodePool->slot[i]; + /* Move slots in use at the beginning of Node Pool array */ + for (i = nodePool->freeSize; i < nodePool->size; i++ ) + nodePool->slot[i - nodePool->freeSize] = nodePool->slot[i]; + } + nodePool->size -= nodePool->freeSize; + nodePool->freeSize = 0; } - nodePool->size -= nodePool->freeSize; - nodePool->freeSize = 0; } - } - - /* Then for Coordinators */ - for (count = 0; count < co_len; count++) - { - int node_num = co_list[count]; - nodePool = databasePool->coordNodePools[node_num - 1]; - if (nodePool) + /* Then for Coordinators */ + for (count = 0; count < co_len; count++) { - /* Check if connections are in use */ - if (nodePool->freeSize != nodePool->size) - { - elog(WARNING, "Pool of Database %s is using Coordinator %d connections", - databasePool->database, node_num); - res = CLEAN_CONNECTION_NOT_COMPLETED; - } + int node_num = co_list[count]; + nodePool = databasePool->coordNodePools[node_num - 1]; - /* Destroy connections currently in Node Pool */ - if (nodePool->slot) + if (nodePool) { - for (i = 0; i < nodePool->freeSize; i++) - destroy_slot(nodePool->slot[i]); + /* Check if connections are in use */ + if (nodePool->freeSize != nodePool->size) + { + elog(WARNING, "Pool of Database %s is using Coordinator %d connections", + databasePool->database, node_num); + res = CLEAN_CONNECTION_NOT_COMPLETED; + } - /* Move slots in use at the beginning of Node Pool array */ - for (i = nodePool->freeSize; i < nodePool->size; i++ ) - nodePool->slot[i - nodePool->freeSize] = nodePool->slot[i]; + /* Destroy connections currently in Node Pool */ + if (nodePool->slot) + { + for (i = 0; i < nodePool->freeSize; i++) + destroy_slot(nodePool->slot[i]); + + /* Move slots in use at the beginning of Node Pool array */ + for (i = nodePool->freeSize; i < nodePool->size; i++ ) + nodePool->slot[i - nodePool->freeSize] = nodePool->slot[i]; + } + nodePool->size -= nodePool->freeSize; + nodePool->freeSize = 0; } - nodePool->size -= nodePool->freeSize; - nodePool->freeSize = 0; } } diff --git a/src/backend/pgxc/pool/poolutils.c b/src/backend/pgxc/pool/poolutils.c index 32cdfea..24a5c72 100644 --- a/src/backend/pgxc/pool/poolutils.c +++ b/src/backend/pgxc/pool/poolutils.c @@ -36,6 +36,8 @@ * Use of CLEAN CONNECTION is limited to a super user. * It is advised to clean connections before shutting down a Node or drop a Database. * + * Pool cleaning is done for all the users of a given database. + * * SQL query synopsis is as follows: * CLEAN CONNECTION TO * (COORDINATOR num | DATANODE num | ALL {FORCE}) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 8bc77ea..552b0d8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -3415,7 +3415,7 @@ BackendStartup(Port *port) if (IS_PGXC_COORDINATOR) { /* User is authenticated and dbname is known at this point */ - PoolManagerConnect(pool_handle, port->database_name); + PoolManagerConnect(pool_handle, port->database_name, port->user_name); InitGTM(); } #endif diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index cb0adb9..0b2c9dd 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -353,6 +353,9 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid) } else { +#ifdef PGXC + if (IS_PGXC_DATANODE || !IsConnFromCoord()) +#endif /* Shouldn't be trying to remove a live transaction here */ Assert(!TransactionIdIsValid(proc->xid)); } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a184866..c8648ee 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2819,26 +2819,6 @@ static struct config_string ConfigureNamesString[] = }, { - {"data_node_users", PGC_POSTMASTER, DATA_NODES, - gettext_noop("User names or addresses of data nodes."), - gettext_noop("Comma separated list or single value, " - "if user names are the same on all data nodes") - }, - &DataNodeUsers, - "postgres", NULL, NULL - }, - - { - {"data_node_passwords", PGC_POSTMASTER, DATA_NODES, - gettext_noop("Passwords of data nodes."), - gettext_noop("Comma separated list or single value, " - "if passwords are the same on all data nodes") - }, - &DataNodePwds, - "postgres", NULL, NULL - }, - - { {"gtm_host", PGC_POSTMASTER, GTM, gettext_noop("Host name or address of GTM"), NULL @@ -2867,26 +2847,6 @@ static struct config_string ConfigureNamesString[] = "5432", NULL, NULL }, - { - {"coordinator_users", PGC_POSTMASTER, COORDINATORS, - gettext_noop("User names or addresses of Coordinators."), - gettext_noop("Comma separated list or single value, " - "if user names are the same on all Coordinators") - }, - &CoordinatorUsers, - "postgres", NULL, NULL - }, - - { - {"coordinator_passwords", PGC_POSTMASTER, COORDINATORS, - gettext_noop("Passwords of Coordinators."), - gettext_noop("Comma separated list or single value, " - "if passwords are the same on all Coordinators") - }, - &CoordinatorPwds, - "postgres", NULL, NULL - }, - #endif #ifdef USE_SSL { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 83c54d4..24bc2fa 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -542,10 +542,6 @@ # (change requires restart) #data_node_ports = '15432,25432' # Port numbers of data nodes # (change requires restart) -#data_node_users = 'postgres' # User names of data nodes - # (change requires restart) -#data_node_passwords = 'postgres' # Passwords of data nodes - # (change requires restart) #primary_data_node = 1 # Which data node to use first for # replicated writes @@ -564,10 +560,6 @@ # (change require restart) #coordinator_ports = '5432' # Port numbers of Coordinators # (change require restart) -#coordinator_users = 'postgres' # User names of Coordinators - # (change requires restart) -#coordinator_passwords = 'postgres' # Passwords of Coordinators - # (change requires restart) #------------------------------------------------------------------------------ # GTM CONNECTION diff --git a/src/include/pgxc/pgxcnode.h b/src/include/pgxc/pgxcnode.h index 321e49c..007e1dc 100644 --- a/src/include/pgxc/pgxcnode.h +++ b/src/include/pgxc/pgxcnode.h @@ -94,7 +94,7 @@ extern void InitMultinodeExecutor(void); /* Open/close connection routines (invoked from Pool Manager) */ extern char *PGXCNodeConnStr(char *host, char *port, char *dbname, char *user, - char *password, char *remote_type); + char *remote_type); extern NODE_CONNECTION *PGXCNodeConnect(char *connstr); extern void PGXCNodeClose(NODE_CONNECTION * conn); extern int PGXCNodeConnected(NODE_CONNECTION * conn); diff --git a/src/include/pgxc/poolmgr.h b/src/include/pgxc/poolmgr.h index 0ae3cc2..7e53b48 100644 --- a/src/include/pgxc/poolmgr.h +++ b/src/include/pgxc/poolmgr.h @@ -28,8 +28,6 @@ typedef struct { char *host; char *port; - char *uname; - char *password; } PGXCNodeConnectionInfo; /* Connection pool entry */ @@ -51,8 +49,8 @@ typedef struct /* All pools for specified database */ typedef struct databasepool { - Oid databaseId; char *database; + char *user_name; PGXCNodePool **dataNodePools; /* one for each Datanode */ PGXCNodePool **coordNodePools; /* one for each Coordinator */ struct databasepool *next; @@ -89,13 +87,9 @@ extern bool PersistentConnections; extern char *DataNodeHosts; extern char *DataNodePorts; -extern char *DataNodeUsers; -extern char *DataNodePwds; extern char *CoordinatorHosts; extern char *CoordinatorPorts; -extern char *CoordinatorUsers; -extern char *CoordinatorPwds; /* Initialize internal structures */ extern int PoolManagerInit(void); @@ -129,7 +123,7 @@ extern void PoolManagerDisconnect(PoolHandle *handle); * for subsequent calls. Associate session with specified database and * initialize respective connection pool */ -extern void PoolManagerConnect(PoolHandle *handle, const char *database); +extern void PoolManagerConnect(PoolHandle *handle, const char *database, const char *user_name); /* Get pooled connections */ extern int *PoolManagerGetConnections(List *datanodelist, List *coordlist); ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/pool/pgxcnode.c | 6 +- src/backend/pgxc/pool/poolmgr.c | 393 ++++++++++--------------- src/backend/pgxc/pool/poolutils.c | 2 + src/backend/postmaster/postmaster.c | 2 +- src/backend/storage/ipc/procarray.c | 3 + src/backend/utils/misc/guc.c | 40 --- src/backend/utils/misc/postgresql.conf.sample | 8 - src/include/pgxc/pgxcnode.h | 2 +- src/include/pgxc/poolmgr.h | 10 +- 9 files changed, 161 insertions(+), 305 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-31 16:21:23
|
Project "Postgres-XC". The branch, master has been updated via 0429a889372c6db0b4b1253624601c42410cc108 (commit) from 124814afe8603b4ec933f6f7b0b646a2a36f53cd (commit) - Log ----------------------------------------------------------------- commit 0429a889372c6db0b4b1253624601c42410cc108 Author: Michael P <mic...@us...> Date: Fri Apr 1 00:31:29 2011 +0900 Support for GRANT and REVOKE Spread GRANT and REVOKE to all the nodes of the cluster. diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 284a52c..49c018b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1008,10 +1008,20 @@ standard_ProcessUtility(Node *parsetree, case T_GrantStmt: ExecuteGrantStmt((GrantStmt *) parsetree); + +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); +#endif break; case T_GrantRoleStmt: GrantRole((GrantRoleStmt *) parsetree); + +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); +#endif break; case T_AlterDefaultPrivilegesStmt: ----------------------------------------------------------------------- Summary of changes: src/backend/tcop/utility.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-31 10:37:23
|
Project "Postgres-XC". The branch, master has been updated via 124814afe8603b4ec933f6f7b0b646a2a36f53cd (commit) from baa0d2e4589347558b6fd894d431c1ff42151492 (commit) - Log ----------------------------------------------------------------- commit 124814afe8603b4ec933f6f7b0b646a2a36f53cd Author: Michael P <mic...@us...> Date: Thu Mar 31 19:36:40 2011 +0900 Remove debug flag from GTM Makefile diff --git a/src/gtm/Makefile.global b/src/gtm/Makefile.global index 684690b..09c8993 100644 --- a/src/gtm/Makefile.global +++ b/src/gtm/Makefile.global @@ -29,7 +29,7 @@ enable_shared = yes # Compilers CPP = gcc -E -CPPFLAGS = -g -D_GNU_SOURCE +CPPFLAGS = -D_GNU_SOURCE override CPPFLAGS := -I$(top_srcdir)/include $(CPPFLAGS) ----------------------------------------------------------------------- Summary of changes: src/gtm/Makefile.global | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-31 10:32:25
|
Project "Postgres-XC". The branch, master has been updated via baa0d2e4589347558b6fd894d431c1ff42151492 (commit) from b9c601ba5509e9c90f1d4d184a514ce47ed7397d (commit) - Log ----------------------------------------------------------------- commit baa0d2e4589347558b6fd894d431c1ff42151492 Author: Michael P <mic...@us...> Date: Thu Mar 31 19:31:02 2011 +0900 Fix for make -j This wasn't compiling correctly. Patch written from Wang Diancheng diff --git a/src/Makefile b/src/Makefile index 2ca5e05..918ad95 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,11 +18,11 @@ all install installdirs uninstall distprep: $(MAKE) -C timezone $@ # GTM should be built before backend because of dependancy $(MAKE) -C gtm $@ + $(MAKE) -C interfaces $@ $(MAKE) -C backend $@ $(MAKE) -C backend/utils/mb/conversion_procs $@ $(MAKE) -C backend/snowball $@ $(MAKE) -C include $@ - $(MAKE) -C interfaces $@ $(MAKE) -C backend/replication/libpqwalreceiver $@ $(MAKE) -C bin $@ $(MAKE) -C pl $@ ----------------------------------------------------------------------- Summary of changes: src/Makefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-31 09:08:43
|
Project "Postgres-XC". The branch, ha_support has been updated via 263fffdb2d9865eac2d6780b2ac7edb6d4c0b857 (commit) from 3df6c0f60081d0097939b34978d3d545f57b7d01 (commit) - Log ----------------------------------------------------------------- commit 263fffdb2d9865eac2d6780b2ac7edb6d4c0b857 Author: Koichi Suzuki <koi...@gm...> Date: Thu Mar 31 18:08:18 2011 +0900 This commit added headers to some of GTM source files. diff --git a/src/gtm/common/aset.c b/src/gtm/common/aset.c index 3c14fb1..300aa05 100644 --- a/src/gtm/common/aset.c +++ b/src/gtm/common/aset.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.77 2008/04/11 22:54:23 tgl Exp $ + * $Postgres-XC$ * * NOTE: * This is a new (Feb. 05, 1999) implementation of the allocation set diff --git a/src/gtm/common/assert.c b/src/gtm/common/assert.c index ea182d5..55da27b 100644 --- a/src/gtm/common/assert.c +++ b/src/gtm/common/assert.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/error/assert.c,v 1.35 2008/01/01 19:45:53 momjian Exp $ + * $Postgres-XC$ * * NOTE * This should eventually work with elog() diff --git a/src/gtm/gtm_ctl/gtm_ctl.c b/src/gtm/gtm_ctl/gtm_ctl.c index e6b277e..91690c9 100644 --- a/src/gtm/gtm_ctl/gtm_ctl.c +++ b/src/gtm/gtm_ctl/gtm_ctl.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/ip.c b/src/gtm/libpq/ip.c index 08929e9..3f719fc 100644 --- a/src/gtm/libpq/ip.c +++ b/src/gtm/libpq/ip.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.43 2009/01/01 17:23:42 momjian Exp $ + * $Postgres-XC$ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard <nk...@lb...>, Linux Based Systems Design diff --git a/src/gtm/libpq/pqcomm.c b/src/gtm/libpq/pqcomm.c index 4543665..4bc9aab 100644 --- a/src/gtm/libpq/pqcomm.c +++ b/src/gtm/libpq/pqcomm.c @@ -31,7 +31,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.198 2008/01/01 19:45:49 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/pqformat.c b/src/gtm/libpq/pqformat.c index 6d8e5f9..2bd6d59 100644 --- a/src/gtm/libpq/pqformat.c +++ b/src/gtm/libpq/pqformat.c @@ -25,7 +25,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/backend/libpq/pqformat.c,v 1.48 2009/01/01 17:23:42 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/pqsignal.c b/src/gtm/libpq/pqsignal.c index 0c7914e..39687bb 100644 --- a/src/gtm/libpq/pqsignal.c +++ b/src/gtm/libpq/pqsignal.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.44 2008/01/01 19:45:49 momjian Exp $ + * $Postgres-XC$ * * NOTES * This shouldn't be in libpq, but the monitor and some other diff --git a/src/gtm/libpq/strlcpy.c b/src/gtm/libpq/strlcpy.c index 28a3740..64fbac4 100644 --- a/src/gtm/libpq/strlcpy.c +++ b/src/gtm/libpq/strlcpy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/strlcpy.c,v 1.5 2008/01/01 19:46:00 momjian Exp $ + * $Postgres-XC$ * * This file was taken from OpenBSD and is used on platforms that don't * provide strlcpy(). The OpenBSD copyright terms follow. diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index 60a612f..8195b39 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_snap.c b/src/gtm/main/gtm_snap.c index c2d818b..6bf86a7 100644 --- a/src/gtm/main/gtm_snap.c +++ b/src/gtm/main/gtm_snap.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_stat.c b/src/gtm/main/gtm_stat.c index d9fa7aa..892e2f8 100644 --- a/src/gtm/main/gtm_stat.c +++ b/src/gtm/main/gtm_stat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_stats.c b/src/gtm/main/gtm_stats.c index 2548cd4..297b8f8 100644 --- a/src/gtm/main/gtm_stats.c +++ b/src/gtm/main/gtm_stats.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_thread.c b/src/gtm/main/gtm_thread.c index 2fd6dc2..fe48e7c 100644 --- a/src/gtm/main/gtm_thread.c +++ b/src/gtm/main/gtm_thread.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_time.c b/src/gtm/main/gtm_time.c index 1e1451e..be30a46 100644 --- a/src/gtm/main/gtm_time.c +++ b/src/gtm/main/gtm_time.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_txn.c b/src/gtm/main/gtm_txn.c index 5715b40..9cfbeb6 100644 --- a/src/gtm/main/gtm_txn.c +++ b/src/gtm/main/gtm_txn.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index 3fbf283..66096f5 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/path/path.c b/src/gtm/path/path.c index 11c6290..7076afe 100644 --- a/src/gtm/path/path.c +++ b/src/gtm/path/path.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/recovery/register.c b/src/gtm/recovery/register.c index 0c40596..5f44425 100644 --- a/src/gtm/recovery/register.c +++ b/src/gtm/recovery/register.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/assert.h b/src/include/gtm/assert.h index 97cfc2d..ace5f7f 100644 --- a/src/include/gtm/assert.h +++ b/src/include/gtm/assert.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/elog.h b/src/include/gtm/elog.h index 9c410db..e21cac0 100644 --- a/src/include/gtm/elog.h +++ b/src/include/gtm/elog.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.98 2009/01/01 17:24:02 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm.h b/src/include/gtm/gtm.h index ad5882b..c2894e3 100644 --- a/src/include/gtm/gtm.h +++ b/src/include/gtm/gtm.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_c.h b/src/include/gtm/gtm_c.h index 116aa67..3d7c179 100644 --- a/src/include/gtm/gtm_c.h +++ b/src/include/gtm/gtm_c.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * c.h + * gtm_c.h * Fundamental C definitions. This is included by every .c file in * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate). * @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/c.h,v 1.234 2009/01/01 17:23:55 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_client.h b/src/include/gtm/gtm_client.h index c86a874..791468a 100644 --- a/src/include/gtm/gtm_client.h +++ b/src/include/gtm/gtm_client.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_conn.h b/src/include/gtm/gtm_conn.h index 40256be..f6c39d0 100644 --- a/src/include/gtm/gtm_conn.h +++ b/src/include/gtm/gtm_conn.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_ext.h b/src/include/gtm/gtm_ext.h index 49b0253..f8963ce 100644 --- a/src/include/gtm/gtm_ext.h +++ b/src/include/gtm/gtm_ext.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_ip.h b/src/include/gtm/gtm_ip.h index 2f89418..262af32 100644 --- a/src/include/gtm/gtm_ip.h +++ b/src/include/gtm/gtm_ip.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * ip.h + * gtm_ip.h * Definitions for IPv6-aware network access. * * These definitions are used by both frontend and backend code. Be careful @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_list.h b/src/include/gtm/gtm_list.h index 9ead69b..f73c9a1 100644 --- a/src/include/gtm/gtm_list.h +++ b/src/include/gtm/gtm_list.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * pg_list.h + * gtm_list.h * interface for PostgreSQL generic linked list package * * This package implements singly-linked homogeneous lists. @@ -31,7 +31,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.59 2008/08/14 18:48:00 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_lock.h b/src/include/gtm/gtm_lock.h index 3da85c1..3404b3d 100644 --- a/src/include/gtm/gtm_lock.h +++ b/src/include/gtm/gtm_lock.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_msg.h b/src/include/gtm/gtm_msg.h index 4ec7dac..b3071a8 100644 --- a/src/include/gtm/gtm_msg.h +++ b/src/include/gtm/gtm_msg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_proxy.h b/src/include/gtm/gtm_proxy.h index ee12fd5..4fcf5f0 100644 --- a/src/include/gtm/gtm_proxy.h +++ b/src/include/gtm/gtm_proxy.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_seq.h b/src/include/gtm/gtm_seq.h index 7e75445..c9e993c 100644 --- a/src/include/gtm/gtm_seq.h +++ b/src/include/gtm/gtm_seq.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_time.h b/src/include/gtm/gtm_time.h index 90f36ea..22d068d 100644 --- a/src/include/gtm/gtm_time.h +++ b/src/include/gtm/gtm_time.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_txn.h b/src/include/gtm/gtm_txn.h index 86a0d49..5b5f75b 100644 --- a/src/include/gtm/gtm_txn.h +++ b/src/include/gtm/gtm_txn.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/ip.h b/src/include/gtm/ip.h index fa4e3d3..cdd69ba 100644 --- a/src/include/gtm/ip.h +++ b/src/include/gtm/ip.h @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-be.h b/src/include/gtm/libpq-be.h index c73335d..8e9805f 100644 --- a/src/include/gtm/libpq-be.h +++ b/src/include/gtm/libpq-be.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.69 2009/01/01 17:23:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-fe.h b/src/include/gtm/libpq-fe.h index 1ae16c1..44ebf58 100644 --- a/src/include/gtm/libpq-fe.h +++ b/src/include/gtm/libpq-fe.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.145 2009/01/01 17:24:03 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-int.h b/src/include/gtm/libpq-int.h index 5c6714b..30775e3 100644 --- a/src/include/gtm/libpq-int.h +++ b/src/include/gtm/libpq-int.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.139 2009/01/01 17:24:03 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/memnodes.h b/src/include/gtm/memnodes.h index 9c55e46..8f5d3e4 100644 --- a/src/include/gtm/memnodes.h +++ b/src/include/gtm/memnodes.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/nodes/memnodes.h,v 1.34 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/memutils.h b/src/include/gtm/memutils.h index 9666c44..fc1e2d3 100644 --- a/src/include/gtm/memutils.h +++ b/src/include/gtm/memutils.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.64 2008/01/01 19:45:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h index e81e9d1..2efaaa4 100644 --- a/src/include/gtm/palloc.h +++ b/src/include/gtm/palloc.h @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/palloc.h,v 1.40 2008/06/28 16:45:22 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/path.h b/src/include/gtm/path.h index e95ca5e..6f18856 100644 --- a/src/include/gtm/path.h +++ b/src/include/gtm/path.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqcomm.h b/src/include/gtm/pqcomm.h index e0de16e..1544615 100644 --- a/src/include/gtm/pqcomm.h +++ b/src/include/gtm/pqcomm.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqcomm.h,v 1.109 2008/10/28 12:10:44 mha Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqexpbuffer.h b/src/include/gtm/pqexpbuffer.h index 039a481..6e4f586 100644 --- a/src/include/gtm/pqexpbuffer.h +++ b/src/include/gtm/pqexpbuffer.h @@ -19,7 +19,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/pqexpbuffer.h,v 1.21 2008/11/26 16:23:11 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqformat.h b/src/include/gtm/pqformat.h index 4a07367..e5b4541 100644 --- a/src/include/gtm/pqformat.h +++ b/src/include/gtm/pqformat.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqformat.h,v 1.27 2009/01/01 17:23:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqsignal.h b/src/include/gtm/pqsignal.h index 523a151..ce90997 100644 --- a/src/include/gtm/pqsignal.h +++ b/src/include/gtm/pqsignal.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.32 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * * NOTES * This shouldn't be in libpq, but the monitor and some other diff --git a/src/include/gtm/register.h b/src/include/gtm/register.h index 7c2461f..0a43bf1 100644 --- a/src/include/gtm/register.h +++ b/src/include/gtm/register.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/stringinfo.h b/src/include/gtm/stringinfo.h index c34e6a3..d504685 100644 --- a/src/include/gtm/stringinfo.h +++ b/src/include/gtm/stringinfo.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/lib/stringinfo.h,v 1.35 2008/01/01 19:45:57 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ ----------------------------------------------------------------------- Summary of changes: src/gtm/common/aset.c | 2 +- src/gtm/common/assert.c | 2 +- src/gtm/gtm_ctl/gtm_ctl.c | 2 +- src/gtm/libpq/ip.c | 2 +- src/gtm/libpq/pqcomm.c | 2 +- src/gtm/libpq/pqformat.c | 2 +- src/gtm/libpq/pqsignal.c | 2 +- src/gtm/libpq/strlcpy.c | 2 +- src/gtm/main/gtm_seq.c | 2 +- src/gtm/main/gtm_snap.c | 2 +- src/gtm/main/gtm_stat.c | 2 +- src/gtm/main/gtm_stats.c | 2 +- src/gtm/main/gtm_thread.c | 2 +- src/gtm/main/gtm_time.c | 2 +- src/gtm/main/gtm_txn.c | 2 +- src/gtm/main/main.c | 2 +- src/gtm/path/path.c | 2 +- src/gtm/recovery/register.c | 2 +- src/include/gtm/assert.h | 2 +- src/include/gtm/elog.h | 2 +- src/include/gtm/gtm.h | 2 +- src/include/gtm/gtm_c.h | 4 ++-- src/include/gtm/gtm_client.h | 2 +- src/include/gtm/gtm_conn.h | 2 +- src/include/gtm/gtm_ext.h | 2 +- src/include/gtm/gtm_ip.h | 4 ++-- src/include/gtm/gtm_list.h | 4 ++-- src/include/gtm/gtm_lock.h | 2 +- src/include/gtm/gtm_msg.h | 2 +- src/include/gtm/gtm_proxy.h | 2 +- src/include/gtm/gtm_seq.h | 2 +- src/include/gtm/gtm_time.h | 2 +- src/include/gtm/gtm_txn.h | 2 +- src/include/gtm/ip.h | 2 +- src/include/gtm/libpq-be.h | 2 +- src/include/gtm/libpq-fe.h | 2 +- src/include/gtm/libpq-int.h | 2 +- src/include/gtm/memnodes.h | 2 +- src/include/gtm/memutils.h | 2 +- src/include/gtm/palloc.h | 2 +- src/include/gtm/path.h | 2 +- src/include/gtm/pqcomm.h | 2 +- src/include/gtm/pqexpbuffer.h | 2 +- src/include/gtm/pqformat.h | 2 +- src/include/gtm/pqsignal.h | 2 +- src/include/gtm/register.h | 2 +- src/include/gtm/stringinfo.h | 2 +- 47 files changed, 50 insertions(+), 50 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 16:15:12
|
Project "Postgres-XC". The branch, master has been updated via b9c601ba5509e9c90f1d4d184a514ce47ed7397d (commit) from 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) - Log ----------------------------------------------------------------- commit b9c601ba5509e9c90f1d4d184a514ce47ed7397d Author: Michael P <mic...@us...> Date: Thu Mar 31 01:12:15 2011 +0900 Fix for bug 3160456: sequence error values If an error occured on GTM for currval or nextval, the incorrect value EINVAL (22) was returned to Postgres-XC node. diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index f6c4a21..6a863d2 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -657,7 +657,7 @@ GTM_SeqGetCurrent(GTM_SequenceKey seqkey) ereport(LOG, (EINVAL, errmsg("The sequence with the given key does not exist"))); - return EINVAL; + return InvalidSequenceValue; } GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); @@ -719,7 +719,7 @@ GTM_SeqGetNext(GTM_SequenceKey seqkey) ereport(LOG, (EINVAL, errmsg("The sequence with the given key does not exist"))); - return EINVAL; + return InvalidSequenceValue; } GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); ----------------------------------------------------------------------- Summary of changes: src/gtm/main/gtm_seq.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:32:00
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been deleted was 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 ----------------------------------------------------------------------- 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 Fix GXID feed issue ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:30:16
|
Project "Postgres-XC". The branch, REL0_9_4_STABLE has been created at 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:28:53
|
Project "Postgres-XC". The annotated tag, v0.9.4 has been created at 3ac5a29e291e47af2ba420685c6776012a26779c (tag) tagging 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) replaces v0.9.3 tagged by Michael P on Thu Mar 31 00:27:51 2011 +0900 - Log ----------------------------------------------------------------- Postgres-XC version 0.9.4 tag Abbas (16): Block creation of concurrent indices To avoid a crash caused by an insert select statement in vacuum.sql To fix a server crash in aggregates as reported in ID 3125430 GetRelationLocInfo can return NULL, this patch adds check for a NULL return at missing places Block FK Constraints and add some missing checks The test case portals finds a NULL connecction in ExecEndRemoteQuery and crashes the server. This patch puts a NULL check to avoid the crash Fixing a few expected output files and changed a warning message to make the output independent of the cluster configuration Add alternate expected output files to take care of regression failures Expected output changed to fix regression failure Add alternate expected output file to fix regression falilure of numeric.sql Fix for server crash 3148037 : does not fix WHERE CURRENT OF, only fixes server crash Fix for server crash as mentioned in bug ID 3170715 Since the creation of unique indices is supposed to fail in XC hence this output is correct This patch fixes a test case in strings.sql This patch fixes the problem in XC that error detail was not being handled. Merge branch 'merge_postgres_9_0_3' of ssh://postgres-xc.git.sourceforge.net/gitroot/postgres-xc/postgres-xc into merge_postgres_9_0_3 Mason Sharp (22): Special hanlding for ANALYZE on the data nodes. Improve performance of "multi-step" queries (an on-going process). Fix bug with primary key in CREATE TABLE statement. Add a message that the RETURNING clause is not yet supported. 1. Support for UPDATE and DELETE WHERE CURRENT OF for Support for COPY SELECT Do not allow the partition column to be updated on hash partitioned Fix some compiler warnings Fix PGXC macro usage Minor cursor changes: Fix for sourceforge.net bug#3013984: Sequence scope Fixed bug where if there are subqueries in the SELECT clause This fixes a couple of issues noticed after the last commit, Add support for INSERT SELECT. Fix a problem when more values are selected than total columns in Fixed a bug with INSERT SELECT when an input value is NULL. Fixed bug in INSERT when omitting a value for the partitioning column. Fixed recently introduced bug with node determination Add support for single-step prepared statements. Added missing #ifdef PGXC Updated regression tests. Block the creation of temp tables until properly supported Michael P (110): Support for CLEAN CONNECTION Block Node Commit on a Datanode. Change Protocol connection between PGXC nodes and GTM/GTM-Proxy. Correction for implicit 2PC Clean up of execRemote.c Improvement of performance with tuple scan Fix for bug 3142311:renaming sequences error Fix for bug 3136262: Improvement of Explicit 2PC error handling Sequence Renaming Node Registering feature Allow only Remote Coordinator to use functionnalities introduced with SQL/MED Fix for partially committed transactions in Implicit 2PC Clean up in Materialize code Fix and Clean up in Executor Base code to support correlated DELETE and UPDATE Support for correlated DELETE for replicated tables The patch implements multiple insert syntax in PGXC. Fix for make -j Fix for bug 3147497 INSERT.. DEFAULT VALUES Fix for replicated tables using multi-INSERT queries. maintenance for 2011, change header files Support for EXECUTE DIRECT CREATE TABLE: new distribution function MODULO Fix for bug 3142430 Fix for bug 3172438: node registration protocol Multiple INSERT support for MODULO tables Fix for bug 3170713: DROP DATABASE wihout cleaning connections Fix for bug 3170708: Default values support for MULTI INSERT Fix for bug 3188711: Fire rules only on Coordinator Block SAVEPOINT because of non-support Fix for bug 3136262: PREPARE information not correctly got Fix for DROP DATABASE Fix for bug 3151626: Support for COPY BINARY Fix for bug 3134395, 3086422, 3136230: 2PC locks Merge with PostgreSQL 9.0.3 Fix for bug 3199029 GTM/GTM-proxy FATAL error handling Merge branch 'master' into merge_postgres_9_0_3 Improve error handling when launching DDL or utilities Merge branch 'master' into merge_postgres_9_0_3 Fix for CREATE INDEX CONCURRENTLY Block PREPARE and EXECUTE for the time being CREATE TABLE default distribution to REPLICATED Change back table defalt type to distributed. Addition of correct output for regress test float4. Fix regression tests for int4 Fix for regression tests float4 Partial fix for regression test float fix Fix for regression test create_table Fix for regression test txid Block trigger as this feature is not supported Partial fix for regression test temp Block FOREIGN constraint creation Block TEMP SEQUENCE and TABLESPACE Fix when transforming a CREATE statement Cleanup of regression files Fix for regression test create_table Fix for regression test returning Fix for regression test inet Block SERIAL sequences Fix for bug 3201711: Sequence view crash Fix for regression test box Fix for bug 3202643: Sequence error Stabilize code for pg_regress tests Fix for bugs 3148479, 3140473: COPY FROM CVS HEADER, COPY TO WITH CSV QUOTE Fix for bug 3141640: non column select Fix for bugs 3124253 and 3202554: Unique remote query node Fix for bug 3205043: pg_dump support for MODULO table Clean up of pgxc_ddl Merge branch 'master' into merge_postgres_9_0_3 Fix for regression test tablespace Fix for regression test point Fix for regression test box Fix for regression test triggers Fix for regression test prepare Fix for regression test case Fix for regression test guc Fix for regression test update Fix for regression test delete Fix for regression test plancache Fix for regression test combocid Fix for regression test copy and point Fix for regression test copyselect Fix for regression test create_misc Fix for regression test create_aggregate Fix for regression test typed_table Fix for regression test sanity_check Fix for regression test select Fix for regression test select_distinct_on Fix for regression test union Fix for regression test transactions Fix for regression test random Fix for regression test hash_index Fix for regression test namespace Fix for regression test portals_p2 Fix for regression test cluster Fix for regression test dependency Fix for regression test rowtypes Fix for regression test returning Fix for regression test select_into Fix for regression test copy2 Fix for regression test truncate Block DEFERRED constraints (DEFERRABLE) Fix for cache lookup bug for type Addition of a check when fetching tuples Fix for regression test create type Fix for regression test privileges Fix for VIEW and SEQUENCE Fix a cache leak WARNING with system cache Fix for bug 3240318: support for lastval Fix GXID feed issue Pavan Deolasee (1): Check for buffer overflow while constructing gtm/gtm_proxy start/stop commands. ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:13:26
|
Project "Postgres-XC". The branch, POSTGRES8_4_3_BASE has been created at 490c08dd37fa44af57cd3a2b3e931ef4f3a94853 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@gm...> - 2011-03-30 12:01:56
|
Thank you Michael; I remember we had similar issue in the past... ---------- Koichi Suzuki 2011/3/30 Michael Paquier <mic...@us...>: > Project "Postgres-XC". > > The branch, merge_postgres_9_0_3 has been updated > via 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) > from 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) > > > - Log ----------------------------------------------------------------- > commit 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 > Author: Michael P <mic...@us...> > Date: Wed Mar 30 20:25:52 2011 +0900 > > Fix GXID feed issue > > Useless calls to GetCurrentTransactionId were the origin > of consuming extra transaction IDs even on backend Datanode > where it should ot take a transaction ID at some moments. > > This problem may cause node crash, due to same transaction IDs being committed > twice or pooler connection issues. > > diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c > index 0b09093..ed6271e 100644 > --- a/src/backend/access/transam/xact.c > +++ b/src/backend/access/transam/xact.c > @@ -1923,13 +1923,16 @@ CommitTransaction(bool contact_gtm) > bool PrepareLocalCoord = false; > bool PreparePGXCNodes = false; > char implicitgid[256]; > - TransactionId xid = GetCurrentTransactionId(); > + TransactionId xid = InvalidTransactionId; > > if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) > PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); > > if (PrepareLocalCoord || PreparePGXCNodes) > + { > + xid = GetCurrentTransactionId(); > sprintf(implicitgid, "T%d", xid); > + } > > /* Save GID where PrepareTransaction can find it again */ > if (PrepareLocalCoord) > > ----------------------------------------------------------------------- > > Summary of changes: > src/backend/access/transam/xact.c | 5 ++++- > 1 files changed, 4 insertions(+), 1 deletions(-) > > > hooks/post-receive > -- > Postgres-XC > > ------------------------------------------------------------------------------ > Enable your software for Intel(R) Active Management Technology to meet the > growing manageability and security demands of your customers. Businesses > are taking advantage of Intel(R) vPro (TM) technology - will your software > be a part of the solution? Download the Intel(R) Manageability Checker > today! http://p.sf.net/sfu/intel-dev2devmar > _______________________________________________ > Postgres-xc-committers mailing list > Pos...@li... > https://lists.sourceforge.net/lists/listinfo/postgres-xc-committers > |
From: Michael P. <mic...@us...> - 2011-03-30 11:28:56
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) from 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) - Log ----------------------------------------------------------------- commit 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 Author: Michael P <mic...@us...> Date: Wed Mar 30 20:25:52 2011 +0900 Fix GXID feed issue Useless calls to GetCurrentTransactionId were the origin of consuming extra transaction IDs even on backend Datanode where it should ot take a transaction ID at some moments. This problem may cause node crash, due to same transaction IDs being committed twice or pooler connection issues. diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 0b09093..ed6271e 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -1923,13 +1923,16 @@ CommitTransaction(bool contact_gtm) bool PrepareLocalCoord = false; bool PreparePGXCNodes = false; char implicitgid[256]; - TransactionId xid = GetCurrentTransactionId(); + TransactionId xid = InvalidTransactionId; if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); if (PrepareLocalCoord || PreparePGXCNodes) + { + xid = GetCurrentTransactionId(); sprintf(implicitgid, "T%d", xid); + } /* Save GID where PrepareTransaction can find it again */ if (PrepareLocalCoord) ----------------------------------------------------------------------- Summary of changes: src/backend/access/transam/xact.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 08:40:30
|
Project "Postgres-XC". The branch, ha_support has been updated via 82670fcb1bf768267195f9a9c33d6f9207ba917b (commit) via 073ac85b8c94800eacd9f2d7f8555a8ae9453022 (commit) from 418e9c622429131005817538966cd50d4779e6dd (commit) - Log ----------------------------------------------------------------- commit 82670fcb1bf768267195f9a9c33d6f9207ba917b Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:20:45 2011 +0900 Revert "Revert "This is to change the file name of gtm.c at src/pgxc/pgxc_clean to"" This reverts commit 073ac85b8c94800eacd9f2d7f8555a8ae9453022. This is to cancel name change of pgxc_clean to fix build problem. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 10cba88..5d41e1a 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/pgxc_clean_gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/gtm.c rename to src/pgxc/pgxc_clean/pgxc_clean_gtm.c commit 073ac85b8c94800eacd9f2d7f8555a8ae9453022 Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:18:28 2011 +0900 Revert "This is to change the file name of gtm.c at src/pgxc/pgxc_clean to" This reverts commit 418e9c622429131005817538966cd50d4779e6dd. Cmmit reverted to restore to the status before pgxc_clean is added. Found erro r to fix. Sorry. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 5d41e1a..10cba88 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/pgxc_clean_gtm.c b/src/pgxc/pgxc_clean/gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/pgxc_clean_gtm.c rename to src/pgxc/pgxc_clean/gtm.c ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 08:04:49
|
Project "Postgres-XC". The branch, ha_support has been updated via 418e9c622429131005817538966cd50d4779e6dd (commit) from dcc82f72fb630f16c965e1e6d3d93b2c6008a150 (commit) - Log ----------------------------------------------------------------- commit 418e9c622429131005817538966cd50d4779e6dd Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:03:58 2011 +0900 This is to change the file name of gtm.c at src/pgxc/pgxc_clean to pgxc_clean_gtm.c to avoid confusion. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 10cba88..5d41e1a 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/pgxc_clean_gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/gtm.c rename to src/pgxc/pgxc_clean/pgxc_clean_gtm.c ----------------------------------------------------------------------- Summary of changes: src/pgxc/pgxc_clean/Makefile | 2 +- src/pgxc/pgxc_clean/{gtm.c => pgxc_clean_gtm.c} | 0 2 files changed, 1 insertions(+), 1 deletions(-) rename src/pgxc/pgxc_clean/{gtm.c => pgxc_clean_gtm.c} (100%) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 03:42:05
|
Project "Postgres-XC". The branch, ha_support has been updated via dcc82f72fb630f16c965e1e6d3d93b2c6008a150 (commit) from 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb (commit) - Log ----------------------------------------------------------------- commit dcc82f72fb630f16c965e1e6d3d93b2c6008a150 Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 12:41:37 2011 +0900 This is an additional commit for pgxc_clean to modifie it's parent Makefile to include pgxc_clean make. diff --git a/src/pgxc/Makefile b/src/pgxc/Makefile index 5ba9ac1..2156013 100644 --- a/src/pgxc/Makefile +++ b/src/pgxc/Makefile @@ -13,7 +13,7 @@ subdir = src/pgxc top_builddir = ../.. include $(top_builddir)/src/Makefile.global -DIRS = xcm +DIRS = xcm pgxc_clean all install installdirs uninstall distprep clean distclean maintainer-clean: $(INSTALL_DATA) $(srcdir)/xcm/pgxc_ha.conf.sample '$(DESTDIR)$(datadir)/pgxc_ha.conf.sample' ----------------------------------------------------------------------- Summary of changes: src/pgxc/Makefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 03:08:40
|
Project "Postgres-XC". The branch, ha_support has been updated via 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb (commit) from 4d3f0a48a979044c6b741f9cd7d4dc37c32548e2 (commit) - Log ----------------------------------------------------------------- commit 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 12:02:46 2011 +0900 This commit is to add "pgxc_clean" tools for HA-support. When a coordinator fails, transactions handled in the coordinator may fail. HOwever, the other coordinator can continue to handle incoming transactions. On the other hand, if there's prepared but not committed/aborted transactions originated from the failed coordinator, it will reman as "unfinished transactions" whose GXID will continue to appear in global snapshots, which gives bad influence to the performance. pgxc_clean deals with this situation. It looks for 2PC transactions and if it is originated by the failed coordinator and if they are not finished. Then pgxc_config will commit or abort (depending upon the whole status of local commits) such transactions so that they don't appear in snapshots. This is implemented by Metro Systems. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile new file mode 100644 index 0000000..10cba88 --- /dev/null +++ b/src/pgxc/pgxc_clean/Makefile @@ -0,0 +1,51 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/pgxc/pgxc_clean +# +# Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation +# +# $PostgreSQL$ +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pgxc_clean - Abort prepared transaction for a Postgres-XC Coordinator" +subdir = src/pgxc/pgxc_clean +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) + +xcm_builddir = $(top_builddir)/src/pgxc/xcm +gtm_builddir = $(top_builddir)/src/gtm + +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +# Switch when libxcm and libgtmclient are installed via 'make install' +# EX_OBJS = $(gtm_builddir)/common/assert.o +EX_OBJS = $(gtm_builddir)/common/assert.o \ + $(gtm_builddir)/client/libgtmclient.a \ + $(xcm_builddir)/libxcm.a + +override LDFLAGS += -L$(top_builddir)/src/gtm/client \ + -L$(top_builddir)/src/pgxc/xcm + +# Switch when libxcm and libgtmclient are installed via 'make install' +# LIBS= -lpthread -lxcm -lgtmclient +LIBS= -lpthread + +all: pgxc_clean + +pgxc_clean: $(OBJS) + $(CC) $(CFLAGS) $(OBJS) $(EX_OBJS) $(libpq_pgport) $(LDFLAGS) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pgxc_clean$(X) '$(DESTDIR)$(bindir)'/pgxc_clean$(X) + +installdirs: + $(mkinstalldirs) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f $(addprefix '$(DESTDIR)$(bindir)'/, pgxc_clean$(X)) + +clean distclean maintainer-clean: + rm -f pgxc_clean$(X) $(OBJS) pgxc_clean.o + diff --git a/src/pgxc/pgxc_clean/README b/src/pgxc/pgxc_clean/README new file mode 100644 index 0000000..a93d617 --- /dev/null +++ b/src/pgxc/pgxc_clean/README @@ -0,0 +1,55 @@ + +Notes on pgxc_clean +================ + +1. Abstract: +------------ + +pgxc_clean is a command line tool which recover 2PC-transactions which are +originated by crashed coordinator. + +2. Usage: +--------- + +Usage: + pgxc_clean --version + pgxc_clean --help + pgxc_clean [--all|--node=NODE_NUMBER] [--user=USERNAME] [--password=PASSWORD] + +General options: + --help show help, then exit + --version output version information, then exit + +Options for originator: + -a, --all all Coordinators in the cluster + -n, --node=NODE_NUMBER given Coordinator number + +Connection options: + -U, --user=USERNAME username to be used to establish connection + against coordinator + -W, --password=PASSWORD password to be used to establish connection + against coordinator + +3. Logging: +----------- + +pgxc_clean uses stdout to output non-error messages, and uses stderr to output +error or warning messages. + +4. Exit status: +--------------- + +pgxc_clean uses different exit codes for each type of error. + + 0: cleanup has been finished successfully + 4: wrong arguement was specified in command line + 6: pgxc_clean tried to connect to all running coordinators, but none of + them accepts connection request + 8: some kind of problem has occurred on GTM component + 9: some kind of problem has occurred on xcm component + 10: some kind of problem has occurred on coordinator component + 11: some kind of problem has occurred on datanode component + 12: pgxc_clean found transaction which has invalid status, such as + committed on a node but aborted on another node + 16: pgxc_clean encountered internal error, mostly out-of-memory + diff --git a/src/pgxc/pgxc_clean/common.c b/src/pgxc/pgxc_clean/common.c new file mode 100644 index 0000000..3f01f67 --- /dev/null +++ b/src/pgxc/pgxc_clean/common.c @@ -0,0 +1,81 @@ +/*------------------------------------------------------------------------- + * + * common.c + * common functions for pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "pgxc_clean.h" + +extern const char *progname; + +/* + * output messages to console + * to stderr: warning and error message + * to stdout: others + */ +void +dispmsg(errlevel el, const char *format, ...) +{ + va_list vl; + time_t t; + struct tm *now; + const char *lvlstr[] = {"[?] ", "[I] ", "[W] ", "[E] ", "[D] "}; + + /* ignore debug messages in non-debug build */ +#ifndef DEBUG + if (el == lvl_debug) + return; +#endif + + time(&t); + now = localtime(&t); + + + if (el == lvl_warn || el == lvl_error) + fprintf(stderr, "[%s] %04d/%02d/%02d %02d:%02d:%02d ", + progname, now->tm_year+1900, now->tm_mon+1, now->tm_mday, + now->tm_hour, now->tm_min, now->tm_sec); + else + fprintf(stdout, "[%s] %04d/%02d/%02d %02d:%02d:%02d ", + progname, now->tm_year+1900, now->tm_mon+1, now->tm_mday, + now->tm_hour, now->tm_min, now->tm_sec); + + switch (el) + { + case lvl_info: + fprintf(stdout, lvlstr[el]); + break; + case lvl_warn: + case lvl_error: + fprintf(stderr, lvlstr[el]); + break; + case lvl_debug: + fprintf(stdout, lvlstr[el]); + break; + default: + fprintf(stdout, lvlstr[0]); + break; + } + + va_start(vl, format); + if (el == lvl_warn || el == lvl_error) + vfprintf(stderr, format, vl); + else + vfprintf(stdout, format, vl); + va_end(vl); + + if (el == lvl_warn || el == lvl_error) + fprintf(stderr, "\n"); + else + { + fprintf(stdout, "\n"); + fflush(stdout); + } +} diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/gtm.c new file mode 100644 index 0000000..e188ba2 --- /dev/null +++ b/src/pgxc/pgxc_clean/gtm.c @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------- + * + * gtm.c + * GTM accessing functions + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/xact.h" +#include "gtm/gtm_client.h" +#include "gtm/libpq-int.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" + +static GTM_Conn *conn_gtm; /* connection to the GTM */ + +/* + * connect2gtm + * connect to GTM, not GTM-proxy + */ +void +connect2gtm(void) +{ + int nRet; + xcm_connPoint *conn_pts; + int n_connections; + char connstr[256]; + + /* XXX should use gtm_proxy? */ + nRet = get_xcm_gtm_connPoints(1, &conn_pts, &n_connections); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get connection point for GTM"); + exit(RESULT_ERR_XCM); + } + + /* build connection string, we don't check overflow */ + snprintf(connstr, sizeof(connstr), + "host=%s port=%d pgxc_node_id=%d remote_type=%d", + conn_pts->addr, conn_pts->port, 0, PGXC_NODE_COORDINATOR); + dispmsg(lvl_debug, "connstr for GTM is \"%s\"", connstr); + free_xcm_connPoints(conn_pts, n_connections); + + /* connect to GTM */ + conn_gtm = connect_gtm(connstr); + if (GTMPQstatus(conn_gtm) != CONNECTION_OK) + { + dispmsg(lvl_error, "couldn't connect to GTM: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_GTM); + } + + dispmsg(lvl_debug, "connected to GTM"); +} + +/* + * disconnect2gtm + * disconnect from GTM + */ +void +disconnect2gtm(void) +{ + disconnect_gtm(conn_gtm); +} + +/* + * remove_gxid_from_snapshot + * remove gid of transaction which has been cleaned-up from GTM's snapshot + */ +void +remove_gxid_from_snapshot(GlobalTransactionId gxid, bool iscommit) +{ + dispmsg(lvl_debug, "BEGIN: remove_gxid_from_snapshot(gid=%d, %s)", + gxid, iscommit ? "commit" : "rollback"); + + if (GTMPQstatus(conn_gtm) != CONNECTION_OK) + { + dispmsg(lvl_error, "invalid connection for GTM: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_INTERNAL); + } + + /* do cleanup */ + if (commit_transaction(conn_gtm, gxid) != 0) + { + dispmsg(lvl_error, "couldn't remove GXID from snapshot: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_GTM); + } + dispmsg(lvl_debug, "gxid=%u removed from snapshot", gxid); +} + +/* + * dump_snapshot + * dump current snapshot in the GTM node + */ +#ifdef DEBUG +void +dump_snapshot(void) +{ + GTM_SnapshotData *snapshot; + GlobalTransactionId gxid; + uint32 snidx; + + dispmsg(lvl_debug, "== %s() ======================", __FUNCTION__); + + gxid = begin_transaction(conn_gtm, GTM_ISOLATION_RC, NULL); + if (gxid == InvalidGlobalTransactionId) + { + dispmsg(lvl_error, "BEGIN transaction failed: %s", + GTMPQerrorMessage(conn_gtm)); + return; + } + else + dispmsg(lvl_debug, "Started a new transaction (GXID:%u)", gxid); + + snapshot = get_snapshot(conn_gtm, gxid, true); + if (snapshot == NULL) + dispmsg(lvl_error, "couldn't get snapshot: %s", + GTMPQerrorMessage(conn_gtm)); + else + for (snidx = 0; snidx < snapshot->sn_xcnt; snidx++) + dispmsg(lvl_debug, "sn_xip[%u]=%d", snidx, snapshot->sn_xip[snidx]); + + if (commit_transaction(conn_gtm, gxid)) + dispmsg(lvl_debug, "COMMIT failed (GXID:%u): %s", gxid, + GTMPQerrorMessage(conn_gtm)); + + dispmsg(lvl_debug, "== %s() ======================", __FUNCTION__); +} +#endif diff --git a/src/pgxc/pgxc_clean/pgxc_clean.c b/src/pgxc/pgxc_clean/pgxc_clean.c new file mode 100644 index 0000000..e81230d --- /dev/null +++ b/src/pgxc/pgxc_clean/pgxc_clean.c @@ -0,0 +1,337 @@ +/*------------------------------------------------------------------------- + * + * pgxc_clean.c + * pgxc_clean is a recovery tool for the coordinator crash. + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "getopt_long.h" + +#include "pgxc_clean.h" +#include "txnctl.h" + +extern char *optarg; +extern int optind, + opterr; + +/* Global */ +const char *progname; + +/* number of nodes */ +int all_coordinator_cnt; /* # of coordinators in the cluster */ +int all_datanode_cnt; /* # of datanodes in the cluster */ +int all_mirror_cnt; /* # of datanode mirrors in the cluster */ + +/* status of each node */ +unsigned *coordsts; /* status of each coordinator */ +MirrorStatus *mirrorsts; /* status of each datanode mirrors */ + +/* result summary */ +uint32 committed; /* number of committed txns */ +uint32 aborted; /* number of aborted txns */ +uint32 didnothing; /* number of do-nothing txns */ + +/* for mirror_mode */ +bool is_mirror_mode_on; /* true means mirror_mode=on */ + +/* static functions */ +static void checkarg(int argc, + char *argv[], + PGXC_NodeId *org_coordid, + char **host, + char **port); +static void help(const char *progname); + +/*------------------------------------------------------------------------- + * pgxc_clean + * + * option parameters: + * --all:recovery all coordinators + * --node:recovery coordinator number + * --username:USERNAME for connect to coordinator + * --password:PASSWORD for connect to coordinator + * + * exit code: + * 0: cleanup has been finished successfully + * 4: wrong arguement was specified in command line + * 6: pgxc_clean tried to connect to all running coordinators, but none + * of them accepts connection request + * 8: some kind of problem has occurred on GTM component + * 9: some kind of problem has occurred on xcm component + * 10: some kind of problem has occurred on coordinator component + * 11: some kind of problem has occurred on datanode component + * 12: pgxc_clean found transaction which has invalid status, such as + * committed on a node but aborted on another node + * 16: pgxc_clean encountered internal error, mostly out-of-memory + * + * notes + * - assume that node configuration is never changed + * -> If a node is added after invoking pgxc_clean, it will be ignored. + * -> If a node fails after invoking pgxc_clean, the failure will be + * detected by pgxc_clean and reported through exit code and log. + * - don't care lock about shared memory for xcm module, just use via API + *------------------------------------------------------------------------- + */ +int +main(int argc, char *argv[]) +{ + char *user = NULL; /* given username */ + char *passwd = NULL; /* given password */ + PGXC_NodeId org_coordid; /* given org coordid, 0 means all */ + PGXC_NodeId coordid; /* temporary coordid */ + + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgxc_clean")); + + /* initialize global variables */ + progname = get_progname(argv[0]); + all_coordinator_cnt = 0; + all_datanode_cnt = 0; + committed = 0; + aborted = 0; + didnothing = 0; + is_mirror_mode_on = false; + + /* check arguments */ + checkarg(argc, argv, &org_coordid, &user, &passwd); + dispmsg(lvl_debug, "%s start object coord=%u user=%s passwd=%s", + progname, org_coordid, user, passwd); + + /* get number of nodes, and status of each node */ + get_cluster_status(); + + /* originator node id must not exceed all_coordinator_cnt */ + if (org_coordid > all_coordinator_cnt) + { + fprintf(stderr, _("%s: NODE_NUMBER %u is out of range\n"), progname, + org_coordid); + exit(RESULT_ERR_ARGV); + } + + /* connect to a coordinator to execute queries */ + connect2coord(user, passwd); + + /* get mirror_mode in this cluster */ + get_mirror_mode(); + + /* connect to GTM */ + connect2gtm(); + + /* dump current snapshot for debug use */ + dump_snapshot(); + + /* + * Get list of 2PC-transactions which were originated on each coordinator, + * and clean them up. + */ + for (coordid = 1; coordid <= all_coordinator_cnt; coordid++) + { + int curr_txidx; /* current txn's index */ + + dispmsg(lvl_debug, "######## doing for originator %u.", coordid); + + /* Skip if originator was specified and this is not it. */ + if (org_coordid != 0 && org_coordid != coordid) + continue; + + /* initialize txinfo area */ + clear_txinfo(); + + /* Get list of transactions which were originated on the coordinator. */ + get_prepared_transactions(coordid); + + for (curr_txidx = 0; curr_txidx < txcnt; curr_txidx++) + { + int result; + + /* Get status of the transaction on each related node. */ + get_committed_transactions(curr_txidx); + + /* Cleanup the transaction */ + result = do_cleanup(curr_txidx); + switch (result) + { + case CLEANUP_COMMIT: + committed++; + break; + case CLEANUP_ROLLBACK: + aborted++; + break; + case CLEANUP_NOTHING: + didnothing++; + break; + case CLEANUP_SKIP: + /* We never reach here */ + break; + default: + break; + } + + } + } + + /* dump current snapshot for debug use */ + dump_snapshot(); + + /* Disconnect from coordinator */ + disconnect2coord(); + + /* Disconnect from GTM */ + disconnect2gtm(); + + /* Print summary of cleanup results. */ + dispmsg(lvl_info, + "cleanup finished: committed=%d aborted=%d did-nothing=%d", + committed, aborted, didnothing); + + exit(RESULT_SUCCESS); +} + + +/*------------------------------------------------------------------------- + * checkarg + * parse command line arguments and return settings through parameters. + * + * returns: + * N/A + *------------------------------------------------------------------------- + */ +static void +checkarg( + int argc, + char *argv[], + PGXC_NodeId *org_coordid, + char **user, + char **passwd) +{ + int c; + int optindex; + bool all_coordinators = false; /* --all/-a was specified */ + bool node_number = false; /* --node/-n was specified */ + static struct option long_options[] = { + {"all", no_argument, NULL, 'a'}, + {"node", required_argument, NULL, 'n'}, + {"username", required_argument, NULL, 'U'}, + {"password", required_argument, NULL, 'W'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + while ((c = getopt_long(argc, argv, "an:U:W:V?", + long_options, &optindex)) != -1) + { + switch (c) + { + case 'a': + all_coordinators = true; + break; + case 'n': + /* check option parameters */ + /* -n NODE_NUMBER */ + /* NODE_NUMBER needs greater than 1 */ + node_number = true; + if (atoi(optarg) <= 0) + { + fprintf(stderr, _("%s: NODE_NUMBER needs greater than 0.\n"), + progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + *org_coordid = atoi(optarg); + break; + case 'U': + *user = optarg; + break; + case 'W': + *passwd = optarg; + break; + case 'V': + puts("pgxc_clean (PostgreSQL) " PG_VERSION); + exit(RESULT_SUCCESS); + break; + case '?': + if (strcmp(argv[optind - 1], "-?") == 0 || + strcmp(argv[optind - 1], "--help") == 0) + { + help(progname); + exit(RESULT_SUCCESS); + } + else + { + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(RESULT_ERR_ARGV); + } + break; + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(RESULT_ERR_ARGV); + break; + } + } + + /* receive user and password for libpq connection */ + if (argc > optind) + *user = strdup(argv[optind]); + if (argc > optind + 1) + *passwd = strdup(argv[optind + 1]); + if (argc > optind + 2) + { + fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), + progname, argv[optind + 2]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + + /* --all and --node are exclusive */ + if (all_coordinators && node_number) + { + fprintf(stderr, _("%s: --all and --node can't be specified together.\n"), + progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + + /* + * We treat all transactions which were originated by all coordinators if + * --all is specified, or neither of --all nor --node was specified. + */ + if (all_coordinators || !node_number) + *org_coordid = 0; + + return; + +} + +/*------------------------------------------------------------------------- + * show help messages + *------------------------------------------------------------------------- + */ +static void +help(const char *progname) +{ + printf(_("%s is a utility to clean up 2PC-transactions.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]\n"), progname); + + printf(_("\nGeneral options:\n")); + printf(_(" -?, --help show this help, then exit\n")); + printf(_(" -V, --version output version information, then exit\n")); + + printf(_("\nOptions for originator:\n")); + printf(_(" -a, --all Clean up all transactions\n")); + printf(_(" -n, --node=NODE_NUMBER Clean up transactions originated on the Coordinator\n")); + + printf(_("\nConnection options:\n")); + printf(_(" -U, --username=USERNAME username used to connect to coordinator\n")); + printf(_(" -W, --password=PASSWORD password used to connect to coordinator\n")); + +} diff --git a/src/pgxc/pgxc_clean/pgxc_clean.h b/src/pgxc/pgxc_clean/pgxc_clean.h new file mode 100644 index 0000000..ae39eed --- /dev/null +++ b/src/pgxc/pgxc_clean/pgxc_clean.h @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------- + * + * pgxc_clean.h + * header file for the pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#ifndef PGXC_CLEAN_H +#define PGXC_CLEAN_H + +#include "gtm/gtm_c.h" + +/* define program exit code */ +#define RESULT_SUCCESS 0 /* normal terminate */ +#define RESULT_ERR_ARGV 4 /* illegal format on option parameters */ +#define RESULT_ERR_CONN2COORD 6 /* couldn't connect to any coordinator */ +#define RESULT_ERR_GTM 8 /* failed to cooperate with GTM */ +#define RESULT_ERR_XCM 9 /* failed to cooperate with xcm */ +#define RESULT_ERR_COORD 10 /* failed to cooperate with coordinator */ +#define RESULT_ERR_DNODE 11 /* failed to cooperate with datanode */ +#define RESULT_ERR_TX_STATUS 12 /* transaction in invalid status found */ +#define RESULT_ERR_INTERNAL 16 /* pgxc_clean internal failure */ + +/* results of cleanup */ +#define CLEANUP_COMMIT 0 +#define CLEANUP_ROLLBACK 1 +#define CLEANUP_SKIP 2 +#define CLEANUP_NOTHING 3 + +/* define error level */ +typedef enum { + lvl_none = 0, + lvl_info, + lvl_warn, + lvl_error, + lvl_debug +} errlevel; + +/* + * Status of a datanode's mirror. + */ +typedef struct MirrorStatus { + PGXC_NodeId datanode_id; /* datanode id */ + int mirror_id; /* mirror id in the datanode */ + unsigned status; /* status of the mirror */ +} MirrorStatus; + +/* + * Status of each node. + * + * coordsts is allocated for all coordinators even if some of them failed. + * mirrorsts is allocated for all datanode mirrors even if some of them failed. + */ +extern unsigned *coordsts; +extern MirrorStatus *mirrorsts; + +/* prototypes */ +/* common.c */ +extern void dispmsg(errlevel el, const char *format, ...); + +/* subfunc.c */ +extern void get_mirror_mode(void); +extern void get_cluster_status(void); +extern void connect2coord(const char *user, const char *passwd); +extern void disconnect2coord(void); +extern void get_prepared_transactions(PGXC_NodeId org_coordid); +extern void get_committed_transactions(int txidx); +extern int do_cleanup(int txidx); +extern void clear_txinfo(void); + +/* gtm.c */ +void connect2gtm(void); +void remove_gxid_from_snapshot(GlobalTransactionId gxid, bool iscommit); +void disconnect2gtm(void); +#ifdef DEBUG +void dump_snapshot(void); +#else +#define dump_snapshot() +#endif + +#endif /* PGXC_CLEAN_H */ diff --git a/src/pgxc/pgxc_clean/subfunc.c b/src/pgxc/pgxc_clean/subfunc.c new file mode 100644 index 0000000..a194e04 --- /dev/null +++ b/src/pgxc/pgxc_clean/subfunc.c @@ -0,0 +1,986 @@ +/*------------------------------------------------------------------------- + * + * subfunc.c + * sub functions for pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "gtm/gtm.h" +#include "gtm/gtm_txn.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" +#include "txnctl.h" +#include "libpq-fe.h" + +/* + * SQL statement formats + */ + +/* SQL format for connected coordinator */ +#define SQLFMT_GETPREPAREDXACT "select * from pg_prepared_xact() where coordnum=%d;" +#define SQLFMT_ISCOMMITTED "select pgxc_is_committed('%u');" +#define SQLFMT_COMMIT "commit prepared '%s';" +#define SQLFMT_ROLLBACK "rollback prepared '%s';" + +/* EXECUTE DIRECT SQL format for un-connected coordinators */ +#define SQLFMT_EDC_GETPREPAREDXACT "EXECUTE DIRECT ON COORDINATOR %d 'select * from pg_prepared_xact() where coordnum=%d';" +#define SQLFMT_EDC_ISCOMMITTED "EXECUTE DIRECT ON COORDINATOR %d 'select pgxc_is_committed(''%u'')';" +#define SQLFMT_EDC_COMMIT "EXECUTE DIRECT ON COORDINATOR %d 'commit prepared ''%s''';" +#define SQLFMT_EDC_ROLLBACK "EXECUTE DIRECT ON COORDINATOR %d 'rollback prepared ''%s''';" + +/* EXECUTE DIRECT SQL format for datanodes */ +#define SQLFMT_EDD_GETPREPAREDXACT "EXECUTE DIRECT ON NODE %s 'select * from pg_prepared_xact() where coordnum=%d';" +#define SQLFMT_EDD_ISCOMMITTED "EXECUTE DIRECT ON NODE %s 'select pgxc_is_committed(''%u'')';" +#define SQLFMT_EDD_COMMIT "EXECUTE DIRECT ON NODE %s 'commit prepared ''%s''';" +#define SQLFMT_EDD_ROLLBACK "EXECUTE DIRECT ON NODE %s 'rollback prepared ''%s''';" + +/* Get mirror_mode from connected coordinator */ +#define SQLFMT_SHOWMIRRORMODE "show mirror_mode;" + +/* + * EXECUTE DIRECT can't invoked COMMIT/ABORT PREPARED on the coordinator + * which pgxc_clean connected directly. So we have to use two connections, + * one is established without "remotetype" option for EXECUTE DIRECT on nodes + * other than connected coordinator, and another is established with + * "remotetype=coordinator" option for invoke transaction management commands + * on the connected coordinator. + */ +PGXC_NodeId con_coordid; /* id of connected coordinator */ +PGconn *conn_coord; /* connection for the coordinator */ +PGconn *conn_other; /* connection for other nodes */ + +extern bool is_mirror_mode_on; /* true means mirror_mode=on */ + +extern int all_coordinator_cnt; /* number of coords in cluster */ +extern int all_datanode_cnt; /* number of dnodes in cluster */ +extern int all_mirror_cnt; /* number of datanode mirrors in cluster */ + +/* static functions */ +static void get_nodests(void); +static bool contains_tx_sts(prepared_txninfo *txinfo, NODE_STS sts); +static void cleanup_txn(prepared_txninfo *txinfo, bool iscommit); + +/* + * get_mirror_mode + * get cluster's mirror_mode. + */ +void +get_mirror_mode(void) +{ + PGresult *res; + dispmsg(lvl_debug, "BEGIN: %s()", __FUNCTION__); + + /* + * Execute query to get mirror_mode. + */ + res = PQexec(conn_coord, SQLFMT_SHOWMIRRORMODE); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn_coord); + dispmsg(lvl_error, + "couldn't get mirror_mode: %s", emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + is_mirror_mode_on = (strcmp(PQgetvalue(res, 0, 0), "on") == 0); + PQclear(res); + + dispmsg(lvl_debug, "mirror_mode=%s", is_mirror_mode_on ? "on" : "off"); +} + +/* + * get_cluster_status + * get cluster configuration and status of each node in the cluster. + */ +void +get_cluster_status(void) +{ + int nRet; + + dispmsg(lvl_debug, "BEGIN: get_cluster_status()"); + + /* get number of coordinators from xcm */ + nRet = get_xcm_coordinator_count(&all_coordinator_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get number of coordinators in the cluster.(%d)", nRet); + exit(RESULT_ERR_XCM); + } + dispmsg(lvl_debug, "number of coordinators is %d", all_coordinator_cnt); + + /* get number of datanodes from xcm */ + nRet = get_xcm_datanode_count(&all_datanode_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get number of datanodes in the cluster.(%d)", nRet); + exit(RESULT_ERR_XCM); + } + dispmsg(lvl_debug, "number of datanodes is %d", all_datanode_cnt); + + /* get running status of all coordinators and datanodes */ + get_nodests(); +} + + +/*------------------------------------------------------------------------- + * connect2coord + * connect to a running coordinator in the cluster which has minimum id. + * + * returns: + * node id of connected coordinator, or 0 if all coordinator have failed. + *------------------------------------------------------------------------- + */ +void +connect2coord(const char *user, const char *passwd) +{ + int nRet; + int nconns = 0; + xcm_connPoint *xcwconn; + char port[10]; + int cdidx; + + dispmsg(lvl_debug, "BEGIN: connect2coord(%s, %s)", user, passwd); + + /* Try all coordinator in order of id */ + for (cdidx = 0; cdidx < all_coordinator_cnt; cdidx++) + { + dispmsg(lvl_debug, + "trying to connect to coordinator %d", + cdidx + 1); + + /* Ignore failed coordinators */ + if (XCM_IS_FAULT(coordsts[cdidx])) + continue; + + /* Get connection information from xcm module. */ + /* XXX: Should we use connection points other than first one? */ + nRet = get_xcm_coordinator_connPoints(cdidx + 1, &nconns, &xcwconn); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get connection point for coordinator %u", + cdidx + 1); + exit(RESULT_ERR_XCM); + } + + /* Convert port number to string */ + snprintf(port, sizeof(port), "%d", xcwconn->port); + + /* + * Connect to coordinator with remotetype option. This connection is + * used to execute ordinary query statements on the connected + * coordinator directly. + */ + conn_coord = PQsetdbLogin(xcwconn->addr, + port, + "-c remotetype=coordinator", + NULL, + "template1", + user, + passwd); + if (!conn_coord || PQstatus(conn_coord) != CONNECTION_OK) + { + dispmsg(lvl_warn, + "couldn't connect to coordinator %u with remotetype: %s", + cdidx + 1, + PQerrorMessage(conn_coord)); + PQfinish(conn_coord); + free_xcm_connPoints(xcwconn, nconns); + continue; + } + + /* + * Connect to coordinator with remotetype option. This connection is + * used to execute EXECUTE DIRECT statements on the node other than + * connected coordinator. + */ + conn_other = PQsetdbLogin(xcwconn->addr, + port, + NULL, + NULL, + "template1", + user, + passwd); + if (!conn_other || PQstatus(conn_other) != CONNECTION_OK) + { + dispmsg(lvl_warn, + "couldn't connect to coordinator %u without remotetype: %s", + cdidx + 1, + PQerrorMessage(conn_other)); + PQfinish(conn_coord); + PQfinish(conn_other); + free_xcm_connPoints(xcwconn, nconns); + continue; + } + + free_xcm_connPoints(xcwconn, nconns); + + /* Now we have two connections against a coordinator for cleanup. */ + con_coordid = cdidx + 1; + dispmsg(lvl_debug, "connected to coordinator %u", con_coordid); + + return; + } + + /* failed to establish connections against coordinator */ + dispmsg(lvl_error, "there is no running coordinator"); + exit(RESULT_ERR_CONN2COORD); +} + +void +disconnect2coord(void) +{ + PQfinish(conn_coord); + PQfinish(conn_other); +} + +/*------------------------------------------------------------------------- + * get_prepared_transactions + * Get list of 2PC-transactions which is prepared on any node. + *------------------------------------------------------------------------- + */ +void +get_prepared_transactions(PGXC_NodeId org_coordid) +{ + int nodeloop, txidx; + + dispmsg(lvl_debug, + "BEGIN: get_prepared_transactions(org_coordid=%u)", + org_coordid); + + /* + * Get list of prepared transactions from each coordinator with + * invoking pg_prepared_xact() and merge them into one list. + */ + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeloop + 1); + PGresult *res; + char sql[512]; + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeloop])) + continue; + + /* Construct query for pg_prepared_xact(). */ + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_GETPREPAREDXACT, org_coordid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_GETPREPAREDXACT, nodeid, + org_coordid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* + * Execute query to get list of transactions which have been prepared + * on the node. + */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pg_prepared_xact() failed on coordinator %u for originator %u :%s", + nodeid, org_coordid, emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + /* store transaction status into the list */ + for (txidx = 0; txidx < PQntuples(res); txidx++) + { + TransactionId transaction; + bool isddl; + bool isimplicit; + + transaction = (TransactionId) atoi(PQgetvalue(res, txidx, 0)); + isddl = (strcmp(PQgetvalue(res, txidx, 5), "t") == 0); + isimplicit = (strcmp(PQgetvalue(res, txidx, 6), "t") == 0); + + set_txinfo( + org_coordid, /* originator coordinator id */ + true, /* True if source was coordinator */ + nodeid, /* nodeid */ + 0, /* mirror_id, 0 if iscoord */ + transaction, /* transaction */ + PQgetvalue(res, txidx, 1), /* gid */ + isddl, /* is_ddl */ + isimplicit, /* is_implicit */ + PQgetvalue(res, txidx, 8)); /* nodelist */ + + } + + PQclear(res); + } + + /* + * Get list of prepared transactions from each datanode with + * invoking pg_prepared_xact() and merge them into one list. + */ + for (nodeloop = 0; nodeloop < all_mirror_cnt; nodeloop++) + { + PGXC_NodeId nodeid = mirrorsts[nodeloop].datanode_id; + int mirror_id = mirrorsts[nodeloop].mirror_id; + PGresult *res; + char sql[512]; + char dnodestr[64]; + PGconn *conn = conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeloop].status)) + continue; + + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT query for pg_prepared_xact(). */ + snprintf(sql, sizeof(sql), SQLFMT_EDD_GETPREPAREDXACT, + dnodestr, org_coordid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get list of prepared transactions. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pg_prepared_xact() failed on datanode %s for originator %u :%s", + dnodestr, org_coordid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + /* store transaction status into the list */ + for (txidx = 0; txidx < PQntuples(res); txidx++) + { + TransactionId transaction; + bool isddl; + bool isimplicit; + + transaction = (TransactionId) atoi(PQgetvalue(res, txidx, 0)); + isddl = (strcmp(PQgetvalue(res, txidx, 5), "t") == 0); + isimplicit = (strcmp(PQgetvalue(res, txidx, 6), "t") == 0); + + set_txinfo( + org_coordid, /* originator coordinator id */ + false, /* true if source was coordinator */ + nodeid, /* nodeid */ + mirror_id, /* mirror_id, 0 if iscoord */ + transaction, /* transaction */ + PQgetvalue(res, txidx, 1), /* gid */ + isddl, /* is_ddl */ + isimplicit, /* is_implicit */ + PQgetvalue(res, txidx, 8)); /* nodelist */ + + } + + PQclear(res); + + } + + /* for debug use */ +#ifdef DEBUG + for(txidx = 0; txidx < txcnt; txidx++) + dump_txinfo(txidx); +#endif + + return; +} + +/*------------------------------------------------------------------------- + * get_committed_transactions + * update status of a transaction on a node to COMMITTED or ABORTED + * whose status has not been clarified. + *------------------------------------------------------------------------- + */ +void +get_committed_transactions(int txidx) +{ + int nodeidx; + prepared_txninfo *txinfo = NULL; + + dispmsg(lvl_debug, "BEGIN: get_committed_transactions(%d)", txidx); + + /* get prepared_txninfo */ + txinfo = get_prepared_txninfo(txidx); + if (!txinfo) + { + dispmsg(lvl_error, "couldn't get prepared transaction info."); + exit(RESULT_ERR_INTERNAL); + } + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeidx + 1); + PGresult *res; + char sql[1024]; + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeidx])) + continue; + + /* Ignore node whose status has been already known */ + if (txinfo->tx_sts_c[nodeidx] != STS_RELATED) + continue; + + /* Determine which connection should be used. */ + if (nodeid == con_coordid) + conn = conn_coord; + else + conn = conn_other; + + /* Construct EXECUTE DIRECT query for pgxc_is_committed(). */ + if (nodeid == con_coordid) + snprintf(sql, sizeof(sql), SQLFMT_ISCOMMITTED, txinfo->txid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_ISCOMMITTED, + nodeid, txinfo->txid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get is committed transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pgxc_is_committed() failed on coordinator %u for transaction %s: %s", + nodeid, txinfo->gid, emsg); + + PQclear(res); + exit(RESULT_ERR_COORD); + } + + /* update status */ + if (strcmp(PQgetvalue(res, 0, 0), "t") == 0) + set_tx_sts(txinfo, true, nodeid, 0, STS_COMMITTED); + else + set_tx_sts(txinfo, true, nodeid, 0, STS_ABORTED); + + PQclear(res); + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + PGXC_NodeId nodeid = mirrorsts[nodeidx].datanode_id; + int mirror_id = mirrorsts[nodeidx].mirror_id; + PGresult *res; + char sql[512]; + char dnodestr[64]; + PGconn *conn = conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeidx].status)) + continue; + + if (txinfo->tx_sts_m[nodeidx] == STS_RELATED) + { + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT query for pgxc_is_committed(). */ + snprintf(sql, sizeof(sql), SQLFMT_EDD_ISCOMMITTED, dnodestr, txinfo->txid); + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get is committed transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pgxc_is_committed() failed on datanode %s for transaction %s: %s", + dnodestr, txinfo->gid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + /* update status */ + if (strcmp(PQgetvalue(res, 0, 0), "t") == 0) + set_tx_sts(txinfo, false, nodeid, mirror_id, STS_COMMITTED); + else + set_tx_sts(txinfo, false, nodeid, mirror_id, STS_ABORTED); + + PQclear(res); + } + } + + /* for debug use, removed on release build */ + dump_txinfo(txidx); +} + +/*------------------------------------------------------------------------- + * do_cleanup + * cleanup prepared transactions on each node along the status of the + * global transaction + *------------------------------------------------------------------------- + */ +int +do_cleanup(int txidx) +{ + prepared_txninfo *txinfo = NULL; + bool is_related, is_committed, is_aborted; + + dispmsg(lvl_debug, "BEGIN: do_cleanup(%d)", txidx); + + /* get prepared_txninfo */ + txinfo = get_prepared_txninfo(txidx); + if (!txinfo) + { + dispmsg(lvl_error, "couldn't get prepared transaction info."); + exit(RESULT_ERR_INTERNAL); + } + + /* get txn-status on each node */ + is_related = contains_tx_sts(txinfo, STS_RELATED); + is_committed = contains_tx_sts(txinfo, STS_COMMITTED); + is_aborted = contains_tx_sts(txinfo, STS_ABORTED); + + /* + * 1. RELATED node is contained(in-Prepare) + * + * 1-1. COMMITTED node is contained ==> illegal txn-condition + * 1-2. ABORTED node is contained ==> illegal txn-condition + * 1-3. otherwise ==> need rollback on prepared-node + */ + if (is_related) + { + /* + * If there are COMMITTED-node or ABORTED-node (or both), the transaction + * condition is wrong. + * Because transaction is not complete prepare-transaction. + */ + if(is_committed || is_aborted) + { + dispmsg(lvl_error, + "transaction(%d:%s) is bad condition. coord[%.*s] dnode[%.*s]", + txinfo->txid, txinfo->gid, all_coordinator_cnt, txinfo->tx_sts_c, + all_mirror_cnt, txinfo->tx_sts_m); + + exit(RESULT_ERR_TX_STATUS); + } + + /* + * The transaction is 'in-Prepare' condition. + * In this case, need to rollback transaction on PREPARED-node. + * XXX: We should do nothing if all node was prepared, shouldn't we? + */ + cleanup_txn(txinfo, false); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, false); + + return CLEANUP_ROLLBACK; + } + + /* + * A transaction which has critical contradiction was found, give + * up whole job. + */ + if (is_committed && is_aborted) + { + dispmsg(lvl_error, + "transaction(%d:%s) is bad condition. coord[%.*s] dnode[%.*s]", + txinfo->txid, txinfo->gid, all_coordinator_cnt, txinfo->tx_sts_c, + all_mirror_cnt, txinfo->tx_sts_m); + + exit(RESULT_ERR_TX_STATUS); + } + + /* + * 3. COMMITTED nodes only + * ==> need commit + */ + if (is_committed) + { + cleanup_txn(txinfo, true); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, true); + + return CLEANUP_COMMIT; + } + + /* + * 4. ABORTED nodes only + * ==> need rollback + */ + if (is_aborted) + { + cleanup_txn(txinfo, false); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, false); + + return CLEANUP_ROLLBACK; + } + + /* + * 5. PREPARED nodes only + * + * 5-1. implicit2PC transaction ==> need commit + * 5-2. explicit2PC transaction ==> do nothing + */ + if (!txinfo->isimplicit) + { + dispmsg(lvl_info, "do nothing."); + return CLEANUP_NOTHING; + } + + /* + * If no commit or abort are execurted, commit in all the involved + * nodes because it is obvious that the transaction was intended to + * be committed. + */ + cleanup_txn(txinfo, true); + + return CLEANUP_COMMIT; +} + +/*------------------------------------------------------------------------ + * clear_txinfo + * clear list of transaction and initialize it + *------------------------------------------------------------------------ + */ +void +clear_txinfo(void) +{ + dispmsg(lvl_debug, "BEGIN: clear_txinfo()"); + init_txinfo(); +} + +/*------------------------------------------------------------------------ + * static functions + *------------------------------------------------------------------------ + */ +/*------------------------------------------------------------------------ + * get_nodests + * get status of all nodes in the cluster + * + * Note: all_coordinator_cnt and all_datanode_cnt MUST be set before + * calling this function. + *------------------------------------------------------------------------ + */ +static void +get_nodests(void) +{ + int nodeloop; + int nRet; + MirrorStatus *mirror; + int failed_cnt; + + dispmsg(lvl_debug, "BEGIN: get_nodests()"); + + /* coordinators */ + /* malloc for sts area */ + coordsts = (unsigned *) malloc(sizeof(unsigned) * all_coordinator_cnt); + if (!coordsts) + { + dispmsg(lvl_error, "couldn't allocate memory for coordsts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + + /* get status of each coordinator from xcm */ + failed_cnt = 0; + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + nRet = get_xcm_coordinator_status(nodeloop + 1, &coordsts[nodeloop]); + if (nRet != XCM_OK && nRet != XCM_ERR_COMP_FAILED) + { + dispmsg(lvl_error, "couldn't get status of coord(%d).(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + failed_cnt += (nRet != XCM_OK); + dispmsg(lvl_debug, "status of coordinator %d is %d", nodeloop + 1, + coordsts[nodeloop]); + } + + /* + * If over half of coordinators have failed, it can be said that the whole + * cluster has failed, so we might give up to cleanup. + * Discussed on Feb 8, 2011. + */ + if (failed_cnt > all_coordinator_cnt / 2) + { + dispmsg(lvl_error, "too many coordinators failed (%d/%d)", + failed_cnt, all_coordinator_cnt); + exit(RESULT_ERR_COORD); + } + + /* count all datanode mirrors */ + all_mirror_cnt = 0; + for (nodeloop = 0; nodeloop < all_datanode_cnt; nodeloop++) + { + int mirror_cnt; + + nRet = get_xcm_mirror_count(nodeloop + 1, &mirror_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get mirror count of datanode %d.(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + + all_mirror_cnt += mirror_cnt; + } + + /* allocate array of MirrorStatus for all of datanode mirrors */ + mirrorsts = (MirrorStatus *) malloc(sizeof(MirrorStatus) * all_mirror_cnt); + if (!mirrorsts) + { + dispmsg(lvl_error, "couldn't allocate memory for mirrorsts.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + + /* get status of each datanode mirror from xcm and store into mirrorsts */ + failed_cnt = 0; + mirror = mirrorsts; + for (nodeloop = 0; nodeloop < all_datanode_cnt; nodeloop++) + { + int mirrorcnt; + int mirrorloop; + char dnodestr[32]; + + nRet = get_xcm_mirror_count(nodeloop + 1, &mirrorcnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get mirror count of datanode %d.(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + + for (mirrorloop = 0; mirrorloop < mirrorcnt; mirrorloop++) + { + mirror->datanode_id = nodeloop + 1; + mirror->mirror_id = mirrorloop + 1; + + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", mirror->datanode_id, mirror->mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", mirror->datanode_id); + + nRet = get_xcm_mirror_status(mirror->datanode_id, + mirror->mirror_id, + &mirror->status); + if (nRet != XCM_OK && nRet != XCM_ERR_COMP_FAILED) + { + dispmsg(lvl_error, "couldn't get status of datanode %s.(%d)", dnodestr, nRet); + free(coordsts); + free(mirrorsts); + exit(RESULT_ERR_XCM); + } + failed_cnt += (nRet != XCM_OK); + dispmsg(lvl_debug, "status of datanode %s is %d", dnodestr, mirror->status); + + mirror++; + } + } + + /* + * If over half of datanodes have failed, it can be said that the whole + * cluster has failed, so we might give up to cleanup. + * Discussed on Feb 8, 2011. + */ + if (failed_cnt > all_mirror_cnt / 2) + { + dispmsg(lvl_error, "too many datanodes failed (%d/%d)", + failed_cnt, all_mirror_cnt); + exit(RESULT_ERR_DNODE); + } + + return; +} + +/*------------------------------------------------------------------------- + * when transaction contains sts returns true + *------------------------------------------------------------------------- + */ +static bool +contains_tx_sts(prepared_txninfo *txinfo, NODE_STS sts) +{ + int nodeidx; + + if (!txinfo) + return false; + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + if (txinfo->tx_sts_c[nodeidx] == sts) + return true; + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + if (txinfo->tx_sts_m[nodeidx] == sts) + return true; + } + + return false; +} + +/*------------------------------------------------------------------------- + * commit or rollback transaction on prepared node + *------------------------------------------------------------------------- + */ +static void +cleanup_txn(prepared_txninfo *txinfo, bool iscommit) +{ + int nodeidx; + char sql[512]; + PGresult *res; + uint32 coord_committed = 0; /* # of committed coordinators */ + uint32 coord_aborted = 0; /* # of aborted coordinators */ + uint32 dnode_committed = 0; /* # of committed datanodes */ + uint32 dnode_aborted = 0; /* # of aborted datanodes */ + + dispmsg(lvl_debug, "BEGIN: cleanup_txn(txid=%u, %s)", + txinfo ? txinfo->txid : 0, + iscommit ? "commit" : "rollback"); + + /* null pointer */ + if (!txinfo) + exit(RESULT_ERR_INTERNAL); + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeidx + 1); + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeidx])) + continue; + + if (txinfo->tx_sts_c[nodeidx] == STS_PREPARED) + { + /* Construct EXECUTE DIRECT for commit. */ + if (iscommit) + { + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_COMMIT, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_COMMIT, + nodeid, txinfo->gid); + } + else + { + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_ROLLBACK, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_ROLLBACK, + nodeid, txinfo->gid); + } + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute commit or rollback prepared transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "couldn't %s on coordinator %u for cleanup transaction %s: %s", + iscommit ? "COMMIT" : "ABORT", nodeid, txinfo->gid, + emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + if (iscommit) + coord_committed++; + else + coord_aborted++; + + PQclear(res); + } + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + PGXC_NodeId nodeid = mirrorsts[nodeidx].datanode_id; + int mirror_id = mirrorsts[nodeidx].mirror_id; + PGconn *conn = conn_other; + char dnodestr[64]; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeidx].status)) + continue; + + if (txinfo->tx_sts_m[nodeidx] == STS_PREPARED) + { + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT for commit. */ + if (iscommit) + snprintf(sql, sizeof(sql), SQLFMT_EDD_COMMIT, + dnodestr, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDD_ROLLBACK, + dnodestr, txinfo->gid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute commit or rollback prepared transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "couldn't %s on datanode %s for cleanup transaction %s: %s", + iscommit ? "COMMIT" : "ABORT", dnodestr, txinfo->gid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + if (iscommit) + dnode_committed++; + else + dnode_aborted++; + + PQclear(res); + } + } + + if (iscommit) + dispmsg(lvl_info, "txid=%u coordinator=%u datanode=%u", + txinfo->txid, coord_committed, dnode_committed); + else + dispmsg(lvl_info, "txid=%u coordinator=%u datanode=%u", + txinfo->txid, coord_aborted, dnode_aborted); +} diff --git a/src/pgxc/pgxc_clean/txnctl.c b/src/pgxc/pgxc_clean/txnctl.c new file mode 100644 index 0000000..cc34a3c --- /dev/null +++ b/src/pgxc/pgxc_clean/txnctl.c @@ -0,0 +1,495 @@ +/*------------------------------------------------------------------------- + * + * txnctl.c + * control for transaction information + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include <string.h> + +#include "gtm/gtm_c.h" +#include "access/gtm.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" +#include "txnctl.h" + +/* Global variables */ +/* external */ +extern int prepared_txcnt; /* number of prepared transactions */ +extern int all_coordinator_cnt; /* number of coords in cluster */ +extern int all_datanode_cnt; /* number of dnodes in cluster */ +extern int all_mirror_cnt; /* number of mirrors in cluster */ +extern bool is_mirror_mode_on; /* true means mirror_mode=on */ +/* status of each node */ +extern unsigned *coordsts; /* status of each coordinator */ +extern MirrorStatus *mirrorsts; /* status of each datanode mirrors */ + +/* private */ +prepared_txninfo **txinfo; /* transaction information structure */ +int txcnt; /* number of registered transactions */ +int malloccnt; /* number of allocated memory */ + +/* private functions */ +static void set_mirrorsts(const char *nodelist, prepared_txninfo *tx, bool iscoord); +static void add_txinfo_area(void); + +/* + * Create new prepared_txninfo entry with given information. + */ +static prepared_txninfo * +create_prepared_txninfo( + PGXC_NodeId org_coordid, + bool iscoord, + PGXC_NodeId nodeid, + TransactionId txid, + char *gid, + bool isddl, + bool isimplicit, + char *nodelist) +{ + prepared_txninfo *mytx; + NODE_STS *coords = NULL; + NODE_STS *mirrors = NULL; + int nodeloop; + + /* + * New transaction was found, allocate memory for one transaction + * information. + */ + mytx = (prepared_txninfo *) calloc(1, sizeof(prepared_txninfo)); + if (!mytx) + { + dispmsg(lvl_error, + "couldn't allocate memory for transaction information.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + + /* Initialize the entry */ + mytx->org_coordid = org_coordid; + mytx->txid = txid; + mytx->gid = strdup(gid); + if (!mytx->gid) + { + dispmsg(lvl_error, "couldn't allocate memory for gid.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + mytx->isddl = isddl; + mytx->isimplicit = isimplicit; + mytx->nodelist = strdup(nodelist); /* XXX: necessary? */ + if (!mytx->nodelist) + { + dispmsg(lvl_error, "couldn't allocate memory for nodelist.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + mytx->tx_sts_c = NULL; + mytx->tx_sts_m = NULL; + + /* + * Allocate status-array for all coordinators in the cluster, though we + * care coordinators only when a transaction includes DDL. + */ + coords = (NODE_STS *) malloc(sizeof(NODE_STS) * all_coordinator_cnt); + if (!coords) + { + dispmsg(lvl_error, + "couldn't allocate memory for coordnode sts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + if ( XCM_IS_FAULT(coordsts[nodeloop]) ) + coords[nodeloop] = STS_FAILED; + else + coords[nodeloop] = STS_UNKNOWN; + } + mytx->tx_sts_c = coords; + + /* + * Allocate status-array for all datanode mirrors in the cluster. + */ + mirrors = (NODE_STS *) malloc(sizeof(NODE_STS) * all_mirror_cnt); + if (!mirrors) + { + dispmsg(lvl_error, + "couldn't allocate memory for datanode sts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + for (nodeloop = 0; nodeloop < all_mirror_cnt; nodeloop++) + { + if (XCM_IS_FAULT(mirrorsts[nodeloop].status)) + mirrors[nodeloop] = STS_FAILED; + else + mirrors[nodeloop] = STS_UNKNOWN; + } + mytx->tx_sts_m = mirrors; + + return mytx; +} + +/*------------------------------------------------------------------------- + * set_txinfo + * store transaction information gotten from a node into transaction list. + * + * parameters: + * PGXC_NodeId org_coordid:çºè¡å coordid + * bool iscoord: True if the source is a coordinator + * PGXC_NodeId nodeid: id of source node + * TransactionId txid:pg_prepared_xact().transaction + * char *gid:pg_prepared_xact().gid + * bool isddl:pg_prepared_xact().is_ddl + * bool isimplicit:pg_prepared_xact().is_implicit + * char *nodelist:pg_prepared_xact().nodelist + * + * returns: + * N/A + *------------------------------------------------------------------------- + */ +void +set_txinfo( + PGXC_NodeId org_coordid, + bool iscoord, + PGXC_NodeId nodeid, + int mirror_id, + TransactionId txid, + char *gid, + bool isddl, + bool isimplicit, + char *nodelist) + +{ + prepared_txninfo *mytx = NULL; + + dispmsg(lvl_debug, "BEGIN: set_txinfo(%d, %s, %u, %d, %u, %s, %s, %s, %s)", + org_coordid, iscoord ? "TRUE" : "FALSE", nodeid, mirror_id, txid, + gid, isddl ? "TRUE" : "FALSE", isimplicit ? "TRUE" : "FALSE", nodelist); + + /* + * If this transaction has not been stored yet, create new transaction + * entry for it. + */ + mytx = get_tx(txid); + if (mytx == NULL) + { + /* Create entry for newly found transaction */ + mytx = create_prepared_txninfo(org_coordid, iscoord, nodeid, txid, gid, + isddl, isimplicit, nodelist); + + /* Expand transaction slot if necessary */ + if (txcnt == malloccnt) + add_txinfo_area(); + + /* store the transaction into transaction list */ + txinfo[txcnt++] = mytx; + } + + /* All coordinators are related node when isddl was true */ + if (mytx->isddl) + { + int coordidx; + + for (coordidx = 0; coordidx < all_coordinator_cnt; coordidx++) + if (mytx->tx_sts_c[coordidx] == STS_UNKNOWN) + mytx->tx_sts_c[coordidx] = STS_RELATED; + } + + /* set status of related datanode to RELATED */ + set_mirrorsts(nodelist, mytx, iscoord); + + /* + * The status of the transaction on the source node is PREPARED, because + * pg_prepared_xact() entry was found on the node. + */ + set_tx_sts(mytx, iscoord, nodeid, mirror_id, STS_PREPARED); + + return; +} + +/*------------------------------------------------------------------------- + * initialize transaction information + *------------------------------------------------------------------------- + */ +void +init_txinfo(void) +{ + dispmsg(lvl_debug, "BEGIN: init_txinfo()"); + + if (txinfo) + { + int txidx; + + for (txidx = 0; txidx < txcnt; txidx++) + { + free(txinfo[txidx]->gid); + free(txinfo[txidx]->nodelist); + free(txinfo[txidx]->tx_sts_c); + free(txinfo[txidx]->tx_sts_m); + free(txinfo[txidx]); + } + free(txinfo); + txinfo = NULL; + } + malloccnt = 0; + txcnt = 0; +} + +/*------------------------------------------------------------------------- + * dump transaction information + *------------------------------------------------------------------------- + */ +#ifdef DEBUG +void +dump_txinfo(int txidx) +{ + dispmsg(lvl_debug, "BEGIN: dump_txinfo(%d/%d)", txidx + 1, txcnt); + + printf("txinfo[%d]=%p\n", txidx, txinfo[txidx]); + + printf("[%d]org_coordid=%d(%p)\n", + txidx, txinfo[txidx]->org_coordid, &txinfo[txidx]->org_coordid); + printf("[%d]txid=%d(%p)\n", + txidx, txinfo[txidx]->txid, &txinfo[txidx]->txid); + printf("[%d]gid=[%s](%p)\n", + txidx, txinfo[txidx]->gid, txinfo[txidx]->gid); + printf("[%d]isddl=%s(%p)\n", + txidx, txinfo[txidx]->isddl ? "TRUE" : "FALSE", &txinfo[txidx]->isddl); + printf("[%d]isimplicit=%s(%p)\n", + txidx, txinfo[txidx]->isimplicit ? "TRUE" : "FALSE", &txinfo[txidx]->isimplicit); + printf("[%d]nodelist=[%s](%p)\n", + txidx, txinfo[txidx]->nodelist, txinfo[txidx]->nodelist); + printf("[%d]tx_sts_c=[%.*s](%p)\n", + txidx, all_coordinator_cnt, txinfo[txidx]->tx_sts_c, txinfo[txidx]->tx_sts_c); + printf("[%d]tx_sts_m=[%.*s](%p)\n", + txidx, all_mirror_cnt, txinfo[txidx]->tx_sts_m, txinfo[txidx]->tx_sts_m); +} +#endif + + +/*------------------------------------------------------------------------- + * get_txid + * return txid of the transaction at the specified index. + *------------------------------------------------------------------------- + */ +TransactionId +get_txid(int txidx) +{ + return txinfo[txidx]->txid; +} + +/*------------------------------------------------------------------------- + * get_tx + * Return transaction entry which has specified transaction id, or NULL + * if there is no such transaction. + *------------------------------------------------------------------------- + */ +prepared_txninfo * +get_tx(TransactionId txid) +{ + int txloop; + + dispmsg(lvl_debug, "BEGIN: get_tx(%d)", txid); + + for (txlo... [truncated message content] |
From: Michael P. <mic...@us...> - 2011-03-29 19:50:21
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) from 82c7049c243ba0849d93b6f73e1b4b96a64f4d9c (commit) - Log ----------------------------------------------------------------- commit 886f9bbe99120dc751a7d9110521a7cd6cc884d9 Author: Michael P <mic...@us...> Date: Wed Mar 30 04:36:37 2011 +0900 Fix for bug 3240318: support for lastval Last value was simply not saved in cache after nextval and setval. diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index aceee06..01df64b 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -623,6 +623,8 @@ nextval_internal(Oid relid) elm->last = result; /* last returned number */ elm->cached = result; /* last fetched number */ elm->last_valid = true; + + last_used_seq = elm; } else { @@ -939,6 +941,15 @@ do_setval(Oid relid, int64 next, bool iscalled) /* Update the on-disk data */ seq->last_value = next; /* last fetched number */ seq->is_called = iscalled; + seq->log_cnt = (iscalled) ? 0 : 1; + + if (iscalled) + { + elm->last = next; /* last returned number */ + elm->last_valid = true; + } + + elm->cached = elm->last; } else { ----------------------------------------------------------------------- Summary of changes: src/backend/commands/sequence.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |