org.apache.flink.runtime.state.gemini.engine.dbms.DiscardOrEvictPageReleaseManager 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.dbms;
import org.apache.flink.runtime.state.gemini.engine.rm.GByteBuffer;
import org.apache.flink.runtime.state.gemini.engine.rm.ReferenceCount.ReleaseType;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
/**
* DiscardOrEvictPageManager. when to evict or discard a page, we add this page to DiscardOrEvictPageManager.
* firstly, this is to handle concurrently access Page by Main thread. for example, Region Thread evict a page, but Main Thread get this page and still not add reference.
* secondly, if the reference of this page is not 0, but it's discarded or evicted, we will keep looking at it.
* Notice: this is not a totally leak detector, for Gemini, we only focus on discarded or evicted page which can be safely released.
* for leak detector, now we don't have. And instead we could check the allocator statistics and pageMemSize statistics to check whether there are any leak.
*/
public class DiscardOrEvictPageReleaseManager {
//see second point of description above.
private final Map discardedPageHaveReferenceMonitor = new ConcurrentHashMap<>();
private final Map evictedPageHaveReferenceMonitor = new ConcurrentHashMap<>();
//see first point of description above.
private final ConcurrentLinkedQueue waitSafeSeqQueue = new ConcurrentLinkedQueue<>();
private final AtomicLong totalWaitQueueSize = new AtomicLong(0);
private final GContext gContext;
public DiscardOrEvictPageReleaseManager(GContext gContext) {
this.gContext = gContext;
}
public void addMonitorPageStillHaveReference(GByteBuffer gByteBuffer, ReleaseType releaseType, Object detail) {
if (releaseType == ReleaseType.Discard) {
discardedPageHaveReferenceMonitor.put(gByteBuffer, detail);
} else {
evictedPageHaveReferenceMonitor.put(gByteBuffer, detail);
}
}
public void addWaitSafeQueue(ReleaseType releaseType, GByteBuffer gByteBuffer) {
if (gByteBuffer.getCnt() != 0) {
//check again for safely. but it rarely happen.
addMonitorPageStillHaveReference(gByteBuffer, releaseType, "safeQueue");
return;
}
//set AccessNum.
gByteBuffer.setSeqID(gContext.getAccessNumber());
totalWaitQueueSize.incrementAndGet();
waitSafeSeqQueue.add(gByteBuffer);
}
public GByteBuffer getGByteBufferFromWaitQueue() {
GByteBuffer gByteBuffer = waitSafeSeqQueue.poll();
if (gByteBuffer != null) {
totalWaitQueueSize.decrementAndGet();
}
return gByteBuffer;
}
public Map getDiscardedPageHaveReferenceMonitor() {
return discardedPageHaveReferenceMonitor;
}
public Map getEvictedPageHaveReferenceMonitor() {
return evictedPageHaveReferenceMonitor;
}
public AtomicLong getTotalWaitQueueSize() {
return totalWaitQueueSize;
}
}