]> git.phdru.name Git - m_librarian.git/commitdiff
Feat(web): Do not allow to run two instances of `ml-web.py`
authorOleg Broytman <phd@phdru.name>
Sun, 8 Apr 2018 18:41:46 +0000 (21:41 +0300)
committerOleg Broytman <phd@phdru.name>
Sun, 8 Apr 2018 22:11:23 +0000 (01:11 +0300)
The second instance redirects browser to the first one and exits.

docs-ru/news.rst
docs/news.rst
m_librarian/web/utils.py
scripts/ml-web.py
tmp/.gitignore [new file with mode: 0644]

index 19b1ad401017798ca5cff635e8552c850c1498c6..3d0e16d1e055f3cd356d88573a953cedb651607e 100644 (file)
@@ -7,5 +7,9 @@ Version 0.1.0 (2018-04-08)
 * Web-интерфейс для поиска авторов, показа списка книг автора,
   загрузки одной книги.
 
+* Программа `ml-web.py` не позволяет запускать два экземпляра.
+  Второй экземпляр перенаправляет web-обозреватель на web-интерфейс
+  первого экземпляра и прекращает работу.
+
 * Опция `--download-to` в скрипте `ml-search.py` задаёт директорию
   для сохранения книг.
index 80498f1cda890ab293f0827b80bbe3130f31989c..6042e69c06879d07d8bfa800e1f2e8d98b5c6443 100644 (file)
@@ -7,6 +7,9 @@ Version 0.1.0 (2018-04-08)
 * Web-interface: Search for authors, list books by an author,
   download a book.
 
+* Do not allow to run two instances of `ml-web.py` web-interfaces.
+  The second instance redirects browser to the first one and exits.
+
 * Option `--download-to` provides the path to the download directory
   in script `ml-search.py`.
 
index 2efe724a6bdf8fcfb10a9e7e1c4ce9d0ca877de8..12be81f47dc572482043dc922c42fea9db637495 100644 (file)
@@ -1,7 +1,48 @@
+from fcntl import flock, LOCK_EX, LOCK_UN, LOCK_NB
+from os import path, remove
+import socket
+
+
+lock_fname = path.join(
+    path.dirname(path.dirname(path.dirname(__file__))),
+    'tmp', 'm_librarian.lock')
+
+
+def get_lock(port):
+    try:
+        lock_file = open(lock_fname, 'r')
+    except IOError:  # no lock file
+        pass
+    else:
+        try:
+            flock(lock_file, LOCK_EX | LOCK_NB)
+        except IOError:  # locked
+            port = int(lock_file.readline())
+            lock_file.close()
+            return None, port
+        else:
+            flock(lock_file, LOCK_UN)
+            lock_file.close()
+
+    lock_file = open(lock_fname, 'w')
+    lock_file.write(str(port))
+    lock_file.close()
+    lock_file = open(lock_fname, 'r')
+    flock(lock_file, LOCK_EX | LOCK_NB)
+    return lock_file, None
+
+
+def close_lock(lock_file):
+    flock(lock_file, LOCK_UN)
+    lock_file.close()
+    lock_file = open(lock_fname, 'w')
+    lock_file.write('')
+    lock_file.close()
+    remove(lock_fname)
+
 
 def get_open_port():
     # https://stackoverflow.com/a/2838309/7976758
-    import socket
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     s.bind(("", 0))
     # s.listen(1)
index bccac810821833844272fd2bf90eae29afbc73ee..0387bc67088abab00d464681cae3f5afd70e6968 100755 (executable)
@@ -9,7 +9,7 @@ from bottle import thread  # portable import
 from m_librarian.db import open_db
 import m_librarian.web.app  # noqa: F401 imported but unused
 from m_librarian.web.server import run_server
-from m_librarian.web.utils import get_open_port
+from m_librarian.web.utils import get_lock, close_lock, get_open_port
 
 
 def start_browser(port):
@@ -27,6 +27,11 @@ if __name__ == '__main__':
     else:
         port = get_open_port()
 
-    open_db()
-    thread.start_new_thread(start_browser, (port,))
-    run_server(port=port)
+    lock_file, old_port = get_lock(port)
+    if lock_file:
+        open_db()
+        thread.start_new_thread(start_browser, (port,))
+        run_server(port=port)
+        close_lock(lock_file)
+    else:  # Another instance of the program is being run at a different port
+        start_browser(old_port)
diff --git a/tmp/.gitignore b/tmp/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore