1515import java .io .File ;
1616import java .io .IOException ;
1717import java .util .ArrayList ;
18+ import java .util .Collections ;
1819import java .util .List ;
1920import java .util .Objects ;
21+ import java .util .function .Predicate ;
22+ import java .util .logging .Logger ;
23+ import java .util .regex .Pattern ;
2024import javax .annotation .Nullable ;
2125import org .jetbrains .annotations .NotNull ;
2226
2327public final class FolderManager implements Closeable {
2428 private final File folder ;
2529 private final Clock clock ;
2630 private final FileStorageConfiguration configuration ;
31+ private final Logger logger = Logger .getLogger (FolderManager .class .getName ());
32+ private static final Pattern NUMBER_PATTERN = Pattern .compile ("\\ d+" );
2733 @ Nullable private ReadableFile currentReadableFile ;
2834 @ Nullable private WritableFile currentWritableFile ;
2935
@@ -46,19 +52,33 @@ public FolderManager(File folder, FileStorageConfiguration configuration, Clock
4652 this .clock = clock ;
4753 }
4854
55+ static class CacheFile {
56+ private final File file ;
57+ private final long createdTimeMillis ;
58+
59+ CacheFile (File file , long createdTimeMillis ) {
60+ this .file = file ;
61+ this .createdTimeMillis = createdTimeMillis ;
62+ }
63+
64+ long getCreatedTimeMillis () {
65+ return createdTimeMillis ;
66+ }
67+ }
68+
4969 @ Override
5070 public void close () throws IOException {
5171 closeCurrentFiles ();
5272 }
5373
5474 @ Nullable
55- public synchronized ReadableFile getReadableFile () throws IOException {
75+ public synchronized ReadableFile getReadableFile (Predicate <CacheFile > excludeFiles )
76+ throws IOException {
5677 currentReadableFile = null ;
57- File readableFile = findReadableFile ( );
58- if (readableFile != null ) {
78+ CacheFile selectedFile = selectReadableFile ( listCacheFiles ( excludeFiles ) );
79+ if (selectedFile != null ) {
5980 currentReadableFile =
60- new ReadableFile (
61- readableFile , Long .parseLong (readableFile .getName ()), clock , configuration );
81+ new ReadableFile (selectedFile .file , selectedFile .createdTimeMillis , clock , configuration );
6282 return currentReadableFile ;
6383 }
6484 return null ;
@@ -93,29 +113,56 @@ public synchronized void clear() throws IOException {
93113 }
94114 }
95115
116+ private List <CacheFile > listCacheFiles (Predicate <CacheFile > exclude ) {
117+ File [] existingFiles = folder .listFiles ();
118+ if (existingFiles == null ) {
119+ return Collections .emptyList ();
120+ }
121+ ArrayList <CacheFile > files = new ArrayList <>();
122+ for (File file : existingFiles ) {
123+ CacheFile cacheFile = fileToCacheFile (file );
124+ if (cacheFile != null && !exclude .test (cacheFile )) {
125+ files .add (cacheFile );
126+ }
127+ }
128+ return Collections .unmodifiableList (files );
129+ }
130+
131+ @ Nullable
132+ private CacheFile fileToCacheFile (File file ) {
133+ String fileName = file .getName ();
134+ if (!NUMBER_PATTERN .matcher (fileName ).matches ()) {
135+ logger .finer (String .format ("Invalid cache file name: '%s'" , fileName ));
136+ return null ;
137+ }
138+ return new CacheFile (file , Long .parseLong (fileName ));
139+ }
140+
96141 @ Nullable
97- private File findReadableFile () throws IOException {
142+ private CacheFile selectReadableFile (List <CacheFile > files ) throws IOException {
143+ if (files .isEmpty ()) {
144+ return null ;
145+ }
146+
98147 long currentTime = nowMillis (clock );
99- File [] existingFiles = folder .listFiles ();
100- File oldestFileAvailable = null ;
148+ CacheFile oldestFileAvailable = null ;
101149 long oldestFileCreationTimeMillis = 0 ;
102- if (existingFiles != null ) {
103- for (File existingFile : existingFiles ) {
104- long existingFileCreationTimeMillis = Long .parseLong (existingFile .getName ());
105- if (isReadyToBeRead (currentTime , existingFileCreationTimeMillis )
106- && !hasExpiredForReading (currentTime , existingFileCreationTimeMillis )) {
107- if (oldestFileAvailable == null
108- || existingFileCreationTimeMillis < oldestFileCreationTimeMillis ) {
109- oldestFileCreationTimeMillis = existingFileCreationTimeMillis ;
110- oldestFileAvailable = existingFile ;
111- }
150+ for (CacheFile existingFile : files ) {
151+ long existingFileCreationTimeMillis = existingFile .createdTimeMillis ;
152+ if (isReadyToBeRead (currentTime , existingFileCreationTimeMillis )
153+ && !hasExpiredForReading (currentTime , existingFileCreationTimeMillis )) {
154+ if (oldestFileAvailable == null
155+ || existingFileCreationTimeMillis < oldestFileCreationTimeMillis ) {
156+ oldestFileCreationTimeMillis = existingFileCreationTimeMillis ;
157+ oldestFileAvailable = existingFile ;
112158 }
113159 }
114160 }
161+
115162 // Checking if the oldest available file is currently the writable file.
116163 if (oldestFileAvailable != null
117164 && currentWritableFile != null
118- && oldestFileAvailable .equals (currentWritableFile .getFile ())) {
165+ && oldestFileAvailable .file . equals (currentWritableFile .getFile ())) {
119166 currentWritableFile .close ();
120167 }
121168 return oldestFileAvailable ;
0 commit comments