Cadabra
Computer algebra system for field theory problems
Server.hh
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #if defined(_WIN32)
5  #define NOMINMAX
6 #endif
7 #include <websocketpp/server.hpp>
8 #include <websocketpp/config/asio_no_tls.hpp>
9 #include <websocketpp/common/functional.hpp>
10 #include <string>
11 #include <signal.h>
12 #include <boost/uuid/uuid.hpp>
13 #include <future>
14 #include <pybind11/pybind11.h>
15 #include <pybind11/embed.h>
16 
17 #include "Stopwatch.hh"
18 #include "ProgressMonitor.hh"
19 
35 
36 class Server : public ProgressMonitor {
37  public:
38  Server();
39  Server(const Server&)=delete;
40  Server(const std::string& socket);
41  ~Server();
42 
46  void run();
47 
48 
53 
54  class CatchOutput {
55  public:
56  CatchOutput();
57  CatchOutput(const CatchOutput&);
58 
59  void write(const std::string& txt);
60  void clear();
61  std::string str() const;
62  private:
63  std::string collect;
64  };
65 
67 
70 
88 
89  uint64_t send(const std::string& output, const std::string& msg_type, uint64_t parent_id=0, bool last_in_sequence=false);
90  void send_json(const std::string&);
91 
92  bool handles(const std::string& otype) const;
93  std::string architecture() const;
94 
95  private:
96  void init();
97 
98  // WebSocket++ dependent parts below.
99  typedef websocketpp::server<websocketpp::config::asio> WebsocketServer;
100  void on_socket_init(websocketpp::connection_hdl hdl, boost::asio::ip::tcp::socket & s);
101  void on_message(websocketpp::connection_hdl hdl, WebsocketServer::message_ptr msg);
102  void on_open(websocketpp::connection_hdl hdl);
103  void on_close(websocketpp::connection_hdl hdl);
105  std::string socket_name;
106 
107  // Connection tracking. There can be multiple connections to
108  // the server, but they all have access to the same Python
109  // scope. With multiple connections, one can inspect the Python
110  // stack from a different client (e.g. for debugging purposes).
111 
112  class Connection {
113  public:
114  Connection();
115 
116  websocketpp::connection_hdl hdl;
117  boost::uuids::uuid uuid;
118  };
119  typedef std::map<websocketpp::connection_hdl, Connection,
120  std::owner_less<websocketpp::connection_hdl>> ConnectionMap;
122 
123  // Mutex to be able to use the websocket layer from both the
124  // main loop and the python-running thread.
125  std::mutex ws_mutex;
126 
127 
128  // Basics for the working thread that processes blocks.
129  std::thread runner;
131  std::condition_variable block_available;
132  void wait_for_job();
133 
134  // Data and connection info for a single block of code.
135  class Block {
136  public:
137  Block(websocketpp::connection_hdl, const std::string&, uint64_t id);
138  websocketpp::connection_hdl hdl; // FIXME: decouple from websocket?
139  std::string input;
140  std::string output;
141  std::string error;
142  uint64_t cell_id;
143  };
144  std::queue<Block> block_queue;
145  websocketpp::connection_hdl current_hdl;
146  uint64_t current_id; // id of the block given to us by the client.
147 
148  // Run a piece of Python code. This is called from a separate
149  // thread constructed by on_message().
150  std::string run_string(const std::string&, bool handle_output=true);
151 
158 
159  void on_block_finished(Block);
160  void on_block_error(Block);
161  void on_kernel_fault(Block);
162 
163 
164 
165 
166  uint64_t return_cell_id; // serial number of cells generated by us.
167 
170  void stop_block();
171  bool started;
172  std::future<std::string> job;
173 
177 
178  void dispatch_message(websocketpp::connection_hdl, const std::string& json_string);
179 
180  // Python global info.
181  pybind11::scoped_interpreter guard;
182  pybind11::module main_module;
183  pybind11::object main_namespace;
184 
186 };
187 
void on_socket_init(websocketpp::connection_hdl hdl, boost::asio::ip::tcp::socket &s)
Definition: Server.cc:187
void on_kernel_fault(Block)
Definition: Server.cc:430
Definition: Server.hh:135
Object representing a Cadabra server, capable of receiving messages on a websocket, running Python code, and sending output back to the client.
Definition: Server.hh:36
std::string error
Definition: Server.hh:141
pybind11::module main_module
Definition: Server.hh:182
int cells_ran
Definition: Server.hh:185
std::string run_string(const std::string &, bool handle_output=true)
Definition: Server.cc:152
pybind11::object main_namespace
Definition: Server.hh:183
std::mutex ws_mutex
Definition: Server.hh:125
~Server()
Definition: Server.cc:52
void write(const std::string &txt)
Definition: Server.cc:65
websocketpp::config::asio_client::message_type::ptr message_ptr
Definition: ComputeThread.hh:13
Definition: ProgressMonitor.hh:10
void on_block_error(Block)
Definition: Server.cc:404
void on_open(websocketpp::connection_hdl hdl)
Definition: Server.cc:198
void on_block_finished(Block)
Called by the run_block() thread upon completion of the task.
Definition: Server.cc:353
std::thread runner
Definition: Server.hh:129
The Stopwach class provides a simple interace to allow timing function calls etc...
Definition: Stopwatch.hh:105
void send_json(const std::string &)
Definition: Server.cc:397
std::string socket_name
Definition: Server.hh:105
void dispatch_message(websocketpp::connection_hdl, const std::string &json_string)
Takes a JSON encoded message and performs the required action to process it.
Definition: Server.cc:307
CatchOutput catchOut
Definition: Server.hh:66
std::string input
Definition: Server.hh:139
uint64_t send(const std::string &output, const std::string &msg_type, uint64_t parent_id=0, bool last_in_sequence=false)
Raw code to send a string (which must be JSON formatted) as a message to the client.
Definition: Server.cc:364
std::condition_variable block_available
Definition: Server.hh:131
Definition: Server.hh:112
bool started
Definition: Server.hh:171
std::string collect
Definition: Server.hh:63
void wait_for_job()
Definition: Server.cc:222
uint64_t cell_id
Definition: Server.hh:142
Python output catching.
Definition: Server.hh:54
CatchOutput()
Definition: Server.cc:57
std::queue< Block > block_queue
Definition: Server.hh:144
uint64_t return_cell_id
Definition: Server.hh:166
void on_close(websocketpp::connection_hdl hdl)
Definition: Server.cc:207
WebsocketServer wserver
Definition: Server.hh:104
void on_message(websocketpp::connection_hdl hdl, WebsocketServer::message_ptr msg)
Definition: Server.cc:292
void stop_block()
Halt the currently running block and prevent execution of any further blocks that may still be on the...
Definition: Server.cc:279
void clear()
Definition: Server.cc:71
uint64_t current_id
Definition: Server.hh:146
CatchOutput catchErr
Definition: Server.hh:66
websocketpp::connection_hdl current_hdl
Definition: Server.hh:145
std::string str() const
Definition: Server.cc:77
std::map< websocketpp::connection_hdl, Connection, std::owner_less< websocketpp::connection_hdl > > ConnectionMap
Definition: Server.hh:120
void run()
The only user-visible part: just instantiate a server object and start it with run().
Definition: Server.cc:456
std::mutex block_available_mutex
Definition: Server.hh:130
Server()
Definition: Server.cc:37
void init()
Definition: Server.cc:101
websocketpp::connection_hdl hdl
Definition: Server.hh:138
Stopwatch server_stopwatch
Definition: Server.hh:68
websocketpp::connection_hdl hdl
Definition: Server.hh:116
std::future< std::string > job
Definition: Server.hh:172
std::string architecture() const
Definition: Server.cc:82
Connection()
Definition: Server.cc:193
bool handles(const std::string &otype) const
Definition: Server.cc:358
pybind11::scoped_interpreter guard
Definition: Server.hh:181
std::string output
Definition: Server.hh:140
Stopwatch sympy_stopwatch
Definition: Server.hh:69
Block(websocketpp::connection_hdl, const std::string &, uint64_t id)
Definition: Server.cc:287
websocketpp::server< websocketpp::config::asio > WebsocketServer
Definition: Server.hh:99
boost::uuids::uuid uuid
Definition: Server.hh:117
ConnectionMap connections
Definition: Server.hh:121