354 lines
11 KiB
C++
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
|