diff --git a/backend/src/builtin-cli.cpp b/backend/src/builtin-cli.cpp index 6446dc4..a6d06ae 100644 --- a/backend/src/builtin-cli.cpp +++ b/backend/src/builtin-cli.cpp @@ -29,7 +29,10 @@ void BookStoreMain(bool is_server, std::string config_dir) { // throw FatalError("Server mode has not been implemented yet", 1); std::unordered_map session_map; std::string cmd; + std::ofstream fout("/tmp/log.txt"); while (std::getline(std::cin, cmd)) { + fout << cmd << std::endl; + fout.flush(); if (cmd[1] == 'O') //`#OpenSession [TempChannelID]` { std::string new_session_token = GenerateRandomString(10); @@ -42,6 +45,7 @@ void BookStoreMain(bool is_server, std::string config_dir) { ss >> temp_channel_id; std::cout << temp_channel_id << " Init 1\n" << new_session_token << ' ' << new_outh_token << std::endl; + std::cout.flush(); } else if (cmd[1] == 'S') return; else if (cmd[1] == 'C') { @@ -52,16 +56,19 @@ void BookStoreMain(bool is_server, std::string config_dir) { if (session_map.find(session_token) == session_map.end()) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } if (session_map[session_token].OuthorizationKey != authentic_key) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } session_map.erase(session_token); std::cout << session_token << ' ' << operation_token << " 0" << std::endl; + std::cout.flush(); } else if (cmd[1] == 'W') { std::stringstream ss(cmd); std::string session_token, operation_token, authentic_key; @@ -70,21 +77,25 @@ void BookStoreMain(bool is_server, std::string config_dir) { if (session_map.find(session_token) == session_map.end()) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } if (session_map[session_token].OuthorizationKey != authentic_key) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } - if (session_map[session_token].login_stack.size()) + if (session_map[session_token].login_stack.size()) { std::cout << session_token << ' ' << operation_token << " 1\n" << engine.QueryUserInfo( session_map[session_token].login_stack.top().first) << std::endl; - else { + std::cout.flush(); + } else { std::cout << session_token << ' ' << operation_token << " 1\n[nobody] -1" << std::endl; + std::cout.flush(); } } else if (cmd[1] == 'R') { std::stringstream ss(cmd); @@ -94,11 +105,13 @@ void BookStoreMain(bool is_server, std::string config_dir) { if (session_map.find(session_token) == session_map.end()) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } if (session_map[session_token].OuthorizationKey != authentic_key) { std::cout << session_token << ' ' << operation_token << " -1" << std::endl; + std::cout.flush(); continue; } std::getline(std::cin, cmd); @@ -107,6 +120,7 @@ void BookStoreMain(bool is_server, std::string config_dir) { std::cout << session_token << ' ' << operation_token << " " << ret.size() << std::endl; for (auto &line : ret) std::cout << line << std::endl; + std::cout.flush(); } } } diff --git a/frontend/Web/index.html b/frontend/Web/index.html index f596e08..a1fca12 100644 --- a/frontend/Web/index.html +++ b/frontend/Web/index.html @@ -4,50 +4,56 @@ Socket.IO chat - + diff --git a/frontend/Web/index.js b/frontend/Web/index.js index 355db04..acd68bd 100644 --- a/frontend/Web/index.js +++ b/frontend/Web/index.js @@ -6,20 +6,150 @@ const { Server } = require('socket.io'); const app = express(); const server = createServer(app); const io = new Server(server); +class Queue { + constructor() { + this.items = []; + } + // 添加元素到队列的尾部 + enqueue(element) { + this.items.push(element); + } + + // 从队列的头部移除元素并返回移除的元素 + dequeue() { + if (this.isEmpty()) { + return null; + } + return this.items.shift(); + } + + // 返回队列的头部元素 + front() { + if (this.isEmpty()) { + return null; + } + return this.items[0]; + } + + // 检查队列是否为空 + isEmpty() { + return this.items.length === 0; + } + + // 返回队列的大小 + size() { + return this.items.length; + } + + // 清空队列 + clear() { + this.items = []; + } +} + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const message_map=new Map(); +const { spawn } = require('child_process'); +const backend=spawn('/workspaces/BH-Bookstore-2023/build/code',['-s','-c','/tmp/conf/']); + +const AsyncLock = require('async-lock'); +const lock = new AsyncLock(); + +function SendRequest(data) { + console.log("SendRequest called"); + return new Promise((resolve, reject) => { + lock.acquire('myLock', (done) => { + console.log("SendRequest acquired lock"); + console.log("sending data to backend: "+data) + backend.stdin.write(data+'\n', (error) => { + done(); + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + }); +} + +function GetResult(session_token,operation_token) { + console.log("GetResult called"); + while(true) + { + if(message_map.has(session_token)) + { + if(message_map.get(session_token).has(operation_token)) + { + const ret=message_map.get(session_token).get(operation_token); + message_map.get(session_token).delete(operation_token); + return ret; + } + } + sleep(100); + } +} +let buffer = ''; +const response_queue=new Queue(); +backend.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + buffer += data.toString(); + while (buffer.includes('\n')) { + const lineEnd = buffer.indexOf('\n'); + const line = buffer.slice(0, lineEnd); + buffer = buffer.slice(lineEnd + 1); + console.log(`C++ Program Output: ${line}`); + response_queue.enqueue(line); + } +}); +// SendRequest("#OpenSession InnerTest") app.get('/', (req, res) => { res.sendFile(join(__dirname, 'index.html')); }); -io.on('connection', (socket) => { +io.on('connection', async (socket) => { console.log('a user connected'); socket.on('disconnect', () => { console.log('user disconnected'); }); - socket.on('chat message', (msg) => { + socket.on('request', async (msg) => { console.log('message: ' + msg); - socket.emit('chat message', '[self]'+msg); - socket.broadcast.emit('chat message', '[other]'+msg); + const substrings = msg.trim().split('\n')[0].split(' '); + const head=substrings[0]; + if(head[1]=='S') + { + backend.stdin.write("#ShutDownSystem\n"); + sleep(1000); + process.exit(0); + } + const session_token=substrings[1]; + if(head[1]=='O') + { + SendRequest(msg); + ret=await GetResult(session_token,"Init"); + console.log("ret: "+ret); + socket.emit('response', ret); + } + else{ + const operation_token=substrings[2]; + const outhentication_key=substrings[3]; + const command=msg.trim().split('\n')[1]; + console.log('head: ' + head); + console.log('session_token: ' + session_token); + console.log('operation_token: ' + operation_token); + console.log('outhentication_key: ' + outhentication_key); + console.log('command: ' + command); + console.log("sending request to backend") + SendRequest(msg); + if(!message_map.has(session_token)) message_map.set(session_token, new Map()); + ret=await GetResult(session_token,operation_token); + console.log("ret: "+ret); + socket.emit('response', ret); + } }); }); diff --git a/frontend/Web/package-lock.json b/frontend/Web/package-lock.json index 485053f..272a80d 100644 --- a/frontend/Web/package-lock.json +++ b/frontend/Web/package-lock.json @@ -9,7 +9,10 @@ "version": "0.0.0.1", "license": "ISC", "dependencies": { + "async-lock": "^1.4.0", + "async-mutex": "^0.4.0", "express": "^4.18.2", + "mutex-js": "^1.1.5", "socket.io": "^4.7.2" } }, @@ -56,6 +59,19 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async-lock": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.0.tgz", + "integrity": "sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==" + }, + "node_modules/async-mutex": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.0.tgz", + "integrity": "sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", @@ -519,6 +535,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/mutex-js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/mutex-js/-/mutex-js-1.1.5.tgz", + "integrity": "sha512-e0PCNr2q4Er5SNrRwE/1yDFe8ILOk0yS4xFuDbO0KOfr3/5VmUcWB6SaTFaxRPqC/MWiGkfBuTRgIGz5EJtlcA==" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -808,6 +829,11 @@ "node": ">=0.6" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", diff --git a/frontend/Web/package.json b/frontend/Web/package.json index 318be37..17be8d2 100644 --- a/frontend/Web/package.json +++ b/frontend/Web/package.json @@ -11,7 +11,10 @@ "license": "ISC", "type": "commonjs", "dependencies": { + "async-lock": "^1.4.0", + "async-mutex": "^0.4.0", "express": "^4.18.2", + "mutex-js": "^1.1.5", "socket.io": "^4.7.2" } }