/* * FileRepAckMirror_ConstructAndInsertMessage * a) reserve ack shared memory * b) construct message header * c) calculate message body crc * d) calculate message header crc * e) insert message header, message header crc and message body into ack shared memory * f) set filerep message state to 'ready' so that message can be consumed * g) signal send ack process so message will be sent to primary immediately */ static int FileRepAckMirror_ConstructAndInsertMessage( FileRepIdentifier_u fileRepIdentifier, FileRepRelationType_e fileRepRelationType, FileRepOperation_e fileRepOperation, FileRepOperationDescription_u fileRepOperationDescription, FileRepAckState_e fileRepAckState, uint32 messageBodyLength, char *messageBody) { FileRepShmemMessageDescr_s *fileRepShmemMessageDescr = NULL; FileRepMessageHeader_s *fileRepMessageHeader = NULL; pg_crc32 *fileRepMessageHeaderCrc = 0; pg_crc32 fileRepMessageHeaderCrcLocal = 0; char *msgPositionInsert = NULL; char *fileRepMessageBody = NULL; uint32 msgLength = 0; uint32 spareField = 0; Assert(messageBodyLength == 0); msgLength = sizeof(FileRepMessageHeader_s) + sizeof(pg_crc32) + messageBodyLength; /* * Shared memory is reserved in advance in order to avoid * holding lock during memcpy() and Crc calculation... * * Construct FileRepShmemMessageDescr_s */ msgPositionInsert = FileRep_ReserveShmem( fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE], msgLength, &spareField, fileRepOperation, FileRepAckShmemLock); if (msgPositionInsert == NULL) { ereport(WARNING, (errmsg("mirror failure, " "could not queue ack message to be sent to primary, " "failover requested"), errhint("run gprecoverseg to re-establish mirror connectivity"), FileRep_errdetail(fileRepIdentifier, fileRepRelationType, fileRepOperation, FILEREP_UNDEFINED), FileRep_errdetail_ShmemAck(), FileRep_errcontext())); return STATUS_ERROR; } fileRepMessageHeader = (FileRepMessageHeader_s *) (msgPositionInsert + sizeof(FileRepShmemMessageDescr_s)); fileRepMessageHeader->fileRepMessageHeaderVersion = FileRepMessageHeaderVersionOne; fileRepMessageHeader->fileRepRelationType = fileRepRelationType; fileRepMessageHeader->fileRepOperation = fileRepOperation; fileRepMessageHeader->fileRepIdentifier = fileRepIdentifier; fileRepMessageHeader->fileRepAckState = fileRepAckState; fileRepMessageHeader->messageCount = spareField; fileRepMessageHeader->messageBodyLength = messageBodyLength; if (messageBodyLength) { FileRep_CalculateCrc((char *) messageBody, messageBodyLength, &fileRepMessageHeader->fileRepMessageBodyCrc); } else { fileRepMessageHeader->fileRepMessageBodyCrc = 0; } switch (fileRepOperation) { case FileRepOperationReconcileXLogEof: case FileRepOperationValidation: case FileRepOperationCreate: fileRepMessageHeader->fileRepOperationDescription = fileRepOperationDescription; break; default: break; } /* * The following fields are not in use during fsync(). * They were zeroed during reserving message buffer. * a) fileRepOperationDescription * b) fileRepMessageBodyCrc * c) messageCount */ fileRepMessageHeaderCrc = (pg_crc32 *) (msgPositionInsert + sizeof(FileRepMessageHeader_s) + sizeof(FileRepShmemMessageDescr_s)); FileRep_CalculateCrc((char *) fileRepMessageHeader, sizeof(FileRepMessageHeader_s), &fileRepMessageHeaderCrcLocal); *fileRepMessageHeaderCrc = fileRepMessageHeaderCrcLocal; FileRep_InsertLogEntry( "M_ConstructAndInsertMessageAck", fileRepIdentifier, fileRepRelationType, fileRepOperation, fileRepMessageHeaderCrcLocal, FILEREP_UNDEFINED, fileRepAckState, FILEREP_UNDEFINED, fileRepMessageHeader->messageCount); if (Debug_filerep_print) ereport(LOG, (errmsg("M_ConstructAndInsertMessageAck construct and insert ack message " "msg header crc '%u' message body length '%d' position insert '%p' ack state '%s' ", fileRepMessageHeaderCrcLocal, messageBodyLength, msgPositionInsert, FileRepAckStateToString[fileRepAckState]), FileRep_errdetail(fileRepIdentifier, fileRepRelationType, fileRepOperation, fileRepMessageHeader->messageCount), FileRep_errdetail_ShmemAck(), FileRep_errcontext())); if (messageBodyLength) { fileRepMessageBody = (char *) (msgPositionInsert + sizeof(FileRepMessageHeader_s) + sizeof(FileRepShmemMessageDescr_s) + sizeof(pg_crc32)); memcpy(fileRepMessageBody, messageBody, messageBodyLength); } fileRepShmemMessageDescr = (FileRepShmemMessageDescr_s*) msgPositionInsert; fileRepShmemMessageDescr->messageSync = FileRep_IsOperationSynchronous(fileRepOperation); fileRepShmemMessageDescr->messageState = FileRepShmemMessageStateReady; LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE); FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE]->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE]->ipcArrayIndex]->refCountSemC); LWLockRelease(FileRepAckShmemLock); return STATUS_OK; }
static int FileRepAckPrimary_RunReceiver(void) { uint32_t msgLength = 0; FileRepConsumerProcIndex_e msgType; int status = STATUS_OK; char *msgPositionInsert; FileRepShmemMessageDescr_s *fileRepShmemMessageDescr; uint32 spareField; FileRep_InsertConfigLogEntry("run receiver"); while (1) { FileRepSubProcess_ProcessSignals(); if (FileRepSubProcess_GetState() != FileRepStateReady && FileRepSubProcess_GetState() != FileRepStateInitialization) { break; } if ( ! FileRepConnServer_AwaitMessageBegin()) { /* call was interrupted ... go back to beginning to process signals */ continue; } status = FileRepConnServer_ReceiveMessageType(&msgType); if (status != STATUS_OK) { break; } /* DATA MESSAGE TYPE */ status = FileRepConnServer_ReceiveMessageLength(&msgLength); if (status != STATUS_OK) { break; } msgPositionInsert = FileRep_ReserveShmem(fileRepAckShmemArray[msgType], msgLength, /* not used */ &spareField, FileRepOperationNotSpecified, FileRepAckShmemLock); if (msgPositionInsert == NULL) { status = STATUS_ERROR; ereport(WARNING, (errmsg("mirror failure, " "could not queue received ack message to be processed, " "failover requested"), errhint("run gprecoverseg to re-establish mirror connectivity"), FileRep_errdetail_Shmem(), FileRep_errdetail_ShmemAck(), FileRep_errcontext())); break; } status = FileRepConnServer_ReceiveMessageData( msgPositionInsert + sizeof(FileRepShmemMessageDescr_s), msgLength); if (status != STATUS_OK) { break; } SIMPLE_FAULT_INJECTOR(FileRepReceiver); fileRepShmemMessageDescr = (FileRepShmemMessageDescr_s*) msgPositionInsert; /* it is not in use */ fileRepShmemMessageDescr->messageSync = FALSE; fileRepShmemMessageDescr->messageState = FileRepShmemMessageStateReady; LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE); FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmemArray[msgType]->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckShmemArray[msgType]->ipcArrayIndex]->refCountSemC); LWLockRelease(FileRepAckShmemLock); FileRep_InsertLogEntry( "P_RunReceiver", FileRep_GetFlatFileIdentifier("", ""), FileRepRelationTypeNotSpecified, FileRepOperationNotSpecified, FILEREP_UNDEFINED, FILEREP_UNDEFINED, FileRepAckStateNotInitialized, spareField, FILEREP_UNDEFINED); } // while(1) FileRepConnServer_CloseConnection(); return status; }