Skip to content

Commit

Permalink
less sleeping
Browse files Browse the repository at this point in the history
  • Loading branch information
hg-ms committed Sep 30, 2024
1 parent 2f5f5f5 commit 1470bcc
Showing 1 changed file with 59 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@
import static org.eclipse.serializer.util.X.notNull;

import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.serializer.afs.types.AFile;
import org.eclipse.serializer.afs.types.AFileSystem;
import org.eclipse.serializer.chars.VarString;
import org.eclipse.serializer.chars.XChars;
import org.eclipse.serializer.collections.ArrayView;
import org.eclipse.serializer.collections.XArrays;
import org.eclipse.serializer.concurrency.XThreads;
import org.eclipse.serializer.memory.XMemory;
import org.eclipse.serializer.util.X;
import org.eclipse.serializer.util.logging.Logging;
Expand Down Expand Up @@ -241,10 +243,34 @@ public void initialize()
final AFile lockFile = fileProvider.provideLockFile();
this.lockFile = StorageLockFile.New(lockFile);

final LockFileData initialFileData = this.lockFileHasContent()
? this.validateExistingLockFileData(true)
: null
;

LockFileData initialFileData = null;
if(this.lockFileHasContent()) {

initialFileData = this.readLockFileData();
if(!this.validateExistingLockFileData(initialFileData))
{
// wait one interval and try a second time
logger.warn("Non expired storage lock found! Retrying once");

ScheduledFuture<Boolean> future = this.executor.schedule(() -> {
return this.validateExistingLockFileData(this.readLockFileData());},
initialFileData.updateInterval,
TimeUnit.MILLISECONDS);

try {
if(!future.get(initialFileData.updateInterval *2, TimeUnit.MILLISECONDS)) {
this.executor.shutdownNow();
throw new StorageException("Storage already in use by: " + initialFileData.identifier);
}
} catch(InterruptedException | ExecutionException | TimeoutException e) {
this.executor.shutdownNow();
throw new StorageException("failed to validate lock file", e);
}
}


}

if(this.isReadOnlyMode())
{
Expand All @@ -263,6 +289,33 @@ public void initialize()
this.lockFile.file().ensureExists();
this.writeLockFileData();
}


private boolean validateExistingLockFileData(final LockFileData lockFileData)
{

final String identifier = this.setup.processIdentity();
if(identifier.equals(lockFileData.identifier))
{
// database is already owned by "this" process (e.g. crash shorty before), so just continue and reuse.
logger.info("Storage already owned by process!");
return true;
}

if(lockFileData.isLongExpired())
{
/*
* The lock file is no longer updated, meaning the database is not used anymore
* and the lockfile is just a zombie, probably left by a crash.
*/
logger.info("Storage lock file outdated, aquiring storage!");
return true;
}

logger.debug("Storage lock file not validated! Owner {}, expire time {}", lockFileData.identifier, lockFileData.expirationTime);

return false;
}

private ByteBuffer ensureReadingBuffer(final int fileLength)
{
Expand Down Expand Up @@ -412,44 +465,7 @@ private boolean lockFileHasContent()
return this.lockFile.exists() && this.lockFile.size() > 0;
}

private LockFileData validateExistingLockFileData(final boolean firstAttempt)
{
final LockFileData existingFiledata = this.readLockFileData();

final String identifier = this.setup.processIdentity();
if(identifier.equals(existingFiledata.identifier))
{
// database is already owned by "this" process (e.g. crash shorty before), so just continue and reuse.
logger.info("Storage already owned by process!");
return existingFiledata;
}

if(existingFiledata.isLongExpired())
{
/*
* The lock file is no longer updated, meaning the database is not used anymore
* and the lockfile is just a zombie, probably left by a crash.
*/
logger.info("Storage lock file outdated, aquiring storage!");
return existingFiledata;
}

// not owned and not expired
if(firstAttempt)
{
// wait one interval and try a second time
logger.warn("Non expired storage lock found!");
XThreads.sleep(existingFiledata.updateInterval);
return this.validateExistingLockFileData(false);

// returning here means no exception (but expiration) on the second attempt, meaning success.
}

// not owned, not expired and still active, meaning really still in use, so exception

throw new StorageException("Storage already in use by: " + existingFiledata.identifier);
}

private void checkForModifiedLockFile()
{
if(this.isReadOnlyMode() && !this.lockFileHasContent())
Expand Down Expand Up @@ -513,7 +529,7 @@ private ArrayView<ByteBuffer> setToWriteBuffer(final LockFileData lockFileData)

private void updateFile()
{
logger.trace("uptating lock file");
logger.trace("updating lock file");

this.checkForModifiedLockFile();
this.writeLockFileData();
Expand Down

0 comments on commit 1470bcc

Please sign in to comment.