/** 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());
  }