}
}
@Override
public void process(KeyFilter filter, final CacheLoaderTask task, final Executor executor, final boolean fetchValue, final boolean fetchMetadata) {
final TaskContext context = new TaskContextImpl();
final KeyFilter notNullFilter = PersistenceUtil.notNull(filter);
final AtomicLong tasksSubmitted = new AtomicLong();
final AtomicLong tasksFinished = new AtomicLong();
forEachOnDisk(fetchMetadata, fetchValue, new EntryFunctor() {
@Override
public boolean apply(int file, int offset, int size,
final byte[] serializedKey, final byte[] serializedMetadata, final byte[] serializedValue,
long seqId, long expiration) throws IOException, ClassNotFoundException {
if (context.isStopped()) {
return false;
}
final Object key = marshaller.objectFromByteBuffer(serializedKey);
if (!notNullFilter.accept(key)) {
return true;
}
EntryPosition entry = temporaryTable.get(key);
if (entry == null) {
entry = index.getPosition(key, serializedKey);
}
if (entry != null) {
FileProvider.Handle handle = fileProvider.getFile(entry.file);
try {
EntryHeader header = EntryRecord.readEntryHeader(handle, entry.offset);
if (header == null) {
throw new IllegalStateException("Cannot read " + entry.file + ":" + entry.offset);
}
if (seqId < header.seqId()) {
return true;
}
} finally {
handle.close();
}
} else {
// entry is not in index = it was deleted
return true;
}
if (serializedValue != null && (expiration < 0 || expiration > timeService.wallClockTime())) {
executor.execute(new Runnable() {
@Override
public void run() {
try {
task.processEntry(marshalledEntryFactory.newMarshalledEntry(key,
serializedValue == null ? null : marshaller.objectFromByteBuffer(serializedValue),
serializedMetadata == null ? null : (InternalMetadata) marshaller.objectFromByteBuffer(serializedMetadata)),
context);
} catch (Exception e) {
log.error("Failed to process task for key " + key, e);
} finally {
long finished = tasksFinished.incrementAndGet();
if (finished == tasksSubmitted.longValue()) {
synchronized (context) {
context.notifyAll();
}
}
}
}
});
tasksSubmitted.incrementAndGet();
return !context.isStopped();
}
return true;
}
}, new FileFunctor() {
@Override
public void afterFile(int file) {
// noop
}
});
while (tasksSubmitted.longValue() > tasksFinished.longValue()) {
synchronized (context) {
try {
context.wait(100);
} catch (InterruptedException e) {
log.error("Iteration was interrupted", e);
Thread.currentThread().interrupt();
return;
}