/** * The {@link InfinispanDirectory#deleteFile(String)} is not deleting the elements from the cache * but instead flagging the file as deletable. This method will really remove the elements from * the cache; should be invoked only by {@link #deleteOrReleaseReadLock(String)} after having * verified that there are no users left in need to read these chunks. * * @param readLockKey the key representing the values to be deleted * @param locksCache the cache containing the locks * @param chunksCache the cache containing the chunks to be deleted * @param metadataCache the cache containing the metadata of elements to be deleted */ static void realFileDelete( FileReadLockKey readLockKey, AdvancedCache<Object, Integer> locksCache, AdvancedCache<?, ?> chunksCache, AdvancedCache<?, ?> metadataCache) { final boolean trace = log.isTraceEnabled(); final String indexName = readLockKey.getIndexName(); final String filename = readLockKey.getFileName(); FileCacheKey key = new FileCacheKey(indexName, filename); if (trace) log.tracef("deleting metadata: %s", key); FileMetadata file = (FileMetadata) metadataCache.remove(key); if (file != null) { // during optimization of index a same file could be deleted twice, so you could // see a null here for (int i = 0; i < file.getNumberOfChunks(); i++) { ChunkCacheKey chunkKey = new ChunkCacheKey(indexName, filename, i); if (trace) log.tracef("deleting chunk: %s", chunkKey); chunksCache.withFlags(Flag.SKIP_REMOTE_LOOKUP, Flag.SKIP_CACHE_LOAD).removeAsync(chunkKey); } } // last operation, as being set as value==0 it prevents others from using it during the // deletion process: if (trace) log.tracef("deleting readlock: %s", readLockKey); locksCache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(readLockKey); }
/** Load implementation for FileCacheKey: must return the metadata of the requested file. */ private FileMetadata loadIntern(final FileCacheKey key) throws IOException { final String fileName = key.getFileName(); final long fileLength = directory.fileLength(fileName); // We're forcing the buffer size of a to-be-read segment to the full file size: final int bufferSize = (int) Math.min(fileLength, (long) autoChunkSize); final FileMetadata meta = new FileMetadata(bufferSize); meta.setSize(fileLength); return meta; }
@Test public void testMultiThreaded() { final Cache<Object, Object> metadata = cacheManager.getCache("metadata"); final Cache<Object, Object> chunks = cacheManager.getCache("chunks"); final Cache<Object, Integer> locks = cacheManager.getCache("locks"); FileMetadata fileMetadata = new FileMetadata(10); fileMetadata.setSize(11); // Make it chunked otherwise no read lock will involved metadata.put(new FileCacheKey("indexName", "fileName", -1), fileMetadata); final LocalLockMergingSegmentReadLocker locker = new LocalLockMergingSegmentReadLocker(locks, chunks, metadata, "indexName", -1); final AtomicBoolean testFailed = new AtomicBoolean(false); final ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS); Runnable stressor = new Runnable() { @Override public void run() { try { int counter = 0; while (testFailed.get() == false) { locker.acquireReadLock("fileName"); Thread.sleep(2); locker.deleteOrReleaseReadLock("fileName"); // Take a break every now and a again to try and avoid the same LocalReadLock being // used constantly if (counter++ % 900 == 0) { System.out.print("."); Thread.sleep(7); } if (metadata.get(new FileCacheKey("indexName", "fileName", -1)) == null) { // Shouldn't have been deleted! testFailed.set(true); System.out.print("X"); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } }; for (int i = 0; i < NUM_THREADS; i++) { exec.execute(stressor); } System.out.println("Stressor threads started..."); exec.shutdown(); try { exec.awaitTermination(TEST_MINUTES_MAX, TimeUnit.MINUTES); } catch (InterruptedException e) { exec.shutdownNow(); } AssertJUnit.assertFalse(testFailed.get()); }
public void testAutoChunkingOnLargeFiles() throws IOException { Directory mockDirectory = createMockDirectory(); FileCacheKey k = new FileCacheKey(INDEX_NAME, FILE_NAME, segmentId); DirectoryLoaderAdaptor adaptor = new DirectoryLoaderAdaptor(mockDirectory, INDEX_NAME, AUTO_BUFFER, -1); Object loaded = adaptor.load(k); AssertJUnit.assertTrue(loaded instanceof FileMetadata); FileMetadata metadata = (FileMetadata) loaded; AssertJUnit.assertEquals(TEST_SIZE, metadata.getSize()); AssertJUnit.assertEquals(AUTO_BUFFER, metadata.getBufferSize()); }