public virtual void TestEmptyInputStream() { ZooKeeper zk = BKJMUtil.ConnectZooKeeper(); BookKeeper bkc = new BookKeeper(new ClientConfiguration(), zk); try { LedgerHandle lh = bkc.CreateLedger(BookKeeper.DigestType.Crc32, Sharpen.Runtime.GetBytesForString ("foobar")); lh.Close(); EditLogLedgerMetadata metadata = new EditLogLedgerMetadata("/foobar", HdfsConstants .NamenodeLayoutVersion, lh.GetId(), unchecked ((int)(0x1234))); try { new BookKeeperEditLogInputStream(lh, metadata, -1); NUnit.Framework.Assert.Fail("Shouldn't get this far, should have thrown"); } catch (IOException ioe) { NUnit.Framework.Assert.IsTrue(ioe.Message.Contains("Invalid first bk entry to read" )); } metadata = new EditLogLedgerMetadata("/foobar", HdfsConstants.NamenodeLayoutVersion , lh.GetId(), unchecked ((int)(0x1234))); try { new BookKeeperEditLogInputStream(lh, metadata, 0); NUnit.Framework.Assert.Fail("Shouldn't get this far, should have thrown"); } catch (IOException ioe) { NUnit.Framework.Assert.IsTrue(ioe.Message.Contains("Invalid first bk entry to read" )); } } finally { bkc.Close(); zk.Close(); } }
/// <summary>Start a new log segment in a BookKeeper ledger.</summary> /// <remarks> /// Start a new log segment in a BookKeeper ledger. /// First ensure that we have the write lock for this journal. /// Then create a ledger and stream based on that ledger. /// The ledger id is written to the inprogress znode, so that in the /// case of a crash, a recovery process can find the ledger we were writing /// to when we crashed. /// </remarks> /// <param name="txId">First transaction id to be written to the stream</param> /// <exception cref="System.IO.IOException"/> public override EditLogOutputStream StartLogSegment(long txId, int layoutVersion) { CheckEnv(); if (txId <= maxTxId.Get()) { throw new IOException("We've already seen " + txId + ". A new stream cannot be created with it" ); } try { string existingInprogressNode = ci.Read(); if (null != existingInprogressNode && zkc.Exists(existingInprogressNode, false) != null) { throw new IOException("Inprogress node already exists"); } if (currentLedger != null) { // bookkeeper errored on last stream, clean up ledger currentLedger.Close(); } currentLedger = bkc.CreateLedger(ensembleSize, quorumSize, ackQuorumSize, BookKeeper.DigestType .Mac, Sharpen.Runtime.GetBytesForString(digestpw, Charsets.Utf8)); } catch (BKException bke) { throw new IOException("Error creating ledger", bke); } catch (KeeperException ke) { throw new IOException("Error in zookeeper while creating ledger", ke); } catch (Exception ie) { Sharpen.Thread.CurrentThread().Interrupt(); throw new IOException("Interrupted creating ledger", ie); } try { string znodePath = InprogressZNode(txId); EditLogLedgerMetadata l = new EditLogLedgerMetadata(znodePath, layoutVersion, currentLedger .GetId(), txId); /* Write the ledger metadata out to the inprogress ledger znode * This can fail if for some reason our write lock has * expired (@see WriteLock) and another process has managed to * create the inprogress znode. * In this case, throw an exception. We don't want to continue * as this would lead to a split brain situation. */ l.Write(zkc, znodePath); maxTxId.Store(txId); ci.Update(znodePath); return(new BookKeeperEditLogOutputStream(conf, currentLedger)); } catch (KeeperException ke) { CleanupLedger(currentLedger); throw new IOException("Error storing ledger metadata", ke); } }