* Web-интерфейс для поиска авторов, показа списка книг автора,
загрузки одной книги.
+* Программа `ml-web.py` не позволяет запускать два экземпляра.
+ Второй экземпляр перенаправляет web-обозреватель на web-интерфейс
+ первого экземпляра и прекращает работу.
+
* Опция `--download-to` в скрипте `ml-search.py` задаёт директорию
для сохранения книг.
* 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`.
+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)
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):
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)