Sleds/libeye/eyelock.h

354 lines
11 KiB
C++

// 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 <string>
#include <map>
#include <mutex>
#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<std::string, std::string> _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