blob: e6bd37cb4cec6dbd35ab32b0b801165fb12bf954 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.bookkeeper.client;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
/**
* Represents the entries of a segment of a ledger which are stored on a single
* bookie in the segments bookie ensemble.
*
* Used for checking and recovery
*/
public class LedgerFragment {
private final int bookieIndex;
private final List<InetSocketAddress> ensemble;
private final long firstEntryId;
private final long lastKnownEntryId;
private final long ledgerId;
private final DistributionSchedule schedule;
private final boolean isLedgerClosed;
LedgerFragment(LedgerHandle lh, long firstEntryId,
long lastKnownEntryId, int bookieIndex) {
this.ledgerId = lh.getId();
this.firstEntryId = firstEntryId;
this.lastKnownEntryId = lastKnownEntryId;
this.bookieIndex = bookieIndex;
this.ensemble = lh.getLedgerMetadata().getEnsemble(firstEntryId);
this.schedule = lh.getDistributionSchedule();
SortedMap<Long, ArrayList<InetSocketAddress>> ensembles = lh
.getLedgerMetadata().getEnsembles();
this.isLedgerClosed = lh.getLedgerMetadata().isClosed()
|| !ensemble.equals(ensembles.get(ensembles.lastKey()));
}
/**
* Returns true, if and only if the ledger fragment will never be modified
* by any of the clients in future, otherwise false. i.e,
* <ol>
* <li>If ledger is in closed state, then no other clients can modify this
* fragment.</li>
* <li>If ledger is not in closed state and the current fragment is not a
* last fragment, then no one will modify this fragment.</li>
* </ol>
*/
public boolean isClosed() {
return isLedgerClosed;
}
long getLedgerId() {
return ledgerId;
}
long getFirstEntryId() {
return firstEntryId;
}
long getLastKnownEntryId() {
return lastKnownEntryId;
}
/**
* Gets the failedBookie address
*/
public InetSocketAddress getAddress() {
return ensemble.get(bookieIndex);
}
/**
* Gets the failedBookie index
*/
public int getBookiesIndex() {
return bookieIndex;
}
/**
* Gets the first stored entry id of the fragment in failed bookie.
*
* @return entryId
*/
public long getFirstStoredEntryId() {
long firstEntry = firstEntryId;
for (int i = 0; i < ensemble.size() && firstEntry <= lastKnownEntryId; i++) {
if (schedule.hasEntry(firstEntry, bookieIndex)) {
return firstEntry;
} else {
firstEntry++;
}
}
return LedgerHandle.INVALID_ENTRY_ID;
}
/**
* Gets the last stored entry id of the fragment in failed bookie.
*
* @return entryId
*/
public long getLastStoredEntryId() {
long lastEntry = lastKnownEntryId;
for (int i = 0; i < ensemble.size() && lastEntry >= firstEntryId; i++) {
if (schedule.hasEntry(lastEntry, bookieIndex)) {
return lastEntry;
} else {
lastEntry--;
}
}
return LedgerHandle.INVALID_ENTRY_ID;
}
/**
* Gets the ensemble of fragment
*
* @return the ensemble for the segment which this fragment is a part of
*/
public List<InetSocketAddress> getEnsemble() {
return this.ensemble;
}
@Override
public String toString() {
return String.format("Fragment(LedgerID: %d, FirstEntryID: %d[%d], "
+ "LastKnownEntryID: %d[%d], Host: %s, Closed: %s)", ledgerId, firstEntryId,
getFirstStoredEntryId(), lastKnownEntryId, getLastStoredEntryId(),
getAddress(), isLedgerClosed);
}
}