18
18
19
19
import com .github .benmanes .caffeine .cache .Caffeine ;
20
20
import com .github .benmanes .caffeine .cache .LoadingCache ;
21
- import org .apache .commons .lang3 .concurrent .AtomicInitializer ;
22
- import org .apache .commons .lang3 .concurrent .ConcurrentException ;
23
21
import org .slf4j .Logger ;
24
22
import org .slf4j .LoggerFactory ;
25
23
32
30
import java .util .Map ;
33
31
import java .util .Map .Entry ;
34
32
import java .util .TreeMap ;
33
+ import java .util .concurrent .atomic .AtomicReference ;
35
34
36
35
/**
37
36
* Information about a book
@@ -52,9 +51,10 @@ public class BookInfo
52
51
private final LoadingCache <Long , IPageInterval > randomAccessCache ;
53
52
54
53
// AtomicInitializer call initialize method again if previous value is null
55
- private final AtomicInitializer <PageInfo > firstPage ;
54
+ private final AtomicReference <PageInfo > firstPage = new AtomicReference <>() ;
56
55
private final PagesLoader pagesLoader ;
57
- private final PageLoader lastPagesLoader ;
56
+ private final PageLoader firstPageLoader ;
57
+ private final PageLoader lastPageLoader ;
58
58
59
59
public BookInfo (BookId id ,
60
60
String fullName ,
@@ -69,23 +69,16 @@ public BookInfo(BookId id,
69
69
this .desc = desc ;
70
70
this .created = created ;
71
71
this .pagesLoader = pagesLoader ;
72
- this .lastPagesLoader = lastPageLoader ;
72
+ this .firstPageLoader = firstPageLoader ;
73
+ this .lastPageLoader = lastPageLoader ;
73
74
74
- this .firstPage = new AtomicInitializer <>() {
75
- @ Override
76
- protected PageInfo initialize () {
77
- return firstPageLoader .load (id );
78
- }
79
- };
80
75
this .hotCache = Caffeine .newBuilder ()
81
76
.maximumSize (HOT_CACHE_SIZE )
82
77
.build (this ::createPageInterval );
83
78
84
79
this .randomAccessCache = Caffeine .newBuilder ()
85
80
.maximumSize (cacheSize )
86
81
.build (this ::createPageInterval );
87
-
88
- initializeHotCache ();
89
82
}
90
83
91
84
public BookId getId ()
@@ -119,17 +112,22 @@ public Collection<PageInfo> getPages()
119
112
120
113
public @ Nullable PageInfo getFirstPage ()
121
114
{
122
- try {
123
- return firstPage .get ();
124
- } catch (ConcurrentException e ) {
125
- LOGGER .error ("Unexpected exception during first page lazy initialization" , e );
126
- return null ;
127
- }
115
+ PageInfo result = firstPage .get ();
116
+
117
+ if (result == null ) {
118
+ result = firstPageLoader .load (id );
119
+ if (!firstPage .compareAndSet (null , result )) {
120
+ // another thread has initialized the reference
121
+ result = firstPage .get ();
122
+ }
123
+ }
124
+
125
+ return result ;
128
126
}
129
127
130
128
public @ Nullable PageInfo getLastPage ()
131
129
{
132
- return lastPagesLoader .load (id );
130
+ return lastPageLoader .load (id );
133
131
}
134
132
135
133
public PageInfo getPage (PageId pageId )
@@ -161,7 +159,7 @@ public PageInfo getPreviousPage(Instant startTimestamp)
161
159
}
162
160
163
161
void invalidate () {
164
- // FIXME: invalidate initializer
162
+ firstPage . set ( null );
165
163
hotCache .invalidateAll ();
166
164
randomAccessCache .invalidateAll ();
167
165
}
@@ -191,14 +189,6 @@ private void invalidate(long epochDay) {
191
189
randomAccessCache .invalidate (epochDay );
192
190
}
193
191
194
- @ SuppressWarnings ("ResultOfMethodCallIgnored" )
195
- private void initializeHotCache () {
196
- long currentEpochDay = currentEpochDay ();
197
- for (int shift = HOT_CACHE_SIZE - 1 ; shift >= 0 ; shift --) {
198
- this .hotCache .get (currentEpochDay - shift );
199
- }
200
- }
201
-
202
192
private IPageInterval getPageInterval (long epochDate ) {
203
193
long currentEpochDate = currentEpochDay ();
204
194
IPageInterval pageInterval = currentEpochDate - epochDate < 2
@@ -300,13 +290,13 @@ public PageInfo find(Instant timestamp)
300
290
301
291
@ Override
302
292
public PageInfo next (Instant startTimestamp ) {
303
- Entry <Instant , PageInfo > result = pageByInstant .ceilingEntry (startTimestamp . plus ( 1 , ChronoUnit . NANOS ) );
293
+ Entry <Instant , PageInfo > result = pageByInstant .higherEntry (startTimestamp );
304
294
return result != null ? result .getValue () : null ;
305
295
}
306
296
307
297
@ Override
308
298
public PageInfo previous (Instant startTimestamp ) {
309
- Entry <Instant , PageInfo > result = pageByInstant .floorEntry (startTimestamp . minus ( 1 , ChronoUnit . NANOS ) );
299
+ Entry <Instant , PageInfo > result = pageByInstant .lowerEntry (startTimestamp );
310
300
return result != null ? result .getValue () : null ;
311
301
}
312
302
0 commit comments