void open() { if (!running) { running = true; writer = new Thread() { public void run() { try { processQueue(); } catch (Throwable ex) { warn(ex, ex.getMessage()); try { close(); } catch (Exception ignored) { warn(ignored, ignored.getMessage()); } } } }; writer.setPriority(Thread.MAX_PRIORITY); writer.setDaemon(true); writer.setName("DataFileAppender Writer Thread"); writer.start(); } }
Future<Boolean> sync() throws IOException { int spinnings = 0; int limit = 100; while (true) { try { if (batching.compareAndSet(false, true)) { Future result = null; if (nextWriteBatch != null) { result = new WriteFuture(nextWriteBatch.latch); batchQueue.put(nextWriteBatch); nextWriteBatch = null; } else { result = new WriteFuture(new CountDownLatch(0)); } batching.set(false); return result; } else { // Spin waiting for new batch ... if (spinnings <= limit) { spinnings++; continue; } else { Thread.sleep(250); continue; } } } catch (InterruptedException ex) { throw new IllegalStateException(ex.getMessage(), ex); } } }
void close() throws IOException { try { if (!shutdown) { if (running) { shutdown = true; while (batching.get() == true) { Thread.sleep(250); } if (nextWriteBatch != null) { batchQueue.put(nextWriteBatch); nextWriteBatch = null; } else { batchQueue.put(NULL_BATCH); } } else { shutdownDone.countDown(); } } shutdownDone.await(); } catch (InterruptedException e) { throw new InterruptedIOException(); } }
private WriteBatch enqueue(WriteCommand writeRecord) throws IOException { WriteBatch currentBatch = null; int spinnings = 0; int limit = 100; 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) { if (nextWriteBatch == null) { DataFile file = journal.getCurrentWriteFile(); boolean canBatch = false; currentBatch = new WriteBatch(file, file.getLength(), writeRecord); canBatch = currentBatch.canBatch(writeRecord); if (!canBatch) { file = journal.rotateWriteFile(); currentBatch = new WriteBatch(file, file.getLength(), writeRecord); } WriteCommand controlRecord = new WriteCommand(new Location(), null, false); currentBatch.doFirstBatch(controlRecord, writeRecord); if (!writeRecord.sync) { inflightWrites.put(controlRecord.location, controlRecord); inflightWrites.put(writeRecord.location, writeRecord); nextWriteBatch = currentBatch; batching.set(false); } else { batchQueue.put(currentBatch); batching.set(false); } break; } else { boolean canBatch = nextWriteBatch.canBatch(writeRecord); if (canBatch && !writeRecord.sync) { nextWriteBatch.doAppendBatch(writeRecord); inflightWrites.put(writeRecord.location, writeRecord); currentBatch = nextWriteBatch; batching.set(false); break; } else if (canBatch && writeRecord.sync) { nextWriteBatch.doAppendBatch(writeRecord); batchQueue.put(nextWriteBatch); currentBatch = nextWriteBatch; nextWriteBatch = null; batching.set(false); break; } else { batchQueue.put(nextWriteBatch); nextWriteBatch = null; batching.set(false); } } } else { // Spin waiting for new batch ... if (spinnings <= limit) { spinnings++; continue; } else { Thread.sleep(250); continue; } } } catch (InterruptedException ex) { throw new IllegalStateException(ex.getMessage(), ex); } } return currentBatch; }