/** * Log a series of writes. These writes are committed "atomically". Since all writes in the log * are serialized, we just need to make sure that all these writes are contiguous. * * @param ops Set of write operations */ public void put(final WriteBatch ops) { // Lock the log so that we can commit several at a time. synchronized (this) { Iterator<TableKey> iter = ops.iterator(); while (iter.hasNext()) { TableKey key = iter.next(); for (WriteBatch.TableWrite write : ops.getValues(key)) { ByteBuffer data = serialize(key, write.value, write.options); if (logBuffer.remaining() < data.position()) { logBuffer = mapWAL(); } data.flip(); logBuffer.put(data); } } } }
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; }