blob: 1a1beaf5079eb840d382836a59b4e54438764be9 [file] [log] [blame]
/*
* 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.geode.internal.cache.eviction;
import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.apache.geode.cache.RegionDestroyedException;
import org.apache.geode.internal.cache.CachePerfStats;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.logging.internal.log4j.api.LogService;
/**
* Takes delta to be evicted and tries to evict the least no of LRU entry which would make
* evictedBytes more than or equal to the delta
*
* @since GemFire 6.0
*/
public class RegionEvictorTask implements Runnable {
private static final Logger logger = LogService.getLogger();
private final CachePerfStats stats;
private final List<LocalRegion> regions;
private final HeapEvictor evictor;
private final long bytesToEvictPerTask;
private final StatisticsClock statisticsClock;
RegionEvictorTask(final CachePerfStats stats, final List<LocalRegion> regions,
final HeapEvictor evictor, final long bytesToEvictPerTask, StatisticsClock statisticsClock) {
this.stats = stats;
this.evictor = evictor;
this.regions = regions;
this.bytesToEvictPerTask = bytesToEvictPerTask;
this.statisticsClock = statisticsClock;
}
List<LocalRegion> getRegionList() {
synchronized (this.regions) {
return this.regions;
}
}
private HeapEvictor getHeapEvictor() {
return this.evictor;
}
@Override
public void run() {
this.stats.incEvictorJobsStarted();
try {
long totalBytesEvicted = 0;
while (true) {
final long start = statisticsClock.getTime();
synchronized (this.regions) {
if (this.regions.isEmpty()) {
return;
}
// consider trying Fisher-Yates shuffle algorithm
for (Iterator<LocalRegion> iterator = regions.iterator(); iterator.hasNext();) {
LocalRegion region = iterator.next();
try {
long bytesEvicted = region.getRegionMap().centralizedLruUpdateCallback();
if (bytesEvicted == 0) {
iterator.remove();
}
totalBytesEvicted += bytesEvicted;
if (totalBytesEvicted >= bytesToEvictPerTask || !getHeapEvictor().mustEvict()
|| this.regions.isEmpty()) {
return;
}
} catch (RegionDestroyedException e) {
region.getCache().getCancelCriterion().checkCancelInProgress(e);
} catch (RuntimeException e) {
region.getCache().getCancelCriterion().checkCancelInProgress(e);
logger.warn(String.format("Exception: %s occurred during eviction ",
new Object[] {e.getMessage()}), e);
} finally {
long end = statisticsClock.getTime();
this.stats.incEvictWorkTime(end - start);
}
}
}
}
} finally {
this.stats.incEvictorJobsCompleted();
}
}
}