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.

1  
// the lockFile must be a file separate from any data files.
2  
// It is created & deleted by this class, and will always have
3  
// size 0.
4  
sclass FileBasedLock implements AutoCloseable {
5  
  File lockFile;
6  
  double timeout = 60.0; // in seconds. refresh happens twice as often
7  
  bool verbose;
8  
  bool haveLock;
9  
  java.util.Timer touchTimer;
10  
  
11  
  // what to put in the lock file when we create it
12  
  settable S contentsForLockFile;
13  
  
14  
  *() {}
15  
  *(File *lockFile) {}
16  
  *(File *lockFile, double *timeout) {}
17  
  
18  
  // returns true iff lock was acquired (or kept)
19  
  synchronized bool tryToLock() {
20  
    if (haveLock) true;
21  
    
22  
    if (fileExists(lockFile)) {
23  
      double age = fileAgeInSeconds(lockFile);
24  
      double remaining = timeout-age;
25  
      print("Lock file age: " + lockFile + ": " + iround(age) + " s"
26  
        + (remaining <= 0
27  
          ? " - old, deleting"
28  
          : " - please start again in " + nSeconds(iceil(remaining))));
29  
        
30  
      if (remaining <= 0) {
31  
        print("Deleting old lock file (program crashed?): " + lockFile + " (age: " + iround(age) + " seconds)");
32  
        deleteFile(lockFile);
33  
      }
34  
    }
35  
    
36  
    try {
37  
      mkdirsForFile(lockFile);
38  
      
39  
      // This does the actual atomic file creation
40  
      java.nio.file.Files.createFile(toPath(lockFile));
41  
      print("Created lock file: " + lockFile);
42  
      
43  
      // Optionally set the lock file's contents
44  
      if (nempty(contentsForLockFile))
45  
        writeContents();
46  
        
47  
      acquired();
48  
      true;
49  
    } catch e {
50  
      printExceptionShort("Can't lock", e);
51  
      false;
52  
    }
53  
  }
54  
  
55  
  void writeContents {
56  
    saveTextFileWithoutTemp(lockFile, unnull(contentsForLockFile));
57  
  }
58  
  
59  
  private void acquired {
60  
    set haveLock;
61  
    startTouchTimer();
62  
  }
63  
  
64  
  void forceLock ctex {
65  
    print("Force-locking " + lockFile);
66  
    writeContents();
67  
    acquired();
68  
  }
69  
  
70  
  S lockError() {
71  
    ret "Couldn't aquire lock file: " + lockFile;
72  
  }
73  
  
74  
  void lockOrFail {
75  
    if (!tryToLock())
76  
      fail(lockError());
77  
  }
78  
  
79  
  synchronized void startTouchTimer {
80  
    if (touchTimer != null) ret;
81  
    double interval = timeout/2;
82  
    touchTimer = doEvery(interval, r doTouch);
83  
    if (verbose) print("Touch timer started for " + lockFile +  " (" + interval + "s)");
84  
  }
85  
86  
  synchronized void doTouch() pcall {
87  
    if (haveLock) {
88  
      if (verbose) print("Touching lock file: " + lockFile);
89  
      //touchExistingFile(lockFile);
90  
      touchFile(lockFile);
91  
    }
92  
  }
93  
     
94  
  public synchronized void close() pcall {
95  
    dispose touchTimer;
96  
    if (haveLock) {
97  
      haveLock = false;
98  
      if (verbose) print("Deleting lock file: " + lockFile);
99  
      deleteFile(lockFile);
100  
    }
101  
  }
102  
  
103  
  synchronized void _simulateCrash {
104  
    dispose touchTimer;
105  
  }
106  
  
107  
  void deleteOnExit {
108  
    if (haveLock)
109  
      lockFile.deleteOnExit();
110  
  }
111  
  
112  
  S actualContents() {
113  
    ret loadTextFile(lockFile);
114  
  }
115  
  
116  
  bool hasExpectedContents() {
117  
    ret eq(unnull(contentsForLockFile), actualContents());
118  
  }
119  
}

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: 375 / 847
Version history: 43 change(s)
Referenced in: [show references]