# Lock Folder
Obtain a lock by posting a bid into a lock folder, and checking for rivals.
#### Installation
```
pip install lockfolder
```
### How to Use It
```
import pathlib
from lockfolder import lockfolder
lockfolder.init()
p = pathlib.Path("path/to/lockfolder")
if lockfolder.lock(p):
print("aquired lock")
...
...
lockfolder.unlock(p)
else:
print("failed to aquire lock")
```
Adapt to context manager, throw-finally systems, decorator, what have
you, as you like.
### Lock Files
Lock files are JSON files that are logically equivalent to:
```
----------[ filename: <GUID>.json ]-----------------------------------
{
"PID": <integer PID>,
"CREATED": <integer timestamp>
}
----------------------------------------------------------------------
```
### Concept
This is a mutex system, that ensures that only one process has access to a resource.
It's defining features are:
* a filesystem folder is used to bid for a lock
* it is cross-platform to contemporary operating systems
* it's very simple
* it has only one external dependency: `psutil`
* it is robust to recycled PIDs
Some of the limitations of this system, are:
* live-locks are possible, which occurs when too many processes all try to get a lock at the same time
* all petitioners will fail to achieve a lock
* insistent petitioners should repeat efforts at connection with an exponential backoff
* security and file permissions are not taken account of
* it is possible for a malicious user or process to manually delete or create lock files
* there is an extremely unlikely possibility of a v4 GUID collision
* PID recycling fails if the same PID is recycled to a competitor within the second (highly unusual)
### Basic Strategy:
* each process self-assigns a GUID
* each process notes its PID
* each process notes its create-time
* a folder keeps the locks for the resource ("bids" and "locks" are the same thing in this system)
* the procedure is "check-bid-check", and if any check shows another bid/lock, the process deletes its own bid (if it got that far) and returns "fail"
* if the "check-bid-check" passes, then the bid is left until the process completes, at which point the bid is deleted
* bids contain the process PID and creation time of the process, and may be deleted by any process that wishes to challenge a prior bid, provided that it can determine that a process created at <create-time> with process ID <PID> is no longer running
* upon a fail, at the programmer's discretion, processes may delay and retry, with delays having a random component, and increasing duration between attempts
### Procedure:
Here is the basic procedure more specifically:
STEP 10. **CHECK** -- check the lock folder for the presence of any files; if there are files, END (error state: FAIL); if there are no files, proceed to step 20
STEP 20. **BID** -- write a file into the lock folder, containing the following, then proceed to step 30
* filename: `(self-selected-GUID-for-this-process).json`
* JSON file content:
* PID: `(process-id)`
* PROCESS-START-TIME: `(timestamp-for-this-process)`
STEP 30. **CHECK** -- check the lock folder for the presence of any files, other than my own: if there are other files, proceed to step 40, otherwise, proceed to step 50
STEP 40. **DELETE & FAIL** -- delete the bid file that was created in step 20, then END (error state: FAIL)
STEP 50. **OPERATE** -- the lock has been acquired (it's the same file as the bid created in step 20) -- do whatever you please with it
STEP 60. **DELETE & END** -- delete the bid file that was created in step 20, then END (error state: SUCCESS)
### Additional Resources
* https://www.reddit.com/r/AskProgramming/comments/186ot93/is_this_checkbidcheck_mutex_strategy_okay/ -- a Reddit thread, in which I requested verification of correctness for this system.
written: 2023-11-29
Raw data
{
"_id": null,
"home_page": "https://github.com/LionKimbro/lockfolder",
"name": "lockfolder",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "mutex,lock,locking,guid",
"author": "Lion Kimbro",
"author_email": "Lion Kimbro <lionkimbro@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/f4/44/0295d7b85f25b59c2ecdd1740104dd40e997ebfe7481f2180e6f1dd0c1ca/lockfolder-1.0.2.tar.gz",
"platform": null,
"description": "# Lock Folder\r\n\r\nObtain a lock by posting a bid into a lock folder, and checking for rivals.\r\n\r\n#### Installation\r\n\r\n```\r\npip install lockfolder\r\n```\r\n\r\n### How to Use It\r\n\r\n\r\n```\r\nimport pathlib\r\nfrom lockfolder import lockfolder\r\n\r\nlockfolder.init()\r\n\r\np = pathlib.Path(\"path/to/lockfolder\")\r\n\r\nif lockfolder.lock(p):\r\n print(\"aquired lock\")\r\n ...\r\n ...\r\n lockfolder.unlock(p)\r\nelse:\r\n print(\"failed to aquire lock\")\r\n```\r\n\r\nAdapt to context manager, throw-finally systems, decorator, what have\r\nyou, as you like.\r\n\r\n\r\n### Lock Files\r\n\r\nLock files are JSON files that are logically equivalent to:\r\n\r\n```\r\n----------[ filename: <GUID>.json ]-----------------------------------\r\n {\r\n \"PID\": <integer PID>,\r\n \"CREATED\": <integer timestamp>\r\n }\r\n----------------------------------------------------------------------\r\n```\r\n\r\n\r\n### Concept\r\n\r\nThis is a mutex system, that ensures that only one process has access to a resource.\r\n\r\nIt's defining features are:\r\n* a filesystem folder is used to bid for a lock\r\n* it is cross-platform to contemporary operating systems\r\n* it's very simple\r\n* it has only one external dependency: `psutil`\r\n* it is robust to recycled PIDs\r\n\r\nSome of the limitations of this system, are:\r\n* live-locks are possible, which occurs when too many processes all try to get a lock at the same time\r\n * all petitioners will fail to achieve a lock\r\n * insistent petitioners should repeat efforts at connection with an exponential backoff\r\n* security and file permissions are not taken account of\r\n * it is possible for a malicious user or process to manually delete or create lock files\r\n* there is an extremely unlikely possibility of a v4 GUID collision\r\n* PID recycling fails if the same PID is recycled to a competitor within the second (highly unusual) \r\n\r\n\r\n### Basic Strategy:\r\n\r\n* each process self-assigns a GUID\r\n* each process notes its PID\r\n* each process notes its create-time\r\n* a folder keeps the locks for the resource (\"bids\" and \"locks\" are the same thing in this system)\r\n* the procedure is \"check-bid-check\", and if any check shows another bid/lock, the process deletes its own bid (if it got that far) and returns \"fail\"\r\n* if the \"check-bid-check\" passes, then the bid is left until the process completes, at which point the bid is deleted\r\n* bids contain the process PID and creation time of the process, and may be deleted by any process that wishes to challenge a prior bid, provided that it can determine that a process created at <create-time> with process ID <PID> is no longer running\r\n* upon a fail, at the programmer's discretion, processes may delay and retry, with delays having a random component, and increasing duration between attempts\r\n\r\n\r\n### Procedure:\r\n\r\nHere is the basic procedure more specifically:\r\n\r\nSTEP 10. **CHECK** -- check the lock folder for the presence of any files; if there are files, END (error state: FAIL); if there are no files, proceed to step 20\r\n\r\nSTEP 20. **BID** -- write a file into the lock folder, containing the following, then proceed to step 30\r\n\r\n* filename: `(self-selected-GUID-for-this-process).json`\r\n* JSON file content:\r\n * PID: `(process-id)`\r\n * PROCESS-START-TIME: `(timestamp-for-this-process)`\r\n\r\nSTEP 30. **CHECK** -- check the lock folder for the presence of any files, other than my own: if there are other files, proceed to step 40, otherwise, proceed to step 50\r\n\r\nSTEP 40. **DELETE & FAIL** -- delete the bid file that was created in step 20, then END (error state: FAIL)\r\n\r\nSTEP 50. **OPERATE** -- the lock has been acquired (it's the same file as the bid created in step 20) -- do whatever you please with it\r\n\r\nSTEP 60. **DELETE & END** -- delete the bid file that was created in step 20, then END (error state: SUCCESS)\r\n\r\n\r\n### Additional Resources\r\n\r\n* https://www.reddit.com/r/AskProgramming/comments/186ot93/is_this_checkbidcheck_mutex_strategy_okay/ -- a Reddit thread, in which I requested verification of correctness for this system.\r\n\r\nwritten: 2023-11-29\r\n\r\n",
"bugtrack_url": null,
"license": "",
"summary": "check-bid-check into a lock folder, to obtain a lock",
"version": "1.0.2",
"project_urls": {
"Bug Tracker": "https://github.com/LionKimbro/lockfolder/issues",
"Homepage": "https://github.com/LionKimbro/lockfolder"
},
"split_keywords": [
"mutex",
"lock",
"locking",
"guid"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f4440295d7b85f25b59c2ecdd1740104dd40e997ebfe7481f2180e6f1dd0c1ca",
"md5": "df974de60df48faf653e562c41026181",
"sha256": "a0cc6fca633503cd265a1ce67f8c0fa229c54af620a972f0ea2ac107cafa62d2"
},
"downloads": -1,
"filename": "lockfolder-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "df974de60df48faf653e562c41026181",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 6522,
"upload_time": "2023-12-01T23:37:45",
"upload_time_iso_8601": "2023-12-01T23:37:45.009759Z",
"url": "https://files.pythonhosted.org/packages/f4/44/0295d7b85f25b59c2ecdd1740104dd40e997ebfe7481f2180e6f1dd0c1ca/lockfolder-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-01 23:37:45",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "LionKimbro",
"github_project": "lockfolder",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "lockfolder"
}