VariableArrayCursor::VariableArrayCursor(uint8_t *addr)
	: BaseObject(addr), curObject_(*this), elemCursor_(UNDEF_CURSOR_POS) {
	rootOId_ = getBaseOId();
	elemNum_ = ValueProcessor::decodeVarSize(curObject_.getBaseAddr());
	curObject_.moveCursor(
		ValueProcessor::getEncodedVarSize(elemNum_));  
}
/*!
	@brief Free Objects related to VariableArray
*/
void VariableArrayCursor::finalize() {
	reset();  
	if (getBaseOId() != UNDEF_OID) {
		while (nextElement(true)) {  
			;
		}
	}
}
VariableArrayCursor::VariableArrayCursor(TransactionContext &txn,
	ObjectManager &objectManager, OId oId, AccessMode accessMode)
	: BaseObject(txn.getPartitionId(), objectManager),
	  curObject_(*this),
	  elemCursor_(UNDEF_CURSOR_POS),
	  accessMode_(accessMode) {
	BaseObject::load(oId, accessMode_);
	rootOId_ = getBaseOId();
	elemNum_ = ValueProcessor::decodeVarSize(curObject_.getBaseAddr());
	curObject_.moveCursor(
		ValueProcessor::getEncodedVarSize(elemNum_));  
}
/*!
	@brief Allocate HashMap Object
*/
int32_t HashMap::initialize(TransactionContext& txn, ColumnType columnType,
	ColumnId columnId, const AllocateStrategy& metaAllocateStrategy,
	bool isUnique) {
	hashMapImage_ = BaseObject::allocate<HashMapImage>(sizeof(HashMapImage),
		metaAllocateStrategy, getBaseOId(), OBJECT_TYPE_HASH_MAP);

	if (columnType == COLUMN_TYPE_STRING) {
		hashMapImage_->thresholdSplit_ = THRESHOLD_SPLIT_STRING;
	}
	else {
		hashMapImage_->thresholdSplit_ = ThresholdSplitNonString;
	}

	hashMapImage_->size_ = 0;
	hashMapImage_->split_ = 0;
	hashMapImage_->front_ = INITIAL_HASH_ARRAY_SIZE;
	hashMapImage_->rear_ = hashMapImage_->front_;
	hashMapImage_->toSplit_ = false;
	hashMapImage_->toMerge_ = false;

	hashMapImage_->keyType_ = columnType;
	hashMapImage_->columnId_ = columnId;
	hashMapImage_->isUnique_ = isUnique ? 1 : 0;

	hashMapImage_->padding1_ = 0;
	hashMapImage_->padding2_ = 0;
	hashMapImage_->padding3_ = 0;
	hashMapImage_->padding4_ = 0;
	hashMapImage_->padding5_ = 0;
	hashMapImage_->padding6_ = 0;
	hashMapImage_->padding7_ = 0;

	hashArray_.initialize(txn, &(hashMapImage_->hashArrayImage_), true);

	while (hashArray_.size() < hashMapImage_->rear_) {
		hashArray_.twiceHashArray(txn);
	}


	return GS_SUCCESS;
}
/*!
	@brief Clone
*/
OId VariableArrayCursor::clone(TransactionContext &txn,
	const AllocateStrategy &allocateStrategy, OId neighborOId) {
	if (UNDEF_OID == getBaseOId()) {
		return UNDEF_OID;
	}
	OId currentNeighborOId = neighborOId;
	OId linkOId = UNDEF_OID;

	uint32_t srcDataLength = getArrayLength();
	if (srcDataLength == 0) {
		uint8_t *srcObj = getBaseAddr();
		Size_t srcObjSize = getObjectManager()->getSize(srcObj);
		BaseObject destObject(txn.getPartitionId(), *getObjectManager());
		OId destOId = UNDEF_OID;
		if (currentNeighborOId != UNDEF_OID) {
			destObject.allocateNeighbor<uint8_t>(srcObjSize, allocateStrategy,
				destOId, currentNeighborOId, OBJECT_TYPE_VARIANT);
		}
		else {
			destObject.allocate<uint8_t>(
				srcObjSize, allocateStrategy, destOId, OBJECT_TYPE_VARIANT);
		}
		memcpy(destObject.getBaseAddr(), srcObj, srcObjSize);
		linkOId = destOId;
	}
	else {
		OId srcOId = UNDEF_OID;
		OId destOId = UNDEF_OID;
		OId prevOId = UNDEF_OID;
		uint8_t *srcObj = NULL;
		BaseObject destObject(txn.getPartitionId(), *getObjectManager());

		uint8_t *srcElem;
		uint32_t srcElemSize;
		uint32_t srcCount;
		uint8_t *lastElem = NULL;
		uint32_t lastElemSize = 0;
		while (nextElement()) {
			srcObj = data();
			srcOId = getElementOId();
			srcElem = getElement(srcElemSize, srcCount);
			if (srcOId != prevOId) {
				Size_t srcObjSize = getObjectManager()->getSize(srcObj);
				if (currentNeighborOId != UNDEF_OID) {
					destObject.allocateNeighbor<uint8_t>(srcObjSize,
						allocateStrategy, destOId, currentNeighborOId,
						OBJECT_TYPE_VARIANT);
				}
				else {
					destObject.allocate<uint8_t>(srcObjSize, allocateStrategy,
						destOId, OBJECT_TYPE_VARIANT);
				}
				currentNeighborOId =
					destOId;  

				memcpy(destObject.getBaseAddr(), srcObj, srcObjSize);
				if (UNDEF_OID == linkOId) {
					linkOId = destOId;
				}
				else {
					assert(lastElem > 0);
					uint8_t *linkOIdAddr =
						lastElem + lastElemSize +
						ValueProcessor::getEncodedVarSize(lastElemSize);
					uint64_t encodedOId =
						ValueProcessor::encodeVarSizeOId(destOId);
					memcpy(linkOIdAddr, &encodedOId, sizeof(uint64_t));
				}
				prevOId = srcOId;
			}
			lastElem = destObject.getBaseAddr() + (srcElem - srcObj);
			lastElemSize = srcElemSize;
		}
	}
	return linkOId;
}