/** * Creates a new instance of the LogMetadata class which contains an additional ledger. * * @param ledgerId The Id of the Ledger to add. * @return A new instance of the LogMetadata class. */ LogMetadata addLedger(long ledgerId) { Preconditions.checkState(this.enabled, "Log is not enabled. Cannot perform any modifications on it."); // Copy existing ledgers. List<LedgerMetadata> newLedgers = new ArrayList<>(this.ledgers.size() + 1); newLedgers.addAll(this.ledgers); // Create and add metadata for the new ledger. int sequence = this.ledgers.size() == 0 ? INITIAL_LEDGER_SEQUENCE : this.ledgers.get(this.ledgers.size() - 1).getSequence() + 1; newLedgers.add(new LedgerMetadata(ledgerId, sequence)); return new LogMetadata(this.epoch + 1, this.enabled, Collections.unmodifiableList(newLedgers), this.truncationAddress, this.updateVersion.get()); }
/** * Creates a new instance of the LedgerAddress class. * * @param metadata The LedgerMetadata for the ledger. * @param entryId The Entry Id inside the Ledger that this Address corresponds to. */ LedgerAddress(LedgerMetadata metadata, long entryId) { this(calculateAppendSequence(metadata.getSequence(), entryId), metadata.getLedgerId()); }
/** * Updates the LastAddConfirmed on individual LedgerMetadata instances based on the provided argument. * * @param lastAddConfirmed A Map of LedgerId to LastAddConfirmed based on which we can update the status. * @return This (unmodified) instance if lastAddConfirmed.isEmpty() or a new instance of the LogMetadata class with * the updated LedgerMetadata instances. */ LogMetadata updateLedgerStatus(Map<Long, Long> lastAddConfirmed) { if (lastAddConfirmed.isEmpty()) { // Nothing to change. return this; } val newLedgers = this.ledgers.stream() .map(lm -> { long lac = lastAddConfirmed.getOrDefault(lm.getLedgerId(), Long.MIN_VALUE); if (lm.getStatus() == LedgerMetadata.Status.Unknown && lac != Long.MIN_VALUE) { LedgerMetadata.Status e = lac == Ledgers.NO_ENTRY_ID ? LedgerMetadata.Status.Empty : LedgerMetadata.Status.NotEmpty; lm = new LedgerMetadata(lm.getLedgerId(), lm.getSequence(), e); } return lm; }) .collect(Collectors.toList()); return new LogMetadata(this.epoch, this.enabled, Collections.unmodifiableList(newLedgers), this.truncationAddress, this.updateVersion.get()); }
private void writeLedger00(RevisionDataOutput output, LedgerMetadata m) throws IOException { output.writeCompactLong(m.getLedgerId()); output.writeCompactInt(m.getSequence()); output.writeByte(m.getStatus().getValue()); }
if (address.getLedgerSequence() < firstLedger.getSequence()) {
metadata.getLedgers().get(i - 1).getSequence() + 1, metadata.getLedgers().get(i).getSequence());
val bkLm = context.bkAdmin.getLedgerMetadata(lh); output("\tLedger %d: Seq=%d, Status=%s, LAC=%d, Length=%d, Bookies=%d, Frags=%d, E/W/A=%d/%d/%d, Ensembles=%s.", lm.getLedgerId(), lm.getSequence(), lm.getStatus(), lh.getLastAddConfirmed(), lh.getLength(), lh.getNumBookies(), lh.getNumFragments(), bkLm.getEnsembleSize(), bkLm.getWriteQuorumSize(), bkLm.getAckQuorumSize(), getEnsembleDescription(bkLm)); } catch (Exception ex) { output("\tLedger %d: Seq = %d, Status = %s. BK: %s", lm.getLedgerId(), lm.getSequence(), lm.getStatus(), ex.getMessage()); } finally { if (lh != null) {
/** * Tests serialization/deserialization. */ @Test(timeout = 5000) public void testSerialization() throws Exception { Supplier<Long> nextLedgerId = new AtomicLong()::incrementAndGet; LogMetadata m1 = null; val lacs = new HashMap<Long, Long>(); for (int i = 0; i < LEDGER_COUNT; i++) { long ledgerId = nextLedgerId.get() * 2; if (m1 == null) { m1 = new LogMetadata(ledgerId).withUpdateVersion(i); } else { m1 = m1.addLedger(ledgerId).withUpdateVersion(i); } if (i % 2 == 0) { // Every other Ledger, update the LastAddConfirmed. lacs.put((long) i, (long) i + 1); } } m1 = m1.updateLedgerStatus(lacs); val serialization = LogMetadata.SERIALIZER.serialize(m1); val m2 = LogMetadata.SERIALIZER.deserialize(serialization); Assert.assertEquals("Unexpected epoch.", m1.getEpoch(), m2.getEpoch()); Assert.assertEquals("Unexpected TruncationAddress.", m1.getTruncationAddress().getSequence(), m2.getTruncationAddress().getSequence()); Assert.assertEquals("Unexpected TruncationAddress.", m1.getTruncationAddress().getLedgerId(), m2.getTruncationAddress().getLedgerId()); AssertExtensions.assertListEquals("Unexpected ledgers.", m1.getLedgers(), m2.getLedgers(), (l1, l2) -> l1.getSequence() == l2.getSequence() && l1.getLedgerId() == l2.getLedgerId() && l1.getStatus() == l2.getStatus()); }
val firstLedgerSeq = m.getLedgers().get(0).getSequence(); LedgerAddress a = m.getNextAddress(new LedgerAddress(firstLedgerSeq - 1, firstLedgerId - 1, 1234), Long.MAX_VALUE); Assert.assertEquals("Unexpected ledger id when input address less than first ledger.", firstLedgerId, a.getLedgerId()); val secondLedgerSeq = m.getLedgers().get(1).getSequence(); LedgerAddress truncationAddress = new LedgerAddress(secondLedgerSeq, secondLedgerId, 1); val m2 = m.truncate(truncationAddress); a = m.getNextAddress(new LedgerAddress(lm.getSequence(), lm.getLedgerId(), 3), 3); if (i == m.getLedgers().size() - 1) { Assert.assertNull("Unexpected result when reached the end of the log.", a);