private JournalTransaction getTransactionInfo(final long txID) { journalLock.readLock().lock(); try { JournalTransaction tx = transactions.get(txID); if (tx == null) { tx = new JournalTransaction(txID, this); JournalTransaction trans = transactions.putIfAbsent(txID, tx); if (trans != null) { tx = trans; } } return tx; } finally { journalLock.readLock().unlock(); } }
public void addNegative(final JournalFile file, final long id) { incCounter(file); addFile(file); if (neg == null) { neg = new ArrayList<>(); } neg.add(new JournalUpdate(file, id, 0)); }
@Override public void run() { journalLock.readLock().lock(); final JournalTransaction tx = getTransactionInfo(txID); try { if (tx != null) { tx.checkErrorCondition(); } JournalInternalRecord deleteRecordTX = new JournalDeleteRecordTX(txID, id, record); JournalFile usedFile = appendRecord(deleteRecordTX, false, false, tx, null); if (logger.isTraceEnabled()) { logger.trace("appendDeleteRecordTransactional::txID=" + txID + ", id=" + id + ", usedFile = " + usedFile); } tx.addNegative(usedFile, id); } catch (Throwable e) { logger.error("appendDeleteRecordTransactional:" + e, e); setErrorCondition(null, tx, e); } finally { journalLock.readLock().unlock(); } } });
@Override public void run() { journalLock.readLock().lock(); final JournalTransaction tx = getTransactionInfo(txID); try { tx.checkErrorCondition(); JournalInternalRecord updateRecordTX = new JournalAddRecordTX( false, txID, id, recordType, persister, record ); JournalFile usedFile = appendRecord( updateRecordTX, false, false, tx, null ); if ( logger.isTraceEnabled() ) { logger.trace( "appendUpdateRecordTransactional::txID=" + txID + ",id=" + id + ", userRecordType=" + recordType + ", record = " + record + ", usedFile = " + usedFile ); } tx.addPositive( usedFile, id, updateRecordTX.getEncodeSize() ); } catch (Throwable e ) { logger.error("appendUpdateRecordTransactional:" + e.getMessage(), e ); setErrorCondition(null, tx, e ); } finally { journalLock.readLock().unlock(); } } });
@Override public void onReadDeleteRecordTX(final long transactionID, final RecordInfo info) throws Exception { hasData.lazySet(true); TransactionHolder tx = loadTransactions.get(transactionID); if (tx == null) { tx = new TransactionHolder(transactionID); loadTransactions.put(transactionID, tx); } tx.recordsToDelete.add(info); JournalTransaction tnp = transactions.get(transactionID); if (tnp == null) { tnp = new JournalTransaction(transactionID, JournalImpl.this); transactions.put(transactionID, tnp); } tnp.addNegative(file, info.id); }
@Override public void onReadCommitRecord(final long transactionID, final int numberOfRecords) throws Exception { if (logger.isTraceEnabled()) { logger.trace("onReadCommitRecord " + transactionID); } if (pendingTransactions.get(transactionID) != null) { // Sanity check, this should never happen ActiveMQJournalLogger.LOGGER.inconsistencyDuringCompacting(transactionID); } else { JournalTransaction newTransaction = newTransactions.remove(transactionID); if (newTransaction != null) { JournalInternalRecord commitRecord = new JournalCompleteRecordTX(TX_RECORD_TYPE.COMMIT, transactionID, null); checkSize(commitRecord.getEncodeSize()); writeEncoder(commitRecord, newTransaction.getCounter(currentFile)); newTransaction.commit(currentFile); } } }
@Override public void onReadAddRecordTX(final long transactionID, final RecordInfo info) throws Exception { checkID(info.id); hasData.lazySet(true); TransactionHolder tx = loadTransactions.get(transactionID); if (tx == null) { tx = new TransactionHolder(transactionID); loadTransactions.put(transactionID, tx); } tx.recordInfos.add(info); JournalTransaction tnp = transactions.get(transactionID); if (tnp == null) { tnp = new JournalTransaction(transactionID, JournalImpl.this); transactions.put(transactionID, tnp); } tnp.addPositive(file, info.id, info.data.length + JournalImpl.SIZE_ADD_RECORD_TX + 1); // +1 = compact // count }
@Override public void onReadPrepareRecord(final long transactionID, final byte[] extraData, final int numberOfRecords) throws Exception { hasData.lazySet(true); TransactionHolder tx = loadTransactions.get(transactionID); if (tx == null) { // The user could choose to prepare empty transactions tx = new TransactionHolder(transactionID); loadTransactions.put(transactionID, tx); } tx.prepared = true; tx.extraData = extraData; JournalTransaction journalTransaction = transactions.get(transactionID); if (journalTransaction == null) { journalTransaction = new JournalTransaction(transactionID, JournalImpl.this); transactions.put(transactionID, journalTransaction); } boolean healthy = checkTransactionHealth(file, journalTransaction, orderedFiles, numberOfRecords); if (healthy) { journalTransaction.prepare(file); } else { ActiveMQJournalLogger.LOGGER.preparedTXIncomplete(transactionID); tx.invalid = true; } }
@Override public void run() { journalLock.readLock().lock(); final JournalTransaction tx = getTransactionInfo(txID); try { tx.checkErrorCondition(); JournalInternalRecord prepareRecord = new JournalCompleteRecordTX(TX_RECORD_TYPE.PREPARE, txID, transactionData); JournalFile usedFile = appendRecord(prepareRecord, true, sync, tx, callback); if (logger.isTraceEnabled()) { logger.trace("appendPrepareRecord::txID=" + txID + ", usedFile = " + usedFile); } tx.prepare(usedFile); } catch (ActiveMQShutdownException e) { result.fail(e); logger.error("appendPrepareRecord:" + e, e); } catch (Throwable e) { result.fail(e); logger.error("appendPrepareRecord:" + e, e); setErrorCondition(callback, tx, e); } finally { journalLock.readLock().unlock(); result.set(tx); } } });
TransactionCallback txcallback = tx.getCallback(currentFile); if (parameterCallback != null) { txcallback.setDelegateCompletion(parameterCallback); tx.fillNumberOfRecords(currentFile, encoder);
txcheck.checkErrorCondition(); tx.checkErrorCondition();
@Override public void onReadAddRecordTX(final long transactionID, final RecordInfo info) throws Exception { if (logger.isTraceEnabled()) { logger.trace("Read Add Recprd TX " + transactionID + " info " + info); } if (pendingTransactions.get(transactionID) != null || containsRecord(info.id)) { JournalTransaction newTransaction = getNewJournalTransaction(transactionID); JournalInternalRecord record = new JournalAddRecordTX(true, transactionID, info.id, info.getUserRecordType(), EncoderPersister.getInstance(),new ByteArrayEncoding(info.data)); record.setCompactCount((short) (info.compactCount + 1)); checkSize(record.getEncodeSize(), info.compactCount); newTransaction.addPositive(currentFile, info.id, record.getEncodeSize()); writeEncoder(record); } }
public void setCompacting() { compacting = true; // Everything is cleared on the transaction... // since we are compacting, everything is at the compactor's level clear(); }
/** * The caller of this method needs to guarantee appendLock.lock before calling this method if being used outside of the lock context. * or else potFilesMap could be affected */ public void prepare(final JournalFile file) { // We don't want the prepare record getting deleted before time addFile(file); }
@Override public void onReadDeleteRecordTX(final long transactionID, final RecordInfo info) throws Exception { if (logger.isTraceEnabled()) { logger.trace("onReadDeleteRecordTX " + transactionID + " info " + info); } if (pendingTransactions.get(transactionID) != null) { JournalTransaction newTransaction = getNewJournalTransaction(transactionID); JournalInternalRecord record = new JournalDeleteRecordTX(transactionID, info.id, new ByteArrayEncoding(info.data)); checkSize(record.getEncodeSize()); writeEncoder(record); newTransaction.addNegative(currentFile, info.id); } // else.. nothing to be done }
@Override public void run() { journalLock.readLock().lock(); // cannot remove otherwise compact may get lost final JournalTransaction tx = transactions.remove(txID); try { if (tx == null) { throw new IllegalStateException("Cannot find tx with id " + txID); } JournalInternalRecord commitRecord = new JournalCompleteRecordTX(TX_RECORD_TYPE.COMMIT, txID, null); JournalFile usedFile = appendRecord(commitRecord, true, sync, tx, callback); if (logger.isTraceEnabled()) { logger.trace("appendCommitRecord::txID=" + txID + ", usedFile = " + usedFile); } tx.commit(usedFile); } catch (ActiveMQShutdownException e) { result.fail(e); logger.error("appendCommitRecord:" + e, e); } catch (Throwable e) { result.fail(e); logger.error("appendCommitRecord:" + e, e); setErrorCondition(callback, tx, e); } finally { journalLock.readLock().unlock(); result.set(tx); } } });
@Override public void run() { journalLock.readLock().lock(); final JournalTransaction tx = getTransactionInfo(txID); try { if (tx != null) { tx.checkErrorCondition(); } JournalInternalRecord addRecord = new JournalAddRecordTX(true, txID, id, recordType, persister, record); JournalFile usedFile = appendRecord(addRecord, false, false, tx, null); if (logger.isTraceEnabled()) { logger.trace("appendAddRecordTransactional:txID=" + txID + ",id=" + id + ", userRecordType=" + recordType + ", record = " + record + ", usedFile = " + usedFile); } tx.addPositive(usedFile, id, addRecord.getEncodeSize()); } catch (Throwable e) { logger.error("appendAddRecordTransactional:" + e, e); setErrorCondition(null, tx, e); } finally { journalLock.readLock().unlock(); } } });