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
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
|
1
(2) |
2
(3) |
3
|
4
(2) |
5
(3) |
6
(2) |
7
(8) |
8
(12) |
9
|
10
|
11
(17) |
12
(16) |
13
(4) |
14
(3) |
15
(5) |
16
|
17
|
18
(1) |
19
(3) |
20
(2) |
21
(1) |
22
(1) |
23
|
24
|
25
(3) |
26
(1) |
27
|
28
|
29
|
30
|
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] |