// Copyright (c) 2013-2015 IONU Security, Inc. All rights reserved. // Copyright (c) 2016 Sequence Logic, Inc. All rights reserved. // // File locking functions and classes #ifndef eyelock_h #define eyelock_h #include #include #include #include "eyejson.h" #ifdef WIN32 #include "Windows.h" # ifdef DLLEXPORT # define LIBEYE_DLL __declspec(dllexport) # else # define LIBEYE_DLL __declspec(dllimport) # endif #else #define LIBEYE_DLL #endif namespace sequencelogic { enum IONU_FILE_LOCK_STATUS { IONU_FILE_LOCK_OK = 0, IONU_FILE_LOCK_ERROR = 1, IONU_FILE_LOCK_TIMEOUT = 2 }; enum IONU_FILE_LOCK_TYPE { IONU_FILE_LOCK_READ, // Read lock IONU_FILE_LOCK_WRITE, // Write lock IONU_FILE_LOCK_CLEAR, // Clear our lock IONU_FILE_LOCK_REMOVE // Remove all locks (used in sequencelogic::RemoveFile, sequencelogic::RenameFile) }; // Define the lock strategy to use #ifdef WIN32 #define LOCK_STRATEGY_MASTER #elif !defined (LOCK_STRATEGY_MEMORY) #define LOCK_STRATEGY_DOTLK #endif // Get informational message about failure to acquire a lock LIBEYE_DLL const std::string GetLastEyeLockMessage(); // Release a lock without respect to existing owners, called after shred and delete of .ionu void ReleaseEyeLock (const std::string filename); // Internal lock utility functions, not exported for client use #ifdef WIN32 bool ReadLockFile (HANDLE fd, const char* buf, size_t bytes); #else bool ReadLockFile (int fd, const char* buf, size_t bytes); #endif #ifdef WIN32 bool WriteLockFile (HANDLE fd, const char* buf, size_t bytes); #else bool WriteLockFile (int fd, const char* buf, size_t bytes); #endif #ifdef WIN32 IONU_FILE_LOCK_STATUS CreateLockFile (HANDLE fd, const std::string& lockfile, const std::string& strpid, const std::string& id, const std::string& rwlock, const std::string& time); #else IONU_FILE_LOCK_STATUS CreateLockFile (int fd, const std::string& lockfile, const std::string& strpid, const std::string& id, const std::string& rwlock, const std::string& time); #endif #ifdef WIN32 IONU_FILE_LOCK_STATUS UpdateLockFile (HANDLE fd, std::string& lockfile, EyeJSONObject* locks); #else IONU_FILE_LOCK_STATUS UpdateLockFile (int fd, std::string& lockfile, EyeJSONObject* locks); #endif bool CheckActiveProcess (const std::string pid); void CleanLocks (EyeJSONObject* locks, const std::string& strpid, const std::string& id, IONU_FILE_LOCK_TYPE ltype); #ifdef LOCK_STRATEGY_DOTLK class EyeFileLock { public: /** * RAII - file locking class, that uses individual .lk files * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileLock(IONU_FILE_LOCK_TYPE ltype, const char* filename, const char* id = nullptr); LIBEYE_DLL virtual ~EyeFileLock(); /** * Convert a read lock to a write lock * @return bool - true if lock was acquired in write state, false on failure */ LIBEYE_DLL bool convertToWrite(); /** * Convert a write lock to a read lock * @return bool - true if lock was acquired in read state, false on failure */ LIBEYE_DLL bool convertToRead(); /** * Attempt to acquire the specified lock type * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR * @return bool - true if lock was acquired in specified state, false on failure */ LIBEYE_DLL bool acquire (IONU_FILE_LOCK_TYPE ltype); /** * Release the current lock * @return bool - true if lock was released, false on failure */ LIBEYE_DLL bool release (); bool acquired() { return _status == IONU_FILE_LOCK_OK; } IONU_FILE_LOCK_TYPE getType() { return _ltype; } IONU_FILE_LOCK_STATUS getStatus() { return _status; } protected: std::string _id; std::string _filename; IONU_FILE_LOCK_TYPE _ltype; IONU_FILE_LOCK_STATUS _status; }; class EyeFileReadLock : public EyeFileLock { public: /** * RAII - Attempt to acquire read lock * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileReadLock(const char* filename, const char* id = nullptr); }; class EyeFileWriteLock : public EyeFileLock { public: /** * RAII - Attempt to acquire write lock * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileWriteLock(const char* filename, const char* id = nullptr); }; /** * Function interface to scheme that uses individual .lk files * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR */ LIBEYE_DLL IONU_FILE_LOCK_STATUS LockFile (const std::string& filename, const std::string& id, IONU_FILE_LOCK_TYPE rwlock); #endif #ifdef LOCK_STRATEGY_MEMORY class EyeFileLock { public: /** * RAII - in memory file locking class, thread safe (not process safe) * @constructor * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileLock(IONU_FILE_LOCK_TYPE ltype, const std::string& filename, const std::string& id = ""); LIBEYE_DLL virtual ~EyeFileLock(); /** * Convert a read lock to a write lock * @return bool - true if lock was acquired in write state, false on failure */ LIBEYE_DLL bool convertToWrite(); /** * Convert a write lock to a read lock * @return bool - true if lock was acquired in read state, false on failure */ LIBEYE_DLL bool convertToRead(); /** * Attempt to acquire the specified lock type * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR * @return bool - true if lock was acquired in specified state, false on failure */ LIBEYE_DLL bool acquire (IONU_FILE_LOCK_TYPE ltype); /** * Release the current lock * @return bool - true if lock was released, false on failure */ LIBEYE_DLL bool release (); bool acquired() { return _status == IONU_FILE_LOCK_OK; } IONU_FILE_LOCK_TYPE getType() { return _ltype; } IONU_FILE_LOCK_STATUS getStatus() { return _status; } protected: std::string _id; std::string _filename; IONU_FILE_LOCK_TYPE _ltype; IONU_FILE_LOCK_STATUS _status; }; class EyeFileReadLock : public EyeFileLock { public: /** * RAII - Attempt to acquire thread safe read file lock (not process safe) * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileReadLock(const std::string& filename, const std::string& id = ""); }; class EyeFileWriteLock : public EyeFileLock { public: /** * RAII - Attempt to acquire thread safe write file lock (not process safe) * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileWriteLock(const std::string& filename, const std::string& id = ""); }; class EyeFileLocker { public: LIBEYE_DLL static EyeFileLocker* GetInstance (); LIBEYE_DLL IONU_FILE_LOCK_STATUS LockFile (IONU_FILE_LOCK_TYPE ltype, const std::string&filename, const std::string& id = ""); size_t GetNumLocks() { return _lockmap.size(); } protected: EyeFileLocker (); ~EyeFileLocker(); private: static EyeFileLocker* _instance; // Singleton static std::mutex _threadLocker; // Mutex to protect access to locked file map std::map _lockmap; // Map of file locks IONU_FILE_LOCK_STATUS LockFileAttempt (const std::string&filename, const std::string& id, IONU_FILE_LOCK_TYPE ltype); }; /** * Function interface to scheme that uses in-memory map to manage multiple file locks * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR */ LIBEYE_DLL IONU_FILE_LOCK_STATUS LockFile (const std::string& filename, const std::string& id, IONU_FILE_LOCK_TYPE rwlock); #endif #ifdef LOCK_STRATEGY_MASTER class EyeFileLock { public: /** * RAII - File locking class, uses a single .lk file in temp directory to manage multiple file locks * @constructor * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileLock(IONU_FILE_LOCK_TYPE ltype, const std::string& filename, const std::string& id = ""); LIBEYE_DLL virtual ~EyeFileLock(); /** * Convert a read lock to a write lock * @return bool - true if lock was acquired in write state, false on failure */ LIBEYE_DLL bool convertToWrite(); /** * Convert a write lock to a read lock * @return bool - true if lock was acquired in read state, false on failure */ LIBEYE_DLL bool convertToRead(); /** * Attempt to acquire the specified lock type * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR * @return bool - true if lock was acquired in specified state, false on failure */ LIBEYE_DLL bool acquire (IONU_FILE_LOCK_TYPE ltype); /** * Release the current lock * @return bool - true if lock was released, false on failure */ LIBEYE_DLL bool release (); bool acquired() { return _status == IONU_FILE_LOCK_OK; } IONU_FILE_LOCK_TYPE getType() { return _ltype; } IONU_FILE_LOCK_STATUS getStatus() { return _status; } protected: std::string _id; std::string _filename; IONU_FILE_LOCK_TYPE _ltype; IONU_FILE_LOCK_STATUS _status; }; class EyeFileReadLock : public EyeFileLock { public: /** * RAII - Attempt to acquire read lock * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileReadLock(const std::string& filename, const std::string& id = ""); }; class EyeFileWriteLock : public EyeFileLock { public: /** * RAII - Attempt to acquire write lock * @constructor * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID */ LIBEYE_DLL EyeFileWriteLock(const std::string& filename, const std::string& id = ""); }; /** * Function interface to scheme that uses a single .lk file in temp directory to manage multiple file locks * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR */ LIBEYE_DLL IONU_FILE_LOCK_STATUS LockFile (const std::string& filename, const std::string& id, IONU_FILE_LOCK_TYPE ltype); /** * Internal function to do one attempt at getting the requested lock * @param filename - path of file to lock * @param id - owner ID for this lock, defaults to thread ID * @param locktype IONU_FILE_LOCK_READ, IONU_FILE_LOCK_WRITE, IONU_FILE_LOCK_CLEAR */ IONU_FILE_LOCK_STATUS LockFileAttempt(const std::string& filename, const std::string& id, IONU_FILE_LOCK_TYPE ltype); #endif } //namespace sequencelogic #endif