All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.runtime.state.gemini.engine.page.DataPageKMapImpl Maven / Gradle / Ivy

There is a newer version: 1.5.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.flink.runtime.state.gemini.engine.page;

import org.apache.flink.api.common.typeutils.TypeSerializer;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.core.memory.DataInputView;
import org.apache.flink.runtime.state.gemini.engine.GRegionContext;
import org.apache.flink.runtime.state.gemini.engine.exceptions.GeminiRuntimeException;
import org.apache.flink.runtime.state.gemini.engine.filter.StateFilter;
import org.apache.flink.runtime.state.gemini.engine.memstore.GSValue;
import org.apache.flink.runtime.state.gemini.engine.page.bmap.BinaryKey;
import org.apache.flink.runtime.state.gemini.engine.page.bmap.BinaryValue;
import org.apache.flink.runtime.state.gemini.engine.page.bmap.ByteBufferDataInputView;
import org.apache.flink.runtime.state.gemini.engine.page.bmap.GBinaryHashMap;
import org.apache.flink.runtime.state.gemini.engine.rm.Allocator;
import org.apache.flink.runtime.state.gemini.engine.rm.GByteBuffer;
import org.apache.flink.runtime.state.gemini.engine.rm.GUnPooledByteBuffer;
import org.apache.flink.runtime.state.gemini.engine.utils.SeqIDUtils;

import javax.annotation.Nullable;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.apache.flink.runtime.state.gemini.engine.page.bmap.GBinaryHashMap.EMPTY_G_BINARY_HASHMAP;

/**
 * DataPageKMapImpl.
 */
public class DataPageKMapImpl extends DataPageKVImpl>> implements DataPageKMap {

	protected final TypeSerializer mkTypeSerializer;
	protected final TypeSerializer mvTypeSerializer;

	public DataPageKMapImpl(
		GBinaryHashMap gBinaryHashMap,
		TypeSerializer mkTypeSerializer,
		TypeSerializer mvTypeSerializer,
		TypeSerializer>> gMapTypeSerializer) {
		super(gBinaryHashMap, gMapTypeSerializer);
		this.mkTypeSerializer = mkTypeSerializer;
		this.mvTypeSerializer = mvTypeSerializer;
	}

	@Override
	public GSValue get(K key, MK mapKey) {
		try {
			BinaryValue binaryValue = this.gBinaryHashMap.get(key);
			if (binaryValue == null) {
				return null;
			}
			// the map related to K is deleted, means all the mapKey is Deleted.
			if (binaryValue.getgValueType() == GValueType.Delete) {
				return new GSValue<>(null, binaryValue.getgValueType(), binaryValue.getSeqID());
			}

			GSValue reuslt = getForMapBinaryValue(getBinaryMap(getDuplicateBB(binaryValue)), mapKey);
			//if this map's type is PutMap, means pages which are prior to this are useless
			if (reuslt == null && binaryValue.getgValueType() == GValueType.PutMap) {
				return new GSValue<>(null, binaryValue.getgValueType(), binaryValue.getSeqID());
			}
			return reuslt;
		} catch (Exception e) {
			throw new GeminiRuntimeException("get exception: " + e.getMessage(), e);
		}
	}

	protected GSValue getForMapBinaryValue(Map mapValueMap, MK mapKey) {
		return getForBinaryValue(mapValueMap.get(mapKey));
	}

	protected GSValue getForBinaryValue(BinaryValue mvBinary) {
		try {
			if (mvBinary == null) {
				return null;
			}
			if (mvBinary.getgValueType() == GValueType.Delete) {
				return new GSValue<>(null, mvBinary.getgValueType(), mvBinary.getSeqID());
			}

			DataInputView byteBufferDataInputView = new ByteBufferDataInputView(mvBinary.getBb(),
				mvBinary.getValueOffset(),
				mvBinary.getValueLen());

			MV value = mvTypeSerializer.deserialize(byteBufferDataInputView);
			return new GSValue<>(value, mvBinary.getgValueType(), mvBinary.getSeqID());
		} catch (Exception e) {
			throw new GeminiRuntimeException("getForBinaryValue has Exception:" + e.getMessage(), e);
		}
	}

	protected static GByteBuffer getDuplicateBB(BinaryValue binaryValue) {
		if (binaryValue.getValueLen() == 0) {
			return null;
		}
		ByteBuffer duplicateByteBuffer = binaryValue.getBb().duplicate();
		duplicateByteBuffer.limit(binaryValue.getValueLen() + binaryValue.getValueOffset());
		duplicateByteBuffer.position(binaryValue.getValueOffset());
		return new GUnPooledByteBuffer(duplicateByteBuffer.slice());
	}

	protected Map getBinaryMap(GByteBuffer valueBB) {
		return new GBinaryHashMap<>(valueBB, mkTypeSerializer);
	}

	@Override
	public boolean contains(K key, MK mapKey) {
		GSValue mvResult = get(key, mapKey);
		return mvResult != null && mvResult.getValue() != null;
	}

	@Override
	public DataPageType getDataPageType() {
		return DataPageType.KHashMap;
	}

	public static  BinaryValue doCompactionMapValue(
		List valueByOrder,
		TypeSerializer mkTypeSerializer,
		TypeSerializer mvTypeSerializer,
		boolean isMajor,
		long version,
		int logicPageId,
		Allocator allcator,
		@Nullable StateFilter stateFilter,
		@Nullable GRegionContext gRegionContext) {

		try {
			List> listByOrder = new ArrayList<>();
			long seqID = SeqIDUtils.INVALID_SEQID;
			GValueType firstValueType = null;

			for (BinaryValue binaryValue : valueByOrder) {
				if (binaryValue.getgValueType() == GValueType.Delete) {
					firstValueType = GValueType.Delete;
					continue;
				}

				GBinaryHashMap mapValue = new GBinaryHashMap<>(getDuplicateBB(binaryValue), mkTypeSerializer);
				//pick up newest page's seqID.
				seqID = Math.max(seqID, binaryValue.getSeqID());
				listByOrder.add(mapValue);
				if (firstValueType == null) {
					firstValueType = binaryValue.getgValueType();
				}
			}

			int index = 0;
			Map newMap = listByOrder.get(index).getBinaryMap();
			long compactionCount = listByOrder.get(index).getCompactionCount();
			index++;
			while (index < listByOrder.size()) {
				newMap.putAll(listByOrder.get(index).getBinaryMap());
				compactionCount += listByOrder.get(index).getCompactionCount();
				index++;
			}

			GBinaryHashMap gBinaryHashMap = GBinaryHashMap.ofBinaryList(DataPageType.KV,
				isMajor,
				version,
				logicPageId,
				mkTypeSerializer,
				allcator,
				newMap,
				compactionCount,
				stateFilter,
				gRegionContext);

			ByteBuffer bb = gBinaryHashMap == EMPTY_G_BINARY_HASHMAP ? null : gBinaryHashMap.getData();
			GValueType gValueType = judgeFinalValueType(bb, firstValueType, isMajor);
			return new BinaryValue(bb, gValueType, seqID, 0, gBinaryHashMap.bytesSize());
		} catch (Exception e) {
			throw new GeminiRuntimeException("Internal BUG " + e.getMessage(), e);
		}
	}

	static GValueType judgeFinalValueType(ByteBuffer bb, GValueType firstValueType, boolean isMajor) {
		//judge a compacted map value's type is a little complicated.
		// Delete -> AddMap -> AddMap,  it only happens when it's minor, and final type can be PutMap
		// PutMap -> AddMap -> AddMap, when it's major, it can be PutMap or AddMap, when it's minor, it only can be PutMap
		// AddMap -> AddMap -> AddMap, when it's major, it can be PutMap or AddMap, when it's minor, it only can be AddMap
		// when compacted map value is null, it only happens when it's major, it can be any one.
		if (bb == null) {
			return GValueType.Delete;
		}

		if (firstValueType == GValueType.Delete) {
			return GValueType.PutMap;
		}
		return firstValueType;
	}

	protected static  Map doCompactValueToBinaryMap(
		List binaryValueReversedOrderList, TypeSerializer mkTypeSerializer) {
		try {

			List> listByReversedOrder = new ArrayList<>();

			for (BinaryValue binaryValue : binaryValueReversedOrderList) {

				GBinaryHashMap mapValue = new GBinaryHashMap<>(getDuplicateBB(binaryValue), mkTypeSerializer);
				listByReversedOrder.add(mapValue);
			}

			int index = listByReversedOrder.size() - 1;
			Map newMap = listByReversedOrder.get(index).getBinaryMap();
			index--;
			while (index >= 0) {
				newMap.putAll(listByReversedOrder.get(index).getBinaryMap());
				index--;
			}

			return newMap;

		} catch (Exception e) {
			throw new GeminiRuntimeException("Internal BUG " + e.getMessage(), e);
		}
	}

	public static  DataPageKMapImpl readKMapPageFrom(
		PageSerdeFlink2Key pageSerdeFlink, GByteBuffer dataPage, int crc) {
		GBinaryHashMap gBinaryHashMap = new GBinaryHashMap<>(dataPage, pageSerdeFlink.getKeySerde(), crc);
		return new DataPageKMapImpl<>(gBinaryHashMap,
			pageSerdeFlink.getKey2Serde(),
			pageSerdeFlink.getValueSerde(),
			pageSerdeFlink.getMapValueTypeSerializer());
	}

	@Override
	public Tuple2 getSplitDataByGBinaryMap(
		GBinaryHashMap gBinaryHashMap1, GBinaryHashMap gBinaryHashMap2) {
		DataPageKMapImpl dataPage1 = gBinaryHashMap1 == EMPTY_G_BINARY_HASHMAP
			? null
			: new DataPageKMapImpl<>(gBinaryHashMap1, mkTypeSerializer, mvTypeSerializer, valueTypeSerializer);
		DataPageKMapImpl dataPage2 = gBinaryHashMap2 == EMPTY_G_BINARY_HASHMAP
			? null
			: new DataPageKMapImpl<>(gBinaryHashMap2, mkTypeSerializer, mvTypeSerializer, valueTypeSerializer);
		return Tuple2.of(dataPage1, dataPage2);

	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy