org.springframework.data.gemfire.DiskStoreFactoryBean Maven / Gradle / Ivy
/*
* Copyright 2010-2020 the original author or authors.
*
* 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
*
* https://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.springframework.data.gemfire;
import static java.util.stream.StreamSupport.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.GemFireCache;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer;
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Spring {@link FactoryBean} used to create {@link DiskStore}.
*
* @author David Turanski
* @author John Blum
* @see org.apache.geode.cache.DiskStore
* @see org.apache.geode.cache.DiskStoreFactory
* @see org.apache.geode.cache.GemFireCache
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
*/
@SuppressWarnings("unused")
public class DiskStoreFactoryBean extends AbstractFactoryBeanSupport implements InitializingBean {
private Boolean allowForceCompaction;
private Boolean autoCompact;
private DiskStore diskStore;
private GemFireCache cache;
private Integer compactionThreshold;
private Integer queueSize;
private Integer writeBufferSize;
private Float diskUsageCriticalPercentage;
private Float diskUsageWarningPercentage;
private Long maxOplogSize;
private Long timeInterval;
private List diskStoreConfigurers = Collections.emptyList();
private DiskStoreConfigurer compositeDiskStoreConfigurer = (beanName, bean) ->
nullSafeCollection(diskStoreConfigurers).forEach(diskStoreConfigurer ->
diskStoreConfigurer.configure(beanName, bean));
private List diskDirs;
@Override
public void afterPropertiesSet() throws Exception {
String diskStoreName = resolveDiskStoreName();
applyDiskStoreConfigurers(diskStoreName);
GemFireCache cache = resolveCache(diskStoreName);
DiskStoreFactory diskStoreFactory = postProcess(configure(createDiskStoreFactory(cache)));
this.diskStore = postProcess(newDiskStore(diskStoreFactory, diskStoreName));
}
/* (non-Javadoc) */
private void applyDiskStoreConfigurers(String diskStoreName) {
applyDiskStoreConfigurers(diskStoreName, getCompositeDiskStoreConfigurer());
}
/**
* Null-safe operation to apply the given array of {@link DiskStoreConfigurer DiskStoreConfigurers}
* to this {@link DiskStoreFactoryBean}.
*
* @param diskStoreName {@link String} containing the name of the {@link DiskStore}.
* @param diskStoreConfigurers array of {@link DiskStoreConfigurer DiskStoreConfigurers} applied
* to this {@link DiskStoreFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
* @see #applyDiskStoreConfigurers(String, Iterable)
*/
protected void applyDiskStoreConfigurers(String diskStoreName, DiskStoreConfigurer... diskStoreConfigurers) {
applyDiskStoreConfigurers(diskStoreName,
Arrays.asList(nullSafeArray(diskStoreConfigurers, DiskStoreConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers}
* to this {@link DiskStoreFactoryBean}.
*
* @param diskStoreName {@link String} containing the name of the {@link DiskStore}.
* @param diskStoreConfigurers {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers} applied
* to this {@link DiskStoreFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
*/
protected void applyDiskStoreConfigurers(String diskStoreName, Iterable diskStoreConfigurers) {
stream(nullSafeIterable(diskStoreConfigurers).spliterator(), false)
.forEach(diskStoreConfigurer -> diskStoreConfigurer.configure(diskStoreName, this));
}
/* (non-Javadoc) */
private GemFireCache resolveCache(String diskStoreName) {
return Optional.ofNullable(this.cache)
.orElseThrow(() -> newIllegalStateException("Cache is required to create DiskStore [%s]", diskStoreName));
}
/* (non-Javadoc) */
final String resolveDiskStoreName() {
return Optional.ofNullable(getBeanName()).filter(StringUtils::hasText)
.orElse(DiskStoreFactory.DEFAULT_DISK_STORE_NAME);
}
/**
* Creates an instance of {@link DiskStoreFactory} using the given {@link GemFireCache} in order to
* construct, configure and initialize a new {@link DiskStore}.
*
* @param cache reference to the {@link GemFireCache} used to create the {@link DiskStoreFactory}.
* @return a new instance of {@link DiskStoreFactory}.
* @see org.apache.geode.cache.GemFireCache#createDiskStoreFactory()
* @see org.apache.geode.cache.DiskStoreFactory
*/
protected DiskStoreFactory createDiskStoreFactory(GemFireCache cache) {
return cache.createDiskStoreFactory();
}
/**
* Configures the given {@link DiskStoreFactory} with the configuration settings present
* on this {@link DiskStoreFactoryBean}
*
* @param diskStoreFactory {@link DiskStoreFactory} to configure.
* @return the given {@link DiskStoreFactory}
* @see org.apache.geode.cache.DiskStoreFactory
*/
protected DiskStoreFactory configure(DiskStoreFactory diskStoreFactory) {
Optional.ofNullable(this.allowForceCompaction).ifPresent(diskStoreFactory::setAllowForceCompaction);
Optional.ofNullable(this.autoCompact).ifPresent(diskStoreFactory::setAutoCompact);
Optional.ofNullable(this.compactionThreshold).ifPresent(diskStoreFactory::setCompactionThreshold);
Optional.ofNullable(this.diskUsageCriticalPercentage).ifPresent(diskStoreFactory::setDiskUsageCriticalPercentage);
Optional.ofNullable(this.diskUsageWarningPercentage).ifPresent(diskStoreFactory::setDiskUsageWarningPercentage);
Optional.ofNullable(this.maxOplogSize).ifPresent(diskStoreFactory::setMaxOplogSize);
Optional.ofNullable(this.queueSize).ifPresent(diskStoreFactory::setQueueSize);
Optional.ofNullable(this.timeInterval).ifPresent(diskStoreFactory::setTimeInterval);
Optional.ofNullable(this.writeBufferSize).ifPresent(diskStoreFactory::setWriteBufferSize);
Optional.ofNullable(this.diskDirs).filter(diskDirs -> !CollectionUtils.isEmpty(diskDirs))
.ifPresent(diskDirs -> {
File[] diskDirFiles = new File[diskDirs.size()];
int[] diskDirSizes = new int[diskDirs.size()];
for (int index = 0; index < diskDirs.size(); index++) {
DiskDir diskDir = diskDirs.get(index);
diskDirFiles[index] = new File(diskDir.location);
diskDirSizes[index] = Optional.ofNullable(diskDir.maxSize)
.orElse(DiskStoreFactory.DEFAULT_DISK_DIR_SIZE);
}
diskStoreFactory.setDiskDirsAndSizes(diskDirFiles, diskDirSizes);
});
return diskStoreFactory;
}
/**
* Constructs a new instance of {@link DiskStore} with the given {@link String name}
* using the provided {@link DiskStoreFactory}
*
* @param diskStoreFactory {@link DiskStoreFactory} used to create the {@link DiskStore}.
* @param diskStoreName {@link String} containing the name of the new {@link DiskStore}.
* @return a new instance of {@link DiskStore} with the given {@link String name}.
* @see org.apache.geode.cache.DiskStoreFactory
* @see org.apache.geode.cache.DiskStore
*/
protected DiskStore newDiskStore(DiskStoreFactory diskStoreFactory, String diskStoreName) {
return diskStoreFactory.create(diskStoreName);
}
/**
* Post-process the {@link DiskStoreFactory} with any custom {@link DiskStoreFactory} or {@link DiskStore}
* configuration settings as required by the application.
*
* @param diskStoreFactory {@link DiskStoreFactory} to process.
* @return the given {@link DiskStoreFactory}.
* @see org.apache.geode.cache.DiskStoreFactory
*/
protected DiskStoreFactory postProcess(DiskStoreFactory diskStoreFactory) {
return diskStoreFactory;
}
/**
* Post-process the provided {@link DiskStore} constructed, configured and initialized
* by this {@link DiskStoreFactoryBean}.
*
* @param diskStore {@link DiskStore} to process.
* @return the given {@link DiskStore}.
* @see org.apache.geode.cache.DiskStore
*/
protected DiskStore postProcess(DiskStore diskStore) {
return diskStore;
}
/**
* Returns a reference to the Composite {@link DiskStoreConfigurer} used to apply additional configuration
* to this {@link DiskStoreFactoryBean} on Spring container initialization.
*
* @return the Composite {@link DiskStoreConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
*/
protected DiskStoreConfigurer getCompositeDiskStoreConfigurer() {
return this.compositeDiskStoreConfigurer;
}
@Override
public DiskStore getObject() throws Exception {
return this.diskStore;
}
@Override
@SuppressWarnings("unchecked")
public Class getObjectType() {
return Optional.ofNullable(this.diskStore).map(DiskStore::getClass).orElse((Class) DiskStore.class);
}
public void setCache(GemFireCache cache) {
this.cache = cache;
}
public void setAllowForceCompaction(Boolean allowForceCompaction) {
this.allowForceCompaction = allowForceCompaction;
}
public void setAutoCompact(Boolean autoCompact) {
this.autoCompact = autoCompact;
}
public void setCompactionThreshold(Integer compactionThreshold) {
validateCompactionThreshold(compactionThreshold);
this.compactionThreshold = compactionThreshold;
}
protected void validateCompactionThreshold(Integer compactionThreshold) {
Assert.isTrue(compactionThreshold == null || (compactionThreshold >= 0 && compactionThreshold <= 100),
String.format("The DiskStore's (%1$s) compaction threshold (%2$d) must be an integer value between 0 and 100 inclusive.",
resolveDiskStoreName(), compactionThreshold));
}
public void setDiskDirs(List diskDirs) {
this.diskDirs = diskDirs;
}
/**
* Null-safe operation to set an array of {@link DiskStoreConfigurer DiskStoreConfigurers} used to
* apply additional configuration to this {@link DiskStoreFactoryBean} when using Annotation-based configuration.
*
* @param diskStoreConfigurers array of {@link DiskStoreConfigurer DiskStoreConfigurers} used to apply
* additional configuration to this {@link DiskStoreFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
* @see #setDiskStoreConfigurers(List)
*/
public void setDiskStoreConfigurers(DiskStoreConfigurer... diskStoreConfigurers) {
setDiskStoreConfigurers(Arrays.asList(nullSafeArray(diskStoreConfigurers, DiskStoreConfigurer.class)));
}
/**
* Null-safe operation to set an {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers}
* used to apply additional configuration to this {@link DiskStoreFactoryBean}
* when using Annotation-based configuration.
*
* @param diskStoreConfigurers {@link Iterable } of {@link DiskStoreConfigurer DiskStoreConfigurers} used to
* apply additional configuration to this {@link DiskStoreFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
*/
public void setDiskStoreConfigurers(List diskStoreConfigurers) {
this.diskStoreConfigurers = Optional.ofNullable(diskStoreConfigurers).orElseGet(Collections::emptyList);
}
public void setDiskUsageCriticalPercentage(Float diskUsageCriticalPercentage) {
this.diskUsageCriticalPercentage = diskUsageCriticalPercentage;
}
public void setDiskUsageWarningPercentage(Float diskUsageWarningPercentage) {
this.diskUsageWarningPercentage = diskUsageWarningPercentage;
}
public void setMaxOplogSize(Long maxOplogSize) {
this.maxOplogSize = maxOplogSize;
}
public void setQueueSize(Integer queueSize) {
this.queueSize = queueSize;
}
public void setTimeInterval(Long timeInterval) {
this.timeInterval = timeInterval;
}
public void setWriteBufferSize(Integer writeBufferSize) {
this.writeBufferSize = writeBufferSize;
}
public static class DiskDir {
final Integer maxSize;
final String location;
public DiskDir(String location) {
this.location = location;
this.maxSize = null;
}
public DiskDir(String location, int maxSize) {
this.location = location;
this.maxSize = maxSize;
}
}
}