use of net.openhft.chronicle.threads.TimingPauser in project Chronicle-Queue by OpenHFT.
the class TableStoreWriteLock method lock.
/**
* Guaranteed to succeed in getting the lock (may involve timeout and recovery) or else throw.
* <p>This is not re-entrant i.e. if you lock and try and lock again it will timeout and recover
*/
@Override
public void lock() {
throwExceptionIfClosed();
assert checkNotAlreadyLocked();
long currentLockValue = 0;
TimingPauser tlPauser = pauser.get();
try {
currentLockValue = lock.getVolatileValue();
while (!lock.compareAndSwapValue(UNLOCKED, PID)) {
if (Thread.currentThread().isInterrupted())
throw new InterruptedRuntimeException("Interrupted for the lock file:" + path);
tlPauser.pause(timeout, TimeUnit.MILLISECONDS);
currentLockValue = lock.getVolatileValue();
}
// noinspection ConstantConditions,AssertWithSideEffects
assert (lockedByThread = Thread.currentThread()) != null && (lockedHere = new StackTrace()) != null;
// success
} catch (TimeoutException e) {
final String lockedBy = getLockedBy(currentLockValue);
final String warningMsg = "Couldn't acquire write lock " + "after " + timeout + " ms " + "for the lock file:" + path + ". " + "Lock was held by " + lockedBy;
if (forceUnlockOnTimeoutWhen == UnlockMode.NEVER)
throw new UnrecoverableTimeoutException(new IllegalStateException(warningMsg + UNLOCK_MAIN_MSG));
else if (forceUnlockOnTimeoutWhen == UnlockMode.LOCKING_PROCESS_DEAD) {
if (forceUnlockIfProcessIsDead())
lock();
else
throw new UnrecoverableTimeoutException(new IllegalStateException(warningMsg + UNLOCK_MAIN_MSG));
} else {
warn().on(getClass(), warningMsg + UNLOCKING_FORCIBLY_MSG);
forceUnlock(currentLockValue);
lock();
}
} finally {
tlPauser.reset();
}
}
use of net.openhft.chronicle.threads.TimingPauser in project Chronicle-Queue by OpenHFT.
the class SingleTableBuilder method build.
// *************************************************************************
//
// *************************************************************************
@NotNull
public TableStore<T> build() {
if (readOnly) {
if (!file.exists())
throw new IORuntimeException("Metadata file not found in readOnly mode");
// Wait a short time for the file to be initialized
TimingPauser pauser = Pauser.balanced();
try {
while (file.length() < OS.mapAlignment()) {
pauser.pause(1, TimeUnit.SECONDS);
}
} catch (TimeoutException e) {
throw new IORuntimeException("Metadata file found in readOnly mode, but not initialized yet");
}
}
MappedBytes bytes = null;
try {
if (!readOnly && file.createNewFile() && !file.canWrite()) {
throw new IllegalStateException("Cannot write to tablestore file " + file);
}
bytes = MappedBytes.mappedBytes(file, OS.SAFE_PAGE_SIZE, OS.SAFE_PAGE_SIZE, readOnly);
// these MappedBytes are shared, but the assumption is they shouldn't grow. Supports 2K entries.
bytes.disableThreadSafetyCheck(true);
// eagerly initialize backing MappedFile page - otherwise wire.writeFirstHeader() will try to lock the file
// to allocate the first byte store and that will cause lock overlap
bytes.readVolatileInt(0);
Wire wire = wireType.apply(bytes);
if (readOnly)
return SingleTableStore.doWithSharedLock(file, v -> {
try {
return readTableStore(wire);
} catch (IOException ex) {
throw Jvm.rethrow(ex);
}
}, () -> null);
else {
MappedBytes finalBytes = bytes;
return SingleTableStore.doWithExclusiveLock(file, v -> {
try {
if (wire.writeFirstHeader()) {
return writeTableStore(finalBytes, wire);
} else {
return readTableStore(wire);
}
} catch (IOException ex) {
throw Jvm.rethrow(ex);
}
}, () -> null);
}
} catch (IOException e) {
throw new IORuntimeException("file=" + file.getAbsolutePath(), e);
} finally {
if (bytes != null)
bytes.clearUsedByThread();
}
}
Aggregations