public void purge(Executor threadPool, PurgeListener task) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Collection<Bucket> expiredBuckets = new ArrayList<Bucket>(BATCH_SIZE);
ExecutorCompletionService ecs = new ExecutorCompletionService(threadPool);
BlockingQueue<Bucket> emptyBuckets = new LinkedBlockingQueue<Bucket>();
// We have to lock and unlock the buckets in the same thread - executor can execute
// the BucketPurger task in different thread. That's why we can't unlock the locks
// there but have to send them to this thread through this queue.
int tasksScheduled = 0;
int tasksCompleted = 0;
try {
String sql = tableManipulation.getSelectExpiredRowsSql();
conn = connectionFactory.getConnection();
ps = conn.prepareStatement(sql);
ps.setLong(1, ctx.getTimeService().wallClockTime());
rs = ps.executeQuery();
while (rs.next()) {
Integer bucketId = rs.getInt(2);
if (immediateLockForWriting(bucketId)) {
if (log.isTraceEnabled()) {
log.tracef("Adding bucket keyed %s for purging.", bucketId);
}
InputStream binaryStream = rs.getBinaryStream(1);
Bucket bucket = unmarshallBucket(binaryStream);
bucket.setBucketId(bucketId);
expiredBuckets.add(bucket);
if (expiredBuckets.size() == BATCH_SIZE) {
++tasksScheduled;
ecs.submit(new BucketPurger(expiredBuckets, task, ctx.getMarshaller(), conn, emptyBuckets));
expiredBuckets = new ArrayList<Bucket>(BATCH_SIZE);
}
} else {
if (log.isTraceEnabled()) {
log.tracef("Could not acquire write lock for %s, this won't be purged even though it has expired elements", bucketId);
}
}
// continuously unlock already purged buckets - we don't want to run out of memory by storing
// them in unlimited collection
tasksCompleted += unlockCompleted(ecs, false); // cannot throw InterruptedException
}
if (!expiredBuckets.isEmpty()) {
++tasksScheduled;
ecs.submit(new BucketPurger(expiredBuckets, task, ctx.getMarshaller(), conn, emptyBuckets));
}
// wait until all tasks have completed
try {
while (tasksCompleted < tasksScheduled) {
tasksCompleted += unlockCompleted(ecs, true);