/** * Performs the post-processing work required after a write. * * @param task the pending operation to be applied */ void afterWrite(Runnable task) { if (buffersWrites()) { for (int i = 0; i < WRITE_BUFFER_RETRIES; i++) { if (writeBuffer().offer(task)) { scheduleAfterWrite(); return; } scheduleDrainBuffers(); } // The maintenance task may be scheduled but not running due to all of the executor's threads // being busy. If all of the threads are writing into the cache then no progress can be made // without assistance. try { performCleanUp(task); } catch (RuntimeException e) { logger.log(Level.SEVERE, "Exception thrown when performing the maintenance task", e); } } else { scheduleAfterWrite(); } }
@Test public void scheduleAfterWrite() { BoundedLocalCache<?, ?> cache = new BoundedLocalCache<Object, Object>( Caffeine.newBuilder(), /* loader */ null, /* async */ false) { @Override void scheduleDrainBuffers() {} }; Map<Integer, Integer> transitions = ImmutableMap.of( IDLE, REQUIRED, REQUIRED, REQUIRED, PROCESSING_TO_IDLE, PROCESSING_TO_REQUIRED, PROCESSING_TO_REQUIRED, PROCESSING_TO_REQUIRED); transitions.forEach((start, end) -> { cache.drainStatus = start; cache.scheduleAfterWrite(); assertThat(cache.drainStatus, is(end)); }); }
/** * Performs the post-processing work required after a write. * * @param task the pending operation to be applied */ void afterWrite(Runnable task) { if (buffersWrites()) { for (int i = 0; i < WRITE_BUFFER_RETRIES; i++) { if (writeBuffer().offer(task)) { scheduleAfterWrite(); return; } scheduleDrainBuffers(); } // The maintenance task may be scheduled but not running due to all of the executor's threads // being busy. If all of the threads are writing into the cache then no progress can be made // without assistance. try { performCleanUp(task); } catch (RuntimeException e) { logger.log(Level.SEVERE, "Exception thrown when performing the maintenance task", e); } } else { scheduleAfterWrite(); } }