diff options
author | Michael Paquier | 2012-07-13 01:52:46 +0000 |
---|---|---|
committer | Michael Paquier | 2012-07-13 01:52:46 +0000 |
commit | 4ecfc866de54c0327fbef19ff803257748bf8480 (patch) | |
tree | 9dd44a927073c30b54ddfe5d10ae23d46cc7e55b | |
parent | 5d8d73970dcd36236df3405801349ec01623753f (diff) |
Change control file of GTM into a text file
This includes latest GXID and sequence information. This configuration
allows an external operator to modify sequence information with a simple
text editor before restarting a GTM.
Some functionalities have been added to include sequence name encoding and
decoding when interacting with control file.
Patch by Andrei Martsinchyk
-rw-r--r-- | src/gtm/main/gtm_seq.c | 216 | ||||
-rw-r--r-- | src/gtm/main/gtm_standby.c | 2 | ||||
-rw-r--r-- | src/gtm/main/gtm_txn.c | 10 | ||||
-rw-r--r-- | src/gtm/main/main.c | 24 | ||||
-rw-r--r-- | src/include/gtm/gtm_seq.h | 4 | ||||
-rw-r--r-- | src/include/gtm/gtm_txn.h | 4 |
6 files changed, 195 insertions, 65 deletions
diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index b050e7a411..d3b2f3339a 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -35,9 +35,6 @@ typedef struct GTM_SeqInfoHashBucket GTM_RWLock shb_lock; } GTM_SeqInfoHashBucket; -static int SeqStartMagic = 0xfafafafa; -static int SeqEndMagic = 0xfefefefe; - #define SEQ_HASH_TABLE_SIZE 1024 static GTM_SeqInfoHashBucket GTMSequences[SEQ_HASH_TABLE_SIZE]; @@ -1610,13 +1607,129 @@ ProcessSequenceRenameCommand(Port *myport, StringInfo message, bool is_backup) /* FIXME: need to check errors */ } + +/* + * Escape whitespace and non-printable characters in the sequence name to + * store it to the control file. + */ +static void +encode_seq_key(GTM_SequenceKey seqkey, char *buffer) +{ + int i; + char c; + char *out; + + out = buffer; + for (i = 0; i < seqkey->gsk_keylen; i++) + { + c = seqkey->gsk_key[i]; + + if (c == '\\') /* double backslach */ + { + *out++ = '\\'; + *out++ = '\\'; + } + else if (c > ' ') /* no need to escape */ + { + *out++ = c; + } + else if (c == '\n') /* below some known non-printable chars */ + { + *out++ = '\\'; + *out++ = 'n'; + } + else if (c == '\r') + { + *out++ = '\\'; + *out++ = 'r'; + } + else if (c == '\t') + { + *out++ = '\\'; + *out++ = 't'; + } + else /* other non-printable chars */ + { + *out++ = '\\'; + if ((int) c < 10) + { + *out++ = '0'; + *out++ = (char) ((int) '0' + (int) c); + } + else + { + *out++ = (char) ((int) '0' + ((int) c) / 10); + *out++ = (char) ((int) '0' + ((int) c) % 10); + } + } + } + /* Add NULL terminator */ + *out++ = '\0'; +} + + +/* + * Decode the string encoded by the encode_seq_key function + */ +static void +decode_seq_key(char* value, GTM_SequenceKey seqkey) +{ + char *in; + char out[1024]; + int len = 0; + + in = value; + while (*in != '\0') + { + if (*in == '\\') /* get escaped character */ + { + in++; /* next value */ + if (*in == '\\') + out[len++] = *in++; + else if (*in == 'n') + { + out[len++] = '\n'; + in++; + } + else if (*in == 'r') + { + out[len++] = '\r'; + in++; + } + else if (*in == 't') + { + out[len++] = '\t'; + in++; + } + else /* \nn format */ + { + int val; + val = ((int) *in++ - (int) '0'); + val *= 10; + val += ((int) *in++ - (int) '0'); + out[len++] = (char) val; + } + } + else /* get plain character */ + { + out[len++] = *in++; + } + } + /* copy result to palloc'ed memory */ + seqkey->gsk_keylen = len; + seqkey->gsk_key = (char *) palloc(len); + memcpy(seqkey->gsk_key, out, len); +} + + void -GTM_SaveSeqInfo(int ctlfd) +GTM_SaveSeqInfo(FILE *ctlf) { GTM_SeqInfoHashBucket *bucket; gtm_ListCell *elem; GTM_SeqInfo *seqinfo = NULL; int hash; + char buffer[1024]; for (hash = 0; hash < SEQ_HASH_TABLE_SIZE; hash++) { @@ -1635,18 +1748,14 @@ GTM_SaveSeqInfo(int ctlfd) GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_READ); - write(ctlfd, &SeqStartMagic, sizeof (SeqStartMagic)); - write(ctlfd, &seqinfo->gs_key->gsk_keylen, sizeof (uint32)); - write(ctlfd, seqinfo->gs_key->gsk_key, seqinfo->gs_key->gsk_keylen); - write(ctlfd, &seqinfo->gs_value, sizeof (GTM_Sequence)); - write(ctlfd, &seqinfo->gs_init_value, sizeof (GTM_Sequence)); - write(ctlfd, &seqinfo->gs_increment_by, sizeof (GTM_Sequence)); - write(ctlfd, &seqinfo->gs_min_value, sizeof (GTM_Sequence)); - write(ctlfd, &seqinfo->gs_max_value, sizeof (GTM_Sequence)); - write(ctlfd, &seqinfo->gs_cycle, sizeof (bool)); - write(ctlfd, &seqinfo->gs_called, sizeof (bool)); - write(ctlfd, &seqinfo->gs_state, sizeof (int32)); - write(ctlfd, &SeqEndMagic, sizeof(SeqEndMagic)); + encode_seq_key(seqinfo->gs_key, buffer); + fprintf(ctlf, "%s\t%ld\t%ld\t%ld\t%ld\t%ld\t%c\t%c\t%x\n", + buffer, seqinfo->gs_value, + seqinfo->gs_init_value, seqinfo->gs_increment_by, + seqinfo->gs_min_value, seqinfo->gs_max_value, + (seqinfo->gs_cycle ? 't' : 'f'), + (seqinfo->gs_called ? 't' : 'f'), + seqinfo->gs_state); GTM_RWLockRelease(&seqinfo->gs_lock); } @@ -1656,15 +1765,16 @@ GTM_SaveSeqInfo(int ctlfd) } + void -GTM_RestoreSeqInfo(int ctlfd) +GTM_RestoreSeqInfo(FILE *ctlf) { - int magic; + char seqname[1024]; - if (ctlfd == -1) + if (ctlf == NULL) return; - while (read(ctlfd, &magic, sizeof (SeqStartMagic)) == sizeof (SeqStartMagic)) + while (fscanf(ctlf, "%s", seqname) == 1) { GTM_SequenceKeyData seqkey; GTM_Sequence increment_by; @@ -1675,38 +1785,58 @@ GTM_RestoreSeqInfo(int ctlfd) int32 state; bool cycle; bool called; + char boolval[16]; - if (magic != SeqStartMagic) + decode_seq_key(seqname, &seqkey); + + if (fscanf(ctlf, "%ld", &curval) != 1) { - elog(LOG, "Start magic mismatch %x - %x", magic, SeqStartMagic); - break; + elog(WARNING, "Corrupted control file"); + return; } - - if (read(ctlfd, &seqkey.gsk_keylen, sizeof (uint32)) != sizeof (uint32)) + if (fscanf(ctlf, "%ld", &startval) != 1) { - elog(LOG, "Failed to read keylen"); - break; + elog(WARNING, "Corrupted control file"); + return; } - - seqkey.gsk_key = palloc(seqkey.gsk_keylen); - read(ctlfd, seqkey.gsk_key, seqkey.gsk_keylen); - - read(ctlfd, &curval, sizeof (GTM_Sequence)); - read(ctlfd, &startval, sizeof (GTM_Sequence)); - read(ctlfd, &increment_by, sizeof (GTM_Sequence)); - read(ctlfd, &minval, sizeof (GTM_Sequence)); - read(ctlfd, &maxval, sizeof (GTM_Sequence)); - read(ctlfd, &cycle, sizeof (bool)); - read(ctlfd, &called, sizeof (bool)); - read(ctlfd, &state, sizeof (int32)); - read(ctlfd, &magic, sizeof(SeqEndMagic)); - - if (magic != SeqEndMagic) + if (fscanf(ctlf, "%ld", &increment_by) != 1) + { + elog(WARNING, "Corrupted control file"); + return; + } + if (fscanf(ctlf, "%ld", &minval) != 1) + { + elog(WARNING, "Corrupted control file"); + return; + } + if (fscanf(ctlf, "%ld", &maxval) != 1) + { + elog(WARNING, "Corrupted control file"); + return; + } + if (fscanf(ctlf, "%s", boolval) == 1) + { + cycle = (*boolval == 't'); + } + else + { + elog(WARNING, "Corrupted control file"); + return; + } + if (fscanf(ctlf, "%s", boolval) == 1) + { + called = (*boolval == 't'); + } + else + { + elog(WARNING, "Corrupted control file"); + return; + } + if (fscanf(ctlf, "%x", &state) != 1) { elog(WARNING, "Corrupted control file"); return; } - GTM_SeqRestore(&seqkey, increment_by, minval, maxval, startval, curval, state, cycle, called); } diff --git a/src/gtm/main/gtm_standby.c b/src/gtm/main/gtm_standby.c index 575d2a12ad..5c2c8f0a4d 100644 --- a/src/gtm/main/gtm_standby.c +++ b/src/gtm/main/gtm_standby.c @@ -71,7 +71,7 @@ gtm_standby_restore_next_gxid(void) GlobalTransactionId next_gxid = InvalidGlobalTransactionId; next_gxid = get_next_gxid(GTM_ActiveConn); - GTM_RestoreTxnInfo(-1, next_gxid); + GTM_RestoreTxnInfo(NULL, next_gxid); elog(LOG, "Restoring the next GXID done."); return 1; diff --git a/src/gtm/main/gtm_txn.c b/src/gtm/main/gtm_txn.c index f507c988e2..ccfd602864 100644 --- a/src/gtm/main/gtm_txn.c +++ b/src/gtm/main/gtm_txn.c @@ -2578,13 +2578,13 @@ GTM_SetShuttingDown(void) } void -GTM_RestoreTxnInfo(int ctlfd, GlobalTransactionId next_gxid) +GTM_RestoreTxnInfo(FILE *ctlf, GlobalTransactionId next_gxid) { GlobalTransactionId saved_gxid; - if (ctlfd != -1) + if (ctlf) { - if ((read(ctlfd, &saved_gxid, sizeof (saved_gxid)) != sizeof (saved_gxid)) && + if ((fscanf(ctlf, "%u", &saved_gxid) != 1) && (!GlobalTransactionIdIsValid(next_gxid))) next_gxid = InitialGXIDValue_Default; else if (!GlobalTransactionIdIsValid(next_gxid)) @@ -2603,7 +2603,7 @@ GTM_RestoreTxnInfo(int ctlfd, GlobalTransactionId next_gxid) } void -GTM_SaveTxnInfo(int ctlfd) +GTM_SaveTxnInfo(FILE *ctlf) { GlobalTransactionId next_gxid; @@ -2611,7 +2611,7 @@ GTM_SaveTxnInfo(int ctlfd) elog(LOG, "Saving transaction info - next_gxid: %u", next_gxid); - write(ctlfd, &next_gxid, sizeof (next_gxid)); + fprintf(ctlf, "%u\n", next_gxid); } /* * TODO diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index cca3c5d1cd..f6c5e8d58e 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -286,7 +286,7 @@ main(int argc, char *argv[]) int status; int i; GlobalTransactionId next_gxid = InvalidGlobalTransactionId; - int ctlfd; + FILE *ctlf; /* * Local variable to hold command line options. @@ -584,10 +584,11 @@ main(int argc, char *argv[]) } else { - ctlfd = open(GTMControlFile, O_RDONLY); - GTM_RestoreTxnInfo(ctlfd, next_gxid); - GTM_RestoreSeqInfo(ctlfd); - close(ctlfd); + ctlf = fopen(GTMControlFile, "r"); + GTM_RestoreTxnInfo(ctlf, next_gxid); + GTM_RestoreSeqInfo(ctlf); + if (ctlf) + fclose(ctlf); } if (Recovery_IsStandby()) @@ -768,7 +769,7 @@ ServerLoop(void) if (GTMAbortPending) { - int ctlfd; + FILE *ctlf; /* * XXX We should do a clean shutdown here. For the time being, just @@ -783,16 +784,15 @@ ServerLoop(void) */ GTM_SetShuttingDown(); - ctlfd = open(GTMControlFile, O_WRONLY | O_TRUNC | O_CREAT, - S_IRUSR | S_IWUSR); - if (ctlfd == -1) + ctlf = fopen(GTMControlFile, "w"); + if (ctlf == NULL) { fprintf(stderr, "Failed to create/open the control file\n"); exit(2); } - GTM_SaveTxnInfo(ctlfd); - GTM_SaveSeqInfo(ctlfd); + GTM_SaveTxnInfo(ctlf); + GTM_SaveSeqInfo(ctlf); #if 0 /* @@ -808,7 +808,7 @@ ServerLoop(void) } #endif - close(ctlfd); + fclose(ctlf); exit(1); } diff --git a/src/include/gtm/gtm_seq.h b/src/include/gtm/gtm_seq.h index 3cd218f3bf..b6fcdc61a9 100644 --- a/src/include/gtm/gtm_seq.h +++ b/src/include/gtm/gtm_seq.h @@ -87,8 +87,8 @@ void ProcessSequenceAlterCommand(Port *myport, StringInfo message, bool is_backu void ProcessSequenceListCommand(Port *myport, StringInfo message); -void GTM_SaveSeqInfo(int ctlfd); -void GTM_RestoreSeqInfo(int ctlfd); +void GTM_SaveSeqInfo(FILE *ctlf); +void GTM_RestoreSeqInfo(FILE *ctlf); int GTM_SeqRestore(GTM_SequenceKey seqkey, GTM_Sequence increment_by, GTM_Sequence minval, diff --git a/src/include/gtm/gtm_txn.h b/src/include/gtm/gtm_txn.h index 0089064cb0..2b29b68735 100644 --- a/src/include/gtm/gtm_txn.h +++ b/src/include/gtm/gtm_txn.h @@ -247,8 +247,8 @@ void ProcessBeginTransactionGetGXIDCommandMulti(Port *myport, StringInfo message void ProcessCommitTransactionCommandMulti(Port *myport, StringInfo message, bool is_backup); void ProcessRollbackTransactionCommandMulti(Port *myport, StringInfo message, bool is_backup) ; -void GTM_SaveTxnInfo(int ctlfd); -void GTM_RestoreTxnInfo(int ctlfd, GlobalTransactionId next_gxid); +void GTM_SaveTxnInfo(FILE *ctlf); +void GTM_RestoreTxnInfo(FILE *ctlf, GlobalTransactionId next_gxid); void GTM_BkupBeginTransaction(char *coord_name, GTM_TransactionHandle txn, GTM_IsolationLevel isolevel, |