com.alibaba.excel.cache.Ehcache Maven / Gradle / Ivy
package com.alibaba.excel.cache;
import java.io.File;
import java.util.ArrayList;
import java.util.Optional;
import java.util.UUID;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.ListUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.ehcache.CacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
/**
* Default cache
*
* @author Jiaju Zhuang
*/
@Slf4j
public class Ehcache implements ReadCache {
public static final int BATCH_COUNT = 100;
/**
* Key index
*/
private int activeIndex = 0;
public static final int DEBUG_CACHE_MISS_SIZE = 1000;
public static final int DEBUG_WRITE_SIZE = 100 * 10000;
private ArrayList dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
private static final CacheManager FILE_CACHE_MANAGER;
private static final CacheConfiguration FILE_CACHE_CONFIGURATION;
private static final CacheManager ACTIVE_CACHE_MANAGER;
private static final File CACHE_PATH_FILE;
private final CacheConfiguration activeCacheConfiguration;
/**
* Bulk storage data
*/
private org.ehcache.Cache fileCache;
/**
* Currently active cache
*/
private org.ehcache.Cache activeCache;
private String cacheAlias;
/**
* Count the number of cache misses
*/
private int cacheMiss = 0;
@Deprecated
public Ehcache(Integer maxCacheActivateSize) {
this(maxCacheActivateSize, null);
}
public Ehcache(Integer maxCacheActivateSize, Integer maxCacheActivateBatchCount) {
// In order to be compatible with the code
// If the user set up `maxCacheActivateSize`, then continue using it
if (maxCacheActivateSize != null) {
this.activeCacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(maxCacheActivateSize, MemoryUnit.MB))
.build();
} else {
this.activeCacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(maxCacheActivateBatchCount, EntryUnit.ENTRIES))
.build();
}
}
static {
CACHE_PATH_FILE = FileUtils.createCacheTmpFile();
FILE_CACHE_MANAGER =
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(CACHE_PATH_FILE)).build(
true);
ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true);
FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Integer.class, ArrayList.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
.disk(20, MemoryUnit.GB)).build();
}
@Override
public void init(AnalysisContext analysisContext) {
cacheAlias = UUID.randomUUID().toString();
try {
fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
} catch (IllegalStateException e) {
//fix Issue #2693,Temporary files may be deleted if there is no operation for a long time, so they need
// to be recreated.
if (CACHE_PATH_FILE.exists()) {
throw e;
}
synchronized (Ehcache.class) {
if (!CACHE_PATH_FILE.exists()) {
if (log.isDebugEnabled()) {
log.debug("cache file dir is not exist retry create");
}
FileUtils.createDirectory(CACHE_PATH_FILE);
}
}
fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
}
activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration);
}
@Override
public void put(String value) {
dataList.add(value);
if (dataList.size() >= BATCH_COUNT) {
fileCache.put(activeIndex, dataList);
activeIndex++;
dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
if (log.isDebugEnabled()) {
int alreadyPut = activeIndex * BATCH_COUNT + dataList.size();
if (alreadyPut % DEBUG_WRITE_SIZE == 0) {
log.debug("Already put :{}", alreadyPut);
}
}
}
@Override
public String get(Integer key) {
if (key == null || key < 0) {
return null;
}
int route = key / BATCH_COUNT;
ArrayList dataList = activeCache.get(route);
if (dataList == null) {
dataList = fileCache.get(route);
activeCache.put(route, dataList);
if (log.isDebugEnabled()) {
if (cacheMiss++ % DEBUG_CACHE_MISS_SIZE == 0) {
log.debug("Cache misses count:{}", cacheMiss);
}
}
}
return dataList.get(key % BATCH_COUNT);
}
@Override
public void putFinished() {
if (CollectionUtils.isEmpty(dataList)) {
return;
}
fileCache.put(activeIndex, dataList);
}
@Override
public void destroy() {
FILE_CACHE_MANAGER.removeCache(cacheAlias);
ACTIVE_CACHE_MANAGER.removeCache(cacheAlias);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy