use of org.apache.activemq.artemis.core.journal.PreparedTransactionInfo in project activemq-artemis by apache.
the class DescribeJournal method printSurvivingRecords.
public static DescribeJournal printSurvivingRecords(Journal journal, PrintStream out, boolean safe) throws Exception {
final Map<Long, PageSubscriptionCounterImpl> counters = new HashMap<>();
out.println("### Surviving Records Summary ###");
List<RecordInfo> records = new LinkedList<>();
List<PreparedTransactionInfo> preparedTransactions = new LinkedList<>();
journal.start();
final StringBuffer bufferFailingTransactions = new StringBuffer();
int messageCount = 0;
Map<Long, Integer> messageRefCounts = new HashMap<>();
int preparedMessageCount = 0;
Map<Long, Integer> preparedMessageRefCount = new HashMap<>();
journal.load(records, preparedTransactions, new TransactionFailureCallback() {
@Override
public void failedTransaction(long transactionID, List<RecordInfo> records1, List<RecordInfo> recordsToDelete) {
bufferFailingTransactions.append("Transaction " + transactionID + " failed with these records:\n");
for (RecordInfo info : records1) {
bufferFailingTransactions.append("- " + describeRecord(info, safe) + "\n");
}
for (RecordInfo info : recordsToDelete) {
bufferFailingTransactions.append("- " + describeRecord(info, safe) + " <marked to delete>\n");
}
}
}, false);
for (RecordInfo info : records) {
PageSubscriptionCounterImpl subsCounter = null;
long queueIDForCounter = 0;
Object o = newObjectEncoding(info);
if (info.getUserRecordType() == JournalRecordIds.ADD_MESSAGE) {
messageCount++;
} else if (info.getUserRecordType() == JournalRecordIds.ADD_REF) {
ReferenceDescribe ref = (ReferenceDescribe) o;
Integer count = messageRefCounts.get(ref.refEncoding.queueID);
if (count == null) {
count = 1;
messageRefCounts.put(ref.refEncoding.queueID, count);
} else {
messageRefCounts.put(ref.refEncoding.queueID, count + 1);
}
} else if (info.getUserRecordType() == JournalRecordIds.ACKNOWLEDGE_REF) {
AckDescribe ref = (AckDescribe) o;
Integer count = messageRefCounts.get(ref.refEncoding.queueID);
if (count == null) {
messageRefCounts.put(ref.refEncoding.queueID, 0);
} else {
messageRefCounts.put(ref.refEncoding.queueID, count - 1);
}
} else if (info.getUserRecordType() == JournalRecordIds.PAGE_CURSOR_COUNTER_VALUE) {
PageCountRecord encoding = (PageCountRecord) o;
queueIDForCounter = encoding.getQueueID();
subsCounter = lookupCounter(counters, queueIDForCounter);
subsCounter.loadValue(info.id, encoding.getValue(), encoding.getPersistentSize());
subsCounter.processReload();
} else if (info.getUserRecordType() == JournalRecordIds.PAGE_CURSOR_COUNTER_INC) {
PageCountRecordInc encoding = (PageCountRecordInc) o;
queueIDForCounter = encoding.getQueueID();
subsCounter = lookupCounter(counters, queueIDForCounter);
subsCounter.loadInc(info.id, encoding.getValue(), encoding.getPersistentSize());
subsCounter.processReload();
}
out.println(describeRecord(info, o, safe));
if (subsCounter != null) {
out.println("##SubsCounter for queue=" + queueIDForCounter + ", value=" + subsCounter.getValue());
out.println();
}
}
if (counters.size() > 0) {
out.println("### Page Counters");
printCounters(out, counters);
}
out.println();
out.println("### Prepared TX ###");
for (PreparedTransactionInfo tx : preparedTransactions) {
out.println(tx.getId());
for (RecordInfo info : tx.getRecords()) {
Object o = newObjectEncoding(info);
out.println("- " + describeRecord(info, o, safe));
if (info.getUserRecordType() == 31) {
preparedMessageCount++;
} else if (info.getUserRecordType() == 32) {
ReferenceDescribe ref = (ReferenceDescribe) o;
Integer count = preparedMessageRefCount.get(ref.refEncoding.queueID);
if (count == null) {
count = 1;
preparedMessageRefCount.put(ref.refEncoding.queueID, count);
} else {
preparedMessageRefCount.put(ref.refEncoding.queueID, count + 1);
}
}
}
for (RecordInfo info : tx.getRecordsToDelete()) {
out.println("- " + describeRecord(info, safe) + " <marked to delete>");
}
}
String missingTX = bufferFailingTransactions.toString();
if (missingTX.length() > 0) {
out.println();
out.println("### Failed Transactions (Missing commit/prepare/rollback record) ###");
}
out.println(bufferFailingTransactions.toString());
out.println("### Message Counts ###");
out.println("message count=" + messageCount);
out.println("message reference count");
for (Map.Entry<Long, Integer> longIntegerEntry : messageRefCounts.entrySet()) {
out.println("queue id " + longIntegerEntry.getKey() + ",count=" + longIntegerEntry.getValue());
}
out.println("prepared message count=" + preparedMessageCount);
for (Map.Entry<Long, Integer> longIntegerEntry : preparedMessageRefCount.entrySet()) {
out.println("queue id " + longIntegerEntry.getKey() + ",count=" + longIntegerEntry.getValue());
}
journal.stop();
return new DescribeJournal(records, preparedTransactions);
}
use of org.apache.activemq.artemis.core.journal.PreparedTransactionInfo in project activemq-artemis by apache.
the class AbstractJournalStorageManager method loadBindingJournal.
@Override
public JournalLoadInformation loadBindingJournal(final List<QueueBindingInfo> queueBindingInfos, final List<GroupingInfo> groupingInfos, final List<AddressBindingInfo> addressBindingInfos) throws Exception {
List<RecordInfo> records = new ArrayList<>();
List<PreparedTransactionInfo> preparedTransactions = new ArrayList<>();
JournalLoadInformation bindingsInfo = bindingsJournal.load(records, preparedTransactions, null);
HashMap<Long, PersistentQueueBindingEncoding> mapBindings = new HashMap<>();
for (RecordInfo record : records) {
long id = record.id;
ActiveMQBuffer buffer = ActiveMQBuffers.wrappedBuffer(record.data);
byte rec = record.getUserRecordType();
if (rec == JournalRecordIds.QUEUE_BINDING_RECORD) {
PersistentQueueBindingEncoding bindingEncoding = newQueueBindingEncoding(id, buffer);
mapBindings.put(bindingEncoding.getId(), bindingEncoding);
} else if (rec == JournalRecordIds.ID_COUNTER_RECORD) {
idGenerator.loadState(record.id, buffer);
} else if (rec == JournalRecordIds.ADDRESS_BINDING_RECORD) {
PersistentAddressBindingEncoding bindingEncoding = newAddressBindingEncoding(id, buffer);
addressBindingInfos.add(bindingEncoding);
} else if (rec == JournalRecordIds.GROUP_RECORD) {
GroupingEncoding encoding = newGroupEncoding(id, buffer);
groupingInfos.add(encoding);
} else if (rec == JournalRecordIds.ADDRESS_SETTING_RECORD) {
PersistedAddressSetting setting = newAddressEncoding(id, buffer);
mapPersistedAddressSettings.put(setting.getAddressMatch(), setting);
} else if (rec == JournalRecordIds.SECURITY_RECORD) {
PersistedRoles roles = newSecurityRecord(id, buffer);
mapPersistedRoles.put(roles.getAddressMatch(), roles);
} else if (rec == JournalRecordIds.QUEUE_STATUS_RECORD) {
QueueStatusEncoding statusEncoding = newQueueStatusEncoding(id, buffer);
PersistentQueueBindingEncoding queueBindingEncoding = mapBindings.get(statusEncoding.queueID);
if (queueBindingEncoding != null) {
queueBindingEncoding.addQueueStatusEncoding(statusEncoding);
} else {
// unlikely to happen, so I didn't bother about the Logger method
ActiveMQServerLogger.LOGGER.infoNoQueueWithID(statusEncoding.queueID, statusEncoding.getId());
this.deleteQueueStatus(statusEncoding.getId());
}
} else {
// unlikely to happen
ActiveMQServerLogger.LOGGER.invalidRecordType(rec, new Exception("invalid record type " + rec));
}
}
for (PersistentQueueBindingEncoding queue : mapBindings.values()) {
queueBindingInfos.add(queue);
}
// just to give a hand to GC
mapBindings.clear();
// This will instruct the IDGenerator to beforeStop old records
idGenerator.cleanup();
return bindingsInfo;
}
use of org.apache.activemq.artemis.core.journal.PreparedTransactionInfo in project activemq-artemis by apache.
the class XmlDataExporter method processMessageJournal.
/**
* Read through the message journal and stuff all the events/data we care about into local data structures. We'll
* use this data later to print all the right information.
*
* @throws Exception will be thrown if anything goes wrong reading the journal
*/
private void processMessageJournal() throws Exception {
ArrayList<RecordInfo> acks = new ArrayList<>();
List<RecordInfo> records = new LinkedList<>();
// We load these, but don't use them.
List<PreparedTransactionInfo> preparedTransactions = new LinkedList<>();
Journal messageJournal = storageManager.getMessageJournal();
ActiveMQServerLogger.LOGGER.debug("Reading journal from " + config.getJournalDirectory());
messageJournal.start();
// Just logging these, no action necessary
TransactionFailureCallback transactionFailureCallback = new TransactionFailureCallback() {
@Override
public void failedTransaction(long transactionID, List<RecordInfo> records1, List<RecordInfo> recordsToDelete) {
StringBuilder message = new StringBuilder();
message.append("Encountered failed journal transaction: ").append(transactionID);
for (int i = 0; i < records1.size(); i++) {
if (i == 0) {
message.append("; Records: ");
}
message.append(records1.get(i));
if (i != (records1.size() - 1)) {
message.append(", ");
}
}
for (int i = 0; i < recordsToDelete.size(); i++) {
if (i == 0) {
message.append("; RecordsToDelete: ");
}
message.append(recordsToDelete.get(i));
if (i != (recordsToDelete.size() - 1)) {
message.append(", ");
}
}
ActiveMQServerLogger.LOGGER.debug(message.toString());
}
};
messageJournal.load(records, preparedTransactions, transactionFailureCallback, false);
// Since we don't use these nullify the reference so that the garbage collector can clean them up
preparedTransactions = null;
for (RecordInfo info : records) {
byte[] data = info.data;
ActiveMQBuffer buff = ActiveMQBuffers.wrappedBuffer(data);
Object o = DescribeJournal.newObjectEncoding(info, storageManager);
if (info.getUserRecordType() == JournalRecordIds.ADD_MESSAGE) {
messages.put(info.id, ((MessageDescribe) o).getMsg().toCore());
} else if (info.getUserRecordType() == JournalRecordIds.ADD_MESSAGE_PROTOCOL) {
messages.put(info.id, ((MessageDescribe) o).getMsg().toCore());
} else if (info.getUserRecordType() == JournalRecordIds.ADD_LARGE_MESSAGE) {
messages.put(info.id, ((MessageDescribe) o).getMsg());
} else if (info.getUserRecordType() == JournalRecordIds.ADD_REF) {
ReferenceDescribe ref = (ReferenceDescribe) o;
HashMap<Long, ReferenceDescribe> map = messageRefs.get(info.id);
if (map == null) {
HashMap<Long, ReferenceDescribe> newMap = new HashMap<>();
newMap.put(ref.refEncoding.queueID, ref);
messageRefs.put(info.id, newMap);
} else {
map.put(ref.refEncoding.queueID, ref);
}
} else if (info.getUserRecordType() == JournalRecordIds.ACKNOWLEDGE_REF) {
acks.add(info);
} else if (info.userRecordType == JournalRecordIds.ACKNOWLEDGE_CURSOR) {
CursorAckRecordEncoding encoding = new CursorAckRecordEncoding();
encoding.decode(buff);
Set<PagePosition> set = cursorRecords.get(encoding.queueID);
if (set == null) {
set = new HashSet<>();
cursorRecords.put(encoding.queueID, set);
}
set.add(encoding.position);
} else if (info.userRecordType == JournalRecordIds.PAGE_TRANSACTION) {
if (info.isUpdate) {
PageUpdateTXEncoding pageUpdate = new PageUpdateTXEncoding();
pageUpdate.decode(buff);
pgTXs.add(pageUpdate.pageTX);
} else {
PageTransactionInfoImpl pageTransactionInfo = new PageTransactionInfoImpl();
pageTransactionInfo.decode(buff);
pageTransactionInfo.setRecordID(info.id);
pgTXs.add(pageTransactionInfo.getTransactionID());
}
}
}
messageJournal.stop();
removeAcked(acks);
}
use of org.apache.activemq.artemis.core.journal.PreparedTransactionInfo in project activemq-artemis by apache.
the class JournalCrashTest method printJournal.
/**
* @throws Exception
*/
private void printJournal() throws Exception {
NIOSequentialFileFactory factory = new NIOSequentialFileFactory(new File(getJournalDir()), 100);
JournalImpl journal = new JournalImpl(ActiveMQDefaultConfiguration.getDefaultJournalFileSize(), 2, 2, 0, 0, factory, "activemq-data", "amq", 100);
ArrayList<RecordInfo> records = new ArrayList<>();
ArrayList<PreparedTransactionInfo> transactions = new ArrayList<>();
journal.start();
journal.load(records, transactions, null);
// System.out.println("===============================================");
// System.out.println("Journal records at the end:");
//
// for (RecordInfo record : records)
// {
// System.out.println(record.id + ", update = " + record.isUpdate);
// }
journal.stop();
}
use of org.apache.activemq.artemis.core.journal.PreparedTransactionInfo in project activemq-artemis by apache.
the class JournalImplTestBase method checkTransactionsEquivalent.
protected void checkTransactionsEquivalent(final List<PreparedTransactionInfo> expected, final List<PreparedTransactionInfo> actual) {
Assert.assertEquals("Lists not same length", expected.size(), actual.size());
Iterator<PreparedTransactionInfo> iterExpected = expected.iterator();
Iterator<PreparedTransactionInfo> iterActual = actual.iterator();
while (iterExpected.hasNext()) {
PreparedTransactionInfo rexpected = iterExpected.next();
PreparedTransactionInfo ractual = iterActual.next();
Assert.assertEquals("ids not same", rexpected.getId(), ractual.getId());
checkRecordsEquivalent(rexpected.getRecords(), ractual.getRecords());
Assert.assertEquals("deletes size not same", rexpected.getRecordsToDelete().size(), ractual.getRecordsToDelete().size());
Iterator<RecordInfo> iterDeletesExpected = rexpected.getRecordsToDelete().iterator();
Iterator<RecordInfo> iterDeletesActual = ractual.getRecordsToDelete().iterator();
while (iterDeletesExpected.hasNext()) {
long lexpected = iterDeletesExpected.next().id;
long lactual = iterDeletesActual.next().id;
Assert.assertEquals("Delete ids not same", lexpected, lactual);
}
}
}
Aggregations