org.apache.flink.runtime.state.gemini.engine.hashtable.GRegionKMapImpl Maven / Gradle / Ivy
/*
* 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.hashtable;
import org.apache.flink.runtime.state.gemini.engine.GRegionContext;
import org.apache.flink.runtime.state.gemini.engine.memstore.GSValue;
import org.apache.flink.runtime.state.gemini.engine.memstore.GSValueMap;
import org.apache.flink.runtime.state.gemini.engine.memstore.WriteBufferKMapHashImpl;
import org.apache.flink.runtime.state.gemini.engine.page.GValueType;
import org.apache.flink.runtime.state.gemini.engine.page.PageIndex;
import org.apache.flink.runtime.state.gemini.engine.page.PageStoreHashKMapImpl;
import org.apache.flink.shaded.guava18.com.google.common.collect.Maps;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.stream.Collectors;
/**
* GRegionKMapImpl.
* K is type of key.
* V is type of value.
*/
public class GRegionKMapImpl extends AbstractGRegionKMapImpl> {
public GRegionKMapImpl(GRegionContext gRegionContext) {
super(gRegionContext, null);
}
public GRegionKMapImpl(GRegionContext gRegionContext, PageIndex pageIndex) {
super(gRegionContext, pageIndex);
}
@Override
void init(PageIndex pageIndex) {
this.pageStore = new PageStoreHashKMapImpl<>(this, pageIndex, regionEventExecutor);
this.writeBuffer = new WriteBufferKMapHashImpl<>(this, regionEventExecutor, pageStore);
}
@Override
public void put(K key, Map value) {
gContext.checkDBStatus();
gContext.incAccessNumber();
long seqID = gRegionContext.getNextSeqID();
writeBuffer.put(key, Maps.transformEntries(value,
(mk, mv) -> GSValue.of(mv, GValueType.PutValue, seqID)));
}
@Override
public Map get(K key) {
gContext.checkDBStatus();
gContext.incAccessNumber();
return internalGet(key, true);
}
@Nullable
private Map mergeTwoMap(@Nullable Map> newer, Map> older, boolean checkReadCopy) {
Map ret = new HashMap<>();
if (older != null) {
ret = older.entrySet().stream()
.filter(e -> !GValueType.Delete.equals(e.getValue().getValueType()) && !gRegionContext.filterState(e.getValue().getSeqID()))
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getValue()));
}
if (newer != null) {
for (Map.Entry> entry : newer.entrySet()) {
if (gRegionContext.filterState(entry.getValue().getSeqID())) {
continue;
}
if (entry.getValue().getValueType().equals(GValueType.Delete)) {
ret.remove(entry.getKey());
} else {
MK mk = entry.getKey();
MV mv = entry.getValue().getValue();
ret.put(checkReadCopy ? copyMKIfNeeded(mk) : mk, checkReadCopy ? copyMVIfNeeded(mv) : mv);
}
}
}
return ret.isEmpty() ? null : ret;
}
private Map genMapFromGSValueMap(GSValueMap gsValueMap, boolean checkReadCopy) {
Map> valueMap = gsValueMap.getValue();
Map ret = new HashMap<>();
if (valueMap != null) {
for (SortedMap.Entry> entry : valueMap.entrySet()) {
if (!GValueType.Delete.equals(entry.getValue().getValueType()) &&
!gRegionContext.filterState(entry.getValue().getSeqID())) {
MK mk = entry.getKey();
MV mv = entry.getValue().getValue();
ret.put(checkReadCopy ? copyMKIfNeeded(mk) : mk, checkReadCopy ? copyMVIfNeeded(mv) : mv);
}
}
}
return ret.isEmpty() ? null : ret;
}
@Override
public Map getOrDefault(K key, Map defaultValue) {
gContext.checkDBStatus();
Map result = get(key);
return (result == null || result.isEmpty()) ? defaultValue : result;
}
@Override
public Map> getAll() {
gContext.checkDBStatus();
Map> results = new HashMap<>();
getAll(results);
return results;
}
@Override
public void getAll(Map> results) {
gContext.checkDBStatus();
//TODO provide better performance.
gContext.incAccessNumber();
Set allKeysIncludeDelete = new HashSet<>();
writeBuffer.allKeysIncludeDeleted(allKeysIncludeDelete);
pageStore.allKeysIncludeDeleted(allKeysIncludeDelete);
for (K key : allKeysIncludeDelete) {
Map mapResult = get(key);
if (mapResult != null) {
results.put(copyKeyIfNeeded(key), mapResult);
}
}
}
@Override
protected Map internalGet(K key, boolean checkReadCopy) {
GSValueMap gsValueMap = writeBuffer.get(key);
if (gsValueMap != null) {
switch (gsValueMap.getValueType()) {
case Delete:
return null;
case PutMap:
return genMapFromGSValueMap(gsValueMap, checkReadCopy);
default:
// nothing need to do.
}
}
Map> mapResult = pageStore.get(key);
return mergeTwoMap(gsValueMap == null ? null : gsValueMap.getValue(), mapResult, checkReadCopy);
}
}