2020/**
2121 * @author Gianlu
2222 */
23- public class CacheManager {
23+ public class CacheManager implements Closeable {
2424 static final byte BYTE_CREATED_AT = 0b1111111;
2525 private static final Logger LOGGER = Logger .getLogger (CacheManager .class );
2626 private static final long CLEAN_UP_THRESHOLD = TimeUnit .DAYS .toMillis (7 );
@@ -29,6 +29,7 @@ public class CacheManager {
2929 private final Map <String , Handler > loadedHandlers ;
3030 private final ControlTable controlTable ;
3131 private final ExecutorService executorService = Executors .newCachedThreadPool (new NameThreadFactory (r -> "cache-io-" + r .hashCode ()));
32+ private volatile boolean closed = false ;
3233
3334 public CacheManager (@ NotNull CacheConfiguration conf ) throws IOException {
3435 this .enabled = conf .cacheEnabled ();
@@ -49,6 +50,7 @@ public CacheManager(@NotNull CacheConfiguration conf) throws IOException {
4950
5051 @ Nullable
5152 Handler handler (@ NotNull ByteString fileId ) {
53+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
5254 if (!enabled ) return null ;
5355
5456 String hexId = Utils .bytesToHex (fileId );
@@ -62,6 +64,21 @@ Handler handler(@NotNull ByteString fileId) {
6264 });
6365 }
6466
67+ @ Override
68+ public void close () throws IOException {
69+ closed = true ;
70+ executorService .shutdown ();
71+
72+ if (controlTable != null ) controlTable .safeSave ();
73+
74+ if (loadedHandlers != null ) {
75+ for (Handler handler : loadedHandlers .values ())
76+ handler .close ();
77+
78+ loadedHandlers .clear ();
79+ }
80+ }
81+
6582 public interface CacheConfiguration {
6683 boolean cacheEnabled ();
6784
@@ -134,6 +151,8 @@ private void safeSave() {
134151 }
135152
136153 void writtenChunk (@ NotNull String fileId , int index ) {
154+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
155+
137156 for (CacheEntry entry : entries ) {
138157 if (fileId .equals (entry .hexId ))
139158 entry .writtenChunk (index );
@@ -143,10 +162,14 @@ void writtenChunk(@NotNull String fileId, int index) {
143162 }
144163
145164 void writeHeaders (@ NotNull String fileId , byte [] headersId , byte [][] headersData , short chunksCount ) {
165+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
166+
146167 entries .add (new CacheEntry (fileId , headersId , headersData , chunksCount ));
147168 }
148169
149170 public void remove (@ NotNull String fileId ) {
171+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
172+
150173 Iterator <CacheEntry > iterator = entries .iterator ();
151174 while (iterator .hasNext ()) {
152175 CacheEntry entry = iterator .next ();
@@ -160,6 +183,8 @@ public void remove(@NotNull String fileId) {
160183 }
161184
162185 void requestHeaders (@ NotNull String fileId , @ NotNull AudioFile file ) {
186+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
187+
163188 for (CacheEntry entry : entries ) {
164189 if (fileId .equals (entry .hexId )) {
165190 entry .requestHeaders (file );
@@ -286,6 +311,7 @@ private Handler(@NotNull String fileId) throws IOException {
286311 }
287312
288313 boolean has (int chunk ) {
314+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
289315 return controlTable .has (fileId , chunk );
290316 }
291317
@@ -295,10 +321,12 @@ public void close() throws IOException {
295321 }
296322
297323 void requestHeaders (@ NotNull AudioFile fetch ) {
324+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
298325 executorService .execute (() -> controlTable .requestHeaders (fileId , fetch ));
299326 }
300327
301328 void requestChunk (int index , @ NotNull AudioFile file ) {
329+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
302330 executorService .execute (() -> {
303331 try {
304332 cache .seek (index * CHUNK_SIZE );
@@ -314,20 +342,24 @@ void requestChunk(int index, @NotNull AudioFile file) {
314342 }
315343
316344 public void write (byte [] buffer , int index ) throws IOException {
345+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
317346 cache .seek (index * CHUNK_SIZE );
318347 cache .write (buffer );
319348 controlTable .writtenChunk (fileId , index );
320349 }
321350
322351 public void remove () {
352+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
323353 controlTable .remove (fileId );
324354 }
325355
326356 void writeHeaders (byte [] headersId , byte [][] headersData , short chunksCount ) {
357+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
327358 controlTable .writeHeaders (fileId , headersId , headersData , chunksCount );
328359 }
329360
330361 boolean hasHeaders () {
362+ if (closed ) throw new IllegalStateException ("CacheManager is closed!" );
331363 return controlTable .hasHeaders (fileId );
332364 }
333365 }
0 commit comments