Skip to content

Commit 4028f2f

Browse files
committed
Use a file cache to reduce file open/close operations
1 parent a610722 commit 4028f2f

File tree

3 files changed

+176
-84
lines changed

3 files changed

+176
-84
lines changed
Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,112 @@
11
package org.radarcns;
22

3-
/**
4-
* Created by joris on 13/04/2017.
5-
*/
6-
public class FileCache {
3+
import java.io.BufferedWriter;
4+
import java.io.Closeable;
5+
import java.io.File;
6+
import java.io.FileWriter;
7+
import java.io.Flushable;
8+
import java.io.IOException;
9+
import java.io.Writer;
10+
import java.util.ArrayList;
11+
import java.util.Collections;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
716

17+
public class FileCache implements Flushable, Closeable {
18+
private static final Logger logger = LoggerFactory.getLogger(FileCache.class);
19+
20+
private final int maxFiles;
21+
private final Map<File, SingleFileCache> caches;
22+
23+
public FileCache(int maxFiles) {
24+
this.maxFiles = maxFiles;
25+
this.caches = new HashMap<>();
26+
}
27+
28+
public void appendLine(File file, String data) throws IOException {
29+
SingleFileCache cache = caches.get(file);
30+
if (cache == null) {
31+
if (caches.size() == maxFiles) {
32+
ArrayList<SingleFileCache> cacheList = new ArrayList<>(caches.values());
33+
Collections.sort(cacheList);
34+
for (int i = 0; i < cacheList.size() / 2; i++) {
35+
SingleFileCache rmCache = cacheList.get(i);
36+
caches.remove(rmCache.getFile());
37+
rmCache.close();
38+
}
39+
}
40+
41+
File dir = file.getParentFile();
42+
if (!file.getParentFile().exists()){
43+
if (dir.mkdirs()) {
44+
logger.info("Created directory: {}", dir.getAbsolutePath());
45+
} else {
46+
logger.warn("FAILED to create directory: " + dir.getAbsolutePath());
47+
}
48+
}
49+
50+
cache = new SingleFileCache(file);
51+
caches.put(file, cache);
52+
}
53+
cache.appendLine(data);
54+
}
55+
56+
@Override
57+
public void flush() throws IOException {
58+
for (SingleFileCache cache : caches.values()) {
59+
cache.flush();
60+
}
61+
}
62+
63+
@Override
64+
public void close() throws IOException {
65+
try {
66+
for (SingleFileCache cache : caches.values()) {
67+
cache.close();
68+
}
69+
} finally {
70+
caches.clear();
71+
}
72+
}
73+
74+
private static class SingleFileCache implements Closeable, Flushable, Comparable<SingleFileCache> {
75+
private final BufferedWriter bufferedWriter;
76+
private final Writer fileWriter;
77+
private final File file;
78+
private long lastUse;
79+
80+
private SingleFileCache(File file) throws IOException {
81+
this.file = file;
82+
this.fileWriter = new FileWriter(file, true);
83+
this.bufferedWriter = new BufferedWriter(fileWriter);
84+
}
85+
86+
private void appendLine(String data) throws IOException {
87+
bufferedWriter.write(data);
88+
bufferedWriter.write('\n');
89+
lastUse = System.nanoTime();
90+
}
91+
92+
@Override
93+
public void close() throws IOException {
94+
bufferedWriter.close();
95+
fileWriter.close();
96+
}
97+
98+
@Override
99+
public void flush() throws IOException {
100+
bufferedWriter.flush();
101+
}
102+
103+
@Override
104+
public int compareTo(SingleFileCache other) {
105+
return Long.compare(lastUse, other.lastUse);
106+
}
107+
108+
private File getFile() {
109+
return file;
110+
}
111+
}
8112
}

src/main/java/org/radarcns/Frequency.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@
33
import org.apache.commons.collections.MapIterator;
44
import org.apache.commons.collections.keyvalue.MultiKey;
55
import org.apache.commons.collections.map.MultiKeyMap;
6-
import org.apache.logging.log4j.LogManager;
7-
import org.apache.logging.log4j.Logger;
86

97
import java.io.*;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
1010

1111

1212
public class Frequency {
13-
private static final Logger logger = LogManager.getLogger(RestructureAvroRecords.class);
13+
private static final Logger logger = LoggerFactory.getLogger(Frequency.class);
1414

1515
private MultiKeyMap bins = new MultiKeyMap();
16-
private String binFilePath;
16+
private File binFilePath;
1717

18-
public void setBinFilePath(String binFilePath) {
18+
public void setBinFilePath(File binFilePath) {
1919
this.binFilePath = binFilePath;
2020
}
2121

2222
public MultiKeyMap getBins() {
2323
return bins;
2424
}
2525

26-
public void addToBin(String topicName, String id, String timestamp, Integer countToAdd) {
26+
public void addToBin(String topicName, String id, String timestamp, int countToAdd) {
2727
Integer count = (Integer) bins.get(topicName, id, timestamp);
2828
if (count == null) {
2929
bins.put(topicName, id, timestamp, countToAdd);
@@ -32,7 +32,7 @@ public void addToBin(String topicName, String id, String timestamp, Integer coun
3232
}
3333
}
3434

35-
public void addToBin(String topicName, String id, Double time, Integer countToAdd) {
35+
public void addToBin(String topicName, String id, Double time, int countToAdd) {
3636
// Hour resolution
3737
String hourlyTimestamp = RestructureAvroRecords.createHourTimestamp(time);
3838

0 commit comments

Comments
 (0)