private WriteBatch enqueue(WriteCommand writeCommand, boolean sync) throws IOException {
        WriteBatch result = null;
        this.enqueueLock.lock();
        try {
            this.startAppendThreadIfNessary();
            if (this.nextWriteBatch == null) {
                result = this.newWriteBatch(writeCommand);
                this.empty.signalAll();
            } else {
                if (this.nextWriteBatch.canAppend(writeCommand)) {
                    this.nextWriteBatch.append(writeCommand);
                    result = this.nextWriteBatch;
                } else {
                    while (this.nextWriteBatch != null) {
                        try {
                            this.notEmpty.await();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    result = this.newWriteBatch(writeCommand);
                    this.empty.signalAll();
                }
            }
            if (!sync) {
                InflyWriteData inflyWriteData = this.inflyWrites.get(writeCommand.bytesKey);
                switch (writeCommand.opItem.op) {
                case OpItem.OP_ADD:
                    if (inflyWriteData == null) {
                        this.inflyWrites.put(writeCommand.bytesKey, new InflyWriteData(writeCommand.data));
                    } else {
                        // update and increase reference count;
                        inflyWriteData.data = writeCommand.data;
                        inflyWriteData.count++;
                    }
                    break;
                case OpItem.OP_DEL:
                    if (inflyWriteData != null) {
                        this.inflyWrites.remove(writeCommand.bytesKey);
                    }
                }

            }
            return result;
        } finally {
            this.enqueueLock.unlock();
        }

    }