1 //===--- 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" 14 #include <system_error> 15 #include <utility> // for std::pair 16 17 namespace llvm { 18 class StringRef; 19 20 /// \brief Class that manages the creation of a lock file to aid 21 /// 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. 28 class LockFileManager { 29 public: 30 /// \brief Describes the state of a lock file. 31 enum LockFileState { 32 /// \brief The lock file has been created and is owned by this instance 33 /// of the object. 34 LFS_Owned, 35 /// \brief The lock file already exists and is owned by some other 36 /// instance. 37 LFS_Shared, 38 /// \brief An error occurred while trying to create or find the lock 39 /// file. 40 LFS_Error 41 }; 42 43 /// \brief Describes the result of waiting for the owner to release the lock. 44 enum WaitForUnlockResult { 45 /// \brief The lock was released successfully. 46 Res_Success, 47 /// \brief Owner died while holding the lock. 48 Res_OwnerDied, 49 /// \brief Reached timeout while waiting for the owner to release the lock. 50 Res_Timeout 51 }; 52 53 private: 54 SmallString<128> FileName; 55 SmallString<128> LockFileName; 56 SmallString<128> UniqueLockFileName; 57 58 Optional<std::pair<std::string, int> > Owner; 59 Optional<std::error_code> Error; 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 70 public: 71 72 LockFileManager(StringRef FileName); 73 ~LockFileManager(); 74 75 /// \brief Determine the state of the lock file. 76 LockFileState getState() const; 77 LockFileState()78 operator LockFileState() const { return getState(); } 79 80 /// \brief For a shared lock, wait until the owner releases the lock. 81 WaitForUnlockResult waitForUnlock(); 82 83 /// \brief Remove the lock file. This may delete a different lock file than 84 /// the one previously read if there is a race. 85 std::error_code unsafeRemoveLockFile(); 86 87 /// \brief Get error message, or "" if there is no error. 88 std::string getErrorMessage() const; 89 90 /// \brief Set error and error message 91 void setError(std::error_code &EC, StringRef ErrorMsg = "") { 92 Error = EC; 93 ErrorDiagMsg = ErrorMsg.str(); 94 } 95 }; 96 97 } // end namespace llvm 98 99 #endif // LLVM_SUPPORT_LOCKFILEMANAGER_H 100