use of org.apache.bookkeeper.bookie.FileInfoBackingCache.CachedFileInfo in project bookkeeper by apache.
the class TestFileInfoBackingCache method testForDeadlocks.
/**
* Of course this can't prove they don't exist, but
* try to shake them out none the less.
*/
@Test
public void testForDeadlocks() throws Exception {
int numRunners = 20;
int maxLedgerId = 10;
AtomicBoolean done = new AtomicBoolean(false);
FileInfoBackingCache cache = new FileInfoBackingCache((ledgerId, createIfNotFound) -> {
File f = new File(baseDir, String.valueOf(ledgerId));
f.deleteOnExit();
return f;
});
Iterable<Future<Set<CachedFileInfo>>> futures = IntStream.range(0, numRunners).mapToObj((i) -> {
Callable<Set<CachedFileInfo>> c = () -> {
Random r = new Random();
List<CachedFileInfo> fileInfos = new ArrayList<>();
Set<CachedFileInfo> allFileInfos = new HashSet<>();
while (!done.get()) {
if (r.nextBoolean() && fileInfos.size() < 5) {
// take a reference
CachedFileInfo fi = cache.loadFileInfo(r.nextInt(maxLedgerId), masterKey);
Assert.assertFalse(fi.isClosed());
allFileInfos.add(fi);
fileInfos.add(fi);
} else {
// release a reference
Collections.shuffle(fileInfos);
if (!fileInfos.isEmpty()) {
fileInfos.remove(0).release();
}
}
}
for (CachedFileInfo fi : fileInfos) {
Assert.assertFalse(fi.isClosed());
fi.release();
}
return allFileInfos;
};
return executor.submit(c);
}).collect(Collectors.toList());
Thread.sleep(TimeUnit.SECONDS.toMillis(10));
done.set(true);
// ensure all threads are finished operating on cache, before checking any
for (Future<Set<CachedFileInfo>> f : futures) {
f.get();
}
for (Future<Set<CachedFileInfo>> f : futures) {
for (CachedFileInfo fi : f.get()) {
Assert.assertTrue(fi.isClosed());
Assert.assertEquals(FileInfoBackingCache.DEAD_REF, fi.getRefCount());
}
}
// They should be loaded fresh (i.e. this load should be only reference)
for (int i = 0; i < maxLedgerId; i++) {
Assert.assertEquals(1, cache.loadFileInfo(i, masterKey).getRefCount());
}
}
use of org.apache.bookkeeper.bookie.FileInfoBackingCache.CachedFileInfo in project bookkeeper by apache.
the class TestFileInfoBackingCache method testRaceGuavaEvictAndReleaseBeforeRetain.
@Test
public void testRaceGuavaEvictAndReleaseBeforeRetain() throws Exception {
AtomicBoolean done = new AtomicBoolean(false);
FileInfoBackingCache cache = new FileInfoBackingCache((ledgerId, createIfNotFound) -> {
File f = new File(baseDir, String.valueOf(ledgerId));
f.deleteOnExit();
return f;
});
Cache<Long, CachedFileInfo> guavaCache = CacheBuilder.newBuilder().maximumSize(1).removalListener(this::guavaEvictionListener).build();
Iterable<Future<Set<CachedFileInfo>>> futures = LongStream.range(0L, 2L).mapToObj((i) -> {
Callable<Set<CachedFileInfo>> c = () -> {
Set<CachedFileInfo> allFileInfos = new HashSet<>();
while (!done.get()) {
CachedFileInfo fi = null;
do {
fi = guavaCache.get(i, () -> cache.loadFileInfo(i, masterKey));
allFileInfos.add(fi);
Thread.sleep(100);
} while (!fi.tryRetain());
Assert.assertFalse(fi.isClosed());
fi.release();
}
return allFileInfos;
};
return executor.submit(c);
}).collect(Collectors.toList());
Thread.sleep(TimeUnit.SECONDS.toMillis(10));
done.set(true);
// ensure all threads are finished operating on cache, before checking any
for (Future<Set<CachedFileInfo>> f : futures) {
f.get();
}
guavaCache.invalidateAll();
for (Future<Set<CachedFileInfo>> f : futures) {
for (CachedFileInfo fi : f.get()) {
Assert.assertTrue(fi.isClosed());
Assert.assertEquals(FileInfoBackingCache.DEAD_REF, fi.getRefCount());
}
}
}
use of org.apache.bookkeeper.bookie.FileInfoBackingCache.CachedFileInfo in project bookkeeper by apache.
the class TestFileInfoBackingCache method basicTest.
@Test
public void basicTest() throws Exception {
FileInfoBackingCache cache = new FileInfoBackingCache((ledgerId, createIfNotFound) -> {
File f = new File(baseDir, String.valueOf(ledgerId));
f.deleteOnExit();
return f;
});
CachedFileInfo fi = cache.loadFileInfo(1, masterKey);
Assert.assertEquals(fi.getRefCount(), 1);
CachedFileInfo fi2 = cache.loadFileInfo(2, masterKey);
Assert.assertEquals(fi2.getRefCount(), 1);
CachedFileInfo fi3 = cache.loadFileInfo(1, null);
Assert.assertEquals(fi, fi3);
Assert.assertEquals(fi3.getRefCount(), 2);
// check that it expires correctly
fi.release();
fi3.release();
Assert.assertEquals(fi.getRefCount(), FileInfoBackingCache.DEAD_REF);
CachedFileInfo fi4 = cache.loadFileInfo(1, null);
Assert.assertFalse(fi4 == fi);
Assert.assertEquals(fi.getRefCount(), FileInfoBackingCache.DEAD_REF);
Assert.assertEquals(fi4.getRefCount(), 1);
Assert.assertEquals(fi.getLf(), fi4.getLf());
}
use of org.apache.bookkeeper.bookie.FileInfoBackingCache.CachedFileInfo in project bookkeeper by apache.
the class IndexPersistenceMgr method updatePage.
/**
* Update the ledger entry page.
*
* @param lep
* ledger entry page
* @return true if it is a new page, otherwise false.
* @throws IOException
*/
boolean updatePage(LedgerEntryPage lep) throws IOException {
if (!lep.isClean()) {
throw new IOException("Trying to update a dirty page");
}
CachedFileInfo fi = null;
try {
fi = getFileInfo(lep.getLedger(), null);
long pos = lep.getFirstEntryPosition();
if (pos >= fi.size()) {
lep.zeroPage();
return true;
} else {
lep.readPage(fi);
return false;
}
} finally {
if (fi != null) {
fi.release();
}
}
}
use of org.apache.bookkeeper.bookie.FileInfoBackingCache.CachedFileInfo in project bookkeeper by apache.
the class IndexPersistenceMgr method removeLedger.
/**
* This method is called whenever a ledger is deleted by the BookKeeper Client
* and we want to remove all relevant data for it stored in the LedgerCache.
*/
void removeLedger(Long ledgerId) throws IOException {
// Delete the ledger's index file and close the FileInfo
CachedFileInfo fi = null;
try {
fi = getFileInfo(ledgerId, null);
// Don't force flush. There's no need since we're deleting the ledger
// anyway, and recreating the file at this point, although safe, will
// force the garbage collector to do more work later.
fi.close(false);
fi.delete();
} finally {
if (fi != null) {
// should release use count
fi.release();
// Remove it from the active ledger manager
activeLedgers.remove(ledgerId);
// Now remove it from cache
writeFileInfoCache.invalidate(ledgerId);
readFileInfoCache.invalidate(ledgerId);
}
}
}
Aggregations