@Override public PagedMessage getMessage(final PagePosition pos) { PageCache cache = getPageCache(pos.getPageNr()); if (cache == null || pos.getMessageNr() >= cache.getNumberOfMessages()) { // sanity check, this should never happen unless there's a bug throw new NonExistentPage("Invalid messageNumber passed = " + pos + " on " + cache); } return cache.getMessage(pos.getMessageNr()); }
@Override public void afterCommit(final Transaction tx) { for (Entry<PageSubscriptionImpl, List<PagePosition>> entry : pendingPositions.entrySet()) { PageSubscriptionImpl cursor = entry.getKey(); List<PagePosition> positions = entry.getValue(); for (PagePosition confirmed : positions) { cursor.processACK(confirmed); cursor.deliveredCount.decrementAndGet(); cursor.deliveredSize.addAndGet(-confirmed.getPersistentSize()); } } }
@Override public int compareTo(PagePosition o) { if (pageNr > o.getPageNr()) { return 1; } else if (pageNr < o.getPageNr()) { return -1; } else if (recordID > o.getRecordID()) { return 1; } else if (recordID < o.getRecordID()) { return -1; } else { return 0; } }
private PagePosition moveNextPage(final PagePosition pos) { PagePosition retPos = pos; while (true) { retPos = retPos.nextPage(); synchronized (consumedPages) { PageCursorInfo pageInfo = consumedPages.get(retPos.getPageNr()); // any deleted or complete page will be ignored on the moveNextPage, we will just keep going if (pageInfo == null || (!pageInfo.isPendingDelete() && pageInfo.getCompleteInfo() == null)) { return retPos; } } } }
private PagedReference internalGetNext(final PagePosition pos) { PagePosition retPos = pos.nextMessage(); PageCache cache = cursorProvider.getPageCache(pos.getPageNr()); if (cache != null && !cache.isLive() && retPos.getMessageNr() >= cache.getNumberOfMessages()) { emptyCache = cache; saveEmptyPageAsConsumedPage(emptyCache); while ((cache == null && retPos.getPageNr() <= pageStore.getCurrentWritingPage()) || (cache != null && retPos.getPageNr() <= pageStore.getCurrentWritingPage() && cache.getNumberOfMessages() == 0)) { emptyCache = cache; retPos = moveNextPage(retPos); cache = cursorProvider.getPageCache(retPos.getPageNr()); PagedMessage serverMessage = cache.getMessage(retPos.getMessageNr());
private PageCursorInfo getPageInfo(final PagePosition pos) { return getPageInfo(pos.getPageNr()); }
private PageCursorInfo processACK(final PagePosition pos) { if (lastAckedPosition == null || pos.compareTo(lastAckedPosition) > 0) { if (logger.isTraceEnabled()) { logger.trace("a new position is being processed as ACK"); } if (lastAckedPosition != null && lastAckedPosition.getPageNr() != pos.getPageNr()) { if (logger.isTraceEnabled()) { logger.trace("Scheduling cleanup on pageSubscription for address = " + pageStore.getAddress() + " queue = " + this.getQueue().getName()); } // there's a different page being acked, we will do the check right away if (autoCleanup) { scheduleCleanupCheck(); } } lastAckedPosition = pos; } PageCursorInfo info = getPageInfo(pos); // This could be null if the page file was removed if (info == null) { // This could become null if the page file was deleted, or if the queue was removed maybe? // it's better to diagnose it (based on support tickets) instead of NPE ActiveMQServerLogger.LOGGER.nullPageCursorInfo(this.getPagingStore().getAddress().toString(), pos.toString(), cursorId); } else { info.addACK(pos); } return info; }
if (position.getRecordID() >= 0) { size = getPersistentSize(cache.getMessage(position.getMessageNr())); } else { size = persistentSize; position.setPersistentSize(size);
encoding.decode(buff); encoding.position.setRecordID(record.id); encoding.decode(buff); encoding.position.setRecordID(record.id); if (!sub.reloadPageCompletion(encoding.position)) { if (logger.isDebugEnabled()) { logger.debug("Complete page " + encoding.position.getPageNr() + " doesn't exist on page manager " + sub.getPagingStore().getAddress());
@Override public void storePageCompleteTransactional(long txID, long queueID, PagePosition position) throws Exception { long recordID = idGenerator.generateID(); position.setRecordID(recordID); messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.PAGE_CURSOR_COMPLETE, new CursorAckRecordEncoding(queueID, position)); }
@Override public void onDeletePage(Page deletedPage) throws Exception { PageCursorInfo info; synchronized (consumedPages) { info = consumedPages.remove(Long.valueOf(deletedPage.getPageId())); } if (info != null) { PagePosition completeInfo = info.getCompleteInfo(); if (completeInfo != null) { try { store.deletePageComplete(completeInfo.getRecordID()); } catch (Exception e) { ActiveMQServerLogger.LOGGER.errorDeletingPageCompleteRecord(e); } info.setCompleteInfo(null); } for (PagePosition deleteInfo : info.acks) { if (deleteInfo.getRecordID() >= 0) { try { store.deleteCursorAcknowledge(deleteInfo.getRecordID()); } catch (Exception e) { ActiveMQServerLogger.LOGGER.errorDeletingPageCompleteRecord(e); } } } info.acks.clear(); } }
@Override public void bookmark(PagePosition position) throws Exception { PageCursorInfo cursorInfo = getPageInfo(position); if (position.getMessageNr() > 0) { cursorInfo.confirmed.addAndGet(position.getMessageNr()); } confirmPosition(position); }
@Override public void redeliver(final PageIterator iterator, final PagePosition position) { iterator.redeliver(position); synchronized (consumedPages) { PageCursorInfo pageInfo = consumedPages.get(position.getPageNr()); if (pageInfo != null) { pageInfo.decrementPendingTX(); } else { // this shouldn't really happen. } } }
@Override public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position) throws Exception { readLock(); try { long ackID = idGenerator.generateID(); position.setRecordID(ackID); messageJournal.appendAddRecordTransactional(txID, ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position)); } finally { readUnLock(); } }
for (PageCursorInfo cursor : consumedPages.values()) { for (PagePosition info : cursor.acks) { if (info.getRecordID() >= 0) { isPersistent = true; store.deleteCursorAcknowledgeTransactional(tx, info.getRecordID()); if (completeInfo != null && completeInfo.getRecordID() >= 0) { store.deletePageComplete(completeInfo.getRecordID()); cursor.setCompleteInfo(null);
public void loadACK(final PagePosition posACK) { if (internalAddACK(posACK) && posACK.getMessageNr() >= 0) { confirmed.incrementAndGet(); } }
@Override public void encode(ActiveMQBuffer buffer) { buffer.writeLong(queueID); buffer.writeLong(position.getPageNr()); buffer.writeInt(position.getMessageNr()); }
Long pageNR = Long.valueOf(encoding.position.getPageNr());
@Override public void storeCursorAcknowledge(long queueID, PagePosition position) throws Exception { readLock(); try { long ackID = idGenerator.generateID(); position.setRecordID(ackID); messageJournal.appendAddRecord(ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position), syncNonTransactional, getContext(syncNonTransactional)); } finally { readUnLock(); } }
@Override public void processReload() throws Exception { if (recoveredACK != null) { if (logger.isTraceEnabled()) { logger.trace("********** processing reload!!!!!!!"); } Collections.sort(recoveredACK); long txDeleteCursorOnReload = -1; for (PagePosition pos : recoveredACK) { lastAckedPosition = pos; PageCursorInfo pageInfo = getPageInfo(pos); if (pageInfo == null) { ActiveMQServerLogger.LOGGER.pageNotFound(pos); if (txDeleteCursorOnReload == -1) { txDeleteCursorOnReload = store.generateID(); } store.deleteCursorAcknowledgeTransactional(txDeleteCursorOnReload, pos.getRecordID()); } else { pageInfo.loadACK(pos); } } if (txDeleteCursorOnReload >= 0) { store.commit(txDeleteCursorOnReload); } recoveredACK.clear(); recoveredACK = null; } }