Search in sources :

Example 1 with WriteBatch

use of org.fusesource.hawtjournal.api.Journal.WriteBatch in project hawtjournal by fusesource.

the class DataFileAppender method processBatches.

/**
     * The async processing loop that writes to the data files and does the
     * force calls. Since the file sync() call is the slowest of all the
     * operations, this algorithm tries to 'batch' or group together several
     * file sync() requests into a single file sync() call. The batching is
     * accomplished attaching the same CountDownLatch instance to every force
     * request in a group.
     */
private void processBatches() {
    try {
        boolean last = false;
        while (true) {
            WriteBatch wb = batchQueue.take();
            if (shutdown) {
                last = true;
            }
            if (!wb.isEmpty()) {
                boolean newOrRotated = lastAppendDataFile != wb.getDataFile();
                if (newOrRotated) {
                    if (lastAppendRaf != null) {
                        lastAppendRaf.close();
                    }
                    lastAppendDataFile = wb.getDataFile();
                    lastAppendRaf = lastAppendDataFile.openRandomAccessFile();
                }
                // perform batch:
                Location latest = wb.perform(lastAppendRaf, journal.getReplicationTarget(), journal.isChecksum());
                // Adjust journal length and pointers:
                journal.addToTotalLength(wb.getSize());
                journal.setLastAppendLocation(latest);
                // Now that the data is on disk, remove the writes from the in-flight cache and notify listeners.
                Collection<WriteCommand> commands = wb.getWrites();
                for (WriteCommand current : commands) {
                    if (!current.isSync()) {
                        journal.getInflightWrites().remove(current.getLocation());
                    }
                }
                if (journal.getListener() != null) {
                    try {
                        journal.getListener().synced(commands.toArray(new WriteCommand[commands.size()]));
                    } catch (Throwable ex) {
                        warn(ex, ex.getMessage());
                    }
                }
                // Signal any waiting threads that the write is on disk.
                wb.getLatch().countDown();
            }
            if (last) {
                break;
            }
        }
    } catch (Exception e) {
        firstAsyncException.compareAndSet(null, e);
    } finally {
        try {
            if (lastAppendRaf != null) {
                lastAppendRaf.close();
            }
        } catch (Throwable ignore) {
        }
        shutdownDone.countDown();
    }
}
Also used : WriteCommand(org.fusesource.hawtjournal.api.Journal.WriteCommand) WriteBatch(org.fusesource.hawtjournal.api.Journal.WriteBatch) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException)

Example 2 with WriteBatch

use of org.fusesource.hawtjournal.api.Journal.WriteBatch in project hawtjournal by fusesource.

the class DataFileAppender method storeItem.

Location storeItem(Buffer data, byte type, boolean sync) throws IOException {
    int size = Journal.HEADER_SIZE + data.getLength();
    Location location = new Location();
    location.setSize(size);
    location.setType(type);
    WriteCommand write = new WriteCommand(location, data, sync);
    WriteBatch batch = enqueue(write);
    location.setLatch(batch.getLatch());
    if (sync) {
        try {
            batch.getLatch().await();
        } catch (InterruptedException e) {
            throw new InterruptedIOException();
        }
    }
    return location;
}
Also used : WriteCommand(org.fusesource.hawtjournal.api.Journal.WriteCommand) InterruptedIOException(java.io.InterruptedIOException) WriteBatch(org.fusesource.hawtjournal.api.Journal.WriteBatch)

Example 3 with WriteBatch

use of org.fusesource.hawtjournal.api.Journal.WriteBatch in project hawtjournal by fusesource.

the class DataFileAppender method enqueue.

private WriteBatch enqueue(WriteCommand writeRecord) throws IOException {
    WriteBatch currentBatch = null;
    int spinnings = 0;
    int limit = SPIN_RETRIES;
    while (true) {
        if (shutdown) {
            throw new IOException("DataFileAppender Writer Thread Shutdown!");
        }
        if (firstAsyncException.get() != null) {
            throw new IOException(firstAsyncException.get());
        }
        try {
            if (batching.compareAndSet(false, true) && !shutdown) {
                try {
                    if (nextWriteBatch == null) {
                        DataFile file = journal.getCurrentWriteFile();
                        boolean canBatch = false;
                        currentBatch = new WriteBatch(file, file.getLength());
                        canBatch = currentBatch.canBatch(writeRecord, journal.getMaxWriteBatchSize(), journal.getMaxFileLength());
                        if (!canBatch) {
                            file = journal.rotateWriteFile();
                            currentBatch = new WriteBatch(file, file.getLength());
                        }
                        WriteCommand controlRecord = currentBatch.prepareBatch();
                        currentBatch.appendBatch(writeRecord);
                        if (!writeRecord.isSync()) {
                            journal.getInflightWrites().put(controlRecord.getLocation(), controlRecord);
                            journal.getInflightWrites().put(writeRecord.getLocation(), writeRecord);
                            nextWriteBatch = currentBatch;
                        } else {
                            batchQueue.put(currentBatch);
                        }
                        break;
                    } else {
                        boolean canBatch = nextWriteBatch.canBatch(writeRecord, journal.getMaxWriteBatchSize(), journal.getMaxFileLength());
                        if (canBatch && !writeRecord.isSync()) {
                            nextWriteBatch.appendBatch(writeRecord);
                            journal.getInflightWrites().put(writeRecord.getLocation(), writeRecord);
                            currentBatch = nextWriteBatch;
                            break;
                        } else if (canBatch && writeRecord.isSync()) {
                            nextWriteBatch.appendBatch(writeRecord);
                            batchQueue.put(nextWriteBatch);
                            currentBatch = nextWriteBatch;
                            nextWriteBatch = null;
                            break;
                        } else {
                            batchQueue.put(nextWriteBatch);
                            nextWriteBatch = null;
                        }
                    }
                } finally {
                    batching.set(false);
                }
            } else {
                // Spin waiting for new batch ...
                if (spinnings <= limit) {
                    spinnings++;
                    continue;
                } else {
                    Thread.sleep(SPIN_BACKOFF);
                    continue;
                }
            }
        } catch (InterruptedException ex) {
            throw new IllegalStateException(ex.getMessage(), ex);
        }
    }
    return currentBatch;
}
Also used : WriteCommand(org.fusesource.hawtjournal.api.Journal.WriteCommand) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException) WriteBatch(org.fusesource.hawtjournal.api.Journal.WriteBatch)

Aggregations

InterruptedIOException (java.io.InterruptedIOException)3 WriteBatch (org.fusesource.hawtjournal.api.Journal.WriteBatch)3 WriteCommand (org.fusesource.hawtjournal.api.Journal.WriteCommand)3 IOException (java.io.IOException)2