use of org.apache.distributedlog.exceptions.BKTransmitException in project bookkeeper by apache.
the class BKLogSegmentWriter method transmit.
/**
* Transmit the current buffer to bookkeeper.
* Synchronised at the class. #write() and #flush()
* are never called at the same time.
* NOTE: This method should only throw known exceptions so that we don't accidentally
* add new code that throws in an inappropriate place.
*
* @return a transmit future for caller to wait for transmit result if we transmit successfully,
* null if no data to transmit
* @throws BKTransmitException if the segment writer is already in error state
* @throws LockingException if the segment writer lost lock before transmit
* @throws WriteException if failed to create the envelope for the data to transmit
* @throws InvalidEnvelopedEntryException when built an invalid enveloped entry
*/
private CompletableFuture<Integer> transmit() throws BKTransmitException, LockingException, WriteException, InvalidEnvelopedEntryException {
EntryBuffer recordSetToTransmit;
transmitLock.lock();
try {
synchronized (this) {
checkWriteLock();
// stream has encountered an error and cannot be written to.
if (!transmitResultUpdater.compareAndSet(this, BKException.Code.OK, BKException.Code.OK)) {
LOG.error("Log Segment {} Trying to write to an errored stream; Error is {}", fullyQualifiedLogSegment, BKException.getMessage(transmitResultUpdater.get(this)));
throw new BKTransmitException("Trying to write to an errored stream;" + " Error code : (" + transmitResultUpdater.get(this) + ") " + BKException.getMessage(transmitResultUpdater.get(this)), transmitResultUpdater.get(this));
}
if (recordSetWriter.getNumRecords() == 0) {
// Control flushes always have at least the control record to flush
transmitDataMisses.inc();
return null;
}
recordSetToTransmit = recordSetWriter;
recordSetWriter = newRecordSetWriter();
outstandingBytes = 0;
if (recordSetToTransmit.hasUserRecords()) {
numBytes += recordSetToTransmit.getNumBytes();
numFlushesSinceRestart++;
}
}
ByteBuf toSend;
try {
toSend = recordSetToTransmit.getBuffer();
FailpointUtils.checkFailPoint(FailpointUtils.FailPointName.FP_TransmitFailGetBuffer);
} catch (IOException e) {
if (e instanceof InvalidEnvelopedEntryException) {
alertStatsLogger.raise("Invalid enveloped entry for segment {} : ", fullyQualifiedLogSegment, e);
}
LOG.error("Exception while enveloping entries for segment: {}", new Object[] { fullyQualifiedLogSegment }, e);
// If a write fails here, we need to set the transmit result to an error so that
// no future writes go through and violate ordering guarantees.
transmitResultUpdater.set(this, BKException.Code.WriteException);
if (e instanceof InvalidEnvelopedEntryException) {
alertStatsLogger.raise("Invalid enveloped entry for segment {} : ", fullyQualifiedLogSegment, e);
throw (InvalidEnvelopedEntryException) e;
} else {
throw new WriteException(streamName, "Envelope Error");
}
}
synchronized (this) {
// update the transmit timestamp
lastTransmitNanos = MathUtils.nowInNano();
BKTransmitPacket packet = new BKTransmitPacket(recordSetToTransmit);
packetPrevious = packet;
entryWriter.asyncAddEntry(toSend, this, packet);
if (recordSetToTransmit.hasUserRecords()) {
transmitDataSuccesses.inc();
} else {
transmitControlSuccesses.inc();
}
lastTransmit.reset().start();
outstandingTransmitsUpdater.incrementAndGet(this);
controlFlushNeeded = false;
return packet.getTransmitFuture();
}
} finally {
transmitLock.unlock();
}
}
use of org.apache.distributedlog.exceptions.BKTransmitException in project bookkeeper by apache.
the class BKLogSegmentEntryReader method readEntriesFromReadAheadCache.
private void readEntriesFromReadAheadCache(PendingReadRequest nextRequest) {
while (!nextRequest.hasReadEnoughEntries()) {
CacheEntry entry;
boolean hitEndOfLogSegment;
synchronized (this) {
entry = readAheadEntries.peek();
hitEndOfLogSegment = (null == entry) && isEndOfLogSegment();
}
// reach end of log segment
if (hitEndOfLogSegment) {
completeExceptionally(new EndOfLogSegmentException(getSegment().getZNodeName()), false);
return;
}
if (null == entry) {
return;
}
// entry is not complete yet.
if (!entry.isDone()) {
// we already reached end of the log segment
if (isEndOfLogSegment(entry.getEntryId())) {
completeExceptionally(new EndOfLogSegmentException(getSegment().getZNodeName()), false);
}
return;
}
if (entry.isSuccess()) {
CacheEntry removedEntry = readAheadEntries.poll();
try {
if (entry != removedEntry) {
DLIllegalStateException ise = new DLIllegalStateException("Unexpected condition at reading from " + getSegment());
completeExceptionally(ise, false);
return;
}
try {
// the reference is retained on `entry.getEntry()`.
// Entry.Reader is responsible for releasing it.
nextRequest.addEntry(processReadEntry(entry.getEntry()));
} catch (IOException e) {
completeExceptionally(e, false);
return;
}
} finally {
removedEntry.release();
}
} else if (skipBrokenEntries && BKException.Code.DigestMatchException == entry.getRc()) {
// skip this entry and move forward
skippedBrokenEntriesCounter.inc();
CacheEntry removedEntry = readAheadEntries.poll();
removedEntry.release();
continue;
} else {
completeExceptionally(new BKTransmitException("Encountered issue on reading entry " + entry.getEntryId() + " @ log segment " + getSegment(), entry.getRc()), false);
return;
}
}
}
Aggregations