
com.hazelcast.cache.impl.eviction.CacheClearExpiredRecordsTask Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2008-2024, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.cache.impl.eviction;
import com.hazelcast.cache.impl.CachePartitionSegment;
import com.hazelcast.cache.impl.ICacheRecordStore;
import com.hazelcast.cache.impl.operation.CacheClearExpiredOperation;
import com.hazelcast.cache.impl.operation.CacheExpireBatchBackupOperation;
import com.hazelcast.internal.eviction.ClearExpiredRecordsTask;
import com.hazelcast.internal.eviction.ExpiredKey;
import com.hazelcast.internal.nearcache.impl.invalidation.InvalidationQueue;
import com.hazelcast.spi.impl.NodeEngine;
import com.hazelcast.spi.impl.operationservice.Operation;
import com.hazelcast.spi.properties.HazelcastProperty;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import static com.hazelcast.cache.impl.ICacheService.SERVICE_NAME;
import static java.util.Collections.sort;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* Clears expired entries.
*
* This task provides per partition expiration
* operation logic. Fires cleanup operations at most partition
* operation thread count or some factor of it in one round.
*
*
* -
* {@value PROP_TASK_PERIOD_SECONDS}: Interval, in seconds,
* at which the background expiration task is going to run.
* Default value is {@value DEFAULT_TASK_PERIOD_SECONDS} seconds.
*
* -
* {@value PROP_CLEANUP_PERCENTAGE}: Scannable percentage
* of entries in a maps' partition in each round. Default
* percentage is {@value DEFAULT_CLEANUP_PERCENTAGE}%.
*
* -
* {@value PROP_CLEANUP_OPERATION_COUNT}: Number of scannable
* partitions in each round. No default value exists. Dynamically
* calculated against partition-count or partition-thread-count.
*
*
*
*
* These parameters can be set node-wide or system-wide
*
* Node-wide setting example:
*
* Config config = new Config();
* config.setProperty({@value PROP_CLEANUP_OPERATION_COUNT}, "3");
* Hazelcast.newHazelcastInstance(config);
*
*
* System-wide setting example:
*
* System.setProperty({@value PROP_CLEANUP_OPERATION_COUNT}, "3");
*
*/
public class CacheClearExpiredRecordsTask
extends ClearExpiredRecordsTask {
public static final String PROP_CLEANUP_ENABLED = "hazelcast.internal.cache.expiration.cleanup.enabled";
public static final String PROP_CLEANUP_PERCENTAGE = "hazelcast.internal.cache.expiration.cleanup.percentage";
public static final String PROP_TASK_PERIOD_SECONDS = "hazelcast.internal.cache.expiration.task.period.seconds";
public static final String PROP_CLEANUP_OPERATION_COUNT = "hazelcast.internal.cache.expiration.cleanup.operation.count";
private static final int DEFAULT_TASK_PERIOD_SECONDS = 5;
private static final int DEFAULT_CLEANUP_PERCENTAGE = 10;
private static final HazelcastProperty TASK_PERIOD_SECONDS
= new HazelcastProperty(PROP_TASK_PERIOD_SECONDS, DEFAULT_TASK_PERIOD_SECONDS, SECONDS);
private static final HazelcastProperty CLEANUP_PERCENTAGE
= new HazelcastProperty(PROP_CLEANUP_PERCENTAGE, DEFAULT_CLEANUP_PERCENTAGE);
private static final HazelcastProperty CLEANUP_OPERATION_COUNT = new HazelcastProperty(PROP_CLEANUP_OPERATION_COUNT);
private static final HazelcastProperty CLEANUP_ENABLED = new HazelcastProperty(PROP_CLEANUP_ENABLED, true);
private final Comparator partitionSegmentComparator = (o1, o2) -> {
long s1 = o1.getLastCleanupTimeBeforeSorting();
long s2 = o2.getLastCleanupTimeBeforeSorting();
return (s1 < s2) ? -1 : ((s1 == s2) ? 0 : 1);
};
public CacheClearExpiredRecordsTask(CachePartitionSegment[] containers, NodeEngine nodeEngine) {
super(SERVICE_NAME, containers, CLEANUP_ENABLED, CLEANUP_OPERATION_COUNT,
CLEANUP_PERCENTAGE, TASK_PERIOD_SECONDS, nodeEngine);
}
@Override
public void tryToSendBackupExpiryOp(ICacheRecordStore store, boolean sendIfAtBatchSize) {
InvalidationQueue expiredKeys = store.getExpiredKeysQueue();
int totalBackupCount = store.getConfig().getTotalBackupCount();
int partitionId = store.getPartitionId();
toBackupSender.trySendExpiryOp(store, expiredKeys,
totalBackupCount, partitionId, sendIfAtBatchSize);
}
@Override
public Iterator storeIterator(CachePartitionSegment container) {
return container.recordStoreIterator();
}
@Override
protected Operation newPrimaryExpiryOp(int expirationPercentage, CachePartitionSegment container) {
return new CacheClearExpiredOperation(expirationPercentage)
.setNodeEngine(nodeEngine)
.setCallerUuid(nodeEngine.getLocalMember().getUuid())
.setPartitionId(container.getPartitionId())
.setValidateTarget(false)
.setServiceName(SERVICE_NAME);
}
@Override
protected Operation newBackupExpiryOp(ICacheRecordStore store, Collection expiredKeys) {
return new CacheExpireBatchBackupOperation(store.getName(), expiredKeys, store.size());
}
@Override
protected void equalizeBackupSizeWithPrimary(CachePartitionSegment container) {
Iterator iterator = container.recordStoreIterator();
while (iterator.hasNext()) {
ICacheRecordStore recordStore = iterator.next();
int totalBackupCount = recordStore.getConfig().getTotalBackupCount();
int partitionId = recordStore.getPartitionId();
toBackupSender.invokeBackupExpiryOperation(Collections.emptyList(),
totalBackupCount, partitionId, recordStore);
}
}
@Override
protected boolean hasExpiredKeyToSendBackup(CachePartitionSegment container) {
Iterator iterator = container.recordStoreIterator();
while (iterator.hasNext()) {
ICacheRecordStore store = iterator.next();
if (!store.getExpiredKeysQueue().isEmpty()) {
return true;
}
}
return false;
}
@Override
protected boolean hasRunningCleanup(CachePartitionSegment container) {
return container.hasRunningCleanupOperation();
}
@Override
protected void setHasRunningCleanup(CachePartitionSegment container) {
container.setRunningCleanupOperation(true);
}
@Override
protected boolean isContainerEmpty(CachePartitionSegment container) {
Iterator iterator = container.recordStoreIterator();
while (iterator.hasNext()) {
ICacheRecordStore store = iterator.next();
if (store.size() > 0) {
return false;
}
}
return true;
}
@Override
protected boolean notHaveAnyExpirableRecord(CachePartitionSegment container) {
Iterator iterator = container.recordStoreIterator();
while (iterator.hasNext()) {
ICacheRecordStore store = iterator.next();
if (store.isExpirable()) {
return false;
}
}
return true;
}
@Override
protected long getLastCleanupTime(CachePartitionSegment container) {
return container.getLastCleanupTime();
}
@Override
protected void sortPartitionContainers(List containers) {
for (CachePartitionSegment segment : containers) {
segment.storeLastCleanupTime();
}
sort(containers, partitionSegmentComparator);
}
@Override
protected ProcessablePartitionType getProcessablePartitionType() {
return ProcessablePartitionType.PRIMARY_PARTITION;
}
@Override
public String toString() {
return CacheClearExpiredRecordsTask.class.getName();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy