Search in sources :

Example 1 with WriteCommand

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

the class DataFileAccessor method readLocation.

Buffer readLocation(Location location) throws IOException {
    WriteCommand asyncWrite = journal.getInflightWrites().get(location);
    Buffer result = null;
    if (asyncWrite != null) {
        result = asyncWrite.getData();
    } else {
        RandomAccessFile raf = getOrCreateRaf(Thread.currentThread(), location.getDataFileId());
        Lock threadLock = getOrCreateLock(Thread.currentThread(), location.getDataFileId());
        accessorLock.lock();
        threadLock.lock();
        try {
            if (location.getSize() == Location.NOT_SET) {
                raf.seek(location.getOffset());
                location.setSize(raf.readInt());
                location.setType(raf.readByte());
            } else {
                raf.seek(Journal.HEADER_SIZE + location.getOffset());
            }
            if (location.isBatchControlRecord()) {
                byte[] data = new byte[raf.readInt()];
                raf.readFully(data);
                result = new Buffer(data, 0, data.length);
            } else {
                byte[] data = new byte[location.getSize() - Journal.HEADER_SIZE];
                raf.readFully(data);
                result = new Buffer(data, 0, data.length);
            }
        } catch (RuntimeException e) {
            throw new IOException("Invalid location: " + location + ", : " + e);
        } finally {
            threadLock.unlock();
            accessorLock.unlock();
        }
    }
    if (!location.isDeletedRecord()) {
        return result;
    } else {
        throw new IOException("Deleted location: " + location);
    }
}
Also used : Buffer(org.fusesource.hawtbuf.Buffer) WriteCommand(org.fusesource.hawtjournal.api.Journal.WriteCommand) RandomAccessFile(java.io.RandomAccessFile) IOException(java.io.IOException) ReentrantLock(java.util.concurrent.locks.ReentrantLock) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Lock(java.util.concurrent.locks.Lock) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock)

Example 2 with WriteCommand

use of org.fusesource.hawtjournal.api.Journal.WriteCommand 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 3 with WriteCommand

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

the class DataFileAccessor method fillLocationDetails.

boolean fillLocationDetails(Location location) throws IOException {
    WriteCommand asyncWrite = journal.getInflightWrites().get(location);
    if (asyncWrite != null) {
        location.setSize(asyncWrite.getLocation().getSize());
        location.setType(asyncWrite.getLocation().getType());
        return true;
    } else {
        RandomAccessFile raf = getOrCreateRaf(Thread.currentThread(), location.getDataFileId());
        Lock threadLock = getOrCreateLock(Thread.currentThread(), location.getDataFileId());
        accessorLock.lock();
        threadLock.lock();
        try {
            if (raf.length() > location.getOffset()) {
                raf.seek(location.getOffset());
                location.setSize(raf.readInt());
                location.setType(raf.readByte());
                if (location.getSize() > 0 && location.getType() != Location.NO_RECORD_TYPE) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } finally {
            threadLock.unlock();
            accessorLock.unlock();
        }
    }
}
Also used : WriteCommand(org.fusesource.hawtjournal.api.Journal.WriteCommand) RandomAccessFile(java.io.RandomAccessFile) ReentrantLock(java.util.concurrent.locks.ReentrantLock) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Lock(java.util.concurrent.locks.Lock) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock)

Example 4 with WriteCommand

use of org.fusesource.hawtjournal.api.Journal.WriteCommand 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 5 with WriteCommand

use of org.fusesource.hawtjournal.api.Journal.WriteCommand 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

WriteCommand (org.fusesource.hawtjournal.api.Journal.WriteCommand)5 IOException (java.io.IOException)3 InterruptedIOException (java.io.InterruptedIOException)3 WriteBatch (org.fusesource.hawtjournal.api.Journal.WriteBatch)3 RandomAccessFile (java.io.RandomAccessFile)2 Lock (java.util.concurrent.locks.Lock)2 ReadWriteLock (java.util.concurrent.locks.ReadWriteLock)2 ReentrantLock (java.util.concurrent.locks.ReentrantLock)2 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)2 Buffer (org.fusesource.hawtbuf.Buffer)1