/** * Opens a ledger for reading purposes (does not fence it). * * @param ledgerMetadata LedgerMetadata for the ledger to open. * @return A BookKeeper LedgerHandle representing the ledger. * @throws DurableDataLogException If an exception occurred. */ public LedgerHandle openLedgerNoFencing(LedgerMetadata ledgerMetadata) throws DurableDataLogException { return Ledgers.openRead(ledgerMetadata.getLedgerId(), this.bkClient, this.config); }
private int getLedgerMetadataIndex(long ledgerId) { return CollectionHelpers.binarySearch(this.ledgers, lm -> Long.compare(ledgerId, lm.getLedgerId())); }
/** * Creates a new instance of the LogMetadata class which contains all the ledgers after (and including) the given address. * * @param upToAddress The address to truncate to. * @return A new instance of the LogMetadata class. */ LogMetadata truncate(LedgerAddress upToAddress) { Preconditions.checkState(this.enabled, "Log is not enabled. Cannot perform any modifications on it."); // Exclude all those Ledgers that have a LedgerId less than the one we are given. An optimization to this would // involve trimming out the ledger which has a matching ledger id and the entry is is the last one, but that would // involve opening the Ledger in BookKeeper and inspecting it, which would take too long. val newLedgers = this.ledgers.stream().filter(lm -> lm.getLedgerId() >= upToAddress.getLedgerId()).collect(Collectors.toList()); return new LogMetadata(this.epoch, this.enabled, Collections.unmodifiableList(newLedgers), upToAddress, this.updateVersion.get()); }
@Override public String toString() { return String.format("LedgerId = %s, Length = %s, Attempts = %s, InProgress = %s, Done = %s, Failed %s", this.writeLedger.get().metadata.getLedgerId(), this.data.getLength(), this.attemptCount, isInProgress(), isDone(), this.failureCause.get() != null); }
/** * 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()); }
while (iterator.hasPrevious() && (nonEmptyCount < MIN_FENCE_LEDGER_COUNT)) { LedgerMetadata ledgerMetadata = iterator.previous(); LedgerHandle handle = openFence(ledgerMetadata.getLedgerId(), bookKeeper, config); if (handle.getLastAddConfirmed() != NO_ENTRY_ID) { result.put(ledgerMetadata.getLedgerId(), handle.getLastAddConfirmed());
val ledgersToDelete = oldMetadata.getLedgers().stream().filter(lm -> !ledgerIdsToKeep.contains(lm.getLedgerId())).iterator(); while (ledgersToDelete.hasNext()) { val lm = ledgersToDelete.next(); try { Ledgers.delete(lm.getLedgerId(), this.bookKeeper); } catch (DurableDataLogException ex) { log.error("{}: Unable to delete truncated ledger {}.", this.traceObjectId, lm.getLedgerId(), ex);
private void collectAllReferencedLedgerIds(Collection<Long> referencedLedgerIds, Context context) throws Exception { referencedLedgerIds.clear(); for (int logId = 0; logId < context.serviceConfig.getContainerCount(); logId++) { @Cleanup DebugLogWrapper log = context.logFactory.createDebugLogWrapper(logId); val m = log.fetchMetadata(); if (m == null) { continue; } for (val lm : m.getLedgers()) { referencedLedgerIds.add(lm.getLedgerId()); } } }
long firstLedgerId = this.writes.peekFirst().getWriteLedger().metadata.getLedgerId(); boolean canSkip = true; } else if (write.getWriteLedger().metadata.getLedgerId() != firstLedgerId) {
private void writeLedger00(RevisionDataOutput output, LedgerMetadata m) throws IOException { output.writeCompactLong(m.getLedgerId()); output.writeCompactInt(m.getSequence()); output.writeByte(m.getStatus().getValue()); }
val currentMetadata = log.loadMetadata(); val lastLedger = currentMetadata.getLedgers().get(currentMetadata.getLedgers().size() - 1); allLedgers.add(new AbstractMap.SimpleImmutableEntry<>(lastLedger.getLedgerId(), shouldAppend ? LedgerMetadata.Status.NotEmpty : LedgerMetadata.Status.Empty)); val metadataLedgers = currentMetadata.getLedgers().stream().map(LedgerMetadata::getLedgerId).collect(Collectors.toSet());
if (lm.getLedgerId() > address.getLedgerId()) { ledgerMetadata = lm; break;
ledger = Ledgers.openRead(metadata.getLedgerId(), this.bookKeeper, this.config); } else { ledger = Ledgers.openFence(metadata.getLedgerId(), this.bookKeeper, this.config);
if (expectedLedgerIds.contains(ledgerId)) { Assert.assertNotNull("Existing LedgerMetadata was not found.", lm); Assert.assertEquals("Unexpected ledger id returned.", ledgerId, lm.getLedgerId()); } else { Assert.assertNull("A LedgerMetadata that did not exist was returned.", lm); .forEach(expectedLedgerIds::add); for (int i = m.getLedgers().size() - skipCount; i < m.getLedgers().size(); i++) { long ledgerId = m.getLedgers().get(i).getLedgerId(); if (!expectedLedgerIds.contains(ledgerId)) { expectedLedgerIds.add(ledgerId);
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 firstLedgerId = m.getLedgers().get(0).getLedgerId(); val firstLedgerSeq = m.getLedgers().get(0).getSequence(); LedgerAddress a = m.getNextAddress(new LedgerAddress(firstLedgerSeq - 1, firstLedgerId - 1, 1234), Long.MAX_VALUE); val secondLedgerId = m.getLedgers().get(1).getLedgerId(); val secondLedgerSeq = m.getLedgers().get(1).getSequence(); LedgerAddress truncationAddress = new LedgerAddress(secondLedgerSeq, secondLedgerId, 1); 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); } else { val nextLm = m.getLedgers().get(i + 1); Assert.assertEquals("Unexpected ledger id when result should be in the next ledger.", nextLm.getLedgerId(), a.getLedgerId()); Assert.assertEquals("Unexpected entry id when result should be in the next ledger.", 0, a.getEntryId());