Beispiel #1
0
void
test__BufferedReadUseBeforeBuffer__IsNextReadLenZero(void **state)
{
    BufferedRead *bufferedRead = palloc(sizeof(BufferedRead));
    int32 memoryLen = 512; /* maxBufferLen + largeReadLen */
	uint8 *memory = malloc(sizeof(memoryLen));
	char *relname = "test";
	int32 maxBufferLen = 128;
	int32 maxLargeReadLen = 128;
	int32 nextBufferLen;
	int32 maxReadAheadLen = 64;
        
	memset(bufferedRead, 0 , sizeof(BufferedRead));
	/*
	 * Initialize the buffer
	 */
	BufferedReadInit(bufferedRead, memory, memoryLen, maxBufferLen, maxLargeReadLen, relname);
	/*
	 * filling up the bufferedRead struct
	 */
	bufferedRead->largeReadLen=100;
	bufferedRead->bufferOffset=0;
	bufferedRead->fileLen=200;
	bufferedRead->temporaryLimitFileLen=200;
	bufferedRead->largeReadPosition=50;

	bufferedRead->maxLargeReadLen = 0; /* this will get assigned to nextReadLen(=0) */

    PG_TRY();
	{
    	/*
    	 * This will throw a ereport(ERROR).
    	 */
		BufferedReadUseBeforeBuffer(bufferedRead, maxReadAheadLen, &nextBufferLen);
	}
	PG_CATCH();
	{
		CurrentMemoryContext = 1; //To be fixed
		ErrorData *edata = CopyErrorData();
		/*
		 * Validate the expected error
		 */
		assert_true(edata->sqlerrcode == ERRCODE_INTERNAL_ERROR);
		assert_true(edata->elevel == ERROR);
	}
	PG_END_TRY();	
}
/*
 * Grow the available length of the current buffer.
 *
 * NOTE: The buffer address returned can be different, even for previously
 * examined buffer data.  In other words, don't keep buffer pointers in
 * the buffer region.  Use offsets to re-establish pointers after this call.
 *
 * If the current file has been completely read, bufferLen will remain
 * the current value.
 */
uint8 *BufferedReadGrowBuffer(
    BufferedRead       *bufferedRead,
    int32              newMaxReadAheadLen,
    int32              *growBufferLen,
    bool 				isUseSplitLen)
{
	int32 originalBufferLen;
	int32 newNextOffset;

	Assert(bufferedRead != NULL);
	Assert(bufferedRead->file >= 0);
	Assert(newMaxReadAheadLen > bufferedRead->bufferLen);
	Assert(newMaxReadAheadLen <= bufferedRead->maxBufferLen);
	Assert(growBufferLen != NULL);

	originalBufferLen = bufferedRead->bufferLen;
	
	newNextOffset = bufferedRead->bufferOffset + newMaxReadAheadLen;
    if (newNextOffset > bufferedRead->largeReadLen)
	{
		/*
		 * Odd boundary.  Use before memory to carry us over.
		 */
		Assert(bufferedRead->largeReadLen - bufferedRead->bufferOffset > 0);
	
		return BufferedReadUseBeforeBuffer(
									bufferedRead, 
									newMaxReadAheadLen,
									growBufferLen,
									isUseSplitLen);
	}

	/*
	 * There is maxReadAheadLen more left in current large-read memory.
	 */
	bufferedRead->bufferLen = newMaxReadAheadLen;
	Assert(bufferedRead->bufferLen > 0);
	
	*growBufferLen = bufferedRead->bufferLen;
	return &bufferedRead->largeReadMemory[bufferedRead->bufferOffset];
}
/*
 * Get the next buffer space for reading with a specified max read-ahead
 * amount.
 *
 * Returns NULL when the current file has been completely read.
 */
uint8 *BufferedReadGetNextBuffer(
    BufferedRead       *bufferedRead,
    int32              maxReadAheadLen,
    int32              *nextBufferLen,
    bool				isUseSplitLen)
{
	int64	inEffectFileLen;

	Assert(bufferedRead != NULL);
	Assert(bufferedRead->file >= 0);
	Assert(maxReadAheadLen > 0);
	Assert(nextBufferLen != NULL);
	if (maxReadAheadLen > bufferedRead->maxBufferLen)
	{
		Assert(maxReadAheadLen <= bufferedRead->maxBufferLen);
		
		elog(ERROR, "Read ahead length %d is greater than maximum buffer length %d",
		     maxReadAheadLen, bufferedRead->maxBufferLen);
	}

	if (bufferedRead->haveTemporaryLimitInEffect)
		inEffectFileLen = bufferedRead->temporaryLimitFileLen;
	else if(isUseSplitLen)
		inEffectFileLen = bufferedRead->splitLen;
	else
		inEffectFileLen = bufferedRead->fileLen;

	Assert(inEffectFileLen!=-1 && inEffectFileLen>=0);
	/*
	 * Finish previous buffer.
	 */
	bufferedRead->bufferOffset += bufferedRead->bufferLen;
	bufferedRead->bufferLen = 0;

	if (bufferedRead->largeReadPosition == inEffectFileLen
        // when the previous call isUseSplitLen is true, while this call is false
        || bufferedRead->largeReadPosition == bufferedRead->fileLen)
	{
		/*
		 * At end of file.
		 */
		*nextBufferLen = 0;
		bufferedRead->haveTemporaryLimitInEffect = false;
		return NULL;
	}
	
	/*
	 * Any more left in current read?
	 */
	if (bufferedRead->bufferOffset == bufferedRead->largeReadLen)
	{
		int64 remainingFileLen=0;
	
		/*
		 * Used exactly all of it.  Attempt read more.
		 */
		bufferedRead->largeReadPosition += bufferedRead->largeReadLen;
		bufferedRead->bufferOffset = 0;
		
        if (bufferedRead->largeReadPosition == bufferedRead->fileLen) {
            // when the previous call isUseSplitLen is true, while this call is false
            remainingFileLen = 0;
        }else{
            remainingFileLen = inEffectFileLen -
		                   bufferedRead->largeReadPosition;
        }
        
		if (remainingFileLen > bufferedRead->maxLargeReadLen)
			bufferedRead->largeReadLen = bufferedRead->maxLargeReadLen;
		else
			bufferedRead->largeReadLen = (int32)remainingFileLen;
		
        if (bufferedRead->largeReadLen == 0)
		{
			/*
			 * At end of file.
			 */
			*nextBufferLen = 0;
			bufferedRead->haveTemporaryLimitInEffect = false;
			return NULL;
		}

		BufferedReadIo(bufferedRead);

		if (maxReadAheadLen > bufferedRead->largeReadLen)
			bufferedRead->bufferLen = bufferedRead->largeReadLen;
		else
			bufferedRead->bufferLen = maxReadAheadLen;

		Assert(bufferedRead->bufferOffset == 0);
		Assert(bufferedRead->bufferLen > 0);

		*nextBufferLen = bufferedRead->bufferLen;
		return bufferedRead->largeReadMemory;
	}

	if (bufferedRead->bufferOffset + maxReadAheadLen > bufferedRead->largeReadLen)
	{
		/*
		 * Odd boundary.  Use before memory to carry us over.
		 */
		Assert(bufferedRead->largeReadLen - bufferedRead->bufferOffset > 0);
	
		return BufferedReadUseBeforeBuffer(
									bufferedRead, 
									maxReadAheadLen,
									nextBufferLen,
									isUseSplitLen);
	}

	/*
	 * We can satisify request from current read.
	 */
	bufferedRead->bufferLen = maxReadAheadLen;	
	Assert(bufferedRead->bufferLen > 0);

	*nextBufferLen = bufferedRead->bufferLen;
	return &bufferedRead->largeReadMemory[bufferedRead->bufferOffset];
}