Пример #1
0
        /// <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();
                }
            }
        }
Пример #2
0
        /// <summary>Skip forward to specified transaction id.</summary>
        /// <remarks>
        /// Skip forward to specified transaction id.
        /// Currently we do this by just iterating forward.
        /// If this proves to be too expensive, this can be reimplemented
        /// with a binary search over bk entries
        /// </remarks>
        /// <exception cref="System.IO.IOException"/>
        public virtual void SkipTo(long txId)
        {
            long        numToSkip = GetFirstTxId() - txId;
            FSEditLogOp op        = null;

            for (long i = 0; i < numToSkip; i++)
            {
                op = ReadOp();
            }
            if (op != null && op.GetTransactionId() != txId - 1)
            {
                throw new IOException("Corrupt stream, expected txid " + (txId - 1) + ", got " +
                                      op.GetTransactionId());
            }
        }
Пример #3
0
        public virtual void TestExcludeInProgressStreams()
        {
            FilePath f = new FilePath(TestEditLog.TestDir + "/excludeinprogressstreams");
            // Don't close the edit log once the files have been set up.
            NNStorage storage = TestEditLog.SetupEdits(Sharpen.Collections.SingletonList <URI>
                                                           (f.ToURI()), 10, false);

            Storage.StorageDirectory sd = storage.DirIterator(NNStorage.NameNodeDirType.Edits
                                                              ).Next();
            FileJournalManager jm = new FileJournalManager(conf, sd, storage);

            // If we exclude the in-progess stream, we should only have 100 tx.
            NUnit.Framework.Assert.AreEqual(100, GetNumberOfTransactions(jm, 1, false, false)
                                            );
            EditLogInputStream elis = GetJournalInputStream(jm, 90, false);

            try
            {
                FSEditLogOp lastReadOp = null;
                while ((lastReadOp = elis.ReadOp()) != null)
                {
                    NUnit.Framework.Assert.IsTrue(lastReadOp.GetTransactionId() <= 100);
                }
            }
            finally
            {
                IOUtils.Cleanup(Log, elis);
            }
        }
Пример #4
0
        /// <summary>
        /// Verify that the given list of streams contains exactly the range of
        /// transactions specified, inclusive.
        /// </summary>
        /// <exception cref="System.IO.IOException"/>
        public static void VerifyEdits(IList <EditLogInputStream> streams, int firstTxnId,
                                       int lastTxnId)
        {
            IEnumerator <EditLogInputStream> iter = streams.GetEnumerator();

            NUnit.Framework.Assert.IsTrue(iter.HasNext());
            EditLogInputStream stream = iter.Next();

            for (int expected = firstTxnId; expected <= lastTxnId; expected++)
            {
                FSEditLogOp op = stream.ReadOp();
                while (op == null)
                {
                    NUnit.Framework.Assert.IsTrue("Expected to find txid " + expected + ", " + "but no more streams available to read from"
                                                  , iter.HasNext());
                    stream = iter.Next();
                    op     = stream.ReadOp();
                }
                NUnit.Framework.Assert.AreEqual(FSEditLogOpCodes.OpMkdir, op.opCode);
                NUnit.Framework.Assert.AreEqual(expected, op.GetTransactionId());
            }
            NUnit.Framework.Assert.IsNull(stream.ReadOp());
            NUnit.Framework.Assert.IsFalse("Expected no more txns after " + lastTxnId + " but more streams are available"
                                           , iter.HasNext());
        }
Пример #5
0
        /// <summary>
        /// Find out how many transactions we can read from a
        /// FileJournalManager, starting at a given transaction ID.
        /// </summary>
        /// <param name="jm">The journal manager</param>
        /// <param name="fromTxId">Transaction ID to start at</param>
        /// <param name="inProgressOk">Should we consider edit logs that are not finalized?</param>
        /// <returns>The number of transactions</returns>
        /// <exception cref="System.IO.IOException"/>
        internal static long GetNumberOfTransactions(FileJournalManager jm, long fromTxId
                                                     , bool inProgressOk, bool abortOnGap)
        {
            long numTransactions = 0;
            long txId            = fromTxId;
            PriorityQueue <EditLogInputStream> allStreams = new PriorityQueue <EditLogInputStream
                                                                               >(64, JournalSet.EditLogInputStreamComparator);

            jm.SelectInputStreams(allStreams, fromTxId, inProgressOk);
            EditLogInputStream elis = null;

            try
            {
                while ((elis = allStreams.Poll()) != null)
                {
                    try
                    {
                        elis.SkipUntil(txId);
                        while (true)
                        {
                            FSEditLogOp op = elis.ReadOp();
                            if (op == null)
                            {
                                break;
                            }
                            if (abortOnGap && (op.GetTransactionId() != txId))
                            {
                                Log.Info("getNumberOfTransactions: detected gap at txId " + fromTxId);
                                return(numTransactions);
                            }
                            txId = op.GetTransactionId() + 1;
                            numTransactions++;
                        }
                    }
                    finally
                    {
                        IOUtils.Cleanup(Log, elis);
                    }
                }
            }
            finally
            {
                IOUtils.Cleanup(Log, Sharpen.Collections.ToArray(allStreams, new EditLogInputStream
                                                                 [0]));
            }
            return(numTransactions);
        }
Пример #6
0
 /// <summary>
 /// Skip edit log operations up to a given transaction ID, or until the
 /// end of the edit log is reached.
 /// </summary>
 /// <remarks>
 /// Skip edit log operations up to a given transaction ID, or until the
 /// end of the edit log is reached.
 /// After this function returns, the next call to readOp will return either
 /// end-of-file (null) or a transaction with a txid equal to or higher than
 /// the one we asked for.
 /// </remarks>
 /// <param name="txid">The transaction ID to read up until.</param>
 /// <returns>
 /// Returns true if we found a transaction ID greater than
 /// or equal to 'txid' in the log.
 /// </returns>
 /// <exception cref="System.IO.IOException"/>
 public virtual bool SkipUntil(long txid)
 {
     while (true)
     {
         FSEditLogOp op = ReadOp();
         if (op == null)
         {
             return(false);
         }
         if (op.GetTransactionId() >= txid)
         {
             cachedOp = op;
             return(true);
         }
     }
 }
Пример #7
0
        public virtual void TestReadFromMiddleOfEditLog()
        {
            FilePath  f       = new FilePath(TestEditLog.TestDir + "/readfrommiddleofeditlog");
            NNStorage storage = TestEditLog.SetupEdits(Sharpen.Collections.SingletonList <URI>
                                                           (f.ToURI()), 10);

            Storage.StorageDirectory sd = storage.DirIterator(NNStorage.NameNodeDirType.Edits
                                                              ).Next();
            FileJournalManager jm   = new FileJournalManager(conf, sd, storage);
            EditLogInputStream elis = GetJournalInputStream(jm, 5, true);

            try
            {
                FSEditLogOp op = elis.ReadOp();
                NUnit.Framework.Assert.AreEqual("read unexpected op", op.GetTransactionId(), 5);
            }
            finally
            {
                IOUtils.Cleanup(Log, elis);
            }
        }
Пример #8
0
        /// <exception cref="System.IO.IOException"/>
        private FSEditLogOp NextOpImpl(bool skipBrokenEdits)
        {
            FSEditLogOp op = null;

            switch (state)
            {
            case EditLogFileInputStream.State.Uninit:
            {
                try
                {
                    Init(true);
                }
                catch (Exception e)
                {
                    Log.Error("caught exception initializing " + this, e);
                    if (skipBrokenEdits)
                    {
                        return(null);
                    }
                    Throwables.PropagateIfPossible <IOException>(e);
                }
                Preconditions.CheckState(state != EditLogFileInputStream.State.Uninit);
                return(NextOpImpl(skipBrokenEdits));
            }

            case EditLogFileInputStream.State.Open:
            {
                op = reader.ReadOp(skipBrokenEdits);
                if ((op != null) && (op.HasTransactionId()))
                {
                    long txId = op.GetTransactionId();
                    if ((txId >= lastTxId) && (lastTxId != HdfsConstants.InvalidTxid))
                    {
                        //
                        // Sometimes, the NameNode crashes while it's writing to the
                        // edit log.  In that case, you can end up with an unfinalized edit log
                        // which has some garbage at the end.
                        // JournalManager#recoverUnfinalizedSegments will finalize these
                        // unfinished edit logs, giving them a defined final transaction
                        // ID.  Then they will be renamed, so that any subsequent
                        // readers will have this information.
                        //
                        // Since there may be garbage at the end of these "cleaned up"
                        // logs, we want to be sure to skip it here if we've read everything
                        // we were supposed to read out of the stream.
                        // So we force an EOF on all subsequent reads.
                        //
                        long skipAmt = log.Length() - tracker.GetPos();
                        if (skipAmt > 0)
                        {
                            if (Log.IsDebugEnabled())
                            {
                                Log.Debug("skipping " + skipAmt + " bytes at the end " + "of edit log  '" + GetName
                                              () + "': reached txid " + txId + " out of " + lastTxId);
                            }
                            tracker.ClearLimit();
                            IOUtils.SkipFully(tracker, skipAmt);
                        }
                    }
                }
                break;
            }

            case EditLogFileInputStream.State.Closed:
            {
                break;
            }
            }
            // return null
            return(op);
        }
Пример #9
0
        /// <exception cref="System.IO.IOException"/>
        protected internal override FSEditLogOp NextOp()
        {
            while (true)
            {
                switch (state)
                {
                case RedundantEditLogInputStream.State.SkipUntil:
                {
                    try
                    {
                        if (prevTxId != HdfsConstants.InvalidTxid)
                        {
                            Log.Info("Fast-forwarding stream '" + streams[curIdx].GetName() + "' to transaction ID "
                                     + (prevTxId + 1));
                            streams[curIdx].SkipUntil(prevTxId + 1);
                        }
                    }
                    catch (IOException e)
                    {
                        prevException = e;
                        state         = RedundantEditLogInputStream.State.StreamFailed;
                    }
                    state = RedundantEditLogInputStream.State.Ok;
                    break;
                }

                case RedundantEditLogInputStream.State.Ok:
                {
                    try
                    {
                        FSEditLogOp op = streams[curIdx].ReadOp();
                        if (op == null)
                        {
                            state = RedundantEditLogInputStream.State.Eof;
                            if (streams[curIdx].GetLastTxId() == prevTxId)
                            {
                                return(null);
                            }
                            else
                            {
                                throw new RedundantEditLogInputStream.PrematureEOFException("got premature end-of-file "
                                                                                            + "at txid " + prevTxId + "; expected file to go up to " + streams[curIdx].GetLastTxId
                                                                                                ());
                            }
                        }
                        prevTxId = op.GetTransactionId();
                        return(op);
                    }
                    catch (IOException e)
                    {
                        prevException = e;
                        state         = RedundantEditLogInputStream.State.StreamFailed;
                    }
                    break;
                }

                case RedundantEditLogInputStream.State.StreamFailed:
                {
                    if (curIdx + 1 == streams.Length)
                    {
                        throw prevException;
                    }
                    long oldLast = streams[curIdx].GetLastTxId();
                    long newLast = streams[curIdx + 1].GetLastTxId();
                    if (newLast < oldLast)
                    {
                        throw new IOException("We encountered an error reading " + streams[curIdx].GetName
                                                  () + ".  During automatic edit log " + "failover, we noticed that all of the remaining edit log "
                                              + "streams are shorter than the current one!  The best " + "remaining edit log ends at transaction "
                                              + newLast + ", but we thought we could read up to transaction " + oldLast + ".  If you continue, metadata will be lost forever!"
                                              );
                    }
                    Log.Error("Got error reading edit log input stream " + streams[curIdx].GetName()
                              + "; failing over to edit log " + streams[curIdx + 1].GetName(), prevException);
                    curIdx++;
                    state = RedundantEditLogInputStream.State.SkipUntil;
                    break;
                }

                case RedundantEditLogInputStream.State.StreamFailedResync:
                {
                    if (curIdx + 1 == streams.Length)
                    {
                        if (prevException is RedundantEditLogInputStream.PrematureEOFException)
                        {
                            // bypass early EOF check
                            state = RedundantEditLogInputStream.State.Eof;
                        }
                        else
                        {
                            streams[curIdx].Resync();
                            state = RedundantEditLogInputStream.State.SkipUntil;
                        }
                    }
                    else
                    {
                        Log.Error("failing over to edit log " + streams[curIdx + 1].GetName());
                        curIdx++;
                        state = RedundantEditLogInputStream.State.SkipUntil;
                    }
                    break;
                }

                case RedundantEditLogInputStream.State.Eof:
                {
                    return(null);
                }
                }
            }
        }
Пример #10
0
        /// <exception cref="System.IO.IOException"/>
        internal static void RunEditLogTest(TestNameNodeRecovery.EditLogTestSetup elts)
        {
            FilePath TestLogName = new FilePath(TestDir, "test_edit_log");

            FSEditLogOp.OpInstanceCache cache = new FSEditLogOp.OpInstanceCache();
            EditLogFileOutputStream     elfos = null;
            EditLogFileInputStream      elfis = null;

            try
            {
                elfos = new EditLogFileOutputStream(new Configuration(), TestLogName, 0);
                elfos.Create(NameNodeLayoutVersion.CurrentLayoutVersion);
                elts.AddTransactionsToLog(elfos, cache);
                elfos.SetReadyToFlush();
                elfos.FlushAndSync(true);
                elfos.Close();
                elfos = null;
                elfis = new EditLogFileInputStream(TestLogName);
                elfis.SetMaxOpSize(elts.GetMaxOpSize());
                // reading through normally will get you an exception
                ICollection <long> validTxIds = elts.GetValidTxIds();
                FSEditLogOp        op         = null;
                long prevTxId = 0;
                try
                {
                    while (true)
                    {
                        op = elfis.NextOp();
                        if (op == null)
                        {
                            break;
                        }
                        Log.Debug("read txid " + op.txid);
                        if (!validTxIds.Contains(op.GetTransactionId()))
                        {
                            NUnit.Framework.Assert.Fail("read txid " + op.GetTransactionId() + ", which we did not expect to find."
                                                        );
                        }
                        validTxIds.Remove(op.GetTransactionId());
                        prevTxId = op.GetTransactionId();
                    }
                    if (elts.GetLastValidTxId() != -1)
                    {
                        NUnit.Framework.Assert.Fail("failed to throw IoException as expected");
                    }
                }
                catch (IOException)
                {
                    if (elts.GetLastValidTxId() == -1)
                    {
                        NUnit.Framework.Assert.Fail("expected all transactions to be valid, but got exception "
                                                    + "on txid " + prevTxId);
                    }
                    else
                    {
                        NUnit.Framework.Assert.AreEqual(prevTxId, elts.GetLastValidTxId());
                    }
                }
                if (elts.GetLastValidTxId() != -1)
                {
                    // let's skip over the bad transaction
                    op       = null;
                    prevTxId = 0;
                    try
                    {
                        while (true)
                        {
                            op = elfis.NextValidOp();
                            if (op == null)
                            {
                                break;
                            }
                            prevTxId = op.GetTransactionId();
                            NUnit.Framework.Assert.IsTrue(validTxIds.Remove(op.GetTransactionId()));
                        }
                    }
                    catch (Exception e)
                    {
                        NUnit.Framework.Assert.Fail("caught IOException while trying to skip over bad " +
                                                    "transaction.   message was " + e.Message + "\nstack trace\n" + StringUtils.StringifyException
                                                        (e));
                    }
                }
                // We should have read every valid transaction.
                NUnit.Framework.Assert.IsTrue(validTxIds.IsEmpty());
            }
            finally
            {
                IOUtils.Cleanup(Log, elfos, elfis);
            }
        }
 /// <summary>Loads edits file, uses visitor to process all elements</summary>
 /// <exception cref="System.IO.IOException"/>
 public override void LoadEdits()
 {
     try
     {
         visitor.Start(inputStream.GetVersion(true));
         while (true)
         {
             try
             {
                 FSEditLogOp op = inputStream.ReadOp();
                 if (op == null)
                 {
                     break;
                 }
                 if (fixTxIds)
                 {
                     if (nextTxId <= 0)
                     {
                         nextTxId = op.GetTransactionId();
                         if (nextTxId <= 0)
                         {
                             nextTxId = 1;
                         }
                     }
                     op.SetTransactionId(nextTxId);
                     nextTxId++;
                 }
                 visitor.VisitOp(op);
             }
             catch (IOException e)
             {
                 if (!recoveryMode)
                 {
                     // Tell the visitor to clean up, then re-throw the exception
                     Log.Error("Got IOException at position " + inputStream.GetPosition());
                     visitor.Close(e);
                     throw;
                 }
                 Log.Error("Got IOException while reading stream!  Resyncing.", e);
                 inputStream.Resync();
             }
             catch (RuntimeException e)
             {
                 if (!recoveryMode)
                 {
                     // Tell the visitor to clean up, then re-throw the exception
                     Log.Error("Got RuntimeException at position " + inputStream.GetPosition());
                     visitor.Close(e);
                     throw;
                 }
                 Log.Error("Got RuntimeException while reading stream!  Resyncing.", e);
                 inputStream.Resync();
             }
         }
         visitor.Close(null);
     }
     finally
     {
         IOUtils.Cleanup(Log, inputStream);
     }
 }
Пример #12
0
        public override void EndElement(string uri, string name, string qName)
        {
            string str = XMLUtils.UnmangleXmlString(cbuf.ToString(), false).Trim();

            cbuf = new StringBuilder();
            switch (state)
            {
            case OfflineEditsXmlLoader.ParseState.ExpectEditsTag:
            {
                throw new XMLUtils.InvalidXmlException("expected <EDITS/>");
            }

            case OfflineEditsXmlLoader.ParseState.ExpectVersion:
            {
                if (!name.Equals("EDITS_VERSION"))
                {
                    throw new XMLUtils.InvalidXmlException("expected </EDITS_VERSION>");
                }
                try
                {
                    int version = System.Convert.ToInt32(str);
                    visitor.Start(version);
                }
                catch (IOException e)
                {
                    // Can't throw IOException from a SAX method, sigh.
                    throw new RuntimeException(e);
                }
                state = OfflineEditsXmlLoader.ParseState.ExpectRecord;
                break;
            }

            case OfflineEditsXmlLoader.ParseState.ExpectRecord:
            {
                if (name.Equals("EDITS"))
                {
                    state = OfflineEditsXmlLoader.ParseState.ExpectEnd;
                }
                else
                {
                    if (!name.Equals("RECORD"))
                    {
                        throw new XMLUtils.InvalidXmlException("expected </EDITS> or </RECORD>");
                    }
                }
                break;
            }

            case OfflineEditsXmlLoader.ParseState.ExpectOpcode:
            {
                if (!name.Equals("OPCODE"))
                {
                    throw new XMLUtils.InvalidXmlException("expected </OPCODE>");
                }
                opCode = FSEditLogOpCodes.ValueOf(str);
                state  = OfflineEditsXmlLoader.ParseState.ExpectData;
                break;
            }

            case OfflineEditsXmlLoader.ParseState.ExpectData:
            {
                throw new XMLUtils.InvalidXmlException("expected <DATA/>");
            }

            case OfflineEditsXmlLoader.ParseState.HandleData:
            {
                stanza.SetValue(str);
                if (stanzaStack.Empty())
                {
                    if (!name.Equals("DATA"))
                    {
                        throw new XMLUtils.InvalidXmlException("expected </DATA>");
                    }
                    state = OfflineEditsXmlLoader.ParseState.ExpectRecord;
                    FSEditLogOp op = opCache.Get(opCode);
                    opCode = null;
                    try
                    {
                        op.DecodeXml(stanza);
                        stanza = null;
                    }
                    finally
                    {
                        if (stanza != null)
                        {
                            System.Console.Error.WriteLine("fromXml error decoding opcode " + opCode + "\n" +
                                                           stanza.ToString());
                            stanza = null;
                        }
                    }
                    if (fixTxIds)
                    {
                        if (nextTxId <= 0)
                        {
                            nextTxId = op.GetTransactionId();
                            if (nextTxId <= 0)
                            {
                                nextTxId = 1;
                            }
                        }
                        op.SetTransactionId(nextTxId);
                        nextTxId++;
                    }
                    try
                    {
                        visitor.VisitOp(op);
                    }
                    catch (IOException e)
                    {
                        // Can't throw IOException from a SAX method, sigh.
                        throw new RuntimeException(e);
                    }
                    state = OfflineEditsXmlLoader.ParseState.ExpectRecord;
                }
                else
                {
                    stanza = stanzaStack.Pop();
                }
                break;
            }

            case OfflineEditsXmlLoader.ParseState.ExpectEnd:
            {
                throw new XMLUtils.InvalidXmlException("not expecting anything after </EDITS>");
            }
            }
        }