private Status MakeRoomForWrite(boolean force) {
		mutex_.isHeldByCurrentThread();
		assert (!writers_.isEmpty());
		boolean allow_delay = !force;
		Status s = Status.OK();
		while (true) {
			if (!bg_error_.ok()) {
				// Yield previous error
				s = bg_error_;
				break;
			} else if (allow_delay
					&& versions_.NumLevelFiles(0) >= config.kL0_SlowdownWritesTrigger) {
				// We are getting close to hitting a hard limit on the number of
				// L0 files. Rather than delaying a single write by several
				// seconds when we hit the hard limit, start delaying each
				// individual write by 1ms to reduce latency variance. Also,
				// this delay hands over some CPU to the compaction thread in
				// case it is sharing the same core as the writer.
				mutex_.unlock();
				env_.SleepForMicroseconds(1000);
				allow_delay = false; // Do not delay a single write more than
										// once
				mutex_.lock();
			} else if (!force
					&& (mem_.ApproximateMemoryUsage() <= options_.write_buffer_size)) {
				// There is room in current memtable
				break;
			} else if (imm_ != null) {
				// We have filled up the current memtable, but the previous
				// one is still being compacted, so we wait.
				bg_cv_.awaitUninterruptibly();
			} else if (versions_.NumLevelFiles(0) >= config.kL0_StopWritesTrigger) {
				// There are too many level-0 files.
				LOG.info("There are too many level-0 files. waiting...\n");
				bg_cv_.awaitUninterruptibly();
			} else {
				// Attempt to switch to a new memtable and trigger compaction of
				// old
				assert (versions_.PrevLogNumber() == 0);
				long new_log_number = versions_.NewFileNumber();
				_WritableFile lfile = env_.NewWritableFile(filename
						.LogFileName(dbname_, new_log_number));
				if (!s.ok()) {
					break;
				}

				// close before reset
				logfile_.Close();
				logfile_ = lfile;
				logfile_number_ = new_log_number;
				log_ = new com.leveldb.common.log.Writer(lfile);
				imm_ = mem_;
				has_imm_.Release_Store(imm_);
				mem_ = new MemTable(internal_comparator_);
				mem_.Ref();
				force = false; // Do not force another compaction if have room
				LOG.info("Attempt to switch to a new memtable and trigger compaction of old");
				MaybeScheduleCompaction();
			}
		}
		return s;
	}