1
- package org .radarcns ;
1
+ package org .radarcns . util ;
2
2
3
3
import java .io .BufferedWriter ;
4
4
import java .io .Closeable ;
14
14
import org .slf4j .Logger ;
15
15
import org .slf4j .LoggerFactory ;
16
16
17
+ /**
18
+ * Caches open file handles. If more than the limit is cached, the half of the files that were used
19
+ * the longest ago cache are evicted from cache.
20
+ */
17
21
public class FileCache implements Flushable , Closeable {
18
22
private static final Logger logger = LoggerFactory .getLogger (FileCache .class );
19
23
@@ -22,35 +26,56 @@ public class FileCache implements Flushable, Closeable {
22
26
23
27
public FileCache (int maxFiles ) {
24
28
this .maxFiles = maxFiles ;
25
- this .caches = new HashMap <>();
29
+ this .caches = new HashMap <>(maxFiles * 4 / 3 + 1 );
26
30
}
27
31
28
- public void appendLine (File file , String data ) throws IOException {
32
+ /**
33
+ * Append a line to given file. This will append a line ending to given data.
34
+ * If the file handle and writer are already open in this cache,
35
+ * those will be used. Otherwise, the file will be opened and the file handle cached.
36
+ *
37
+ * @param file file to append data to
38
+ * @param data data without line ending
39
+ * @return true if the cache was used, false if a new file was opened.
40
+ * @throws IOException when failing to open a file or writing to it.
41
+ */
42
+ public boolean appendLine (File file , String data ) throws IOException {
29
43
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
- }
44
+ if (cache != null ) {
45
+ cache .appendLine (data );
46
+ return true ;
47
+ } else {
48
+ ensureCapacity ();
40
49
41
50
File dir = file .getParentFile ();
42
51
if (!file .getParentFile ().exists ()){
43
52
if (dir .mkdirs ()) {
44
- logger .info ("Created directory: {}" , dir .getAbsolutePath ());
53
+ logger .debug ("Created directory: {}" , dir .getAbsolutePath ());
45
54
} else {
46
- logger .warn ("FAILED to create directory: " + dir .getAbsolutePath ());
55
+ logger .warn ("FAILED to create directory: {}" , dir .getAbsolutePath ());
47
56
}
48
57
}
49
58
50
59
cache = new SingleFileCache (file );
51
60
caches .put (file , cache );
61
+ cache .appendLine (data );
62
+ return false ;
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Ensure that a new filecache can be added. Evict files used longest ago from cache if needed.
68
+ */
69
+ private void ensureCapacity () throws IOException {
70
+ if (caches .size () == maxFiles ) {
71
+ ArrayList <SingleFileCache > cacheList = new ArrayList <>(caches .values ());
72
+ Collections .sort (cacheList );
73
+ for (int i = 0 ; i < cacheList .size () / 2 ; i ++) {
74
+ SingleFileCache rmCache = cacheList .get (i );
75
+ caches .remove (rmCache .getFile ());
76
+ rmCache .close ();
77
+ }
52
78
}
53
- cache .appendLine (data );
54
79
}
55
80
56
81
@ Override
0 commit comments