LibrePCB Developers Documentation
|
This class can be used to implement file-based directory locks. More...
#include <directorylock.h>
Public Types | |
enum class | LockStatus |
The return type of getStatus() More... | |
typedef std::function< bool(const FilePath &dir, LockStatus status, const QString &user)> | LockHandlerCallback |
Callback type used to determine whether a lock should be overridden or not. | |
Public Member Functions | |
DirectoryLock () noexcept | |
The default constructor. | |
DirectoryLock (const DirectoryLock &other)=delete | |
Copy constructor. | |
DirectoryLock (const FilePath &dir) noexcept | |
A constructor which will call setDirToLock() | |
~DirectoryLock () noexcept | |
The destructor (this may also unlock the locked file) | |
void | setDirToLock (const FilePath &dir) noexcept |
Specify the directory for which you need the lock. | |
const FilePath & | getDirToLock () const noexcept |
Get the filepath of the directory to lock (passed by setDirToLock()) | |
const FilePath & | getLockFilepath () const noexcept |
Get the filepath of the lock file (NOT the directory to lock!) | |
LockStatus | getStatus (QString *lockedByUser=nullptr) const |
Get the lock status of the specified directory. | |
void | tryLock (LockHandlerCallback lockHandler=nullptr) |
Lock the specified directory if not already locked. | |
bool | unlockIfLocked () |
Unlock the specified directory if it was locked by this object. | |
void | lock () |
Lock the specified directory (create/update the lock file) | |
void | unlock () |
Unlock the specified directory (remove the lock file) | |
DirectoryLock & | operator= (const DirectoryLock &rhs)=delete |
Static Private Member Functions | |
static QSet< FilePath > & | dirsLockedByThisAppInstance () noexcept |
Get the global set of filepaths locked by this application instance. | |
Private Attributes | |
FilePath | mDirToLock |
The filepath to the directory to lock (passed by setDirToLock()) | |
FilePath | mLockFilePath |
The filepath to the lock file. | |
bool | mLockedByThisObject |
This attribute defines if the lock is active by this object. | |
This class can be used to implement file-based directory locks.
Many classes of this project open some directories (workspaces, projects, library elements, ...). But it's very dangerous if a directory is opened multiple times simultaneously (by the same or another instance of the application, maybe even on different computers if the directories are located on a network drive). To avoid such problems, this class provides a mechanism to create directory locks.
How such a directory lock works:
Let's say that you want to open the directory "/foo/bar/". Then a lock file with the filepath "/foo/bar/.lock" will be created. After closing the directory, the lock file will be removed. So, while the directory (e.g. a project) is open, there will be a lock file in the same directory. If the same or another instance of the application now wants to open the same directory at the same time, the lock file is detected and opening the directory will be denied.
The lock file is a simple UTF-8 encoded text file with 5 lines with following values:
Example:
The lock file (and especially its content) is also used to detect application crashes. If the application crashes while a directory was locked, the lock file will still exist after the application crashed. Now, if the user tries to open the locked directory again, the content of the lock file will be parsed. If the username and the hostname in the lock file is equal to the current user which tries to get the lock, it's clear that the lock file does NOT exist because the locked directory is already open, but that the application crashed while the directory was locked. If there exists a backup of the locked directory (e.g. project auto-save), this allows to ask the user whether the backup should be restored or not.
How to use this class:
First, you need to create an instance of this class for the directory you want to protect with a lock. There are two different constructors for this purpose. If you use the default constructor, you need to call setDirToLock() afterwards. Now you can read the lock status of the specified directory with getStatus(). With lock() you can create the lock file, and with unlock() you can remove the lock file. There are also the two convenience methods tryLock() and unlockIfLocked(), just read their documentation for more information.
Code Example:
typedef std::function<bool(const FilePath& dir, LockStatus status, const QString& user)> LockHandlerCallback |
Callback type used to determine whether a lock should be overridden or not.
dir | The directory to be locked. |
status | The current status of the lock (see getStatus()). |
user | Name of the user which currently holds the lock. |
true | Override lock. |
false | Do not override lock. |
librepcb::UserCanceled | to abort locking the directory. |
|
strong |
The return type of getStatus()
|
noexcept |
The default constructor.
|
delete |
Copy constructor.
other | The object to copy |
|
explicitnoexcept |
A constructor which will call setDirToLock()
dir | See setDirToLock() |
|
noexcept |
The destructor (this may also unlock the locked file)
|
noexcept |
Specify the directory for which you need the lock.
dir | The filepath to the directory to lock |
|
inlinenoexcept |
Get the filepath of the directory to lock (passed by setDirToLock())
|
inlinenoexcept |
Get the filepath of the lock file (NOT the directory to lock!)
DirectoryLock::LockStatus getStatus | ( | QString * | lockedByUser = nullptr | ) | const |
Get the lock status of the specified directory.
lockedByUser | If not nullptr and the directory is locked, the username of the current lock is written into this string. |
Exception | on error (e.g. invalid filepath, no access rights, ...) |
void tryLock | ( | LockHandlerCallback | lockHandler = nullptr | ) |
Lock the specified directory if not already locked.
This is a save method to get a lock without the need for first reading the lock status with getStatus(). Depending on the lock status, this method does following:
lockHandler | If supplied and the directory is already locked, this callback gets called to determine whether the lock should be overridden or not. If not supplied and the directory is locked, an exception will be thrown. |
Exception | on error (e.g. already locked, no access rights, ...) |
bool unlockIfLocked | ( | ) |
Unlock the specified directory if it was locked by this object.
If the specified directory is locked by this object, this method calls unlock(). Otherwise this method does nothing.
Exception | on error (e.g. invalid filepath, no access rights, ...) |
void lock | ( | ) |
Lock the specified directory (create/update the lock file)
Exception | on error (e.g. invalid filepath, no access rights, ...) |
void unlock | ( | ) |
Unlock the specified directory (remove the lock file)
Exception | on error (e.g. invalid filepath, no access rights, ...) |
|
delete |
|
staticprivatenoexcept |
Get the global set of filepaths locked by this application instance.
|
private |
The filepath to the directory to lock (passed by setDirToLock())
|
private |
The filepath to the lock file.
Example: If the filepath "/foo/bar" was passed to setDirToLock(), this attribute will have the value "/foo/bar/.lock".
|
private |
This attribute defines if the lock is active by this object.
If lock() was called successfully, mLockedByThisObject is set to true. If unlock() was called successfully, mLockedByThisObject is set to false.
In other words: This attribute is true while this object has the ownership over the lock file (between calling lock() and unlock()).
The only goal of this attribute is to decide whether the destructor should remove the lock or not. If the destructor is called while this attribute is true, the destructor will call unlock() to remove the file lock.