All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
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.
org.apache.flink.runtime.state.gemini.engine.page.LogicalPageChainImpl 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.page;
import org.apache.flink.runtime.state.gemini.engine.exceptions.GeminiRuntimeException;
import org.apache.flink.runtime.state.gemini.engine.page.bmap.GBinarySplitHashMap;
import org.apache.flink.runtime.state.gemini.engine.snapshot.RegionSnapshot;
import org.apache.flink.runtime.state.gemini.engine.snapshot.SnapshotMetaFile;
import org.apache.flink.util.Preconditions;
import org.apache.flink.shaded.guava18.com.google.common.base.MoreObjects;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Spliterators;
import java.util.stream.StreamSupport;
import static org.apache.flink.runtime.state.gemini.engine.page.PageAddress.COMPOSITE_PAGE_ADDRESS;
import static org.apache.flink.runtime.state.gemini.engine.page.PageAddress.SINGLE_PAGE_ADDRESS;
import static org.apache.flink.runtime.state.gemini.engine.snapshot.SnapshotMetaFile.writerFunc;
/**
* The default implementation of {@link LogicalPageChain}.
*/
public class LogicalPageChainImpl implements LogicalPageChain {
private volatile int chainIndex = -1;
private volatile PageAddress[] pageAddresses;
// 1 byte indicates status, 3 bytes indicate page size
private volatile byte pageStatus;
private volatile int pageSize = 0;
public LogicalPageChainImpl(PageStatus pageStatus) {
this.pageStatus = pageStatus.getCode();
}
public LogicalPageChainImpl(PageStatus pageStatus, int defaultChainLen) {
this.pageStatus = pageStatus.getCode();
initChainPageImpl(defaultChainLen);
}
private LogicalPageChainImpl(
LogicalPageChainImpl logicalPageChain,
Map copiedDataPage) {
this.chainIndex = logicalPageChain.chainIndex;
// not copy the page in WaitSplitting status
if (logicalPageChain.pageAddresses != null) {
this.pageAddresses = new PageAddress[logicalPageChain.pageAddresses.length];
System.arraycopy(logicalPageChain.pageAddresses, 0, this.pageAddresses, 0, this.chainIndex + 1);
}
//add Reference count.
DataPage dataPage;
for (int i = 0; i <= this.chainIndex; i++) {
dataPage = this.pageAddresses[i].getDataPage();
if (dataPage != null) {
copiedDataPage.put(this.pageAddresses[i], dataPage);
}
}
this.pageStatus = logicalPageChain.pageStatus;
}
private void initChainPageImpl(int defaultChainLen) {
Preconditions.checkArgument(defaultChainLen >= 3, "defaultChainLen too small");
pageAddresses = new PageAddress[defaultChainLen];
}
@Override
public boolean compareAndSetStatus(
PageStatus expectedPageStatus, PageStatus targetStatus) {
if (expectedPageStatus == null) {
pageStatus = targetStatus.getCode();
return true;
}
if (pageStatus != expectedPageStatus.getCode()) {
return false;
}
synchronized (this) {
if (pageStatus != expectedPageStatus.getCode()) {
return false;
} else {
pageStatus = targetStatus.getCode();
return true;
}
}
}
@Override
public void addPageSize(int pageSize) {
this.pageSize += pageSize;
}
@Override
public int getPageSize() {
return this.pageSize;
}
@Override
public int getSubPageNum() {
int subPageNum = 0;
for (int i = 0; i <= chainIndex; i++) {
subPageNum += pageAddresses[i].getSubPageNum();
}
return subPageNum;
}
@Override
public int getSubPageSize() {
int subPageSize = 0;
for (int i = 0; i <= chainIndex; i++) {
subPageSize += pageAddresses[i].getSubPageDataLen();
}
return subPageSize;
}
@Override
public PageStatus getPageStatus() {
return PageStatus.valueOf(pageStatus);
}
@Override
public PageAddress getPageAddress(int chainIndex) {
Preconditions.checkArgument(chainIndex >= 0 && chainIndex <= this.chainIndex, "logicPage overflow");
return this.pageAddresses[chainIndex];
}
@Override
public PageAddress createPage(DataPage dataPage) {
//no concurrence
Preconditions.checkArgument(chainIndex < pageAddresses.length, "logicPage overflow");
checkSpace();
PageAddress pageAddress;
if (dataPage.getGBinaryHashMap() instanceof GBinarySplitHashMap) {
pageAddress = new PageAddressCompositeImpl(dataPage);
} else {
pageAddress = new PageAddressSingleImpl(dataPage);
}
pageAddresses[chainIndex + 1] = pageAddress;
chainIndex++;
pageAddress.setChainIndex(chainIndex);
return pageAddress;
}
@Override
public int insertPage(PageAddress pageAddress) {
//no concurrence
Preconditions.checkArgument(chainIndex < pageAddresses.length, "logicPage overflow");
checkSpace();
pageAddresses[++chainIndex] = pageAddress;
pageAddress.setChainIndex(chainIndex);
return chainIndex;
}
private void checkSpace() {
// TODO: #SR optimize this deepcopy
// change the deepcopy logic in PageIndexHashImpl().
// do not new the logichainedpage, reference the chain and log the chainIndex.
if (chainIndex == pageAddresses.length - 1) {
PageAddress[] newpageAddresses = new PageAddress[pageAddresses.length + 1];
System.arraycopy(pageAddresses, 0, newpageAddresses, 0, pageAddresses.length);
pageAddresses = newpageAddresses;
}
}
@Override
public int getCurrentPageChainIndex() {
return this.chainIndex;
}
@Override
public int getPageChainCapacity() {
return pageAddresses.length;
}
@Override
public LogicalPageChain copy(Map copiedDataPage) {
if (this == PageIndexHashImpl.WAIT_SPLITTING_PAGE) {
return PageIndexHashImpl.WAIT_SPLITTING_PAGE;
}
return new LogicalPageChainImpl(this, copiedDataPage);
}
@Override
public Iterator pageIterator() {
// for WaitSplitting page
if (pageAddresses == null) {
return Collections.emptyIterator();
}
return Arrays.stream(pageAddresses).filter(Objects::nonNull)
.flatMap(index -> StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
index.pageIterator(), 0), false))
.iterator();
}
@Override
public void snapshot(Collection regionSnapshots) throws IOException {
writerFunc(regionSnapshots, w -> w.writeInt(chainIndex));
for (int i = 0; i <= chainIndex; i++) {
PageAddress pageAddress = pageAddresses[i];
writerFunc(regionSnapshots, w -> w.writeByte(pageAddress.getPageAddressType()));
pageAddress.snapshot(regionSnapshots);
}
}
@Override
public void restore(SnapshotMetaFile.Reader reader, PageStoreStats pageStoreStats) throws IOException {
chainIndex = reader.readInt();
this.pageAddresses = new PageAddress[chainIndex + 1];
for (int i = 0; i <= chainIndex; ++i) {
PageAddress pageAddress;
byte pageType = reader.readByte();
switch (pageType) {
case SINGLE_PAGE_ADDRESS:
pageAddress = PageAddressSingleImpl.restore(reader, pageStoreStats);
break;
case COMPOSITE_PAGE_ADDRESS:
pageAddress = PageAddressCompositeImpl.restore(reader, pageStoreStats);
break;
default:
throw new GeminiRuntimeException("error pageAddress:" + pageType);
}
pageStoreStats.addLogicSubPageCount(pageAddress.getSubPageNum());
pageStoreStats.addLogicSubPageSize(pageAddress.getSubPageDataLen());
pageAddresses[i] = pageAddress;
addPageSize(pageAddress.getDataLen());
}
pageStoreStats.addLogicPageChainLen(chainIndex + 1);
pageStoreStats.addLogicPageChainCapacity(chainIndex + 1);
}
@Override
public Set getAllDataPageReferenced() {
Set set = new HashSet<>();
for (PageAddress address : pageAddresses) {
DataPage dataPage = address.getDataPage();
if (dataPage != null) {
set.add(dataPage);
}
}
return set;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).
add("pageAddresses", Arrays.toString(pageAddresses)).
toString();
}
}