blob: 86db0b2b1020ea964a8755a754bdf0fd3917a662 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===--- LockFileManager.h - File-level locking utility ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#ifndef LLVM_SUPPORT_LOCKFILEMANAGER_H
10#define LLVM_SUPPORT_LOCKFILEMANAGER_H
11
12#include "llvm/ADT/Optional.h"
13#include "llvm/ADT/SmallString.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010014#include <system_error>
15#include <utility> // for std::pair
16
17namespace llvm {
18class StringRef;
19
Andrew Scullcdfcccc2018-10-05 20:58:37 +010020/// Class that manages the creation of a lock file to aid
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010021/// implicit coordination between different processes.
22///
23/// The implicit coordination works by creating a ".lock" file alongside
24/// the file that we're coordinating for, using the atomicity of the file
25/// system to ensure that only a single process can create that ".lock" file.
26/// When the lock file is removed, the owning process has finished the
27/// operation.
28class LockFileManager {
29public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010030 /// Describes the state of a lock file.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010031 enum LockFileState {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010032 /// The lock file has been created and is owned by this instance
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010033 /// of the object.
34 LFS_Owned,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010035 /// The lock file already exists and is owned by some other
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010036 /// instance.
37 LFS_Shared,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010038 /// An error occurred while trying to create or find the lock
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010039 /// file.
40 LFS_Error
41 };
42
Andrew Scullcdfcccc2018-10-05 20:58:37 +010043 /// Describes the result of waiting for the owner to release the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010044 enum WaitForUnlockResult {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010045 /// The lock was released successfully.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046 Res_Success,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010047 /// Owner died while holding the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010048 Res_OwnerDied,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010049 /// Reached timeout while waiting for the owner to release the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010050 Res_Timeout
51 };
52
53private:
54 SmallString<128> FileName;
55 SmallString<128> LockFileName;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010056 SmallString<128> UniqueLockFileName;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010057
58 Optional<std::pair<std::string, int> > Owner;
59 std::error_code ErrorCode;
60 std::string ErrorDiagMsg;
61
62 LockFileManager(const LockFileManager &) = delete;
63 LockFileManager &operator=(const LockFileManager &) = delete;
64
65 static Optional<std::pair<std::string, int> >
66 readLockFile(StringRef LockFileName);
67
68 static bool processStillExecuting(StringRef Hostname, int PID);
69
70public:
71
72 LockFileManager(StringRef FileName);
73 ~LockFileManager();
74
Andrew Scullcdfcccc2018-10-05 20:58:37 +010075 /// Determine the state of the lock file.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010076 LockFileState getState() const;
77
78 operator LockFileState() const { return getState(); }
79
Andrew Scullcdfcccc2018-10-05 20:58:37 +010080 /// For a shared lock, wait until the owner releases the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010081 WaitForUnlockResult waitForUnlock();
82
Andrew Scullcdfcccc2018-10-05 20:58:37 +010083 /// Remove the lock file. This may delete a different lock file than
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010084 /// the one previously read if there is a race.
85 std::error_code unsafeRemoveLockFile();
86
Andrew Scullcdfcccc2018-10-05 20:58:37 +010087 /// Get error message, or "" if there is no error.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010088 std::string getErrorMessage() const;
89
Andrew Scullcdfcccc2018-10-05 20:58:37 +010090 /// Set error and error message
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010091 void setError(const std::error_code &EC, StringRef ErrorMsg = "") {
92 ErrorCode = EC;
93 ErrorDiagMsg = ErrorMsg.str();
94 }
95};
96
97} // end namespace llvm
98
99#endif // LLVM_SUPPORT_LOCKFILEMANAGER_H