greenplumn cdbvarblock 源码
greenplumn cdbvarblock 代码
文件路径:/src/backend/cdb/cdbvarblock.c
/*-------------------------------------------------------------------------
*
* cdbvarblock.c
* A general data package that has variable-length item array that can be
* efficiently indexed once complete.
*
* (See .h file for usage comments)
*
* Portions Copyright (c) 2007-2009, greenplum inc
* Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates.
*
*
* IDENTIFICATION
* src/backend/cdb/cdbvarblock.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "cdb/cdbvarblock.h"
static VarBlockByteLen VarBlockGetItemLen(
VarBlockReader *varBlockReader,
int itemIndex);
static void VarBlockGetItemPtrAndLen(
VarBlockReader *varBlockReader,
int itemIndex,
uint8 **itemPtr,
VarBlockByteLen *itemLen);
static VarBlockByteOffset VarBlockGetOffset(
VarBlockHeader *header,
VarBlockByteOffset offsetToOffsetArray,
int itemIndex);
/*
* Initialize the VarBlock maker.
*
* Since we are going to pack the item offset array
* right after the variable-length item array when
* finished, we need a temporary buffer for the
* offsets while we are making the block. The caller
* supplies the tempScratchSpace parameter for this
* purpose.
*
* Note that tempScratchSpaceLen in effect
* serves as the maximum number of items (UNDONE: more on 2-byte vs. 3-byte).
*/
void
VarBlockMakerInit(
VarBlockMaker *varBlockMaker,
uint8 *buffer,
VarBlockByteLen maxBufferLen,
uint8 *tempScratchSpace,
int tempScratchSpaceLen)
{
Assert(varBlockMaker != NULL);
Assert(buffer != NULL);
/* UNDONE:And ALIGN(4) */
Assert(maxBufferLen >= VARBLOCK_HEADER_LEN);
/* UNDONE:And even. */
Assert(tempScratchSpace != NULL);
/* UNDONE:And ALIGN(4). */
Assert(tempScratchSpaceLen > 0);
/* UNDONE:And even. */
varBlockMaker->header = (VarBlockHeader *) buffer;
varBlockMaker->maxBufferLen = maxBufferLen;
varBlockMaker->currentItemLenSum = 0;
varBlockMaker->tempScratchSpace = tempScratchSpace;
varBlockMaker->tempScratchSpaceLen = tempScratchSpaceLen;
varBlockMaker->nextItemPtr = &buffer[VARBLOCK_HEADER_LEN];
/* UNDONE: Fix the constant to be the $MIN of approx. 16k (or 32k) */
/* UNDONE: and maxBufferLen... */
varBlockMaker->last2ByteOffsetPtr = &buffer[63 * 1024];
varBlockMaker->currentItemCount = 0;
varBlockMaker->maxItemCount = tempScratchSpaceLen / 2;
memset(buffer, 0, VARBLOCK_HEADER_LEN);
VarBlockSet_version(varBlockMaker->header, InitialVersion);
VarBlockSet_offsetsAreSmall(varBlockMaker->header, true);
}
/*
* Get a pointer to the next variable-length item so it can
* be filled in.
*
* Returns NULL when there is no more space left in the VarBlock.
*/
uint8 *
VarBlockMakerGetNextItemPtr(
VarBlockMaker *varBlockMaker,
VarBlockByteLen itemLen)
{
int currentItemCount;
uint8 *buffer;
uint8 *nextItemPtr;
VarBlockByteOffset nextItemOffset;
VarBlockByteLen newItemLenSum;
VarBlockByteLen offsetArrayLenRounded;
VarBlockByteLen newTotalLen;
uint8 *tempScratchSpace;
VarBlockByteOffset16 *tempOffsetArray16;
VarBlockByteOffset24 tempOffset24;
Assert(varBlockMaker != NULL);
Assert(itemLen >= 0);
currentItemCount = varBlockMaker->currentItemCount;
if (currentItemCount >= varBlockMaker->maxItemCount)
{
/*
* Reached a limit on the number of items based on the scratch
* space...
*/
return NULL;
}
buffer = (uint8 *) varBlockMaker->header;
nextItemPtr = varBlockMaker->nextItemPtr;
nextItemOffset = (VarBlockByteOffset) (nextItemPtr - buffer);
newItemLenSum = varBlockMaker->currentItemLenSum + itemLen;
tempScratchSpace = varBlockMaker->tempScratchSpace;
/*
* We require VarBlocks to given to us on 4 byte boundaries...
*/
if (VarBlockGet_offsetsAreSmall(varBlockMaker->header))
{
int newMaxItemCount;
/*
* Will small 2 byte offsets still work?
*/
if (nextItemPtr > varBlockMaker->last2ByteOffsetPtr)
{
int r;
/*
* Try out large 3-byte offsets.
*/
/*
* Round-up to even length.
*/
offsetArrayLenRounded = (currentItemCount + 1) *
VARBLOCK_BYTE_OFFSET_24_LEN;
offsetArrayLenRounded = ((offsetArrayLenRounded + 1) / 2) * 2;
newTotalLen = VARBLOCK_HEADER_LEN +
((newItemLenSum + 1) / 2) * 2 +
offsetArrayLenRounded;
if (newTotalLen > varBlockMaker->maxBufferLen)
return NULL;
/* Out of space. */
newMaxItemCount = varBlockMaker->tempScratchSpaceLen /
VARBLOCK_BYTE_OFFSET_24_LEN;
if (currentItemCount >= newMaxItemCount)
{
/*
* Reached a limit on the number of items based on the scratch
* space with large offsets...
*/
return NULL;
}
VarBlockSet_offsetsAreSmall(varBlockMaker->header, false);
varBlockMaker->maxItemCount = newMaxItemCount;
/*
* Reverse move to use 3-byte offsets.
*/
tempOffsetArray16 = (VarBlockByteOffset16 *) tempScratchSpace;
for (r = currentItemCount; r >= 0; r--)
{
tempOffset24.byteOffset24 = tempOffsetArray16[r];
memcpy(tempScratchSpace + (r * VARBLOCK_BYTE_OFFSET_24_LEN),
&tempOffset24,
VARBLOCK_BYTE_OFFSET_24_LEN);
}
tempOffset24.byteOffset24 = nextItemOffset;
memcpy(tempScratchSpace +
(currentItemCount * VARBLOCK_BYTE_OFFSET_24_LEN),
&tempOffset24,
VARBLOCK_BYTE_OFFSET_24_LEN);
}
else
{
/*
* Normal calculation.
*/
newTotalLen = VARBLOCK_HEADER_LEN +
((newItemLenSum + 1) / 2) * 2 +
currentItemCount * 2 + 2;
if (newTotalLen > varBlockMaker->maxBufferLen)
return NULL;
/* Out of space. */
tempOffsetArray16 = (VarBlockByteOffset16 *) tempScratchSpace;
tempOffsetArray16[currentItemCount] =
(VarBlockByteOffset16) nextItemOffset;
}
}
else
{
/*
* Large 3 byte ofsets.
*/
/*
* Round-up to even length.
*/
offsetArrayLenRounded = (currentItemCount + 1) *
VARBLOCK_BYTE_OFFSET_24_LEN;
offsetArrayLenRounded = ((offsetArrayLenRounded + 1) / 2) * 2;
newTotalLen = VARBLOCK_HEADER_LEN +
((newItemLenSum + 1) / 2) * 2 +
offsetArrayLenRounded;
if (newTotalLen > varBlockMaker->maxBufferLen)
return NULL;
/* Out of space. */
tempOffset24.byteOffset24 = nextItemOffset;
memcpy(tempScratchSpace +
(currentItemCount * VARBLOCK_BYTE_OFFSET_24_LEN),
&tempOffset24,
VARBLOCK_BYTE_OFFSET_24_LEN);
}
varBlockMaker->nextItemPtr += itemLen;
varBlockMaker->currentItemCount++;
varBlockMaker->currentItemLenSum = newItemLenSum;
return nextItemPtr;
}
/*
* Get the variable-length item count.
*/
int
VarBlockMakerItemCount(
VarBlockMaker *varBlockMaker)
{
Assert(varBlockMaker != NULL);
return varBlockMaker->currentItemCount;
}
/*
* Finish making the VarBlock.
*
* The item-offsets array will be added to the end.
*/
VarBlockByteLen
VarBlockMakerFinish(
VarBlockMaker *varBlockMaker)
{
uint8 *buffer;
int itemCount;
VarBlockByteLen itemLenSum;
uint8 *tempScratchSpace;
VarBlockByteOffset offsetToOffsetArray;
int z;
int multiplier;
VarBlockByteLen offsetArrayLen;
VarBlockByteLen offsetArrayLenRounded;
VarBlockByteLen bufferLen;
Assert(varBlockMaker != NULL);
buffer = (uint8 *) varBlockMaker->header;
itemCount = varBlockMaker->currentItemCount;
itemLenSum = varBlockMaker->currentItemLenSum;
tempScratchSpace = varBlockMaker->tempScratchSpace;
/*
* offsetArrays start on even boundary.
*/
offsetToOffsetArray = VARBLOCK_HEADER_LEN +
((itemLenSum + 1) / 2) * 2;
if (VarBlockGet_offsetsAreSmall(varBlockMaker->header))
{
memcpy(&buffer[offsetToOffsetArray], tempScratchSpace, itemCount * 2);
multiplier = 2;
}
else
{
memcpy(&buffer[offsetToOffsetArray],
tempScratchSpace,
itemCount * VARBLOCK_BYTE_OFFSET_24_LEN);
/* UNDONE: Zero out odd byte. */
multiplier = VARBLOCK_BYTE_OFFSET_24_LEN;
}
/*
* Zero the pad between the last item and the offset array for data
* security.
*/
for (z = VARBLOCK_HEADER_LEN + itemLenSum; z < offsetToOffsetArray; z++)
{
buffer[z] = 0;
}
VarBlockSet_itemLenSum(varBlockMaker->header, itemLenSum);
VarBlockSet_itemCount(varBlockMaker->header, itemCount);
/*
* Round-up to even length.
*/
offsetArrayLen = itemCount * multiplier;
offsetArrayLenRounded = ((offsetArrayLen + 1) / 2) * 2;
/*
* Zero the pad between the last offset and the rounded-up end of VarBlock
* for data security.
*/
for (z = offsetToOffsetArray + offsetArrayLen;
z < offsetToOffsetArray + offsetArrayLenRounded;
z++)
{
buffer[z] = 0;
}
bufferLen = offsetToOffsetArray + offsetArrayLenRounded;
/* #ifdef DEBUG */
/* if(VarBlockIsValid(buffer, bufferLen) != VarBlockCheckOk) */
/* { */
/* // UNDONE: Use elog. */
/* fprintf(stderr, "VarBlockIsValid not ok (detail = '%s')", */
/* VarBlockCheckErrorStr); */
/* exit(1); */
/* } */
/* #endif */
return bufferLen;
}
static VarBlockByteOffset
VarBlockGetOffset(
VarBlockHeader *header,
VarBlockByteOffset offsetToOffsetArray,
int itemIndex)
{
uint8 *offsetArray;
Assert(header != NULL);
Assert(offsetToOffsetArray >= VARBLOCK_HEADER_LEN);
Assert(itemIndex >= 0);
Assert(itemIndex < VarBlockGet_itemCount(header));
offsetArray = ((uint8 *) header) + offsetToOffsetArray;
if (VarBlockGet_offsetsAreSmall(header))
{
return ((VarBlockByteOffset16 *) offsetArray)[itemIndex];
}
else
{
VarBlockByteOffset24 offset24;
memcpy(&offset24,
offsetArray + (itemIndex * VARBLOCK_BYTE_OFFSET_24_LEN),
VARBLOCK_BYTE_OFFSET_24_LEN);
return offset24.byteOffset24;
}
}
#define MAX_VARBLOCK_CHECK_ERROR_STR 200
static char VarBlockCheckErrorStr[MAX_VARBLOCK_CHECK_ERROR_STR] = "\0";
/*
* Return a string message for the last check error.
*/
char *
VarBlockGetCheckErrorStr(void)
{
return VarBlockCheckErrorStr;
}
/*
* Determine if the header looks valid.
*
* peekLen must be at least VARBLOCK_HEADER_LEN bytes.
*/
VarBlockCheckError
VarBlockHeaderIsValid(
uint8 *buffer,
VarBlockByteLen peekLen)
{
VarBlockHeader *header;
Assert(buffer != NULL);
Assert(peekLen >= VARBLOCK_HEADER_LEN);
header = (VarBlockHeader *) buffer;
if (VarBlockGet_version(header) != InitialVersion)
{
sprintf(VarBlockCheckErrorStr,
"Invalid initial version %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
VarBlockGet_version(header),
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckBadVersion;
}
if (VarBlockGet_reserved(header) != 0)
{
sprintf(VarBlockCheckErrorStr,
"Reserved not 0 (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckReservedNot0;
}
if (VarBlockGet_moreReserved(header) != 0)
{
sprintf(VarBlockCheckErrorStr,
"More reserved not 0 (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckMoreReservedNot0;
}
/*
* Can't do checking of itemSumLen and itemCount without access to whole
* VarBlock.
*/
return VarBlockCheckOk;
}
/*
* Determine if the whole VarBlock looks valid.
*
* bufferLen must be VarBlock length.
*/
VarBlockCheckError
VarBlockIsValid(
uint8 *buffer,
VarBlockByteLen bufferLen)
{
VarBlockHeader *header;
int headerLen = VARBLOCK_HEADER_LEN;
VarBlockCheckError varBlockCheckError;
int itemLenSum;
int itemCount;
VarBlockByteOffset offsetToOffsetArray;
int z;
Assert(buffer != NULL);
Assert(bufferLen >= VARBLOCK_HEADER_LEN);
header = (VarBlockHeader *) buffer;
varBlockCheckError = VarBlockHeaderIsValid(buffer, bufferLen);
if (varBlockCheckError != VarBlockCheckOk)
return varBlockCheckError;
/*
* Now do checking of itemSumLen and itemCount.
*/
itemLenSum = VarBlockGet_itemLenSum(header);
if (itemLenSum >= bufferLen)
{
sprintf(VarBlockCheckErrorStr,
"itemLenSum %d greater than or equal to bufferLen %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
itemLenSum,
bufferLen,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckItemSumLenBad1;
}
offsetToOffsetArray = VARBLOCK_HEADER_LEN +
((itemLenSum + 1) / 2) * 2;
if (offsetToOffsetArray > bufferLen)
{
sprintf(VarBlockCheckErrorStr,
"offsetToOffsetArray %d greater than bufferLen %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
offsetToOffsetArray,
bufferLen,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckItemSumLenBad2;
}
/*
* Verify the data security zero pad between the last item and the
* offset array.
*/
for (z = VARBLOCK_HEADER_LEN + itemLenSum; z < offsetToOffsetArray; z++)
{
if (buffer[z] != 0)
{
sprintf(VarBlockCheckErrorStr,
"Bad zero pad at offset %d between items and offset array (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
z,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckZeroPadBad1;
}
}
itemCount = VarBlockGet_itemCount(header);
if (itemCount == 0)
{
if (offsetToOffsetArray != bufferLen)
{
sprintf(VarBlockCheckErrorStr,
"offsetToOffsetArray %d should equal bufferLen %d for itemCount 0 (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
offsetToOffsetArray,
bufferLen,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckItemCountBad1;
}
}
else
{
int multiplier;
VarBlockByteLen actualOffsetArrayLenRounded;
VarBlockByteLen calculatedOffsetArrayLen;
VarBlockByteLen calculatedOffsetArrayLenRounded;
VarBlockByteOffset offset;
int i;
if (VarBlockGet_offsetsAreSmall(header))
{
multiplier = 2;
}
else
{
multiplier = VARBLOCK_BYTE_OFFSET_24_LEN;
}
actualOffsetArrayLenRounded = bufferLen - offsetToOffsetArray;
/* Since itemCount was from 24-bits and the multipler is small, */
/* this multiply should be safe. */
calculatedOffsetArrayLen = itemCount * multiplier;
calculatedOffsetArrayLenRounded =
((calculatedOffsetArrayLen + 1) / 2) * 2;
if (actualOffsetArrayLenRounded != calculatedOffsetArrayLenRounded)
{
sprintf(VarBlockCheckErrorStr,
"actual OffsetArray length %d should equal calculated OffsetArray length %d for itemCount %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
actualOffsetArrayLenRounded,
calculatedOffsetArrayLenRounded,
itemCount,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckItemCountBad2;
}
/*
* The first offset is right after the header.
*/
offset = VarBlockGetOffset(header, offsetToOffsetArray, 0);
if (offset != VARBLOCK_HEADER_LEN)
{
sprintf(VarBlockCheckErrorStr,
"offset %d at index 0 is bad -- must equal %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
offset,
headerLen,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckOffsetBad1;
}
for (i = 1; i < itemCount; i++)
{
VarBlockByteOffset prevOffset = offset;
if (offset < prevOffset)
{
sprintf(VarBlockCheckErrorStr,
"offset %d at index %d is bad -- less than previous offset %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
offset,
i,
prevOffset,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckOffsetBad2;
}
if (offset > itemLenSum + VARBLOCK_HEADER_LEN)
{
sprintf(VarBlockCheckErrorStr,
"offset %d at index %d is bad -- greater than itemLenSum and header %d (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
offset,
i,
itemLenSum + headerLen,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckOffsetBad3;
}
}
/*
* Verify the data security zero pad between the last offset and the
* rounded-up end of the VarBlock.
*/
for (z = offsetToOffsetArray + calculatedOffsetArrayLen;
z < offsetToOffsetArray + calculatedOffsetArrayLenRounded;
z++)
{
if (buffer[z] != 0)
{
sprintf(VarBlockCheckErrorStr,
"Bad zero pad at offset %d between last offset and the rounded-up end of buffer (bytes_0_3 0x%08x, bytes_4_7 0x%08x)",
z,
header->bytes_0_3, header->bytes_4_7);
return VarBlockCheckZeroPadBad2;
}
}
}
return VarBlockCheckOk;
}
/*
* Initialize the VarBlock reader.
*/
void
VarBlockReaderInit(
VarBlockReader *varBlockReader,
uint8 *buffer,
VarBlockByteLen bufferLen)
{
VarBlockHeader *header;
VarBlockByteLen itemLenSum;
VarBlockByteOffset offsetToOffsetArray;
int divisor;
int calculatedItemCount;
Assert(varBlockReader != NULL);
Assert(buffer != NULL);
/* UNDONE:And ALIGN(4) */
Assert(bufferLen >= VARBLOCK_HEADER_LEN);
/* UNDONE:And even. */
header = (VarBlockHeader *) buffer;
varBlockReader->header = header;
varBlockReader->bufferLen = bufferLen;
itemLenSum = VarBlockGet_itemLenSum(header);
/*
* offsetArrays start on even boundary.
*/
offsetToOffsetArray = VARBLOCK_HEADER_LEN +
((itemLenSum + 1) / 2) * 2;
if (VarBlockGet_offsetsAreSmall(header))
{
divisor = 2;
}
else
{
divisor = VARBLOCK_BYTE_OFFSET_24_LEN;
}
calculatedItemCount = (bufferLen - offsetToOffsetArray) / divisor;
Assert(calculatedItemCount == VarBlockGet_itemCount(header));
varBlockReader->offsetToOffsetArray = offsetToOffsetArray;
varBlockReader->nextIndex = 0;
varBlockReader->nextItemPtr = &buffer[VARBLOCK_HEADER_LEN];
}
static VarBlockByteLen
VarBlockGetItemLen(
VarBlockReader *varBlockReader,
int itemIndex)
{
VarBlockHeader *header;
VarBlockByteLen itemLen;
VarBlockByteOffset offset;
Assert(varBlockReader != NULL);
Assert(itemIndex >= 0);
header = varBlockReader->header;
offset = VarBlockGetOffset(
header,
varBlockReader->offsetToOffsetArray,
itemIndex);
if (itemIndex < VarBlockGet_itemCount(header) - 1)
{
VarBlockByteOffset nextOffset;
nextOffset = VarBlockGetOffset(
header,
varBlockReader->offsetToOffsetArray,
itemIndex + 1);
itemLen = nextOffset - offset;
Assert(itemLen >= 0);
}
else
{
Assert(itemIndex == VarBlockGet_itemCount(header) - 1);
itemLen =
VARBLOCK_HEADER_LEN +
VarBlockGet_itemLenSum(header) -
offset;
Assert(itemLen >= 0);
}
return itemLen;
}
static void
VarBlockGetItemPtrAndLen(
VarBlockReader *varBlockReader,
int itemIndex,
uint8 **itemPtr,
VarBlockByteLen *itemLen)
{
VarBlockHeader *header;
uint8 *buffer;
VarBlockByteOffset offset;
Assert(varBlockReader != NULL);
header = varBlockReader->header;
buffer = (uint8 *) header;
offset = VarBlockGetOffset(
header,
varBlockReader->offsetToOffsetArray,
itemIndex);
if (itemIndex < VarBlockGet_itemCount(header) - 1)
{
VarBlockByteOffset nextOffset;
nextOffset = VarBlockGetOffset(
header,
varBlockReader->offsetToOffsetArray,
itemIndex + 1);
*itemLen = nextOffset - offset;
Assert(*itemLen >= 0);
}
else
{
Assert(itemIndex == VarBlockGet_itemCount(header) - 1);
*itemLen =
VARBLOCK_HEADER_LEN +
VarBlockGet_itemLenSum(header) -
offset;
Assert(*itemLen >= 0);
}
*itemPtr = &buffer[offset];
}
/*
* Get a pointer to the next variable-length item.
*
* Returns NULL when there are no more items.
*/
uint8 *
VarBlockReaderGetNextItemPtr(
VarBlockReader *varBlockReader,
VarBlockByteLen *itemLen)
{
uint8 *nextItemPtr;
Assert(varBlockReader != NULL);
Assert(itemLen != NULL);
if (varBlockReader->nextIndex >=
VarBlockGet_itemCount(varBlockReader->header))
{
return NULL;
}
*itemLen = VarBlockGetItemLen(varBlockReader, varBlockReader->nextIndex);
nextItemPtr = varBlockReader->nextItemPtr;
varBlockReader->nextItemPtr += *itemLen;
varBlockReader->nextIndex++;
return nextItemPtr;
}
/*
* Get the variable-length item count.
*/
int
VarBlockReaderItemCount(
VarBlockReader *varBlockReader)
{
Assert(varBlockReader != NULL);
return VarBlockGet_itemCount(varBlockReader->header);
}
/*
* Get a pointer to a variable-length item.
*/
uint8 *
VarBlockReaderGetItemPtr(
VarBlockReader *varBlockReader,
int itemIndex,
VarBlockByteLen *itemLen)
{
uint8 *nextItemPtr;
Assert(varBlockReader != NULL);
Assert(itemIndex >= 0);
Assert(itemIndex < VarBlockGet_itemCount(varBlockReader->header));
VarBlockGetItemPtrAndLen(varBlockReader, itemIndex, &nextItemPtr, itemLen);
return nextItemPtr;
}
VarBlockByteLen
VarBlockCollapseToSingleItem(
uint8 *target,
uint8 *source,
int32 sourceLen)
{
VarBlockReader varBlockReader;
uint8 *itemPtr;
VarBlockByteLen itemLen;
VarBlockReaderInit(
&varBlockReader,
source,
sourceLen);
Assert(VarBlockReaderItemCount(&varBlockReader) == 1);
/*
* Copy out item, even if it destroys the VarBlock.
*/
itemPtr = VarBlockReaderGetItemPtr(
&varBlockReader,
/* itemIndex */ 0,
&itemLen);
/*
* Slide data back. Since we have overlapping data, we use memmove which
* knows how to do that instead of memcpy which isn't guaranteed to do
* that right.
*/
memmove(target,
itemPtr,
itemLen);
return itemLen;
}
相关信息
相关文章
greenplumn cdbappendonlystorageformat 源码
greenplumn cdbappendonlystorageread 源码
greenplumn cdbappendonlystoragewrite 源码
greenplumn cdbappendonlyxlog 源码
greenplumn cdbbufferedappend 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦