/// <summary> /// Find the id of the last edit log transaction writen to a edit log /// ledger. /// </summary> /// <exception cref="System.IO.IOException"/> /// <exception cref="Org.Apache.Hadoop.Contrib.Bkjournal.BookKeeperJournalManager.SegmentEmptyException /// "/> private long RecoverLastTxId(EditLogLedgerMetadata l, bool fence) { LedgerHandle lh = null; try { if (fence) { lh = bkc.OpenLedger(l.GetLedgerId(), BookKeeper.DigestType.Mac, Sharpen.Runtime.GetBytesForString (digestpw, Charsets.Utf8)); } else { lh = bkc.OpenLedgerNoRecovery(l.GetLedgerId(), BookKeeper.DigestType.Mac, Sharpen.Runtime.GetBytesForString (digestpw, Charsets.Utf8)); } } catch (BKException bke) { throw new IOException("Exception opening ledger for " + l, bke); } catch (Exception ie) { Sharpen.Thread.CurrentThread().Interrupt(); throw new IOException("Interrupted opening ledger for " + l, ie); } BookKeeperEditLogInputStream @in = null; try { long lastAddConfirmed = lh.GetLastAddConfirmed(); if (lastAddConfirmed == -1) { throw new BookKeeperJournalManager.SegmentEmptyException(); } @in = new BookKeeperEditLogInputStream(lh, l, lastAddConfirmed); long endTxId = HdfsConstants.InvalidTxid; FSEditLogOp op = @in.ReadOp(); while (op != null) { if (endTxId == HdfsConstants.InvalidTxid || op.GetTransactionId() == endTxId + 1) { endTxId = op.GetTransactionId(); } op = @in.ReadOp(); } return(endTxId); } finally { if (@in != null) { @in.Close(); } } }
/// <summary>Finalize a log segment.</summary> /// <remarks> /// Finalize a log segment. If the journal manager is currently /// writing to a ledger, ensure that this is the ledger of the log segment /// being finalized. /// Otherwise this is the recovery case. In the recovery case, ensure that /// the firstTxId of the ledger matches firstTxId for the segment we are /// trying to finalize. /// </remarks> /// <exception cref="System.IO.IOException"/> public override void FinalizeLogSegment(long firstTxId, long lastTxId) { CheckEnv(); string inprogressPath = InprogressZNode(firstTxId); try { Stat inprogressStat = zkc.Exists(inprogressPath, false); if (inprogressStat == null) { throw new IOException("Inprogress znode " + inprogressPath + " doesn't exist"); } EditLogLedgerMetadata l = EditLogLedgerMetadata.Read(zkc, inprogressPath); if (currentLedger != null) { // normal, non-recovery case if (l.GetLedgerId() == currentLedger.GetId()) { try { currentLedger.Close(); } catch (BKException bke) { Log.Error("Error closing current ledger", bke); } currentLedger = null; } else { throw new IOException("Active ledger has different ID to inprogress. " + l.GetLedgerId () + " found, " + currentLedger.GetId() + " expected"); } } if (l.GetFirstTxId() != firstTxId) { throw new IOException("Transaction id not as expected, " + l.GetFirstTxId() + " found, " + firstTxId + " expected"); } l.FinalizeLedger(lastTxId); string finalisedPath = FinalizedLedgerZNode(firstTxId, lastTxId); try { l.Write(zkc, finalisedPath); } catch (KeeperException.NodeExistsException) { if (!l.Verify(zkc, finalisedPath)) { throw new IOException("Node " + finalisedPath + " already exists" + " but data doesn't match" ); } } maxTxId.Store(lastTxId); zkc.Delete(inprogressPath, inprogressStat.GetVersion()); string inprogressPathFromCI = ci.Read(); if (inprogressPath.Equals(inprogressPathFromCI)) { ci.Clear(); } } catch (KeeperException e) { throw new IOException("Error finalising ledger", e); } catch (Exception ie) { Sharpen.Thread.CurrentThread().Interrupt(); throw new IOException("Error finalising ledger", ie); } }