diff --git a/cradle-core/src/main/java/com/exactpro/cradle/BookInfo.java b/cradle-core/src/main/java/com/exactpro/cradle/BookInfo.java index f05ffba9..c3fa8c27 100644 --- a/cradle-core/src/main/java/com/exactpro/cradle/BookInfo.java +++ b/cradle-core/src/main/java/com/exactpro/cradle/BookInfo.java @@ -18,8 +18,6 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; -import org.apache.commons.lang3.concurrent.AtomicInitializer; -import org.apache.commons.lang3.concurrent.ConcurrentException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +30,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicReference; /** * Information about a book @@ -52,9 +51,10 @@ public class BookInfo private final LoadingCache randomAccessCache; // AtomicInitializer call initialize method again if previous value is null - private final AtomicInitializer firstPage; + private final AtomicReference firstPage = new AtomicReference<>(); private final PagesLoader pagesLoader; - private final PageLoader lastPagesLoader; + private final PageLoader firstPageLoader; + private final PageLoader lastPageLoader; public BookInfo(BookId id, String fullName, @@ -69,14 +69,9 @@ public BookInfo(BookId id, this.desc = desc; this.created = created; this.pagesLoader = pagesLoader; - this.lastPagesLoader = lastPageLoader; + this.firstPageLoader = firstPageLoader; + this.lastPageLoader = lastPageLoader; - this.firstPage = new AtomicInitializer<>() { - @Override - protected PageInfo initialize() { - return firstPageLoader.load(id); - } - }; this.hotCache = Caffeine.newBuilder() .maximumSize(HOT_CACHE_SIZE) .build(this::createPageInterval); @@ -84,8 +79,6 @@ protected PageInfo initialize() { this.randomAccessCache = Caffeine.newBuilder() .maximumSize(cacheSize) .build(this::createPageInterval); - - initializeHotCache(); } public BookId getId() @@ -119,17 +112,22 @@ public Collection getPages() public @Nullable PageInfo getFirstPage() { - try { - return firstPage.get(); - } catch (ConcurrentException e) { - LOGGER.error("Unexpected exception during first page lazy initialization", e); - return null; - } + PageInfo result = firstPage.get(); + + if (result == null) { + result = firstPageLoader.load(id); + if (!firstPage.compareAndSet(null, result)) { + // another thread has initialized the reference + result = firstPage.get(); + } + } + + return result; } public @Nullable PageInfo getLastPage() { - return lastPagesLoader.load(id); + return lastPageLoader.load(id); } public PageInfo getPage(PageId pageId) @@ -161,7 +159,7 @@ public PageInfo getPreviousPage(Instant startTimestamp) } void invalidate() { - // FIXME: invalidate initializer + firstPage.set(null); hotCache.invalidateAll(); randomAccessCache.invalidateAll(); } @@ -191,14 +189,6 @@ private void invalidate(long epochDay) { randomAccessCache.invalidate(epochDay); } - @SuppressWarnings("ResultOfMethodCallIgnored") - private void initializeHotCache() { - long currentEpochDay = currentEpochDay(); - for (int shift = HOT_CACHE_SIZE - 1; shift >= 0; shift--) { - this.hotCache.get(currentEpochDay - shift); - } - } - private IPageInterval getPageInterval(long epochDate) { long currentEpochDate = currentEpochDay(); IPageInterval pageInterval = currentEpochDate - epochDate < 2 @@ -300,13 +290,13 @@ public PageInfo find(Instant timestamp) @Override public PageInfo next(Instant startTimestamp) { - Entry result = pageByInstant.ceilingEntry(startTimestamp.plus(1, ChronoUnit.NANOS)); + Entry result = pageByInstant.higherEntry(startTimestamp); return result != null ? result.getValue() : null; } @Override public PageInfo previous(Instant startTimestamp) { - Entry result = pageByInstant.floorEntry(startTimestamp.minus(1, ChronoUnit.NANOS)); + Entry result = pageByInstant.lowerEntry(startTimestamp); return result != null ? result.getValue() : null; } diff --git a/cradle-core/src/main/java/com/exactpro/cradle/CradleStorage.java b/cradle-core/src/main/java/com/exactpro/cradle/CradleStorage.java index be90e492..a36e2378 100644 --- a/cradle-core/src/main/java/com/exactpro/cradle/CradleStorage.java +++ b/cradle-core/src/main/java/com/exactpro/cradle/CradleStorage.java @@ -1469,7 +1469,6 @@ public PageInfo updatePageName(BookId bookId, String pageName, String newPageNam } public PageInfo updatePageName(BookId bookId, Instant pageStart, String pageName, String newPageName) throws CradleStorageException { - getBookCache().getBook(bookId); PageInfo updatedPageInfo = doUpdatePageName(bookId, pageName, newPageName); try { diff --git a/cradle-core/src/test/java/com/exactpro/cradle/BookInfoTest.java b/cradle-core/src/test/java/com/exactpro/cradle/BookInfoTest.java index bdf5bbc6..da0a8d96 100644 --- a/cradle-core/src/test/java/com/exactpro/cradle/BookInfoTest.java +++ b/cradle-core/src/test/java/com/exactpro/cradle/BookInfoTest.java @@ -32,10 +32,10 @@ public class BookInfoTest { public static Random RANDOM = new Random(); public static final BookId BOOK_ID = new BookId("test-book"); - public static final List PAGES; + private static final List PAGES; static { - PAGES = new ArrayList<>(); + List pages = new ArrayList<>(); Instant start = Instant.now().minus(7, ChronoUnit.DAYS); Instant end = Instant.now(); Instant current = start; @@ -43,9 +43,11 @@ public class BookInfoTest { do { previous = current; current = current.plus(1, ChronoUnit.HOURS); - PAGES.add(createPageInfo(previous, current)); + pages.add(createPageInfo(previous, current)); } while (current.isBefore(end)); - PAGES.add(createPageInfo(current, current)); + pages.add(createPageInfo(current, current)); + + PAGES = Collections.unmodifiableList(pages); } @Test