示例#1
0
void
DtxContextInfo_Deserialize(const char *serializedDtxContextInfo,
						   int serializedDtxContextInfolen,
						   DtxContextInfo *dtxContextInfo)
{
	int i;
	DistributedSnapshot *ds = &dtxContextInfo->distributedSnapshot;

	DtxContextInfo_Reset(dtxContextInfo);

	if (serializedDtxContextInfolen > 0)
	{
		int xipsize;
		const char *p = serializedDtxContextInfo;
		int32 maxCount;

		elog((Debug_print_full_dtm ? LOG : DEBUG5),
			 "DtxContextInfo_Deserialize serializedDtxContextInfolen = %d.",
		     serializedDtxContextInfolen);

		memcpy(&dtxContextInfo->distributedXid, p, sizeof(DistributedTransactionId));
		p += sizeof(DistributedTransactionId);

		if (dtxContextInfo->distributedXid != InvalidDistributedTransactionId)
		{
			memcpy(&dtxContextInfo->distributedTimeStamp, p, sizeof(DistributedTransactionTimeStamp));
			p += sizeof(DistributedTransactionTimeStamp);
			memcpy(dtxContextInfo->distributedId, p, TMGIDSIZE);
			if (strlen(dtxContextInfo->distributedId) >= TMGIDSIZE)
				elog(PANIC, "Distribute transaction identifier too long (%d)",
					 (int)strlen(dtxContextInfo->distributedId));
			p += TMGIDSIZE;
			memcpy(&dtxContextInfo->curcid, p, sizeof(CommandId));
			p += sizeof(CommandId);
		}
		else
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "DtxContextInfo_Deserialize distributedXid was InvalidDistributedTransactionId");
		}

		memcpy(&dtxContextInfo->segmateSync, p, sizeof(uint32));
		p += sizeof(uint32);
		memcpy(&dtxContextInfo->nestingLevel, p, sizeof(uint32));
		p += sizeof(uint32);
		memcpy(&dtxContextInfo->haveDistributedSnapshot, p, sizeof(bool));
		p += sizeof(bool);

		memcpy(&dtxContextInfo->cursorContext, p, sizeof(bool));
		p += sizeof(bool);

		elog((Debug_print_full_dtm ? LOG : DEBUG3),
			 "DtxContextInfo_Deserialize distributedTimeStamp %u, distributedXid = %u, curcid %d nestingLevel %d segmateSync %u as %s",
			 dtxContextInfo->distributedTimeStamp, dtxContextInfo->distributedXid, 
			 dtxContextInfo->curcid, dtxContextInfo->nestingLevel, 
			 dtxContextInfo->segmateSync, (Gp_is_writer ? "WRITER" : "READER"));

		if (dtxContextInfo->haveDistributedSnapshot)
		{
			memcpy(&ds->header.distribTransactionTimeStamp, p, sizeof(DistributedTransactionTimeStamp));
			p += sizeof(DistributedTransactionTimeStamp);
			memcpy(&ds->header.xminAllDistributedSnapshots, p, sizeof(DistributedTransactionId));
			p += sizeof(DistributedTransactionId);
			memcpy(&ds->header.distribSnapshotId, p, sizeof(DistributedSnapshotId));
			p += sizeof(DistributedSnapshotId);
			memcpy(&ds->header.xmin, p, sizeof(DistributedTransactionId));
			p += sizeof(DistributedTransactionId);
			memcpy(&ds->header.xmax, p, sizeof(DistributedTransactionId));
			p += sizeof(DistributedTransactionId);
			memcpy(&ds->header.count, p, sizeof(int32));
			p += sizeof(int32);

			/*
			 * Copy this one to a local variable first.
			 */
			memcpy(&maxCount, p, sizeof(int32));
			p += sizeof(int32);
			if (maxCount < 0 || ds->header.count > maxCount)
			{
				elog(ERROR, "Invalid distributed snapshot received (maxCount %d, count %d)",
				     maxCount, ds->header.count);
			}

			/*
			 * If we have allocated space for the in-progress distributed
			 * transactions, check against that space.  Otherwise,
			 * use the received maxCount as guide in allocating space.
			 */
			if (ds->inProgressXidArray != NULL)
			{
				if (ds->header.maxCount == 0)
				{
					elog(ERROR, "Bad allocation of in-progress array");
				}

				if (ds->header.count > ds->header.maxCount)
				{
					elog(ERROR, "Too many distributed transactions for snapshot (maxCount %d, count %d)",
					     ds->header.maxCount, ds->header.count);
				}
			}
			else
			{
				Assert(ds->inProgressXidArray == NULL);

				if (maxCount > 0)
				{
					if (maxCount < ds->header.maxCount)
					{
						maxCount = ds->header.maxCount;
					}
					else
					{
						ds->header.maxCount = maxCount;
					}

					ds->inProgressXidArray = (DistributedTransactionId *)malloc(maxCount * sizeof(DistributedTransactionId));
					if (ds->inProgressXidArray == NULL)
					{
						ereport(ERROR,
								(errcode(ERRCODE_OUT_OF_MEMORY),
								 errmsg("out of memory")));
					}
				}
			}

			if (ds->header.count > 0)
			{
				Assert(ds->inProgressXidArray != NULL);

				xipsize = sizeof(DistributedTransactionId) * ds->header.count;
				memcpy(ds->inProgressXidArray, p, xipsize);
				p += xipsize;
			}
		}
		else
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "DtxContextInfo_Deserialize no distributed snapshot");
		}

		memcpy(&dtxContextInfo->distributedTxnOptions, p, sizeof(int));
		p += sizeof(int);

		if (DEBUG5 >= log_min_messages || Debug_print_full_dtm)
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "DtxContextInfo_Deserialize distributedTimeStamp %u, distributedXid = %u, "
				 "distributedId = %s",
			     dtxContextInfo->distributedTimeStamp,
				 dtxContextInfo->distributedXid,
				 dtxContextInfo->distributedId);

			if (dtxContextInfo->haveDistributedSnapshot)
			{
				elog((Debug_print_full_dtm ? LOG : DEBUG5),
				     "distributedSnapshotHeader (xminAllDistributedSnapshots %u, xmin = %u, xmax = %u, count = %d, maxCount = %d)",
				     ds->header.xminAllDistributedSnapshots,
					 ds->header.xmin,
					 ds->header.xmax,
					 ds->header.count,
					 ds->header.maxCount);

				for (i = 0; i < ds->header.count; i++)
				{
					elog((Debug_print_full_dtm ? LOG : DEBUG5),
						 "....    inProgressXidArray[%d] = %u",
					     i, ds->inProgressXidArray[i]);
				}

				elog((Debug_print_snapshot_dtm ? LOG : DEBUG5),
					 "[Distributed Snapshot #%u] *Deserialize* currcid = %d (gxid = %u, '%s')",
					 ds->header.distribSnapshotId,
					 dtxContextInfo->curcid,
					 getDistributedTransactionId(),
					 DtxContextToString(DistributedTransactionContext));
			}

			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "DtxContextInfo_Deserialize txnOptions = 0x%x",
				 dtxContextInfo->distributedTxnOptions);
		}
	}
	else
	{
		Assert(dtxContextInfo->distributedXid == InvalidDistributedTransactionId);
		Assert(dtxContextInfo->distributedTxnOptions == 0);
	}
}
示例#2
0
char *
qdSerializeDtxContextInfo(int *size, bool wantSnapshot, bool inCursor,
						  int txnOptions, char *debugCaller)
{
	char *serializedDtxContextInfo;

	Snapshot snapshot;
	int	serializedLen;
	DtxContextInfo *pDtxContextInfo = NULL;

	/*
	 * If we already have a LatestSnapshot set then no reason to try
	 * and get a new one. just use that one. But... there is one important
	 * reason why this HAS to be here. ROLLBACK stmts get dispatched to QEs
	 * in the abort transaction code. This code tears down enough stuff such
	 * that you can't call GetTransactionSnapshot() within that code. So we
	 * need to use the LatestSnapshot since we can't re-gen a new one.
	 * 
	 * It is also very possible that for a single user statement which may
	 * only generate a single snapshot that we will dispatch multiple statements
	 * to our qExecs. Something like:
	 * 
	 *    					  QD			  QEs
	 *    					  |				  |
	 * User SQL Statement --->|		BEGIN	  |
	 *    					  |-------------->|
	 *    					  |		STMT	  |
	 *    					  |-------------->|
	 *    					  |    PREPARE	  |
	 *    					  |-------------->|
	 *    					  |    COMMIT	  |
	 *    					  |-------------->|
	 *    					  |				  |
	 * 
	 * This may seem like a problem because all four of those will dispatch
	 * the same snapshot with the same curcid. But... this is OK because
	 * BEGIN, PREPARE, and COMMIT don't need Snapshots on the QEs.
	 * 
	 * NOTE: This will be a problem if we ever need to dispatch more than one
	 * statement to the qExecs and more than one needs a snapshot!
	 */
	*size = 0;
	snapshot = NULL;

	if (wantSnapshot)
	{

		if (LatestSnapshot == NULL &&
			SerializableSnapshot == NULL && !IsAbortInProgress())
		{
			/*
			 * unfortunately, the dtm issues a select for prepared xacts at the
			 * beginning and this is before a snapshot has been set up.  so we need
			 * one for that but not for when we dont have a valid XID.
			 * 
			 * but we CANT do this if an ABORT is in progress... instead we'll send
			 * a NONE since the qExecs dont need the information to do a ROLLBACK.
			 */
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "qdSerializeDtxContextInfo calling GetTransactionSnapshot to make snapshot");

			GetTransactionSnapshot();
		}

		if (LatestSnapshot != NULL)
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "qdSerializeDtxContextInfo using LatestSnapshot");

			snapshot = LatestSnapshot;
			elog((Debug_print_snapshot_dtm ? LOG : DEBUG5),
				 "[Distributed Snapshot #%u] *QD Use Latest* currcid = %d (gxid = %u, '%s')",
				 LatestSnapshot->distribSnapshotWithLocalMapping.header.
				 distribSnapshotId, LatestSnapshot->curcid,
				 getDistributedTransactionId(),
				 DtxContextToString(DistributedTransactionContext));
		}
		else if (SerializableSnapshot != NULL)
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "qdSerializeDtxContextInfo using SerializableSnapshot");

			snapshot = SerializableSnapshot;
			elog((Debug_print_snapshot_dtm ? LOG : DEBUG5),
				 "[Distributed Snapshot #%u] *QD Use Serializable* currcid = %d (gxid = %u, '%s')",
				 SerializableSnapshot->distribSnapshotWithLocalMapping.header.
				 distribSnapshotId, SerializableSnapshot->curcid,
				 getDistributedTransactionId(),
				 DtxContextToString(DistributedTransactionContext));

		}
	}

	switch (DistributedTransactionContext)
	{
		case DTX_CONTEXT_QD_DISTRIBUTED_CAPABLE:
		case DTX_CONTEXT_LOCAL_ONLY:
			if (snapshot != NULL)
			{
				DtxContextInfo_CreateOnMaster(&TempQDDtxContextInfo,
											  &snapshot->
											  distribSnapshotWithLocalMapping,
											  snapshot->curcid, txnOptions);
			}
			else
			{
				DtxContextInfo_CreateOnMaster(&TempQDDtxContextInfo,
											  NULL, 0, txnOptions);
			}

			TempQDDtxContextInfo.cursorContext = inCursor;

			if (DistributedTransactionContext ==
				DTX_CONTEXT_QD_DISTRIBUTED_CAPABLE && snapshot != NULL)
			{
				updateSharedLocalSnapshot(&TempQDDtxContextInfo, snapshot,
										  "qdSerializeDtxContextInfo");
			}

			pDtxContextInfo = &TempQDDtxContextInfo;
			break;

		case DTX_CONTEXT_QD_RETRY_PHASE_2:
		case DTX_CONTEXT_QE_ENTRY_DB_SINGLETON:
		case DTX_CONTEXT_QE_AUTO_COMMIT_IMPLICIT:
		case DTX_CONTEXT_QE_TWO_PHASE_EXPLICIT_WRITER:
		case DTX_CONTEXT_QE_TWO_PHASE_IMPLICIT_WRITER:
		case DTX_CONTEXT_QE_READER:
		case DTX_CONTEXT_QE_PREPARED:
		case DTX_CONTEXT_QE_FINISH_PREPARED:
			elog(FATAL, "Unexpected distribute transaction context: '%s'",
				 DtxContextToString(DistributedTransactionContext));

		default:
			elog(FATAL, "Unrecognized DTX transaction context: %d",
				 (int) DistributedTransactionContext);
	}

	serializedLen = DtxContextInfo_SerializeSize(pDtxContextInfo);
	Assert(serializedLen > 0);

	*size = serializedLen;
	serializedDtxContextInfo = palloc(*size);

	DtxContextInfo_Serialize(serializedDtxContextInfo, pDtxContextInfo);

	elog((Debug_print_full_dtm ? LOG : DEBUG5),
		 "qdSerializeDtxContextInfo (called by %s) returning a snapshot of %d bytes (ptr is %s)",
		 debugCaller, *size,
		 (serializedDtxContextInfo != NULL ? "Non-NULL" : "NULL"));
	return serializedDtxContextInfo;
}
示例#3
0
void
DtxContextInfo_Serialize(char *buffer, DtxContextInfo *dtxContextInfo)
{
	char *p = buffer;
	int i;
	int used;
	DistributedSnapshot *ds = &dtxContextInfo->distributedSnapshot;

	memcpy(p, &dtxContextInfo->distributedXid, sizeof(DistributedTransactionId));
	p += sizeof(DistributedTransactionId);
	if (dtxContextInfo->distributedXid != InvalidDistributedTransactionId)
	{
		memcpy(p, &dtxContextInfo->distributedTimeStamp, sizeof(DistributedTransactionTimeStamp)); 
		p += sizeof(DistributedTransactionTimeStamp);
		if (strlen(dtxContextInfo->distributedId) >= TMGIDSIZE)
			elog(PANIC, "Distribute transaction identifier too long (%d)",
				 (int)strlen(dtxContextInfo->distributedId));
		memcpy(p, dtxContextInfo->distributedId, TMGIDSIZE);
		p += TMGIDSIZE;		
		memcpy(p, &dtxContextInfo->curcid, sizeof(CommandId));
		p += sizeof(CommandId);
	}
	else
	{
		elog((Debug_print_full_dtm ? LOG : DEBUG5),
			 "DtxContextInfo_Serialize only copied InvalidDistributedTransactionId");
	}

	elog((Debug_print_full_dtm ? LOG : DEBUG3),
		 "DtxContextInfo_Serialize distributedTimeStamp %u, distributedXid = %u, curcid %d nestingLevel %d segmateSync %u",
		 dtxContextInfo->distributedTimeStamp, dtxContextInfo->distributedXid, 
		 dtxContextInfo->curcid, dtxContextInfo->nestingLevel, dtxContextInfo->segmateSync);

	memcpy(p, &dtxContextInfo->segmateSync, sizeof(uint32));
	p += sizeof(uint32);

	memcpy(p, &dtxContextInfo->nestingLevel, sizeof(uint32));
	p += sizeof(uint32);

	memcpy(p, &dtxContextInfo->haveDistributedSnapshot, sizeof(bool));
	p += sizeof(bool);

	memcpy(p, &dtxContextInfo->cursorContext, sizeof(bool));
	p += sizeof(bool);

	if (dtxContextInfo->haveDistributedSnapshot)
	{
		memcpy(p, &ds->header.distribTransactionTimeStamp, sizeof(DistributedTransactionTimeStamp)); 
		p += sizeof(DistributedTransactionTimeStamp);
		memcpy(p, &ds->header.xminAllDistributedSnapshots, sizeof(DistributedTransactionId)); 
		p += sizeof(DistributedTransactionId);
		memcpy(p, &ds->header.distribSnapshotId, sizeof(DistributedSnapshotId)); 
		p += sizeof(DistributedSnapshotId);
		memcpy(p, &ds->header.xmin, sizeof(DistributedTransactionId)); 
		p += sizeof(DistributedTransactionId);
		memcpy(p, &ds->header.xmax, sizeof(DistributedTransactionId)); 
		p += sizeof(DistributedTransactionId);
		memcpy(p, &ds->header.count, sizeof(int32)); p += sizeof(int32);
		memcpy(p, &ds->header.maxCount, sizeof(int32)); p += sizeof(int32);

		memcpy(p, ds->inProgressXidArray, sizeof(DistributedTransactionId)*ds->header.count); 
		p += sizeof(DistributedTransactionId)*ds->header.count;

	}

	memcpy(p, &dtxContextInfo->distributedTxnOptions, sizeof(int));
	p += sizeof(int);

	used = (p - buffer);
	
	if (DEBUG5 >= log_min_messages || Debug_print_full_dtm || Debug_print_snapshot_dtm)
	{
		elog((Debug_print_full_dtm ? LOG : DEBUG5),
			 "DtxContextInfo_Serialize distributedTimeStamp %u, distributedXid = %u, "
			 "curcid %d",
			 dtxContextInfo->distributedTimeStamp,
			 dtxContextInfo->distributedXid, 
			 dtxContextInfo->curcid);

		if (dtxContextInfo->haveDistributedSnapshot)
		{
			elog((Debug_print_full_dtm ? LOG : DEBUG5),
				 "distributedSnapshotHeader (xminAllDistributedSnapshots %u, xmin = %u, xmax = %u, count = %d, maxCount = %d)",
				 ds->header.xminAllDistributedSnapshots,
				 ds->header.xmin, 
				 ds->header.xmax,
				 ds->header.count,
				 ds->header.maxCount);
			for (i = 0; i < ds->header.count; i++)
			{
				elog((Debug_print_full_dtm ? LOG : DEBUG5),
					 "....    inProgressXidArray[%d] = %u", 
				     i, ds->inProgressXidArray[i]);
			}
			elog((Debug_print_snapshot_dtm ? LOG : DEBUG5),
				 "[Distributed Snapshot #%u] *Serialize* currcid = %d (gxid = %u, '%s')", 
			 	 ds->header.distribSnapshotId,
			 	 dtxContextInfo->curcid,
			 	 getDistributedTransactionId(),
				 DtxContextToString(DistributedTransactionContext));
		}
		elog((Debug_print_full_dtm ? LOG : DEBUG5),"DtxContextInfo_Serialize txnOptions = 0x%x", dtxContextInfo->distributedTxnOptions);
		elog((Debug_print_full_dtm ? LOG : DEBUG5),"DtxContextInfo_Serialize copied %d bytes", used);
	}
}