package com.think.uiloader.data.cache.internal;
import android.annotation.SuppressLint;
import java.io.File;
import java.util.List;
/**
* Created by borney on 3/1/17.
*/
@SuppressLint("NewApi")
class DiskCacheManager implements Cache {
private FileManager fileManager;
private String cacheDir;
private int maxCount;
private int maxSpace;
private long age;
DiskCacheManager(FileManager fileManager, String cacheDir, int maxCount, int maxSpace,
long age) {
this.fileManager = fileManager;
this.cacheDir = cacheDir;
this.maxCount = maxCount;
this.maxSpace = maxSpace;
this.age = age;
}
@Override
public <T> void putByteMapper(String key, T obj, ByteMapper<T> mapper) {
//ensure total file count and space
byte[] bytes = mapper.getBytes(obj);
ensureTotalCount();
ensureTotalSpace(bytes);
//create cache file
File file = buildFile(key);
createNotExistsParent(file);
//write data to cache file
fileManager.writeBytes(file, bytes);
//update file and it's parent list modify time
updateLastModified(file, System.currentTimeMillis());
}
@Override
public <T> T getByteMapper(String key, ByteMapper<T> mapper) {
File file = buildFile(key);
if (file.exists()) {
byte[] bytes = fileManager.readBytes(file);
return mapper.getObject(bytes);
} else {
return null;
}
}
@Override
public boolean isExpired(String key) {
return isExpired(key, age);
}
@Override
public boolean isExpired(String key, long age) {
File file = buildFile(key);
return System.currentTimeMillis() - file.lastModified() > age;
}
@Override
public void evict(String key) {
File file = buildFile(key);
fileManager.deleFile(file);
}
@Override
public void evictAll() {
fileManager.deleFile(new File(cacheDir));
}
@Override
public boolean isCached(String key) {
File file = buildFile(key);
return file.exists() && fileManager.calFileSize(file) != 0;
}
private void ensureTotalSpace(byte[] bytes) {
int objSize = bytes.length;
File file = new File(cacheDir);
long cacheSize = fileManager.calFileSize(file);
while (cacheSize + objSize > maxSpace) {
long removeSize = removeLastModifiedFile(file);
cacheSize -= removeSize;
}
}
private void ensureTotalCount() {
File file = new File(cacheDir);
int size = fileManager.calFileCount(file);
while (size > maxCount) {
removeLastModifiedFile(file);
size--;
}
}
private File buildFile(String key) {
return new File(key);
}
private void createNotExistsParent(File file) {
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
}
private void updateLastModified(File file, long time) {
if (file.getPath().equals(cacheDir)) {
return;
}
file.setLastModified(time);
updateLastModified(file.getParentFile(), time);
}
private long removeLastModifiedFile(File parent) {
List<File> files = fileManager.allFiles(parent);
if (!files.isEmpty()) {
File lastModifyFile = files.get(0);
long removedSize = lastModifyFile.length();
for (File f : files) {
if (f.lastModified() < lastModifyFile.lastModified()) {
lastModifyFile = f;
removedSize = lastModifyFile.length();
}
}
lastModifyFile.delete();
return removedSize;
}
return 0;
}
}