}
private int replayTx(final long offset, final long cmdBufLen, final TxCommand txCmd, final DataFile dataFile)
throws InvalidProtocolBufferException {
final TransactionOperation command = TransactionOperation.parseFrom(txCmd.getCmdContent());
final TransactionId xid = TransactionId.valueOf(command.getTransactionId());
try {
// �ط�������־
switch (command.getType()) {
case XA_PREPARE:
this.transactionStore.replayPrepare(xid);
break;
case XA_COMMIT:
case LOCAL_COMMIT:
final Tx tx = this.transactionStore.replayCommit(xid, command.getWasPrepared());
if (tx == null) {
break;
}
if (tx.getOperations().isEmpty()) {
break;
}
final Map<MessageStore, List<Long>> ids = tx.getMsgIds();
final Map<MessageStore, List<PutCommand>> putCmds = tx.getPutCommands();
// ��ȡ�������ݣ������Ϣ��λ����Ϣ
final int attachmentLen = command.getDataLength();
final ByteBuffer buf = ByteBuffer.allocate(attachmentLen);
// �������ݵ�����λ�ã���㣫4���ֽڵ�cmd���ȣ�cmd������
final long dataOffset = 4 + offset + cmdBufLen;
dataFile.read(buf, dataOffset);
buf.flip();
final Map<String, AddMsgLocation> locations = AddMsgLocationUtils.decodeLocations(buf);
final AtomicBoolean replayed = new AtomicBoolean(false);
final AtomicInteger counter = new AtomicInteger();
if (ids != null && !ids.isEmpty()) {
for (final Map.Entry<MessageStore, List<Long>> entry : ids.entrySet()) {
final MessageStore msgStore = entry.getKey();
final AddMsgLocation addedLocation = locations.get(msgStore.getDescription());
// û�������Ϣ����Ҫ�������
final List<Long> idList = entry.getValue();
final List<PutCommand> cmdList = putCmds.get(msgStore);
if (addedLocation == null) {
counter.incrementAndGet();
msgStore.append(idList, cmdList, new AppendCallback() {
@Override
public void appendComplete(final Location newLocation) {
replayed.set(true);
final int checksum =
CheckSum.crc32(MessageUtils.makeMessageBuffer(idList, cmdList).array());
locations.put(msgStore.getDescription(),
new AddMsgLocation(newLocation.getOffset(), newLocation.getLength(), checksum,
msgStore.getDescription()));
counter.decrementAndGet();
}
});
}
else {
// �����ط�
counter.incrementAndGet();
msgStore.replayAppend(addedLocation.getOffset(), addedLocation.getLength(),
addedLocation.checksum, idList, cmdList, new AppendCallback() {
@Override
public void appendComplete(final Location newLocation) {
// ����طŵ�ʱ�������λ�ã�����Ҫ����λ����Ϣ
if (newLocation != null) {
replayed.set(true);
locations.put(msgStore.getDescription(),
new AddMsgLocation(newLocation.getOffset(), newLocation.getLength(),
addedLocation.checksum, addedLocation.storeDesc));
}
counter.decrementAndGet();
}
});
}
}
}
// ������طţ���дλ����Ϣ
if (replayed.get()) {
// �ȴ��ص����
while (counter.get() > 0) {
Thread.sleep(50);
}
dataFile.write(dataOffset, AddMsgLocationUtils.encodeLocation(locations));
dataFile.force();
}
// ���ظ������ݴ�С
dataFile.decrement();
return attachmentLen;
case LOCAL_ROLLBACK:
case XA_ROLLBACK:
this.transactionStore.replayRollback(xid);
dataFile.decrement();
break;
default:
throw new IOException("Invalid journal command type: " + command.getType());
}
}
catch (final IOException e) {
log.error("Recovery Failure: Could not replay: " + txCmd + ", reason: " + e, e);
}