Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

119
LINES

< > BotCompany Repo | #1029788 // FileBasedLock (crash-safe, should work even over NFS)

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (10117L) is out of date.

// the lockFile must be a file separate from any data files.
// It is created & deleted by this class, and will always have
// size 0.
sclass FileBasedLock implements AutoCloseable {
  File lockFile;
  double timeout = 60.0; // in seconds. refresh happens twice as often
  bool verbose;
  bool haveLock;
  java.util.Timer touchTimer;
  
  // what to put in the lock file when we create it
  settable S contentsForLockFile;
  
  *() {}
  *(File *lockFile) {}
  *(File *lockFile, double *timeout) {}
  
  // returns true iff lock was acquired (or kept)
  synchronized bool tryToLock() {
    if (haveLock) true;
    
    if (fileExists(lockFile)) {
      double age = fileAgeInSeconds(lockFile);
      double remaining = timeout-age;
      print("Lock file age: " + lockFile + ": " + iround(age) + " s"
        + (remaining <= 0
          ? " - old, deleting"
          : " - please start again in " + nSeconds(iceil(remaining))));
        
      if (remaining <= 0) {
        print("Deleting old lock file (program crashed?): " + lockFile + " (age: " + iround(age) + " seconds)");
        deleteFile(lockFile);
      }
    }
    
    try {
      mkdirsForFile(lockFile);
      
      // This does the actual atomic file creation
      java.nio.file.Files.createFile(toPath(lockFile));
      print("Created lock file: " + lockFile);
      
      // Optionally set the lock file's contents
      if (nempty(contentsForLockFile))
        writeContents();
        
      acquired();
      true;
    } catch e {
      printExceptionShort("Can't lock", e);
      false;
    }
  }
  
  void writeContents {
    saveTextFileWithoutTemp(lockFile, unnull(contentsForLockFile));
  }
  
  private void acquired {
    set haveLock;
    startTouchTimer();
  }
  
  void forceLock ctex {
    print("Force-locking " + lockFile);
    writeContents();
    acquired();
  }
  
  S lockError() {
    ret "Couldn't aquire lock file: " + lockFile;
  }
  
  void lockOrFail {
    if (!tryToLock())
      fail(lockError());
  }
  
  synchronized void startTouchTimer {
    if (touchTimer != null) ret;
    double interval = timeout/2;
    touchTimer = doEvery(interval, r doTouch);
    if (verbose) print("Touch timer started for " + lockFile +  " (" + interval + "s)");
  }

  synchronized void doTouch() pcall {
    if (haveLock) {
      if (verbose) print("Touching lock file: " + lockFile);
      //touchExistingFile(lockFile);
      touchFile(lockFile);
    }
  }
     
  public synchronized void close() pcall {
    dispose touchTimer;
    if (haveLock) {
      haveLock = false;
      if (verbose) print("Deleting lock file: " + lockFile);
      deleteFile(lockFile);
    }
  }
  
  synchronized void _simulateCrash {
    dispose touchTimer;
  }
  
  void deleteOnExit {
    if (haveLock)
      lockFile.deleteOnExit();
  }
  
  S actualContents() {
    ret loadTextFile(lockFile);
  }
  
  bool hasExpectedContents() {
    ret eq(unnull(contentsForLockFile), actualContents());
  }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1029788
Snippet name: FileBasedLock (crash-safe, should work even over NFS)
Eternal ID of this version: #1029788/44
Text MD5: 38f91f36d9d25d5119cdc81c262e7b1f
Author: stefan
Category: javax / io
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-11-30 16:56:19
Source code size: 3082 bytes / 119 lines
Pitched / IR pitched: No / No
Views / Downloads: 373 / 843
Version history: 43 change(s)
Referenced in: [show references]