public void close() { if (shuttingDown.getAndSet(true)) { return; } mutex.lock(); try { while (backgroundCompaction != null) { backgroundCondition.awaitUninterruptibly(); } } finally { mutex.unlock(); } compactionExecutor.shutdown(); try { compactionExecutor.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } try { versions.destroy(); } catch (IOException ignored) { } try { log.close(); } catch (IOException ignored) { } tableCache.close(); dbLock.release(); }
void startIdleState() { lock.lock(); try { final Thread currentThread = Thread.currentThread(); final Thread currentIdleThread = threadsRequestingIdle.peekFirst(); if (currentIdleThread == currentThread) { assert idleStateCount > 0; ++idleStateCount; assert idleStateCount > 0; return; } threadsRequestingIdle.add(currentThread); while ((activitiyCount > 0) || (threadsRequestingIdle.getFirst() != currentThread)) condition.awaitUninterruptibly(); assert idleStateCount == 0; assert activitiyCount == 0; assert threadsRequestingIdle.getFirst() == currentThread; idleStateCount = 1; } finally { lock.unlock(); } }
void startRequest(boolean isFileScopeRequest) { lock.lock(); try { while (!canStartRequest(isFileScopeRequest)) condition.awaitUninterruptibly(); ++activitiyCount; } finally { lock.unlock(); } }
private void awaitForCloseUninterruptibly() { _mutex.lock(); try { while (!isClosed()) { _connectionClosed.awaitUninterruptibly(); } } finally { _mutex.unlock(); } }
/** Acquire one permit from the semaphore in a manner that cannot be interrupted. */ public void acquireUninterruptibly() { // TODO - you fill in here. lock.lock(); try { while (availablePermits() == 0) permitAvailable.awaitUninterruptibly(); numAvailablePermits--; } finally { lock.unlock(); } }
/** Acquire one permit from the semaphore in a manner that cannot be interrupted. */ public void acquireUninterruptibly() { // TODO - you fill in here. reentrantLock.lock(); try { while (permits == 0) { condition.awaitUninterruptibly(); } permits--; } finally { reentrantLock.unlock(); } }
void endAllowingFileScopeRequests() { lock.lock(); try { final Thread currentThread = Thread.currentThread(); final Thread currentIdleThread = threadsRequestingIdle.peekFirst(); assert currentThread == currentIdleThread; assert allowFileScopeRequests; while (activitiyCount > 0) condition.awaitUninterruptibly(); allowFileScopeRequests = false; } finally { lock.unlock(); } }
public void compactRange(int level, Slice start, Slice end) { Preconditions.checkArgument(level >= 0, "level is negative"); Preconditions.checkArgument( level + 1 < NUM_LEVELS, "level is greater than or equal to %s", NUM_LEVELS); Preconditions.checkNotNull(start, "start is null"); Preconditions.checkNotNull(end, "end is null"); mutex.lock(); try { while (this.manualCompaction != null) { backgroundCondition.awaitUninterruptibly(); } ManualCompaction manualCompaction = new ManualCompaction(level, start, end); this.manualCompaction = manualCompaction; maybeScheduleCompaction(); while (this.manualCompaction == manualCompaction) { backgroundCondition.awaitUninterruptibly(); } } finally { mutex.unlock(); } }
public void flushMemTable() { mutex.lock(); try { // force compaction makeRoomForWrite(true); // todo bg_error code while (immutableMemTable != null) { backgroundCondition.awaitUninterruptibly(); } } finally { mutex.unlock(); } }
private void makeRoomForWrite(boolean force) { Preconditions.checkState(mutex.isHeldByCurrentThread()); boolean allowDelay = !force; while (true) { // todo background processing system need work // if (!bg_error_.ok()) { // // Yield previous error // s = bg_error_; // break; // } else if (allowDelay && versions.numberOfFilesInLevel(0) > L0_SLOWDOWN_WRITES_TRIGGER) { // 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. try { mutex.unlock(); Thread.sleep(1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } finally { mutex.lock(); } // Do not delay a single write more than once allowDelay = false; } else if (!force && memTable.approximateMemoryUsage() <= options.writeBufferSize()) { // There is room in current memtable break; } else if (immutableMemTable != null) { // We have filled up the current memtable, but the previous // one is still being compacted, so we wait. backgroundCondition.awaitUninterruptibly(); } else if (versions.numberOfFilesInLevel(0) >= L0_STOP_WRITES_TRIGGER) { // There are too many level-0 files. // Log(options_.info_log, "waiting...\n"); backgroundCondition.awaitUninterruptibly(); } else { // Attempt to switch to a new memtable and trigger compaction of old Preconditions.checkState(versions.getPrevLogNumber() == 0); // close the existing log try { log.close(); } catch (IOException e) { throw new RuntimeException("Unable to close log file " + log.getFile(), e); } // open a new log long logNumber = versions.getNextFileNumber(); try { this.log = Logs.createLogWriter( new File(databaseDir, Filename.logFileName(logNumber)), logNumber); } catch (IOException e) { throw new RuntimeException( "Unable to open new log file " + new File(databaseDir, Filename.logFileName(logNumber)).getAbsoluteFile(), e); } // create a new mem table immutableMemTable = memTable; memTable = new MemTable(internalKeyComparator); // Do not force another compaction there is space available force = false; maybeScheduleCompaction(); } } }
public Object down(Event evt) { switch (evt.getType()) { case Event.LOCK: LockInfo info = (LockInfo) evt.getArg(); ClientLock lock = getLock(info.getName()); if (!info.isTrylock()) { if (info.isLockInterruptibly()) { try { lock.lockInterruptibly(); } catch (InterruptedException e) { Thread.currentThread() .interrupt(); // has to be checked by caller who has to rethrow ... } } else lock.lock(); } else { if (info.isUseTimeout()) { try { return lock.tryLock(info.getTimeout(), info.getTimeUnit()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { return lock.tryLock(); } } return null; case Event.UNLOCK: info = (LockInfo) evt.getArg(); lock = getLock(info.getName(), false); if (lock != null) lock.unlock(); return null; case Event.UNLOCK_ALL: unlockAll(); return null; case Event.LOCK_AWAIT: info = (LockInfo) evt.getArg(); lock = getLock(info.getName(), false); if (lock == null || !lock.acquired) { throw new IllegalMonitorStateException(); } Condition condition = lock.newCondition(); if (info.isUseTimeout()) { try { return condition.awaitNanos(info.getTimeUnit().toNanos(info.getTimeout())); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else if (info.isLockInterruptibly()) { try { condition.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { condition.awaitUninterruptibly(); } break; case Event.LOCK_SIGNAL: AwaitInfo awaitInfo = (AwaitInfo) evt.getArg(); lock = getLock(awaitInfo.getName(), false); if (lock == null || !lock.acquired) { throw new IllegalMonitorStateException(); } sendSignalConditionRequest(awaitInfo.getName(), awaitInfo.isAll()); break; case Event.SET_LOCAL_ADDRESS: local_addr = (Address) evt.getArg(); break; case Event.VIEW_CHANGE: handleView((View) evt.getArg()); break; } return down_prot.down(evt); }