Search in sources :

Example 6 with WriteException

use of com.twitter.distributedlog.exceptions.WriteException in project distributedlog by twitter.

the class BKLogSegmentWriter method transmit.

/**
     * Transmit the current buffer to bookkeeper.
     * Synchronised at the class. #write() and #setReadyToFlush()
     * 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 Future<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 (!transmitResult.compareAndSet(BKException.Code.OK, BKException.Code.OK)) {
                LOG.error("Log Segment {} Trying to write to an errored stream; Error is {}", fullyQualifiedLogSegment, BKException.getMessage(transmitResult.get()));
                throw new BKTransmitException("Trying to write to an errored stream;" + " Error code : (" + transmitResult.get() + ") " + BKException.getMessage(transmitResult.get()), transmitResult.get());
            }
            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++;
            }
        }
        Buffer 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.
            transmitResult.set(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) {
            BKTransmitPacket packet = new BKTransmitPacket(recordSetToTransmit);
            packetPrevious = packet;
            entryWriter.asyncAddEntry(toSend.getData(), 0, toSend.size(), this, packet);
            if (recordSetToTransmit.hasUserRecords()) {
                transmitDataSuccesses.inc();
            } else {
                transmitControlSuccesses.inc();
            }
            lastTransmit.reset().start();
            outstandingTransmits.incrementAndGet();
            controlFlushNeeded = false;
            return packet.getTransmitFuture();
        }
    } finally {
        transmitLock.unlock();
    }
}
Also used : Buffer(com.twitter.distributedlog.io.Buffer) WriteException(com.twitter.distributedlog.exceptions.WriteException) BKTransmitException(com.twitter.distributedlog.exceptions.BKTransmitException) IOException(java.io.IOException) InvalidEnvelopedEntryException(com.twitter.distributedlog.exceptions.InvalidEnvelopedEntryException)

Example 7 with WriteException

use of com.twitter.distributedlog.exceptions.WriteException in project distributedlog by twitter.

the class BKLogSegmentWriter method addCompleteDeferredProcessing.

private void addCompleteDeferredProcessing(final BKTransmitPacket transmitPacket, final long entryId, final int rc) {
    boolean cancelPendingPromises = false;
    EntryBuffer recordSet = transmitPacket.getRecordSet();
    synchronized (this) {
        if (transmitResult.compareAndSet(BKException.Code.OK, rc)) {
            // If this is the first time we are setting an error code in the transmitResult then
            // we must cancel pending promises; once this error has been set, more records will not
            // be enqueued; they will be failed with WriteException
            cancelPendingPromises = (BKException.Code.OK != rc);
        } else {
            LOG.warn("Log segment {} entryId {}: Tried to set transmit result to ({}) but is already ({})", new Object[] { fullyQualifiedLogSegment, entryId, rc, transmitResult.get() });
        }
        if (transmitResult.get() != BKException.Code.OK) {
            if (recordSet.hasUserRecords()) {
                transmitDataPacketSize.registerFailedEvent(recordSet.getNumBytes());
            }
        } else {
            // visible by advancing the lastAck
            if (recordSet.hasUserRecords()) {
                transmitDataPacketSize.registerSuccessfulEvent(recordSet.getNumBytes());
                controlFlushNeeded = true;
                if (immediateFlushEnabled) {
                    if (0 == minDelayBetweenImmediateFlushMs) {
                        backgroundFlush(true);
                    } else {
                        scheduleFlushWithDelayIfNeeded(new Callable<Void>() {

                            @Override
                            public Void call() throws Exception {
                                backgroundFlush(true);
                                return null;
                            }
                        }, immFlushSchedFutureRef);
                    }
                }
            }
        }
        // update last dlsn before satisifying future
        if (BKException.Code.OK == transmitResult.get()) {
            DLSN lastDLSNInPacket = recordSet.finalizeTransmit(logSegmentSequenceNumber, entryId);
            if (recordSet.hasUserRecords()) {
                if (null != lastDLSNInPacket && lastDLSN.compareTo(lastDLSNInPacket) < 0) {
                    lastDLSN = lastDLSNInPacket;
                }
            }
        }
    }
    if (BKException.Code.OK == transmitResult.get()) {
        recordSet.completeTransmit(logSegmentSequenceNumber, entryId);
    } else {
        recordSet.abortTransmit(FutureUtils.transmitException(transmitResult.get()));
    }
    if (cancelPendingPromises) {
        // Since the writer is in a bad state no more packets will be tramsitted, and its safe to
        // assign a new empty packet. This is to avoid a race with closeInternal which may also
        // try to cancel the current packet;
        final BKTransmitPacket packetCurrentSaved;
        synchronized (this) {
            packetCurrentSaved = new BKTransmitPacket(recordSetWriter);
            recordSetWriter = newRecordSetWriter();
        }
        packetCurrentSaved.getRecordSet().abortTransmit(new WriteCancelledException(streamName, FutureUtils.transmitException(transmitResult.get())));
    }
}
Also used : WriteCancelledException(com.twitter.distributedlog.exceptions.WriteCancelledException) EndOfStreamException(com.twitter.distributedlog.exceptions.EndOfStreamException) BKException(org.apache.bookkeeper.client.BKException) BKTransmitException(com.twitter.distributedlog.exceptions.BKTransmitException) TransactionIdOutOfOrderException(com.twitter.distributedlog.exceptions.TransactionIdOutOfOrderException) WriteCancelledException(com.twitter.distributedlog.exceptions.WriteCancelledException) LogRecordTooLongException(com.twitter.distributedlog.exceptions.LogRecordTooLongException) LockingException(com.twitter.distributedlog.exceptions.LockingException) IOException(java.io.IOException) InvalidEnvelopedEntryException(com.twitter.distributedlog.exceptions.InvalidEnvelopedEntryException) WriteException(com.twitter.distributedlog.exceptions.WriteException) FlushException(com.twitter.distributedlog.exceptions.FlushException)

Example 8 with WriteException

use of com.twitter.distributedlog.exceptions.WriteException in project distributedlog by twitter.

the class DistributedLogMultiStreamWriter method write.

public synchronized Future<DLSN> write(ByteBuffer buffer) {
    int logRecordSize = buffer.remaining();
    if (logRecordSize > MAX_LOGRECORD_SIZE) {
        return Future.exception(new LogRecordTooLongException("Log record of size " + logRecordSize + " written when only " + MAX_LOGRECORD_SIZE + " is allowed"));
    }
    // if exceed max number of bytes
    if ((recordSetWriter.getNumBytes() + logRecordSize) > MAX_LOGRECORDSET_SIZE) {
        flush();
    }
    Promise<DLSN> writePromise = new Promise<DLSN>();
    try {
        recordSetWriter.writeRecord(buffer, writePromise);
    } catch (LogRecordTooLongException e) {
        return Future.exception(e);
    } catch (WriteException e) {
        recordSetWriter.abortTransmit(e);
        recordSetWriter = newRecordSetWriter();
        return Future.exception(e);
    }
    if (recordSetWriter.getNumBytes() >= bufferSize) {
        flush();
    }
    return writePromise;
}
Also used : Promise(com.twitter.util.Promise) WriteException(com.twitter.distributedlog.exceptions.WriteException) DLSN(com.twitter.distributedlog.DLSN) LogRecordTooLongException(com.twitter.distributedlog.exceptions.LogRecordTooLongException)

Aggregations

WriteException (com.twitter.distributedlog.exceptions.WriteException)8 LogRecordTooLongException (com.twitter.distributedlog.exceptions.LogRecordTooLongException)4 IOException (java.io.IOException)4 BKTransmitException (com.twitter.distributedlog.exceptions.BKTransmitException)3 InvalidEnvelopedEntryException (com.twitter.distributedlog.exceptions.InvalidEnvelopedEntryException)2 ZKDistributedLock (com.twitter.distributedlog.lock.ZKDistributedLock)2 Test (org.junit.Test)2 DLSN (com.twitter.distributedlog.DLSN)1 EndOfStreamException (com.twitter.distributedlog.exceptions.EndOfStreamException)1 FlushException (com.twitter.distributedlog.exceptions.FlushException)1 LockingException (com.twitter.distributedlog.exceptions.LockingException)1 TransactionIdOutOfOrderException (com.twitter.distributedlog.exceptions.TransactionIdOutOfOrderException)1 WriteCancelledException (com.twitter.distributedlog.exceptions.WriteCancelledException)1 Buffer (com.twitter.distributedlog.io.Buffer)1 Promise (com.twitter.util.Promise)1 URI (java.net.URI)1 BKException (org.apache.bookkeeper.client.BKException)1