Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.bmap;
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.page.DataPage;
import org.apache.flink.runtime.state.gemini.engine.page.PageAddress;
import org.apache.flink.runtime.state.gemini.engine.page.PageAddressSingleImpl;
import org.apache.flink.runtime.state.gemini.engine.page.PageContext;
import org.apache.flink.runtime.state.gemini.engine.rm.GByteBuffer;
import org.apache.flink.runtime.state.gemini.engine.rm.GSharedUnreferencedByteBuffer;
import org.apache.flink.util.Preconditions;
import javax.annotation.Nullable;
import static org.apache.flink.runtime.state.gemini.engine.page.PageContext.INVALID_PAGE_CONTEXT;
/**
* The class GBufferAddressMapping is used to record a set of sub DataPage address. when putting a data page
* into the mapping, it will return an id of the sub page. We can get the {@link GByteBuffer} of sub page using
* the id. Notice that this class is not thread safe. Be careful when using it in a concurrent environment.
*/
public class GBufferAddressMapping {
GRegionContext gRegionContext;
private PageAddress[] mapping;
private int logicPageChainIndex;
private int logicPageHashCode;
private int nextId;
private static final int EMPTY_SUB_PAGE_ADDRESS_ID = -1;
private static final int PAGE_ADDRESS_ARRAY_DEFAULT_LENGTH = 16;
public GBufferAddressMapping(GRegionContext gRegionContext, int logicPageChainIndex, int logicPageHashCode) {
this.gRegionContext = gRegionContext;
this.mapping = new PageAddress[PAGE_ADDRESS_ARRAY_DEFAULT_LENGTH];
this.logicPageChainIndex = logicPageChainIndex;
this.logicPageHashCode = logicPageHashCode;
this.nextId = 0; //TODO index 0 for special use in the future.
}
public GBufferAddressMapping(PageAddress[] subPages, GRegionContext gRegionContext, int logicPageChainIndex, int logicPageHashCode) {
this.gRegionContext = gRegionContext;
this.mapping = subPages;
this.nextId = subPages.length;
this.logicPageChainIndex = logicPageChainIndex;
this.logicPageHashCode = logicPageHashCode;
}
public void setLogicPageChainIndex(int newLogicPageChainIndex) {
this.logicPageChainIndex = newLogicPageChainIndex;
}
public void setLogicPageHashCode(int newLogicPageHashCode) {
this.logicPageHashCode = newLogicPageHashCode;
}
public int putGByteBufferAddress(DataPage dataPage) {
if (isEmptySubPage(dataPage)) {
return EMPTY_SUB_PAGE_ADDRESS_ID;
}
if (nextId == mapping.length) {
PageAddress[] newMapping = new PageAddress[mapping.length * 2];
System.arraycopy(mapping, 0, newMapping, 0, mapping.length);
mapping = newMapping;
}
int id = nextId++;
mapping[id] = new PageAddressSingleImpl(dataPage);
return id;
}
public int putGByteBufferAddress(PageAddress pageAddress) {
if (pageAddress == null) {
return EMPTY_SUB_PAGE_ADDRESS_ID;
}
Preconditions.checkArgument(pageAddress instanceof PageAddressSingleImpl);
if (nextId == mapping.length) {
PageAddress[] newMapping = new PageAddress[mapping.length * 2];
System.arraycopy(mapping, 0, newMapping, 0, mapping.length);
mapping = newMapping;
}
int id = nextId++;
mapping[id] = pageAddress;
return id;
}
private boolean isEmptySubPage(DataPage subPage) {
return subPage.getGBinaryHashMap() == null || subPage.getGBinaryHashMap().getGByteBuffer() == null || subPage.getGBinaryHashMap().getGByteBuffer().capacity() == 0;
}
public @Nullable GByteBuffer getGByteBuffer(int id, MK mapKey) {
//Notice: the returned GByteBuffer may be null
PageAddress pageAddress = getGByteBufferAddress(id);
return getGByteBuffer(pageAddress, mapKey);
}
public @Nullable PageAddress getGByteBufferAddress(int id) {
if (id == EMPTY_SUB_PAGE_ADDRESS_ID) {
return null;
}
if (id >= nextId || id >= mapping.length) {
throw new IndexOutOfBoundsException("index=" + id + ", nextId=" + nextId + ", mappingLen=" + mapping.length);
}
return mapping[id];
}
public @Nullable GByteBuffer getGByteBuffer(PageAddress pageAddress, MK mapKey) {
if (pageAddress == null) {
return null;
}
Preconditions.checkArgument(pageAddress instanceof PageAddressSingleImpl);
DataPage dataPage = pageAddress.getDataPageNoReference();
//pageAddress.hasDataPage() is to protect the logic. because compositePage is not permitted to access it.
if (pageAddress.hasDataPage() && dataPage != null) {
this.gRegionContext.getGContext().getSupervisor().getCacheManager().getCacheStats().addSubPageCacheHitCount();
dataPage.addRequestCount(this.gRegionContext.getGContext().getSupervisor().getCacheManager().getCurrentTickTime(),
1);
return new GSharedUnreferencedByteBuffer(dataPage.getGBinaryHashMap().getGByteBuffer());
}
PageContext pageContext = INVALID_PAGE_CONTEXT;
if (logicPageChainIndex >= 0) {
pageContext = PageContext.of(gRegionContext.getRegionId(), logicPageChainIndex, logicPageHashCode,
PageContext.CacheStatus.IN_LRU);
}
if (mapKey != null && !gRegionContext.getGContext().getSupervisor().getBloomFilterManager().mightContain(
pageAddress,
mapKey.hashCode())) {
this.gRegionContext.getGContext().getSupervisor().getCacheManager().getCacheStats().addBloomFilterHitCount();
return null;
}
GByteBuffer buffer = gRegionContext.getGContext().getSupervisor().getFetchPolicy().fetchSubPage(pageAddress,
pageContext,
gRegionContext,
true);
buffer.release();
return new GSharedUnreferencedByteBuffer(buffer);
}
public int[] mergeMapping(GBufferAddressMapping subMapping, int[] oldIdList) {
int[] newIdList = new int[oldIdList.length];
PageAddress[] address = subMapping.getPageAddressArray();
for (int i = 0; i < oldIdList.length; i++) {
if (oldIdList[i] == EMPTY_SUB_PAGE_ADDRESS_ID) {
newIdList[i] = EMPTY_SUB_PAGE_ADDRESS_ID;
continue;
}
if (nextId == mapping.length) {
PageAddress[] newMapping = new PageAddress[mapping.length * 2];
System.arraycopy(mapping, 0, newMapping, 0, mapping.length);
mapping = newMapping;
}
newIdList[i] = nextId;
mapping[nextId++] = address[oldIdList[i]];
}
return newIdList;
}
public GByteBuffer pollGByteBuffer() {
if (isEmpty()) {
throw new GeminiRuntimeException("Exception inGBufferAddressMapping: attempt to poll GByteBuffer from a empty mapping");
}
nextId--;
PageAddress bufferAddress = mapping[nextId];
mapping[nextId] = null;
return new GSharedUnreferencedByteBuffer(bufferAddress.getGByteBufferNoReference());
}
public int size() {
return nextId;
}
public boolean isEmpty() {
return nextId == 0;
}
public PageAddress[] getSubPageAddress() {
PageAddress[] subPageAddress = new PageAddress[nextId];
System.arraycopy(mapping, 0, subPageAddress, 0, nextId);
return subPageAddress;
}
private PageAddress[] getPageAddressArray() {
return mapping;
}
}