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

org.apache.flink.runtime.state.gemini.engine.page.PageAddress 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.runtime.state.gemini.engine.filecache.InfiniteCapacityFileCache;
import org.apache.flink.runtime.state.gemini.engine.page.compress.GCompressAlgorithm;

import org.apache.flink.shaded.guava18.com.google.common.base.MoreObjects;

import static org.apache.flink.runtime.state.gemini.engine.page.PageConstants.NO_PAGE;

/**
 * PageAddress.
 */
public class PageAddress {

	private static final byte PAGE_VALID_MASK = (byte) 0x01;

	private static final byte LOCAL_VALID_MASK = (byte) 0x02;

	private static final byte DFS_VALID_MASK = (byte) 0x04;

	private DataPage dataPage;
	private volatile long dfsAddress;
	private volatile long localAddress;

	private volatile long requestCount = 0;

	//for disk len indicator.
	// TODO onMemDataLen and onDiskDataLen will combine to a Long and GCompressAlgorithm.
	private final int onMemDataLen;

	private final int checksum;

	/**
	 * Currently only the 3 low bits are used, and the other 5 bits are reserved.
	 * 1. bit 0: the status of page. 0 is invalid(discarded), and 1 is valid. The
	 * semantic of invalid here is that the page is no longer in page index, and
	 * we can not access it through page index later, but it's not guaranteed that
	 * no access to it later because someone may reference it before it's discarded
	 * and has not released the reference after it's discarded.
	 * 2. bit 1: the status of local address, 0 is invalid, and 1 is valid.
	 * 3. bit 2: the status of dfs address, 0 is invalid, and 1 is valid.
	 * The semantic of invalid for local/dfs address is that the data pointed by the
	 * address exists on some storage. It's the duty of file cache to set the status
	 * of page address. When the page is flushed successfully, it should be set valid,
	 * when it was evicted or the file contains the data is deleted, it should be set
	 * invalid. But actually, we may not explicitly set the status to invalid, at least
	 * in {@link InfiniteCapacityFileCache},
	 * that's once the status is set valid, it will never been set back to invalid,
	 * because it's much complicated to find the pages which use the file to be deleted.
	 * So we need other ways to guarantee the safety:
	 * 1. if the address status is invalid, do not access the data pointed by the address
	 * 2. if the status of page and address are both valid, it's safe because we'll not
	 * release the reference of file and file will not be deleted
	 * 3. if the status of page is invalid and the address is valid, we use MVCC (access number)
	 * to delay the deletion of file to ensure the safety.
	 */
	private volatile byte status;

	public PageAddress(long requestCount, DataPage dataPage) {
		this.dataPage = dataPage;
		this.onMemDataLen = dataPage.getSize();
		this.requestCount = requestCount;
		// init status: page is used, local and dfs address are both invalid
		this.status = 0x01;
		this.checksum = dataPage.getCheckSum();
	}

	public PageAddress(int onMemDataLen, int onDiskDataLen, byte dataLenType, int checksum, long requestCount) {
		// TODO: #SR how to set requestCount???
		this.status = 0x01;
		//TODO we should snapshot this.
		this.onMemDataLen = onMemDataLen;
		this.requestCount = requestCount;
		this.checksum = checksum;
		//TODO support compressing when flush.
	}

	public DataPage getDataPage() {
		if (dataPage != null) {
			dataPage.addReferenceCount();
		}
		return dataPage;
	}

	public DataPage getDataPageNoReference() {
		return dataPage;
	}

	public boolean hasDataPage() {
		return dataPage != null;
	}

	public long getDfsAddress() {
		return dfsAddress;
	}

	public long getLocalAddress() {
		return localAddress;
	}

	public long getVersion() {
		return dataPage != null ? dataPage.getVersion() : NO_PAGE;
	}

	public void setDataPage(DataPage dataPage) {
		this.dataPage = dataPage;
	}

	public void setDfsAddress(long dfsAddress) {
		this.dfsAddress = dfsAddress;
	}

	public void setLocalAddress(long localAddress) {
		this.localAddress = localAddress;
	}

	/**
	 * Set status of page, true is valid, and false is invalid.
	 */
	public void setPageStatus(boolean flag) {
		byte st = status;
		this.status = (byte) (flag ? (st | PAGE_VALID_MASK) : (st & (~PAGE_VALID_MASK)));
	}

	public boolean isPageValid() {
		return (status & PAGE_VALID_MASK) != 0;
	}

	/**
	 * Set status of local address, true is valid, and false is invalid.
	 */
	public void setLocalStatus(boolean flag) {
		byte st = status;
		this.status = (byte) (flag ? (st | LOCAL_VALID_MASK) : (st & (~LOCAL_VALID_MASK)));
	}

	public boolean isLocalValid() {
		return (status & LOCAL_VALID_MASK) != 0;
	}

	/**
	 * Set status of dfs address, true is valid, and false is invalid.
	 */
	public void setDfsStatus(boolean flag) {
		byte st = status;
		this.status = (byte) (flag ? (st | DFS_VALID_MASK) : (st & (~DFS_VALID_MASK)));
	}

	public boolean isDfsValid() {
		return (status & DFS_VALID_MASK) != 0;
	}

	@Override
	public String toString() {
		MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).
			add("dataPage", dataPage).
			add("dfsAddress", dfsAddress).
			add("localAddress", localAddress).
			add("compressCode", getOndiskDataCompressionAlgorithm()).
			add("onDiskDataLen", onMemDataLen).
			add("onMemDataLen", onMemDataLen).
			add("requestCount", this.requestCount);
		if (dataPage != null) {
			helper.add("compactionCount", dataPage.getCompactionCount());
		}
		return helper.toString();
	}

	public int getDataLen() {
		return this.onMemDataLen;
	}

	public int getOnDiskDataLen() {
		return onMemDataLen;
	}

	public GCompressAlgorithm getOndiskDataCompressionAlgorithm() {
		return GCompressAlgorithm.None;
	}

	public void afterFlush(int onDiskDataLen, GCompressAlgorithm gCompressAlgorithm) {
		//need lock outside.
		//TODO support compressing when flush.
	}

	public long getRequestCount() {
		return this.requestCount;
	}

	public void addRequestCount(int i) {
		this.requestCount += i;
	}

	public int getChecksum() {
		return checksum;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy