1919
2020import com .fasterxml .jackson .core .JsonParseException ;
2121import com .fasterxml .jackson .databind .JsonMappingException ;
22+ import com .github .benmanes .caffeine .cache .Cache ;
23+ import com .github .benmanes .caffeine .cache .Caffeine ;
24+ import com .github .benmanes .caffeine .cache .RemovalCause ;
2225import java .io .IOException ;
2326import java .net .URI ;
24- import java .util .Collections ;
25- import java . util . HashMap ;
26- import java . util . Map ;
27+ import java .util .concurrent . TimeUnit ;
28+ import org . apache . hadoop . conf . Configuration ;
29+ import org . apache . hadoop . hbase . HBaseConfiguration ;
2730import org .apache .hadoop .hbase .TableNotFoundException ;
2831import org .apache .hadoop .hbase .filter .Filter ;
2932import org .apache .hadoop .hbase .rest .model .ScannerModel ;
@@ -46,9 +49,7 @@ public class ScannerResource extends ResourceBase {
4649
4750 private static final Logger LOG = LoggerFactory .getLogger (ScannerResource .class );
4851
49- static final Map <String , ScannerInstanceResource > scanners =
50- Collections .synchronizedMap (new HashMap <String , ScannerInstanceResource >());
51-
52+ private static final Cache <String , ScannerInstanceResource > scanners = setupScanners ();
5253 TableResource tableResource ;
5354
5455 /**
@@ -59,8 +60,23 @@ public ScannerResource(TableResource tableResource) throws IOException {
5960 this .tableResource = tableResource ;
6061 }
6162
63+ private static Cache <String , ScannerInstanceResource > setupScanners () {
64+ final Configuration conf = HBaseConfiguration .create ();
65+
66+ int size = conf .getInt (REST_SCANNERCACHE_SIZE , DEFAULT_REST_SCANNERCACHE_SIZE );
67+ long evictTimeoutMs = conf .getTimeDuration (REST_SCANNERCACHE_EXPIRE_TIME ,
68+ DEFAULT_REST_SCANNERCACHE_EXPIRE_TIME_MS , TimeUnit .MILLISECONDS );
69+
70+ Cache <String , ScannerInstanceResource > cache =
71+ Caffeine .newBuilder ().removalListener (ScannerResource ::removalListener ).maximumSize (size )
72+ .expireAfterAccess (evictTimeoutMs , TimeUnit .MILLISECONDS )
73+ .<String , ScannerInstanceResource > build ();
74+
75+ return cache ;
76+ }
77+
6278 static boolean delete (final String id ) {
63- ScannerInstanceResource instance = scanners .remove (id );
79+ ScannerInstanceResource instance = scanners .asMap (). remove (id );
6480 if (instance != null ) {
6581 instance .generator .close ();
6682 return true ;
@@ -69,6 +85,12 @@ static boolean delete(final String id) {
6985 }
7086 }
7187
88+ static void removalListener (String key , ScannerInstanceResource value , RemovalCause cause ) {
89+ if (cause .wasEvicted ()) {
90+ delete (key );
91+ }
92+ }
93+
7294 Response update (final ScannerModel model , final boolean replace , final UriInfo uriInfo ) {
7395 servlet .getMetrics ().incrementRequests (1 );
7496 if (servlet .isReadOnly ()) {
@@ -140,7 +162,7 @@ public Response post(final ScannerModel model, final @Context UriInfo uriInfo) {
140162 @ Path ("{scanner: .+}" )
141163 public ScannerInstanceResource getScannerInstanceResource (final @ PathParam ("scanner" ) String id )
142164 throws IOException {
143- ScannerInstanceResource instance = scanners .get (id );
165+ ScannerInstanceResource instance = scanners .getIfPresent (id );
144166 if (instance == null ) {
145167 servlet .getMetrics ().incrementFailedGetRequests (1 );
146168 return new ScannerInstanceResource ();
0 commit comments