-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathCacheManager.java
More file actions
126 lines (110 loc) · 4.68 KB
/
CacheManager.java
File metadata and controls
126 lines (110 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package top.gregtao.concerto.config;
import top.gregtao.concerto.ConcertoClient;
import top.gregtao.concerto.ConcertoServer;
import top.gregtao.concerto.util.ConcertoRunner;
import top.gregtao.concerto.util.Pair;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
public class CacheManager {
public static String CACHE_ROOT_FOLDER = "Concerto/cache/";
public static CacheManager IMAGE_CACHE_MANAGER = new CacheManager("images");
private final File folder;
private int maxSize = 1000 * 1000 * 100; // 100 MB
public CacheManager(String name) {
this.folder = new File(CACHE_ROOT_FOLDER + name);
if (!this.folder.exists() && !this.folder.mkdirs()) {
throw new RuntimeException("Cannot mkdir");
}
}
public CacheManager(String name, int maxSize) {
this(name);
this.maxSize = maxSize;
}
public static void cleanAllCache() {
Path cacheRoot = Paths.get(CACHE_ROOT_FOLDER);
if (!Files.exists(cacheRoot) || !Files.isDirectory(cacheRoot)) {
ConcertoServer.LOGGER.error("Cache folder does not exist or is not a directory: {}", cacheRoot);
return;
}
try (Stream<Path> walk = Files.walk(cacheRoot, 1)) {
walk.filter(path -> !path.equals(cacheRoot)).forEach(CacheManager::deleteRecursively);
} catch (IOException e) {
ConcertoServer.LOGGER.error("Failed to scan cache folder: {}", cacheRoot, e);
}
}
private static void deleteRecursively(Path path) {
try (Stream<Path> walk = Files.walk(path)) {
walk.sorted(Comparator.reverseOrder()).forEach(p -> {
try {
Files.delete(p);
} catch (IOException e) {
ConcertoServer.LOGGER.error("Failed to delete: {}", p, e);
}
});
} catch (IOException e) {
ConcertoServer.LOGGER.error("Failed to traverse path: {}", path, e);
}
}
public File getChild(String child) {
return new File(this.folder.getAbsolutePath() + "/" + child);
}
public long getTotalSize() {
long size = 0;
for (File file : Objects.requireNonNull(this.folder.listFiles())) {
size += file.isFile() ? file.length() : 0;
}
return size;
}
public void removeEarliest() {
File[] files = this.folder.listFiles();
if (files == null || files.length == 0) return;
AtomicLong size = new AtomicLong();
List<Pair<Pair<File, Long>, Long>> list = Arrays.stream(files).filter(File::isFile).map(file -> {
long len = file.length();
size.addAndGet(len);
try {
BasicFileAttributes attributes = Files.getFileAttributeView(
file.toPath(), BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS).readAttributes();
return Pair.of(Pair.of(file, len), attributes.creationTime().toMillis());
} catch (IOException e) {
ConcertoClient.LOGGER.warn("Error occurs while trying removing a file", e);
return Pair.of(Pair.of(file, len), 0L);
}
}).sorted(Comparator.comparingLong(Pair::getSecond)).toList();
long finalSize = size.get();
int pos = 0;
while (finalSize > this.maxSize && pos < list.size()) {
Pair<File, Long> pair = list.get(pos).getFirst();
if (pair.getFirst().delete()) {
finalSize -= pair.getSecond();
} else {
ConcertoClient.LOGGER.warn("Cannot remove file {}", pair.getFirst().getAbsolutePath());
}
++pos;
}
}
public boolean exists(String filename) {
File file = this.getChild(filename);
return file.exists() && !file.isDirectory();
}
public void addFile(String filename, InputStream inputStream) throws IOException {
File file = this.getChild(filename);
if (file.exists() || (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) || !file.createNewFile()) return;
try (FileOutputStream outputStream = new FileOutputStream(file)) {
outputStream.write(inputStream.readAllBytes());
}
inputStream.close();
if (this.getTotalSize() > this.maxSize) ConcertoRunner.run(this::removeEarliest);
}
}