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

org.apache.flink.runtime.state.gemini.engine.vm.FetchPolicyImpl 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.vm;

import org.apache.flink.runtime.state.gemini.engine.GRegionContext;
import org.apache.flink.runtime.state.gemini.engine.dbms.GContext;
import org.apache.flink.runtime.state.gemini.engine.filecache.FileCache;
import org.apache.flink.runtime.state.gemini.engine.handler.GeminiEventExecutorGroup;
import org.apache.flink.runtime.state.gemini.engine.page.DataPage;
import org.apache.flink.runtime.state.gemini.engine.page.LogicChainedPage;
import org.apache.flink.runtime.state.gemini.engine.page.PageAddress;
import org.apache.flink.runtime.state.gemini.engine.rm.ReferenceCount.ReleaseType;

import org.apache.flink.shaded.guava18.com.google.common.util.concurrent.ThreadFactoryBuilder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * FetchPolicyImpl.
 * aim to reduce the IO access num. for now only support preFetch pages which is belonged to a same logic page.
 * non thread safe.
 */
public class FetchPolicyImpl implements FetchPolicy {

	private static final Logger LOG = LoggerFactory.getLogger(FetchPolicyImpl.class);

	private final DataPageLRU readPageCacheLRU;
	private final CacheStats cacheStats;
	private final FileCache fileCache;
	private final ExecutorService preFetchExecutor;
	private final AtomicInteger currentPrefetchingNum = new AtomicInteger(0);
	private final int maxPrefchingNum;

	public FetchPolicyImpl(
		GContext gContext, CacheStats cacheStats, DataPageLRU readPageCacheLRU) {
		this.readPageCacheLRU = readPageCacheLRU;
		this.cacheStats = cacheStats;
		this.fileCache = gContext.getSupervisor().getFileCache();

		ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(
			gContext.getGConfiguration().getExcetorPrefixName() + "geminiPrefetch-%d").build();
		this.preFetchExecutor = new GeminiEventExecutorGroup(gContext.getGConfiguration().getFlushThreadNum(),
			namedThreadFactory,
			gContext.getGConfiguration().getFetchThreadSleepTimeNS(), gContext);
		this.maxPrefchingNum = gContext.getGConfiguration().getMaxCompactionChainThreshold();
	}

	void preFetch(LogicChainedPage logicChainedPage, int startIndex, GRegionContext gRegionContext) {
		/**
		 * logicChainedPage and startIndex are pointed to other Pages needed to prefetch.
		 */
		while (startIndex >= 0 && gRegionContext.getGContext().isDBNormal()) {
			PageAddress pageAddress = logicChainedPage.getPageAddress(startIndex);
			startIndex--;
			if (pageAddress.hasDataPage()) {
				continue;
			}
			//too slow?
			if (currentPrefetchingNum.get() > maxPrefchingNum) {
				return;
			}
			FutureDataPage futureDataPageOld = this.readPageCacheLRU.get(pageAddress);
			if (futureDataPageOld != null && !futureDataPageOld.isFail()) {
				return;
			}

			currentPrefetchingNum.incrementAndGet();
			FutureDataPage futureDataPage = new FutureDataPage(pageAddress.getDataLen());
			//readPageCacheLRU is a small cache, and finally we should put this pages to Cache by commit this pages to RegionEvent,
			//for now, we have not implement this logic, and depends on compaction to update the Cache.
			this.readPageCacheLRU.put(pageAddress, futureDataPage);
			//TODO in the future, we should combine the preFetchExecutor and evictExecutor,
			//TODO that means when we preFetch some pages,evictHandler will skip these pages.
			this.preFetchExecutor.submit(() -> asyncFetch(futureDataPage, pageAddress, gRegionContext));
		}
	}

	private void asyncFetch(FutureDataPage futureDataPage, PageAddress pageAddress, GRegionContext gRegionContext) {
		//todo to resuse dataPage need send to Region handler.
		try {
			DataPage dataPage = this.fileCache.getPage(
				pageAddress,
				gRegionContext,
				gRegionContext.getGContext().getSupervisor().getFlushExecutorGroup().next());
			if (!futureDataPage.complete(dataPage)) {
				dataPage.delReferenceCount(ReleaseType.Normal);
			}
		} catch (Exception e) {
			futureDataPage.completeExceptionally(e);
		} finally {
			currentPrefetchingNum.decrementAndGet();
		}
	}

	@Override
	public DataPage fetch(
		PageAddress pageAddress,
		LogicChainedPage logicChainedPage,
		int startIndex,
		GRegionContext gRegionContext,
		boolean prefetch,
		boolean doCache) {
		//PageAddress can not be updated, so can be as Key.
		final FutureDataPage futureDataPage = this.readPageCacheLRU.get(pageAddress);
		if (futureDataPage != null) {
			if (futureDataPage.isDone()) {
				try {
					DataPage dataPage = futureDataPage.get();
					dataPage.addReferenceCount();
					this.cacheStats.addPageCacheLRUHitCount();
					return dataPage;
				} catch (Exception e) {
					//futureDataPage fail. try new.
				}
			}
		}
		if (prefetch) {
			preFetch(logicChainedPage, startIndex - 1, gRegionContext);
		}
		DataPage dataPage = this.fileCache.getPage(pageAddress,
			gRegionContext,
			gRegionContext.getGContext().getSupervisor().getFlushExecutorGroup().next());
		if (doCache) {
			this.readPageCacheLRU.put(pageAddress, new FutureDataPage(dataPage));
			dataPage.addReferenceCount();
		}
		return dataPage;
	}

	@Override
	public DataPageLRU getDataPageLRU() {
		return this.readPageCacheLRU;
	}

	@Override
	public void close() {
		this.preFetchExecutor.shutdownNow();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy