{
if (completeDelete)
{
counter.delete();
}
Transaction tx = new TransactionImpl(store);
boolean persist = false;
final ArrayList<PageCursorInfo> completedPages = new ArrayList<PageCursorInfo>();
// First get the completed pages using a lock
synchronized (consumedPages)
{
// lastAckedPosition = null means no acks were done yet, so we are not ready to cleanup
if (lastAckedPosition == null)
{
return;
}
for (Entry<Long, PageCursorInfo> entry : consumedPages.entrySet())
{
PageCursorInfo info = entry.getValue();
if (info.isDone() && !info.isPendingDelete())
{
Page currentPage = pageStore.getCurrentPage();
if (currentPage != null && entry.getKey() == pageStore.getCurrentPage().getPageId() &&
currentPage.isLive())
{
HornetQServerLogger.LOGGER.trace("We can't clear page " + entry.getKey() +
" now since it's the current page");
}
else
{
info.setPendingDelete();
completedPages.add(entry.getValue());
}
}
}
}
for (PageCursorInfo infoPG : completedPages)
{
// HORNETQ-1017: There are a few cases where a pending transaction might set a big hole on the page system
// where we need to ignore these pages in case of a restart.
// for that reason when we delete complete ACKs we store a single record per page file that will
// be removed once the page file is deleted
// notice also that this record is added as part of the same transaction where the information is deleted.
// In case of a TX Failure (a crash on the server) this will be recovered on the next cleanup once the
// server is restarted.
// first will mark the page as complete
if (isPersistent())
{
PagePosition completePage = new PagePositionImpl(infoPG.getPageId(), infoPG.getNumberOfMessages());
infoPG.setCompleteInfo(completePage);
store.storePageCompleteTransactional(tx.getID(), this.getId(), completePage);
if (!persist)
{
persist = true;
tx.setContainsPersistent();
}
}
// it will delete the page ack records
for (PagePosition pos : infoPG.acks)
{
if (pos.getRecordID() >= 0)
{
store.deleteCursorAcknowledgeTransactional(tx.getID(), pos.getRecordID());
if (!persist)
{
// only need to set it once
tx.setContainsPersistent();
persist = true;
}
}
}
infoPG.acks.clear();
}
tx.addOperation(new TransactionOperationAbstract()
{
@Override
public void afterCommit(final Transaction tx1)
{
executor.execute(new Runnable()
{
public void run()
{
if (!completeDelete)
{
cursorProvider.scheduleCleanup();
}
}
});
}
});
tx.commit();
}