blob: 57e4fbd84cd954630b846d4424a0e91813341119 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===--- LockFileManager.h - File-level locking utility ---------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8#ifndef LLVM_SUPPORT_LOCKFILEMANAGER_H
9#define LLVM_SUPPORT_LOCKFILEMANAGER_H
10
11#include "llvm/ADT/Optional.h"
12#include "llvm/ADT/SmallString.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010013#include <system_error>
14#include <utility> // for std::pair
15
16namespace llvm {
17class StringRef;
18
Andrew Scullcdfcccc2018-10-05 20:58:37 +010019/// Class that manages the creation of a lock file to aid
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010020/// implicit coordination between different processes.
21///
22/// The implicit coordination works by creating a ".lock" file alongside
23/// the file that we're coordinating for, using the atomicity of the file
24/// system to ensure that only a single process can create that ".lock" file.
25/// When the lock file is removed, the owning process has finished the
26/// operation.
27class LockFileManager {
28public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010029 /// Describes the state of a lock file.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010030 enum LockFileState {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010031 /// The lock file has been created and is owned by this instance
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010032 /// of the object.
33 LFS_Owned,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010034 /// The lock file already exists and is owned by some other
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035 /// instance.
36 LFS_Shared,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010037 /// An error occurred while trying to create or find the lock
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010038 /// file.
39 LFS_Error
40 };
41
Andrew Scullcdfcccc2018-10-05 20:58:37 +010042 /// Describes the result of waiting for the owner to release the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010043 enum WaitForUnlockResult {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010044 /// The lock was released successfully.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010045 Res_Success,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010046 /// Owner died while holding the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010047 Res_OwnerDied,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010048 /// Reached timeout while waiting for the owner to release the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010049 Res_Timeout
50 };
51
52private:
53 SmallString<128> FileName;
54 SmallString<128> LockFileName;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010055 SmallString<128> UniqueLockFileName;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010056
57 Optional<std::pair<std::string, int> > Owner;
58 std::error_code ErrorCode;
59 std::string ErrorDiagMsg;
60
61 LockFileManager(const LockFileManager &) = delete;
62 LockFileManager &operator=(const LockFileManager &) = delete;
63
64 static Optional<std::pair<std::string, int> >
65 readLockFile(StringRef LockFileName);
66
67 static bool processStillExecuting(StringRef Hostname, int PID);
68
69public:
70
71 LockFileManager(StringRef FileName);
72 ~LockFileManager();
73
Andrew Scullcdfcccc2018-10-05 20:58:37 +010074 /// Determine the state of the lock file.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010075 LockFileState getState() const;
76
77 operator LockFileState() const { return getState(); }
78
Andrew Scullcdfcccc2018-10-05 20:58:37 +010079 /// For a shared lock, wait until the owner releases the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010080 WaitForUnlockResult waitForUnlock();
81
Andrew Scullcdfcccc2018-10-05 20:58:37 +010082 /// Remove the lock file. This may delete a different lock file than
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010083 /// the one previously read if there is a race.
84 std::error_code unsafeRemoveLockFile();
85
Andrew Scullcdfcccc2018-10-05 20:58:37 +010086 /// Get error message, or "" if there is no error.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010087 std::string getErrorMessage() const;
88
Andrew Scullcdfcccc2018-10-05 20:58:37 +010089 /// Set error and error message
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010090 void setError(const std::error_code &EC, StringRef ErrorMsg = "") {
91 ErrorCode = EC;
92 ErrorDiagMsg = ErrorMsg.str();
93 }
94};
95
96} // end namespace llvm
97
98#endif // LLVM_SUPPORT_LOCKFILEMANAGER_H