// Appends a new packet of buffered deletes to the stream, // setting its generation: public synchronized long push(FrozenBufferedUpdates packet) { /* * The insert operation must be atomic. If we let threads increment the gen * and push the packet afterwards we risk that packets are out of order. * With DWPT this is possible if two or more flushes are racing for pushing * updates. If the pushed packets get our of order would loose documents * since deletes are applied to the wrong segments. */ packet.setDelGen(nextGen++); assert packet.any(); assert checkDeleteStats(); assert packet.delGen() < nextGen; assert updates.isEmpty() || updates.get(updates.size() - 1).delGen() < packet.delGen() : "Delete packets must be in order"; updates.add(packet); numTerms.addAndGet(packet.numTermDeletes); bytesUsed.addAndGet(packet.bytesUsed); if (infoStream.isEnabled("BD")) { infoStream.message( "BD", "push deletes " + packet + " delGen=" + packet.delGen() + " packetCount=" + updates.size() + " totBytesUsed=" + bytesUsed.get()); } assert checkDeleteStats(); return packet.delGen(); }
public void testPartiallyAppliedGlobalSlice() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InterruptedException { final DocumentsWriterDeleteQueue queue = new DocumentsWriterDeleteQueue(); Field field = DocumentsWriterDeleteQueue.class.getDeclaredField("globalBufferLock"); field.setAccessible(true); ReentrantLock lock = (ReentrantLock) field.get(queue); lock.lock(); Thread t = new Thread() { @Override public void run() { queue.addDelete(new Term("foo", "bar")); } }; t.start(); t.join(); lock.unlock(); assertTrue("changes in del queue but not in slice yet", queue.anyChanges()); queue.tryApplyGlobalSlice(); assertTrue("changes in global buffer", queue.anyChanges()); FrozenBufferedUpdates freezeGlobalBuffer = queue.freezeGlobalBuffer(null); assertTrue(freezeGlobalBuffer.any()); assertEquals(1, freezeGlobalBuffer.termCount); assertFalse("all changes applied", queue.anyChanges()); }