From e0b41fab2cb01f688d823719ce177a012cee6b00 Mon Sep 17 00:00:00 2001 From: happyZYM Date: Wed, 19 Jun 2024 14:05:07 +0000 Subject: [PATCH] ready to write UI --- .gitignore | 9 +++++- UI/gunicorn.conf.py | 66 +++++++++++++++++++++++++++++++++++++++++ UI/main.py | 63 +++++++++++++++++++++++++++++++++++++++ UI/templates/about.html | 8 +++++ UI/templates/base.html | 27 +++++++++++++++++ UI/templates/index.html | 8 +++++ src/main.cpp | 61 ++++++++++++++++++++++++++++++++++++- 7 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 UI/gunicorn.conf.py create mode 100644 UI/templates/about.html create mode 100644 UI/templates/base.html create mode 100644 UI/templates/index.html diff --git a/.gitignore b/.gitignore index 6db5ace..bb3642f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,11 @@ /build /mbuild /.clang-format -/test/data \ No newline at end of file +/test/data + +# Ignore all .env files +**/.env +**/.env.* + +# Ignore all __pycache__ directories +**/__pycache__/ \ No newline at end of file diff --git a/UI/gunicorn.conf.py b/UI/gunicorn.conf.py new file mode 100644 index 0000000..0081e45 --- /dev/null +++ b/UI/gunicorn.conf.py @@ -0,0 +1,66 @@ +import os +import subprocess +import signal +import atexit +from flask import Flask, render_template +from dotenv import load_dotenv +import socket + +# Load environment variables from .env file +load_dotenv() + +# Get configuration from environment variables +backend_ip = os.getenv('BACKEND_IP') +backend_port = os.getenv('BACKEND_PORT') +backend_log_level = os.getenv('BACKEND_LOG_LEVEL') +backend_data_directory = os.getenv('BACKEND_DATA_DIRECTORY') +backend_log_file = os.getenv('BACKEND_LOG_FILE') +backend_path = os.getenv('BACKEND_PATH') + +# Command to start the backend process +backend_command = [ + backend_path, + "-d", backend_data_directory, + "-l", backend_log_file, + "--level", backend_log_level, + "server", + "--port", backend_port, + "--address", backend_ip +] + +backend_process = None + +def start_backend(): + global backend_process + # Try to acquire the lock without blocking, timeout if another process holds the lock + print("Starting backend process...") + backend_process = subprocess.Popen(backend_command, preexec_fn = os.setsid) + print(f"Backend process started with PID: {backend_process.pid}") +def on_starting(server): + # 这里放置启动后台进程的逻辑 + start_backend() + +def when_ready(server): + print("Server is ready. Spawning workers") +def send_exit_command(ip, port): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.connect((ip, int(port))) + sock.sendall(b'exit\n') + response = sock.recv(1024) # Optional: read response from server + print(f"Received response: {response.decode('utf-8')}") + except Exception as e: + print(f"Failed to send exit command: {e}") + +def stop_backend(): + global backend_process + if backend_process is not None: + print(f"Sending exit command to backend process at {backend_ip}:{backend_port}...") + send_exit_command(backend_ip, backend_port) + print(f"Waiting for backend process with PID: {backend_process.pid} to terminate...") + backend_process.wait() + print("Backend process stopped.") + backend_process = None + +def on_exit(server): + stop_backend() \ No newline at end of file diff --git a/UI/main.py b/UI/main.py index e69de29..5204e15 100644 --- a/UI/main.py +++ b/UI/main.py @@ -0,0 +1,63 @@ +import os +import subprocess +import signal +import atexit +from flask import Flask, render_template +from dotenv import load_dotenv +import time +import socket + +# Load environment variables from .env file +load_dotenv() + +app = Flask(__name__) + +# Get configuration from environment variables +backend_ip = os.getenv('BACKEND_IP') +backend_port = os.getenv('BACKEND_PORT') +backend_log_level = os.getenv('BACKEND_LOG_LEVEL') +backend_data_directory = os.getenv('BACKEND_DATA_DIRECTORY') +backend_log_file = os.getenv('BACKEND_LOG_FILE') +backend_path = os.getenv('BACKEND_PATH') + +# Command to start the backend process +backend_command = [ + backend_path, + "-d", backend_data_directory, + "-l", backend_log_file, + "--level", backend_log_level, + "server", + "--port", backend_port, + "--address", backend_ip +] + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect((backend_ip, int(backend_port))) +def ExecCommand(command): + command=command+'\n' + sock.sendall(command.encode('utf-8')) + response = sock.recv(1024*1024) + response= response.decode('utf-8') + _, _, response = response.partition(" ") + return response + +# Signal handler for graceful shutdown +def signal_handler(signum, frame): + # stop_backend() + time.sleep(10) + exit(0) + +# Register signal handlers +signal.signal(signal.SIGINT, signal_handler) +signal.signal(signal.SIGTERM, signal_handler) + +@app.route('/') +def home(): + return render_template('index.html') + +@app.route('/about') +def about(): + return render_template('about.html') + +if __name__ == '__main__': + app.run(debug=True) diff --git a/UI/templates/about.html b/UI/templates/about.html new file mode 100644 index 0000000..272b858 --- /dev/null +++ b/UI/templates/about.html @@ -0,0 +1,8 @@ +{% extends 'base.html' %} + +{% block title %}About Us - Train Ticket Booking{% endblock %} + +{% block content %} +

About Us

+

This is a demo site for booking train tickets.

+{% endblock %} diff --git a/UI/templates/base.html b/UI/templates/base.html new file mode 100644 index 0000000..b7b7b1e --- /dev/null +++ b/UI/templates/base.html @@ -0,0 +1,27 @@ + + + + + + {% block title %}Train Ticket Booking{% endblock %} + + + + +
+ {% block content %}{% endblock %} +
+ + diff --git a/UI/templates/index.html b/UI/templates/index.html new file mode 100644 index 0000000..162b225 --- /dev/null +++ b/UI/templates/index.html @@ -0,0 +1,8 @@ +{% extends 'base.html' %} + +{% block title %}Home - Train Ticket Booking{% endblock %} + +{% block content %} +

Welcome to the Train Ticket Booking System

+

Use this site to book your train tickets easily.

+{% endblock %} diff --git a/src/main.cpp b/src/main.cpp index 3669d50..3339d95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "basic_defs.h" #ifdef ENABLE_ADVANCED_FEATURE #include +#include #include "dataguard/dataguard.h" #endif #include "engine.h" @@ -20,6 +21,51 @@ const bool optimize_enabled = false; // #else // const bool global_log_enabled = true; // #endif + +#ifdef ENABLE_ADVANCED_FEATURE + +// 处理每个连接的函数 +void handle_client(sockpp::tcp_socket client, TicketSystemEngine &engine) { + try { + std::string line; + std::string buffer; + + // 读取客户端发送的数据 + while (true) { + char data[1024]; + ssize_t n = client.read(data, sizeof(data)); + if (n <= 0) { + break; // 连接关闭或出现错误 + } + buffer.append(data, n); + + // 检查是否收到完整的一行 + size_t pos; + while ((pos = buffer.find('\n')) != std::string::npos) { + line = buffer.substr(0, pos); + buffer.erase(0, pos + 1); + line = "[0] " + line; + + // 调用 TicketSystemEngine 的 Execute 方法处理命令 + std::string response = engine.Execute(line); + + // 发送响应给客户端 + client.write(response); + + // 检查是否需要退出 + if (*engine.its_time_to_exit_ptr) { + exit(0); + return; + } + } + } + } catch (const std::exception &e) { + LOG->error("Exception handling client: {}", e.what()); + } +} + +#endif // ENABLE_ADVANCED_FEATURE + int main(int argc, char *argv[]) { argparse::ArgumentParser program("zts-core", main_version + "-" + build_version); argparse::ArgumentParser fsck_command("fsck"); @@ -102,7 +148,20 @@ int main(int argc, char *argv[]) { return 1; } else LOG->info("successfully bind to address {} port {}", address, port); - throw std::runtime_error("Server mode not implemented"); + // throw std::runtime_error("Server mode not implemented"); + TicketSystemEngine engine(data_directory); + while (true) { + // 接受新的客户端连接 + sockpp::tcp_socket client = acceptor.accept(); + if (!client) { + LOG->error("Error accepting incoming connection: {}", acceptor.last_error_str()); + } else { + LOG->info("New client connected from {}", client.peer_address().to_string()); + + // 创建一个线程来处理客户端连接 + std::thread(handle_client, std::move(client), std::ref(engine)).detach(); + } + } } else { #endif std::ios::sync_with_stdio(false);