195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//===--- LockFileManager.h - File-level locking utility ---------*- C++ -*-===//
295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//                     The LLVM Compiler Infrastructure
495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor// This file is distributed under the University of Illinois Open Source
695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor// License. See LICENSE.TXT for details.
795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//===----------------------------------------------------------------------===//
995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#ifndef LLVM_SUPPORT_LOCKFILEMANAGER_H
1095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#define LLVM_SUPPORT_LOCKFILEMANAGER_H
1195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
1295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/ADT/Optional.h"
1395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/ADT/SmallString.h"
1495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/ADT/StringRef.h"
1595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/Support/system_error.h"
1695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <utility> // for std::pair
1795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
1895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregornamespace llvm {
1995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
2095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// \brief Class that manages the creation of a lock file to aid
2195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// implicit coordination between different processes.
2295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor///
2395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// The implicit coordination works by creating a ".lock" file alongside
2495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// the file that we're coordinating for, using the atomicity of the file
2595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// system to ensure that only a single process can create that ".lock" file.
2695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// When the lock file is removed, the owning process has finished the
2795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// operation.
2895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorclass LockFileManager {
2995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorpublic:
3095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  /// \brief Describes the state of a lock file.
3195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  enum LockFileState {
3295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// \brief The lock file has been created and is owned by this instance
3395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// of the object.
3495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    LFS_Owned,
3595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// \brief The lock file already exists and is owned by some other
3695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// instance.
3795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    LFS_Shared,
3895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// \brief An error occurred while trying to create or find the lock
3995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    /// file.
4095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    LFS_Error
4195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  };
4295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
4395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorprivate:
4495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  SmallString<128> LockFileName;
4595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  SmallString<128> UniqueLockFileName;
4695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
4795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  Optional<std::pair<std::string, int> > Owner;
4895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  Optional<error_code> Error;
4995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
5095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileManager(const LockFileManager &);
5195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileManager &operator=(const LockFileManager &);
5295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
5395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  static Optional<std::pair<std::string, int> >
5495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  readLockFile(StringRef LockFileName);
5595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
5695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  static bool processStillExecuting(StringRef Hostname, int PID);
5795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
5895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorpublic:
5995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileManager(StringRef FileName);
6195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  ~LockFileManager();
6295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  /// \brief Determine the state of the lock file.
6495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileState getState() const;
6595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  operator LockFileState() const { return getState(); }
6795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  /// \brief For a shared lock, wait until the owner releases the lock.
6995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  void waitForUnlock();
7095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor};
7195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
7295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor} // end namespace llvm
7395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
7495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif // LLVM_SUPPORT_LOCKFILEMANAGER_H
75