Search in sources :

Example 6 with Buffer

use of com.twitter.distributedlog.io.Buffer in project distributedlog by twitter.

the class TestEntry method testEmptyRecordSet.

@Test(timeout = 20000)
public void testEmptyRecordSet() throws Exception {
    Writer writer = Entry.newEntry("test-empty-record-set", 1024, true, CompressionCodec.Type.NONE, NullStatsLogger.INSTANCE);
    assertEquals("zero bytes", 0, writer.getNumBytes());
    assertEquals("zero records", 0, writer.getNumRecords());
    Buffer buffer = writer.getBuffer();
    Entry recordSet = Entry.newBuilder().setData(buffer.getData(), 0, buffer.size()).setLogSegmentInfo(1L, 0L).setEntryId(0L).build();
    Reader reader = recordSet.reader();
    Assert.assertNull("Empty record set should return null", reader.nextRecord());
}
Also used : ByteBuffer(java.nio.ByteBuffer) Buffer(com.twitter.distributedlog.io.Buffer) Reader(com.twitter.distributedlog.Entry.Reader) Writer(com.twitter.distributedlog.Entry.Writer) Test(org.junit.Test)

Example 7 with Buffer

use of com.twitter.distributedlog.io.Buffer 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 8 with Buffer

use of com.twitter.distributedlog.io.Buffer in project distributedlog by twitter.

the class EnvelopedEntryWriter method getBuffer.

@Override
public synchronized Buffer getBuffer() throws InvalidEnvelopedEntryException, IOException {
    if (!envelopeBeforeTransmit) {
        return buffer;
    }
    // We can't escape this allocation because things need to be read from one byte array
    // and then written to another. This is the destination.
    Buffer toSend = new Buffer(buffer.size());
    byte[] decompressed = buffer.getData();
    int length = buffer.size();
    EnvelopedEntry entry = new EnvelopedEntry(EnvelopedEntry.CURRENT_VERSION, codec, decompressed, length, statsLogger);
    // This will cause an allocation of a byte[] for compression. This can be avoided
    // but we can do that later only if needed.
    entry.writeFully(new DataOutputStream(toSend));
    return toSend;
}
Also used : Buffer(com.twitter.distributedlog.io.Buffer) DataOutputStream(java.io.DataOutputStream)

Aggregations

Buffer (com.twitter.distributedlog.io.Buffer)8 Test (org.junit.Test)6 Writer (com.twitter.distributedlog.Entry.Writer)4 ByteBuffer (java.nio.ByteBuffer)4 DataOutputStream (java.io.DataOutputStream)3 Reader (com.twitter.distributedlog.Entry.Reader)2 LogRecordTooLongException (com.twitter.distributedlog.exceptions.LogRecordTooLongException)2 Future (com.twitter.util.Future)2 Promise (com.twitter.util.Promise)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 DataInputStream (java.io.DataInputStream)2 NullStatsLogger (org.apache.bookkeeper.stats.NullStatsLogger)2 BKTransmitException (com.twitter.distributedlog.exceptions.BKTransmitException)1 InvalidEnvelopedEntryException (com.twitter.distributedlog.exceptions.InvalidEnvelopedEntryException)1 WriteException (com.twitter.distributedlog.exceptions.WriteException)1 IOException (java.io.IOException)1