diff --git a/doc/src/api/vpr/contexts.rst b/doc/src/api/vpr/contexts.rst
index ec69aea8404..f29f48dd8b6 100644
--- a/doc/src/api/vpr/contexts.rst
+++ b/doc/src/api/vpr/contexts.rst
@@ -43,3 +43,7 @@ Structures
.. doxygenstruct:: TimingContext
:project: vpr
:members:
+
+.. doxygenstruct:: ServerContext
+ :project: vpr
+ :members:
\ No newline at end of file
diff --git a/doc/src/api/vpr/index.rst b/doc/src/api/vpr/index.rst
index 37410b72b9c..2ca57515464 100644
--- a/doc/src/api/vpr/index.rst
+++ b/doc/src/api/vpr/index.rst
@@ -11,3 +11,4 @@ VPR API
netlist
route_tree
rr_graph
+ server
diff --git a/doc/src/api/vpr/server.rst b/doc/src/api/vpr/server.rst
new file mode 100644
index 00000000000..2bda680bbc1
--- /dev/null
+++ b/doc/src/api/vpr/server.rst
@@ -0,0 +1,83 @@
+========
+Server
+========
+
+server::update
+--------------
+
+.. doxygenfunction:: server::update
+ :project: vpr
+
+server::GateIO
+--------------
+
+.. doxygenclass:: server::GateIO
+ :project: vpr
+ :members:
+
+server::Task
+------------
+
+.. doxygenfile:: commcmd.h
+ :project: vpr
+
+.. doxygenclass:: server::Task
+ :project: vpr
+ :members:
+
+server::TaskResolver
+--------------------
+
+.. doxygenclass:: server::TaskResolver
+ :project: vpr
+ :members:
+
+.. doxygenstruct:: server::CritPathsResult
+ :project: vpr
+ :members:
+
+.. doxygenfunction:: server::calc_critical_path
+ :project: vpr
+
+.. doxygenenum:: e_timing_report_detail
+ :project: vpr
+
+comm::Telegram
+--------------
+
+.. doxygenclass:: comm::TelegramHeader
+ :project: vpr
+ :members:
+
+.. doxygenstruct:: comm::TelegramFrame
+ :project: vpr
+ :members:
+
+.. doxygenclass:: comm::TelegramBuffer
+ :project: vpr
+ :members:
+
+.. doxygenclass:: comm::ByteArray
+ :project: vpr
+ :members:
+
+Parsers
+-------
+
+.. doxygenclass:: server::TelegramOptions
+ :project: vpr
+ :members:
+
+.. doxygenclass:: comm::TelegramParser
+ :project: vpr
+ :members:
+
+
+Compression utils
+-----------------
+
+.. doxygenfunction:: try_compress
+ :project: vpr
+
+.. doxygenfunction:: try_decompress
+ :project: vpr
diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst
index af611dad5c4..3895d071ee5 100644
--- a/doc/src/vpr/command_line_usage.rst
+++ b/doc/src/vpr/command_line_usage.rst
@@ -1824,6 +1824,27 @@ The following options are used to enable power estimation in VPR.
Instructions on generating this file are provided in :ref:`power_estimation`.
+Server Mode Options
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+If VPR is in server mode, it listens on a socket for commands from a client. Currently, this is used to enable interactive timing analysis and visualization of timing paths in the VPR UI under the control of a separate client.
+
+The following options are used to enable server mode in VPR.
+
+.. seealso:: :ref:`server_mode` for more details.
+
+.. option:: --server
+
+ Run in server mode. Accept single client application connection and respond to client requests
+
+ **Default:** ``off``
+
+.. option:: --port PORT
+
+ Server port number.
+
+ **Default:** ``60555``
+
Command-line Auto Completion
----------------------------
diff --git a/doc/src/vtr/index.rst b/doc/src/vtr/index.rst
index 4978bc440bf..4b02b7fe432 100644
--- a/doc/src/vtr/index.rst
+++ b/doc/src/vtr/index.rst
@@ -43,6 +43,7 @@ VTR also includes a set of benchmark designs known to work with the design flow.
running_vtr
benchmarks
power_estimation/index.rst
+ server_mode/index.rst
tasks
run_vtr_flow
run_vtr_task
diff --git a/doc/src/vtr/server_mode/comm_telegram_body_structure.odg b/doc/src/vtr/server_mode/comm_telegram_body_structure.odg
new file mode 100755
index 00000000000..9f10c8e7b5b
Binary files /dev/null and b/doc/src/vtr/server_mode/comm_telegram_body_structure.odg differ
diff --git a/doc/src/vtr/server_mode/comm_telegram_body_structure.svg b/doc/src/vtr/server_mode/comm_telegram_body_structure.svg
new file mode 100644
index 00000000000..7b2897b1088
--- /dev/null
+++ b/doc/src/vtr/server_mode/comm_telegram_body_structure.svg
@@ -0,0 +1,293 @@
+
+
+
diff --git a/doc/src/vtr/server_mode/comm_telegram_structure.odg b/doc/src/vtr/server_mode/comm_telegram_structure.odg
new file mode 100755
index 00000000000..68d2872aa12
Binary files /dev/null and b/doc/src/vtr/server_mode/comm_telegram_structure.odg differ
diff --git a/doc/src/vtr/server_mode/comm_telegram_structure.svg b/doc/src/vtr/server_mode/comm_telegram_structure.svg
new file mode 100755
index 00000000000..25e7602152d
--- /dev/null
+++ b/doc/src/vtr/server_mode/comm_telegram_structure.svg
@@ -0,0 +1,584 @@
+
+
+
diff --git a/doc/src/vtr/server_mode/index.rst b/doc/src/vtr/server_mode/index.rst
new file mode 100644
index 00000000000..66972681241
--- /dev/null
+++ b/doc/src/vtr/server_mode/index.rst
@@ -0,0 +1,208 @@
+.. _server_mode:
+
+Server Mode
+================
+
+If VPR is in server mode, it listens on a socket for commands from a client. Currently, this is used to enable interactive timing analysis and visualization of timing paths in the VPR UI under the control of a separate client.
+VPR provides the ability to run in server mode using the following command-line arguments.
+
+.. code-block:: none
+
+ --server --port_num 60555
+
+Server mode may only accept a single client application connection and respond to two types of requests: **get critical path report** and **highlight selected critical path elements**.
+
+Communication telegram
+-------------------------
+
+Telegram consists of two parts: a fixed-size **telegram header** and a variable-size **telegram body**.
+The telegram header contains helper information required to properly extract the telegram body sequence from the data flow.
+
+.. _fig_comm_telegram_structure:
+
+.. figure:: comm_telegram_structure.*
+
+ Communication telegram structure.
+
+.. note:: The telegram body itself could be compressed with zlib to minimize the amount of data transferred over the socket.
+ This compression is applied to the response of the 'get critical path report' request. The compressor ID byte in the telegram header signals whether the telegram body is compressed.
+ When the compressor ID is null, the telegram body is not compressed. If the compressor ID is 'z', it means the body is compressed with zlib.
+
+.. note:: The checksum field contains the telegram body checksum. This checksum is used to validate the consistency of the telegram body during the dispatching phase.
+ If checksums are mismatched, the telegram is considered invalid and is skipped in processing.
+
+
+.. _fig_comm_telegram_body_structure:
+
+.. figure:: comm_telegram_body_structure.*
+
+ Communication telegram body structure.
+
+ **telegram body** is a flat **JSON** structure.
+
+ **CMD** could have following integer values:
+
+ - 0 - command id for **get critical path**
+ - 1 - command id for **highlight selected path elements**
+
+ JOB_ID is a unique ID for a task. It is used to associate the request with the response by matching the same JOB_ID. Each new client request should increment the JOB_ID value; otherwise, it will not be clear which request the current response belongs to.
+
+
+Get critical path timing report example
+---------------------------------------
+
+ Let's take a look at an example of a request timing report telegram body with the following options:
+
+ - path_num = 1
+ - path_type = "setup"
+ - details_level = "netlist"
+ - is_flat_routing = false
+
+ .. code-block:: json
+ :caption: telegram body **REQUEST** example
+ :linenos:
+
+ {
+ "JOB_ID": "1",
+ "CMD": "0",
+ "OPTIONS": "int:path_num:1;string:path_type:setup;string:details_level:netlist;bool:is_flat_routing:0"
+ }
+
+ **path_type** could have following string values:
+
+ - "setup"
+ - "hold"
+
+ **details_level** could have following string values:
+
+ - "netlist"
+ - "aggregated"
+ - "detailed"
+ - "debug"
+
+ Response will look like:
+
+ .. code-block:: json
+ :caption: telegram body **RESPONSE** example
+ :linenos:
+
+ {
+ "JOB_ID": "1",
+ "CMD": "0",
+ "OPTIONS": "int:path_num:1;string:path_type:setup;string:details_level:netlist;bool:is_flat_routing:0",
+ "DATA": "
+ #Timing report of worst 1 path(s)
+ # Unit scale: 1e-09 seconds
+ # Output precision: 3
+
+ #Path 1
+ Startpoint: count[1].Q[0] (dffsre clocked by clk)
+ Endpoint : count[13].D[0] (dffsre clocked by clk)
+ Path Type : setup
+
+ Point Incr Path
+ ------------------------------------------------------------------------------------------
+ clock clk (rise edge) 0.000 0.000
+ clock source latency 0.000 0.000
+ clk.inpad[0] (.input) 0.000 0.000
+ count[1].C[0] (dffsre) 0.715 0.715
+ count[1].Q[0] (dffsre) [clock-to-output] 0.286 1.001
+ count_adder_carry_p_cout[2].p[0] (adder_carry) 0.573 1.574
+ count_adder_carry_p_cout[2].cout[0] (adder_carry) 0.068 1.642
+ count_adder_carry_p_cout[3].cin[0] (adder_carry) 0.043 1.685
+ count_adder_carry_p_cout[3].cout[0] (adder_carry) 0.070 1.755
+ count_adder_carry_p_cout[4].cin[0] (adder_carry) 0.053 1.808
+ count_adder_carry_p_cout[4].cout[0] (adder_carry) 0.070 1.877
+ count_adder_carry_p_cout[5].cin[0] (adder_carry) 0.043 1.921
+ count_adder_carry_p_cout[5].cout[0] (adder_carry) 0.070 1.990
+ count_adder_carry_p_cout[6].cin[0] (adder_carry) 0.053 2.043
+ count_adder_carry_p_cout[6].cout[0] (adder_carry) 0.070 2.113
+ count_adder_carry_p_cout[7].cin[0] (adder_carry) 0.043 2.156
+ count_adder_carry_p_cout[7].cout[0] (adder_carry) 0.070 2.226
+ count_adder_carry_p_cout[8].cin[0] (adder_carry) 0.053 2.279
+ count_adder_carry_p_cout[8].cout[0] (adder_carry) 0.070 2.348
+ count_adder_carry_p_cout[9].cin[0] (adder_carry) 0.043 2.391
+ count_adder_carry_p_cout[9].cout[0] (adder_carry) 0.070 2.461
+ count_adder_carry_p_cout[10].cin[0] (adder_carry) 0.053 2.514
+ count_adder_carry_p_cout[10].cout[0] (adder_carry) 0.070 2.584
+ count_adder_carry_p_cout[11].cin[0] (adder_carry) 0.043 2.627
+ count_adder_carry_p_cout[11].cout[0] (adder_carry) 0.070 2.696
+ count_adder_carry_p_cout[12].cin[0] (adder_carry) 0.053 2.749
+ count_adder_carry_p_cout[12].cout[0] (adder_carry) 0.070 2.819
+ count_adder_carry_p_cout[13].cin[0] (adder_carry) 0.043 2.862
+ count_adder_carry_p_cout[13].cout[0] (adder_carry) 0.070 2.932
+ count_adder_carry_p_cout[14].cin[0] (adder_carry) 0.053 2.985
+ count_adder_carry_p_cout[14].sumout[0] (adder_carry) 0.040 3.025
+ count_dffsre_Q_D[13].in[0] (.names) 0.564 3.589
+ count_dffsre_Q_D[13].out[0] (.names) 0.228 3.818
+ count[13].D[0] (dffsre) 0.000 3.818
+ data arrival time 3.818
+
+ clock clk (rise edge) 0.000 0.000
+ clock source latency 0.000 0.000
+ clk.inpad[0] (.input) 0.000 0.000
+ count[13].C[0] (dffsre) 0.715 0.715
+ clock uncertainty 0.000 0.715
+ cell setup time -0.057 0.659
+ data required time 0.659
+ ------------------------------------------------------------------------------------------
+ data required time 0.659
+ data arrival time -3.818
+ ------------------------------------------------------------------------------------------
+ slack (VIOLATED) -3.159
+
+
+ #End of timing report
+ #RPT METADATA:
+ path_index/clock_launch_path_elements_num/arrival_path_elements_num
+ 0/2/30
+ ",
+ "STATUS": "1"
+ }
+
+Draw selected critical path elements example
+--------------------------------------------
+
+ Let's take a look at an example of a request timing report telegram body with the following options:
+
+ - path_elements = path 0 and it's sub-elements 10,11,12,13,14,15,20,21,22,23,24,25
+ - high_light_mode = "crit path flylines delays"
+ - draw_path_contour = 1
+
+ .. code-block:: json
+ :caption: telegram body **REQUEST** example
+ :linenos:
+
+ {
+ "JOB_ID": "2",
+ "CMD": "1",
+ "OPTIONS": "string:path_elements:0#10,11,12,13,14,15,20,21,22,23,24,25;string:high_light_mode:crit path flylines delays;bool:draw_path_contour:1"
+ }
+
+ **high_light_mode** could have following string values:
+
+ - "crit path flylines"
+ - "crit path flylines delays"
+ - "crit path routing"
+ - "crit path routing delays"
+
+ Response will look like:
+
+ .. code-block:: json
+ :caption: telegram body **RESPONSE** example
+ :linenos:
+
+ {
+ "JOB_ID": "2",
+ "CMD": "1",
+ "OPTIONS": "string:path_elements:0#10,11,12,13,14,15,20,21,22,23,24,25;string:high_light_mode:crit path flylines delays;bool:draw_path_contour:1",
+ "DATA": "",
+ "STATUS": "1"
+ }
+
+ .. note:: If status is not 1, the field ***DATA*** contains error string.
+
+
+
+
+
diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp
index e23e98083cf..e8656ef1dc8 100644
--- a/vpr/src/base/vpr_api.cpp
+++ b/vpr/src/base/vpr_api.cpp
@@ -828,9 +828,9 @@ RouteStatus vpr_route_flow(const Netlist<>& net_list,
routing_delay_calc = std::make_shared(atom_ctx.nlist, atom_ctx.lookup, net_delay, is_flat);
timing_info = make_setup_hold_timing_info(routing_delay_calc, router_opts.timing_update_type);
#ifndef NO_SERVER
- if (g_vpr_ctx.server().gateIO().is_running()) {
- g_vpr_ctx.mutable_server().set_timing_info(timing_info);
- g_vpr_ctx.mutable_server().set_routing_delay_calc(routing_delay_calc);
+ if (g_vpr_ctx.server().gate_io.is_running()) {
+ g_vpr_ctx.mutable_server().timing_info = timing_info;
+ g_vpr_ctx.mutable_server().routing_delay_calc = routing_delay_calc;
}
#endif /* NO_SERVER */
} else {
@@ -1080,7 +1080,7 @@ void vpr_init_server(const t_vpr_setup& vpr_setup) {
#ifndef NO_SERVER
if (vpr_setup.ServerOpts.is_server_mode_enabled) {
/* Set up a server and its callback to be triggered at 100ms intervals by the timer's timeout event. */
- server::GateIO& gate_io = g_vpr_ctx.mutable_server().mutable_gateIO();
+ server::GateIO& gate_io = g_vpr_ctx.mutable_server().gate_io;
if (!gate_io.is_running()) {
gate_io.start(vpr_setup.ServerOpts.port_num);
g_timeout_add(/*interval_ms*/ 100, server::update, &application);
diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h
index 201157609fd..b6ccba2d4d9 100644
--- a/vpr/src/base/vpr_context.h
+++ b/vpr/src/base/vpr_context.h
@@ -568,35 +568,18 @@ struct NocContext : public Context {
* @brief State relating to server mode
*
* This should contain only data structures that
- * related to server state.
+ * relate to the vpr server state.
*/
-class ServerContext : public Context {
- public:
- const server::GateIO& gateIO() const { return gate_io_; }
- server::GateIO& mutable_gateIO() { return gate_io_; }
-
- const server::TaskResolver& task_resolver() const { return task_resolver_; }
- server::TaskResolver& mutable_task_resolver() { return task_resolver_; }
-
- void set_crit_paths(std::vector&& crit_paths) { crit_paths_ = std::move(crit_paths); }
- const std::vector& crit_paths() const { return crit_paths_; }
-
- void clear_crit_path_elements() { crit_path_element_indexes_.clear(); }
- void set_crit_path_elements(const std::map>& crit_path_element_indexes) { crit_path_element_indexes_ = crit_path_element_indexes; }
- std::map> crit_path_element_indexes() const { return crit_path_element_indexes_; }
-
- void set_draw_crit_path_contour(bool draw_crit_path_contour) { draw_crit_path_contour_ = draw_crit_path_contour; }
- bool draw_crit_path_contour() const { return draw_crit_path_contour_; }
-
- void set_timing_info(const std::shared_ptr& timing_info) { timing_info_ = timing_info; }
- const std::shared_ptr& timing_info() const { return timing_info_; }
-
- void set_routing_delay_calc(const std::shared_ptr& routing_delay_calc) { routing_delay_calc_ = routing_delay_calc; }
- const std::shared_ptr& routing_delay_calc() const { return routing_delay_calc_; }
+struct ServerContext : public Context {
+ /**
+ * @brief \ref server::GateIO.
+ */
+ server::GateIO gate_io;
- private:
- server::GateIO gate_io_;
- server::TaskResolver task_resolver_;
+ /**
+ * @brief \ref server::TaskResolver.
+ */
+ server::TaskResolver task_resolver;
/**
* @brief Stores the critical path items.
@@ -605,7 +588,7 @@ class ServerContext : public Context {
* Once calculated upon request, it provides the value for a specific critical path
* to be rendered upon user request.
*/
- std::vector crit_paths_;
+ std::vector crit_paths;
/**
* @brief Stores the selected critical path elements.
@@ -613,24 +596,25 @@ class ServerContext : public Context {
* This value is used to render the selected critical path elements upon client request.
* The std::map key plays role of path index, where the element indexes are stored as std::set.
*/
- std::map> crit_path_element_indexes_;
+ std::map> crit_path_element_indexes;
/**
* @brief Stores the flag indicating whether to draw the critical path contour.
*
- * If the flag is set to true, the non-selected critical path elements will be drawn as a contour, while selected elements will be drawn as usual.
+ * If True, the entire path will be rendered with some level of transparency, regardless of the selection of path elements. However, selected path elements will be drawn in full color.
+ * This feature is helpful in visual debugging, to see how the separate path elements are mapped into the whole path.
*/
- bool draw_crit_path_contour_ = false;
+ bool draw_crit_path_contour = false;
/**
* @brief Reference to the SetupHoldTimingInfo calculated during the routing stage.
*/
- std::shared_ptr timing_info_;
+ std::shared_ptr timing_info;
/**
* @brief Reference to the PostClusterDelayCalculator calculated during the routing stage.
*/
- std::shared_ptr routing_delay_calc_;
+ std::shared_ptr routing_delay_calc;
};
#endif /* NO_SERVER */
diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp
index 6b774d53a7b..ec4f764868f 100644
--- a/vpr/src/draw/draw.cpp
+++ b/vpr/src/draw/draw.cpp
@@ -255,9 +255,9 @@ static void draw_main_canvas(ezgl::renderer* g) {
draw_placement_macros(g);
#ifndef NO_SERVER
- if (g_vpr_ctx.server().gateIO().is_running()) {
+ if (g_vpr_ctx.server().gate_io.is_running()) {
const ServerContext& server_ctx = g_vpr_ctx.server(); // shortcut
- draw_crit_path_elements(server_ctx.crit_paths(), server_ctx.crit_path_element_indexes(), server_ctx.draw_crit_path_contour(), g);
+ draw_crit_path_elements(server_ctx.crit_paths, server_ctx.crit_path_element_indexes, server_ctx.draw_crit_path_contour, g);
} else {
draw_crit_path(g);
}
diff --git a/vpr/src/draw/draw_basic.h b/vpr/src/draw/draw_basic.h
index 250f90802ef..d939b43b8ec 100644
--- a/vpr/src/draw/draw_basic.h
+++ b/vpr/src/draw/draw_basic.h
@@ -111,6 +111,10 @@ void draw_crit_path(ezgl::renderer* g);
*
* This function draws critical path elements based on the provided timing paths
* and indexes map. It is primarily used in server mode, where items are drawn upon request.
+ *
+ * @param paths The vector of TimingPath objects representing the critical paths.
+ * @param indexes The map of sets, where the map keys are path indices in std::vector, and each set contains the indices of the data_arrival_path elements ( @ref tatum::TimingPath ) to draw.
+ * @param g Pointer to the ezgl::renderer object on which the elements will be drawn.
*/
void draw_crit_path_elements(const std::vector& paths, const std::map>& indexes, bool draw_crit_path_contour, ezgl::renderer* g);
diff --git a/vpr/src/server/bytearray.h b/vpr/src/server/bytearray.h
index d414ae0817c..154153be6f9 100644
--- a/vpr/src/server/bytearray.h
+++ b/vpr/src/server/bytearray.h
@@ -10,35 +10,99 @@
namespace comm {
/**
- * @brief ByteArray as a simple wrapper over std::vector
+ * @brief ByteArray is a simple wrapper over std::vector that provides a user-friendly interface for manipulating array data..
*/
class ByteArray : public std::vector {
public:
static const std::size_t DEFAULT_SIZE_HINT = 1024;
- ByteArray(const char* data)
+ /**
+ * @brief Constructs a ByteArray from a null-terminated C string.
+ *
+ * Constructs a ByteArray object from the specified null-terminated C string.
+ * The constructor interprets the input string as a sequence of bytes until the
+ * null terminator '\0' is encountered, and initializes the ByteArray with those bytes.
+ *
+ * @param data A pointer to the null-terminated C string from which to construct the ByteArray.
+ */
+ explicit ByteArray(const char* data)
: std::vector(data, data + std::strlen(data))
{}
+ /**
+ * @brief Constructs a ByteArray from a raw character array.
+ *
+ * Constructs a ByteArray object from the specified raw character array,
+ * with the given size. This constructor interprets the input data as a sequence
+ * of bytes and initializes the ByteArray with those bytes.
+ *
+ * @param data A pointer to the raw character array from which to construct the ByteArray.
+ * @param size The size of the raw character array, in bytes.
+ */
ByteArray(const char* data, std::size_t size)
: std::vector(data, data + size)
{}
- ByteArray(std::size_t size_hint = DEFAULT_SIZE_HINT) {
+ /**
+ * @brief Constructs a byte array with the specified size hint.
+ *
+ * This constructor initializes the byte array with an initial capacity determined by the size hint.
+ *
+ * @param size_hint The initial capacity hint for the byte array.
+ */
+ explicit ByteArray(std::size_t size_hint = DEFAULT_SIZE_HINT) {
reserve(size_hint);
}
+ /**
+ * @brief Constructs a byte array from the elements in the range [first, last).
+ *
+ * This constructor initializes the byte array with the elements in the range [first, last),
+ * where `first` and `last` are iterators defining the range.
+ *
+ * @tparam Iterator The type of iterator used to specify the range.
+ * @param first An iterator to the first element in the range.
+ * @param last An iterator to the last element in the range.
+ */
template
ByteArray(Iterator first, Iterator last): std::vector(first, last) {}
+ /**
+ * @brief Appends the content of another byte array to the end of this byte array.
+ *
+ * This function adds all the bytes from the specified byte array `appendix`
+ * to the end of this byte array.
+ *
+ * @param appendix The byte array whose content is to be appended.
+ */
void append(const ByteArray& appendix) {
insert(end(), appendix.begin(), appendix.end());
}
+ /**
+ * @brief Appends a byte to the end of the byte array.
+ *
+ * This function adds the specified byte to the end of the byte array.
+ *
+ * @param b The byte to append to the byte array.
+ */
void append(char b) {
push_back(b);
}
+ /**
+ * @brief Finds the position of the specified sequence in the byte array.
+ *
+ * This function searches for the specified sequence of characters within the byte array.
+ * If the sequence is found, it returns a pair containing `true` and the starting index of the sequence.
+ * If the sequence is not found, it returns a pair containing `false` and `0`.
+ *
+ * @param sequence A pointer to the sequence of characters to search for.
+ * @param sequence_size The size of the sequence to search for.
+ * @return A `std::pair` where the first element is a boolean indicating whether the sequence was
+ * found (`true`) or not (`false`), and the second element is the starting index of the sequence if
+ * found.
+ */
std::pair find_sequence(const char* sequence, std::size_t sequence_size) {
const std::size_t ssize = size();
if (ssize >= sequence_size) {
@@ -58,14 +122,41 @@ class ByteArray : public std::vector {
return std::make_pair(false, 0);
}
+ /**
+ * @brief Converts the container to a std::string_view.
+ *
+ * This operator allows the container to be implicitly converted to a `std::string_view`,
+ * providing a non-owning view into the container's data.
+ *
+ * @return A `std::string_view` representing the container's data.
+ */
operator std::string_view() const {
return std::string_view(this->data(), this->size());
}
+ /**
+ * @brief Calculates the checksum of the elements in the container.
+ *
+ * This function iterates over each element in the container and adds their unsigned integer representations
+ * to the sum. The result is returned as a 32-bit unsigned integer.
+ *
+ * @return The checksum of the elements in the container.
+ */
uint32_t calc_check_sum() {
return calc_check_sum(*this);
}
+ /**
+ * @brief Calculates the checksum of the elements in the given iterable container.
+ *
+ * This function template calculates the checksum of the elements in the provided iterable container.
+ * It iterates over each element in the container and adds their unsigned integer representations to the sum.
+ * The result is returned as a 32-bit unsigned integer.
+ *
+ * @tparam T The type of the iterable container.
+ * @param iterable The iterable container whose elements checksum is to be calculated.
+ * @return The checksum of the elements in the iterable container.
+ */
template
static uint32_t calc_check_sum(const T& iterable) {
uint32_t sum = 0;
diff --git a/vpr/src/server/commcmd.h b/vpr/src/server/commcmd.h
new file mode 100644
index 00000000000..28f3f69f452
--- /dev/null
+++ b/vpr/src/server/commcmd.h
@@ -0,0 +1,18 @@
+#ifndef COMMCMD_H
+#define COMMCMD_H
+
+#ifndef NO_SERVER
+
+namespace comm {
+
+enum class CMD : int {
+ NONE=-1,
+ GET_PATH_LIST_ID=0,
+ DRAW_PATH_ID=1
+};
+
+} // namespace comm
+
+#endif /* NO_SERVER */
+
+#endif /* COMMCMD_H */
diff --git a/vpr/src/server/commconstants.h b/vpr/src/server/commconstants.h
index 545c00a977b..2eaeed60386 100644
--- a/vpr/src/server/commconstants.h
+++ b/vpr/src/server/commconstants.h
@@ -12,7 +12,7 @@ inline const std::string KEY_CMD{"CMD"};
inline const std::string KEY_OPTIONS{"OPTIONS"};
inline const std::string KEY_DATA{"DATA"};
inline const std::string KEY_STATUS{"STATUS"};
-inline const std::string ECHO_DATA{"ECHO"};
+inline const std::string ECHO_TELEGRAM_BODY{"ECHO"};
const unsigned char ZLIB_COMPRESSOR_ID = 'z';
const unsigned char NONE_COMPRESSOR_ID = '\x0';
@@ -28,11 +28,6 @@ inline const std::string OPTION_DRAW_PATH_CONTOUR{"draw_path_contour"};
inline const std::string KEY_SETUP_PATH_LIST{"setup"};
inline const std::string KEY_HOLD_PATH_LIST{"hold"};
-enum CMD {
- CMD_GET_PATH_LIST_ID=0,
- CMD_DRAW_PATH_ID
-};
-
} // namespace comm
#endif /* NO_SERVER */
diff --git a/vpr/src/server/gateio.cpp b/vpr/src/server/gateio.cpp
index 573797cb44e..d40431e7da9 100644
--- a/vpr/src/server/gateio.cpp
+++ b/vpr/src/server/gateio.cpp
@@ -134,10 +134,10 @@ GateIO::ActivityStatus GateIO::handle_telegrams(std::vectordata};
+ std::string message{telegram_frame->body};
bool is_echo_telegram = false;
- if ((message.size() == comm::ECHO_DATA.size()) && (message == comm::ECHO_DATA)) {
- m_logger.queue(LogLevel::Detail, "received", comm::ECHO_DATA);
+ if ((message.size() == comm::ECHO_TELEGRAM_BODY.size()) && (message == comm::ECHO_TELEGRAM_BODY)) {
+ m_logger.queue(LogLevel::Detail, "received", comm::ECHO_TELEGRAM_BODY);
is_echo_telegram = true;
status = ActivityStatus::CLIENT_ACTIVITY;
}
@@ -148,7 +148,7 @@ GateIO::ActivityStatus GateIO::handle_telegrams(std::vector cmd_opt = comm::TelegramParser::try_extract_field_cmd(message);
std::optional options_opt = comm::TelegramParser::try_extract_field_options(message);
if (job_id_opt && cmd_opt && options_opt) {
- TaskPtr task = std::make_unique(job_id_opt.value(), cmd_opt.value(), options_opt.value());
+ TaskPtr task = std::make_unique(job_id_opt.value(), static_cast(cmd_opt.value()), options_opt.value());
const comm::TelegramHeader& header = telegram_frame->header;
m_logger.queue(LogLevel::Info, "received:", header.info(), task->info(/*skipDuration*/true));
std::unique_lock lock(m_tasks_mutex);
@@ -167,17 +167,17 @@ GateIO::ActivityStatus GateIO::handle_client_alive_tracker(sockpp::tcp6_socket&
if (client_alive_tracker_ptr) {
/// handle sending echo to client
if (client_alive_tracker_ptr->is_time_to_sent_echo()) {
- comm::TelegramHeader echo_header = comm::TelegramHeader::construct_from_data(comm::ECHO_DATA);
+ comm::TelegramHeader echo_header = comm::TelegramHeader::construct_from_body(comm::ECHO_TELEGRAM_BODY);
std::string message{echo_header.buffer()};
- message.append(comm::ECHO_DATA);
+ message.append(comm::ECHO_TELEGRAM_BODY);
try {
std::size_t bytes_sent = client.write(message);
if (bytes_sent == message.size()) {
- m_logger.queue(LogLevel::Detail, "sent", comm::ECHO_DATA);
+ m_logger.queue(LogLevel::Detail, "sent", comm::ECHO_TELEGRAM_BODY);
client_alive_tracker_ptr->on_echo_sent();
}
} catch(...) {
- m_logger.queue(LogLevel::Debug, "fail to sent", comm::ECHO_DATA);
+ m_logger.queue(LogLevel::Debug, "fail to sent", comm::ECHO_TELEGRAM_BODY);
status = ActivityStatus::COMMUNICATION_PROBLEM;
}
}
diff --git a/vpr/src/server/gateio.h b/vpr/src/server/gateio.h
index 8dfb9ce686e..aa9036459c5 100644
--- a/vpr/src/server/gateio.h
+++ b/vpr/src/server/gateio.h
@@ -26,16 +26,16 @@ namespace server {
*
* Operable only with a single client. As soon as client connection is detected
* it begins listening on the specified port number for incoming client requests,
- * collects and encapsulates them into tasks.
- * The incoming tasks are extracted and handled by the top-level logic (TaskResolver).
- * Once the tasks are resolved by the TaskResolver, they are returned
- * to be sent back to the client as a response.
+ * collects and encapsulates them into tasks (see @ref Task).
+ * The incoming tasks are extracted and handled by the top-level logic @ref TaskResolver in the main thread.
+ * Once the tasks are resolved by the @ref TaskResolver, they are returned to be sent back to the client app as a response.
+ * Moving @ref Task across threads happens in @ref server::update.
*
- * @note:
+ * @note
* - The GateIO instance should be created and managed from the main thread, while its internal processing
* and IO operations are performed asynchronously in a separate thread. This separation ensures smooth IO behavior
* and responsiveness of the application.
- * - Gateio is not started automatically upon creation, you have to use the 'start' method with the port number.
+ * - GateIO is not started automatically upon creation, you have to use the 'start' method with the port number.
* - The socket is initialized in a non-blocking mode to function properly in a multithreaded environment.
*/
class GateIO
@@ -141,6 +141,9 @@ class GateIO
const int LOOP_INTERVAL_MS = 100;
public:
+ /**
+ * @brief Default constructor for GateIO.
+ */
GateIO();
~GateIO();
@@ -150,7 +153,11 @@ class GateIO
GateIO(GateIO&&) = delete;
GateIO& operator=(GateIO&&) = delete;
- // Check if the port listening process is currently running
+ /**
+ * @brief Returns a bool indicating whether or not the port listening process is currently running.
+ *
+ * @return True if the port listening process is running, false otherwise.
+ */
bool is_running() const { return m_is_running.load(); }
/**
@@ -161,7 +168,7 @@ class GateIO
*
* @param tasks A reference to a vector where the received tasks will be moved.
*/
- void take_received_tasks(std::vector&);
+ void take_received_tasks(std::vector& tasks);
/**
* @brief Moves tasks to the send queue.
@@ -172,12 +179,12 @@ class GateIO
*
* @param tasks A reference to a vector containing the tasks to be moved to the send queue.
*/
- void move_tasks_to_send_queue(std::vector&);
+ void move_tasks_to_send_queue(std::vector& tasks);
/**
* @brief Prints log messages for the GateIO.
*
- * @note Must be called from main thread since it's invoke std::cout.
+ * @note Must be called from the main thread since it's invoke std::cout.
* Calling this method from other threads may result in unexpected behavior.
*/
void print_logs();
@@ -189,9 +196,9 @@ class GateIO
* Once started,the server will continue running in a separate thread and will accept connection only from a single client
* attempting to connect to the specified port.
*
- * @param portNum The port number on which the server will listen for incoming connection.
+ * @param port_num The port number on which the server will listen for incoming connection.
*/
- void start(int portNum);
+ void start(int port_num);
/**
* @brief Stops the server and terminates the listening thread.
diff --git a/vpr/src/server/pathhelper.cpp b/vpr/src/server/pathhelper.cpp
index fb0dfd621b9..c3bfca88e50 100644
--- a/vpr/src/server/pathhelper.cpp
+++ b/vpr/src/server/pathhelper.cpp
@@ -34,8 +34,8 @@ static void collect_crit_path_metadata(std::stringstream& ss, const std::vector<
*/
CritPathsResultPtr calc_critical_path(const std::string& report_type, int crit_path_num, e_timing_report_detail details_level, bool is_flat_routing) {
// shortcuts
- const std::shared_ptr& timing_info = g_vpr_ctx.server().timing_info();
- const std::shared_ptr& routing_delay_calc = g_vpr_ctx.server().routing_delay_calc();
+ const std::shared_ptr& timing_info = g_vpr_ctx.server().timing_info;
+ const std::shared_ptr& routing_delay_calc = g_vpr_ctx.server().routing_delay_calc;
auto& timing_ctx = g_vpr_ctx.timing();
auto& atom_ctx = g_vpr_ctx.atom();
diff --git a/vpr/src/server/pathhelper.h b/vpr/src/server/pathhelper.h
index e79dc270f88..8d2244a885a 100644
--- a/vpr/src/server/pathhelper.h
+++ b/vpr/src/server/pathhelper.h
@@ -18,15 +18,34 @@ namespace server {
* It contains the critical path list and the generated report as a string.
*/
struct CritPathsResult {
+ /**
+ * @brief Checks if the CritPathsResult contains report.
+ * @return True if contains report, false otherwise.
+ */
bool is_valid() const { return !report.empty(); }
+
+ /**
+ * @brief Vector containing timing paths.
+ */
std::vector paths;
+
+ /**
+ * @brief String containing the generated report.
+ */
std::string report;
};
using CritPathsResultPtr = std::shared_ptr;
-/**
- * @brief Helper function to calculate critical path timing report with specified parameters.
- */
+/**
+* @brief Calculates the critical path.
+
+* This function calculates the critical path based on the provided parameters.
+* @param type The type of the critical path. Must be either "setup" or "hold".
+* @param crit_path_num The max number of critical paths to record.
+* @param details_level The level of detail for the timing report. See @ref e_timing_report_detail.
+* @param is_flat_routing Indicates whether flat routing should be used.
+* @return A `CritPathsResultPtr` which is a pointer to the result of the critical path calculation (see @ref CritPathsResult).
+*/
CritPathsResultPtr calc_critical_path(const std::string& type, int crit_path_num, e_timing_report_detail details_level, bool is_flat_routing);
} // namespace server
diff --git a/vpr/src/server/serverupdate.cpp b/vpr/src/server/serverupdate.cpp
index caf06d5e890..de45c45936d 100644
--- a/vpr/src/server/serverupdate.cpp
+++ b/vpr/src/server/serverupdate.cpp
@@ -9,12 +9,12 @@
namespace server {
gboolean update(gpointer data) {
- const bool is_running = g_vpr_ctx.server().gateIO().is_running();
+ const bool is_running = g_vpr_ctx.server().gate_io.is_running();
if (is_running) {
// shortcuts
ezgl::application* app = static_cast(data);
- GateIO& gate_io = g_vpr_ctx.mutable_server().mutable_gateIO();
- TaskResolver& task_resolver = g_vpr_ctx.mutable_server().mutable_task_resolver();
+ GateIO& gate_io = g_vpr_ctx.mutable_server().gate_io;
+ TaskResolver& task_resolver = g_vpr_ctx.mutable_server().task_resolver;
std::vector tasks_buff;
@@ -24,7 +24,7 @@ gboolean update(gpointer data) {
}
tasks_buff.clear();
- const bool is_server_context_initialized = g_vpr_ctx.server().timing_info() && g_vpr_ctx.server().routing_delay_calc();
+ const bool is_server_context_initialized = g_vpr_ctx.server().timing_info && g_vpr_ctx.server().routing_delay_calc;
if (is_server_context_initialized) {
bool has_finished_tasks = task_resolver.update(app);
diff --git a/vpr/src/server/task.cpp b/vpr/src/server/task.cpp
index bf99164aafc..f05ada6d835 100644
--- a/vpr/src/server/task.cpp
+++ b/vpr/src/server/task.cpp
@@ -10,7 +10,7 @@
namespace server {
-Task::Task(int jobId, int cmd, const std::string& options)
+Task::Task(int jobId, comm::CMD cmd, const std::string& options)
: m_job_id(jobId), m_cmd(cmd), m_options(options) {
m_creation_time = std::chrono::high_resolution_clock::now();
}
@@ -27,25 +27,25 @@ void Task::chop_num_sent_bytes_from_response_buffer(std::size_t bytes_sent_num)
}
}
-bool Task::options_match(const class std::unique_ptr& other) {
+bool Task::options_match(const std::unique_ptr& other) {
if (other->options().size() != m_options.size()) {
return false;
}
return other->options() == m_options;
}
-void Task::fail(const std::string& error) {
+void Task::set_fail(const std::string& error) {
m_is_finished = true;
m_error = error;
bake_response();
}
-void Task::success() {
+void Task::set_success() {
m_is_finished = true;
bake_response();
}
-void Task::success(std::string&& result) {
+void Task::set_success(std::string&& result) {
m_result = std::move(result);
m_is_finished = true;
bake_response();
@@ -55,7 +55,7 @@ std::string Task::info(bool skip_duration) const {
std::stringstream ss;
ss << "task["
<< "id=" << std::to_string(m_job_id)
- << ",cmd=" << std::to_string(m_cmd);
+ << ",cmd=" << std::to_string(static_cast(m_cmd));
if (!skip_duration) {
ss << ",exists=" << get_pretty_duration_str_from_ms(time_ms_elapsed());
}
@@ -73,7 +73,7 @@ void Task::bake_response() {
ss << "{";
ss << "\"" << comm::KEY_JOB_ID << "\":\"" << m_job_id << "\",";
- ss << "\"" << comm::KEY_CMD << "\":\"" << m_cmd << "\",";
+ ss << "\"" << comm::KEY_CMD << "\":\"" << static_cast(m_cmd) << "\",";
ss << "\"" << comm::KEY_OPTIONS << "\":\"" << m_options << "\",";
if (has_error()) {
ss << "\"" << comm::KEY_DATA << "\":\"" << m_error << "\",";
@@ -100,7 +100,7 @@ void Task::bake_response() {
}
std::string body{std::move(body_opt.value())};
- m_telegram_header = comm::TelegramHeader::construct_from_data(body, compressor_id);
+ m_telegram_header = comm::TelegramHeader::construct_from_body(body, compressor_id);
m_response_buffer.append(m_telegram_header.buffer().begin(), m_telegram_header.buffer().end());
m_response_buffer.append(body);
diff --git a/vpr/src/server/task.h b/vpr/src/server/task.h
index 0082c48f223..3d29e49373f 100644
--- a/vpr/src/server/task.h
+++ b/vpr/src/server/task.h
@@ -8,6 +8,7 @@
#include
#include "telegramheader.h"
+#include "commcmd.h"
namespace server {
@@ -19,41 +20,167 @@ namespace server {
*/
class Task {
public:
- Task(int job_id, int cmd, const std::string& options = "");
+ /**
+ * @brief Constructs a new Task object.
+ *
+ * @param job_id The ID of the job associated with the task.
+ * @param cmd The command ID (see @ref comm::CMD) associated with the task.
+ * @param options Additional options for the task (default: empty string).
+ */
+ Task(int job_id, comm::CMD cmd, const std::string& options = "");
Task(const Task&) = delete;
Task& operator=(const Task&) = delete;
+ /**
+ * @brief Gets the job ID associated with the task.
+ *
+ * @return The job ID.
+ */
int job_id() const { return m_job_id; }
- int cmd() const { return m_cmd; }
-
- void chop_num_sent_bytes_from_response_buffer(std::size_t bytesSentNum);
-
- bool options_match(const class std::unique_ptr& other);
+ /**
+ * @brief Gets the command ID associated with the task.
+ *
+ * @return The command ID (see @ref comm::CMD).
+ */
+ comm::CMD cmd() const { return m_cmd; }
+
+ /**
+ * @brief Removes the specified number of bytes from the response buffer.
+ *
+ * This method removes the specified number of bytes from the beginning of the response buffer.
+ * It is typically used after sending a response to discard the bytes that have been sent.
+ *
+ * @param bytes_sent_num The number of bytes to remove from the response buffer.
+ */
+ void chop_num_sent_bytes_from_response_buffer(std::size_t bytes_sent_num);
+
+ /**
+ * @brief Checks if the options of this task match the options of another task.
+ *
+ * This method compares the options of this task with the options of another task
+ * and returns true if they match, otherwise returns false.
+ *
+ * @param other The other task to compare options with.
+ * @return True if the options match, false otherwise.
+ */
+ bool options_match(const std::unique_ptr& other);
+
+ /**
+ * @brief Retrieves the response buffer.
+ *
+ * This method returns a constant reference to the response buffer, which contains the data after task execution.
+ *
+ * @return A constant reference to the response buffer.
+ */
const std::string& response_buffer() const { return m_response_buffer; }
+ /**
+ * @brief Checks if the task has finished execution.
+ *
+ * This method returns true if the task has finished execution; otherwise, it returns false.
+ *
+ * @return True if the task has finished execution, false otherwise.
+ */
bool is_finished() const { return m_is_finished; }
+
+ /**
+ * @brief Checks if the task has encountered an error.
+ *
+ * This method returns true if the task has encountered an error; otherwise, it returns false.
+ *
+ * @return True if the task has encountered an error, false otherwise.
+ */
bool has_error() const { return !m_error.empty(); }
+
+ /**
+ * @brief Retrieves the error message associated with the task.
+ *
+ * This method returns the error message associated with the task, if any.
+ *
+ * @return A constant reference to the error message string.
+ */
const std::string& error() const { return m_error; }
+ /**
+ * @brief Retrieves the original number of response bytes.
+ *
+ * This method returns the original number of response bytes before any chopping operation.
+ *
+ * @return The original number of response bytes.
+ */
std::size_t orig_reponse_bytes_num() const { return m_orig_reponse_bytes_num; }
+ /**
+ * @brief Checks if the response has been fully sent.
+ *
+ * This method returns true if the entire response has been successfully sent,
+ * otherwise it returns false.
+ *
+ * @return True if the response has been fully sent, false otherwise.
+ */
bool is_response_fully_sent() const { return m_is_response_fully_sent; }
- void fail(const std::string& error);
- void success();
- void success(std::string&& result);
-
+ /**
+ * @brief Marks the task as failed with the specified error message.
+ *
+ * This method sets the task's error message to the provided error string,
+ * indicating that the task has failed.
+ *
+ * @param error The error message describing the reason for the task's failure.
+ */
+ void set_fail(const std::string& error);
+
+ /**
+ * @brief Marks the task as successfully completed.
+ */
+ void set_success();
+
+ /**
+ * @brief Marks the task as successfully completed with the specified result.
+ *
+ * This method marks the task as successfully completed and stores the result.
+ * It takes an rvalue reference to a string, allowing for efficient move semantics.
+ *
+ * @param result An rvalue reference to a string describing the result of the task execution.
+ * The content of this string will be moved into the task's result storage.
+ */
+ void set_success(std::string&& result);
+
+ /**
+ * @brief Generates a string containing information about the task.
+ *
+ * This method generates a string containing information about the task,
+ * including its identifier, command, options, and optionally its duration.
+ *
+ * @param skip_duration If true, the duration information will be omitted from the string.
+ *
+ * @return A string containing information about the task.
+ */
std::string info(bool skip_duration = false) const;
+ /**
+ * @brief Retrieves the TelegramHeader associated with the task.
+ *
+ * This method returns a reference to the TelegramHeader associated with the task.
+ *
+ * @return A reference to the TelegramHeader associated with the task.
+ */
const comm::TelegramHeader& telegram_header() const { return m_telegram_header; }
+ /**
+ * @brief Retrieves the options associated with the task.
+ *
+ * This method returns a reference to the options string associated with the task.
+ *
+ * @return A reference to the options string associated with the task.
+ */
const std::string& options() const { return m_options; }
private:
int m_job_id = -1;
- int m_cmd = -1;
+ comm::CMD m_cmd = comm::CMD::NONE;
std::string m_options;
std::string m_result;
std::string m_error;
diff --git a/vpr/src/server/taskresolver.cpp b/vpr/src/server/taskresolver.cpp
index 0f90cb354ca..5298521ece0 100644
--- a/vpr/src/server/taskresolver.cpp
+++ b/vpr/src/server/taskresolver.cpp
@@ -18,12 +18,12 @@ void TaskResolver::own_task(TaskPtr&& new_task) {
if (task->cmd() == new_task->cmd()) {
if (task->options_match(new_task)) {
std::string msg = "similar task is already in execution, reject new " + new_task->info() + " and waiting for old " + task->info() + " execution";
- new_task->fail(msg);
+ new_task->set_fail(msg);
} else {
// handle case when task has same cmd but different options
if (new_task->job_id() > task->job_id()) {
std::string msg = "old " + task->info() + " is overridden by a new " + new_task->info();
- task->fail(msg);
+ task->set_fail(msg);
}
}
}
@@ -64,12 +64,12 @@ bool TaskResolver::update(ezgl::application* app) {
for (auto& task: m_tasks) {
if (!task->is_finished()) {
switch(task->cmd()) {
- case comm::CMD_GET_PATH_LIST_ID: {
+ case comm::CMD::GET_PATH_LIST_ID: {
process_get_path_list_task(app, task);
has_processed_task = true;
break;
}
- case comm::CMD_DRAW_PATH_ID: {
+ case comm::CMD::DRAW_PATH_ID: {
process_draw_critical_path_task(app, task);
has_processed_task = true;
break;
@@ -88,7 +88,7 @@ void TaskResolver::process_get_path_list_task(ezgl::application*, const TaskPtr&
if (!options.has_errors()) {
ServerContext& server_ctx = g_vpr_ctx.mutable_server(); // shortcut
- server_ctx.clear_crit_path_elements(); // reset selection if path list options has changed
+ server_ctx.crit_path_element_indexes.clear(); // reset selection if path list options has changed
// read options
const int n_critical_path_num = options.get_int(comm::OPTION_PATH_NUM, 1);
@@ -101,22 +101,22 @@ void TaskResolver::process_get_path_list_task(ezgl::application*, const TaskPtr&
if (details_level_opt) {
CritPathsResultPtr crit_paths_result = calc_critical_path(path_type, n_critical_path_num, details_level_opt.value(), is_flat);
if (crit_paths_result->is_valid()) {
- server_ctx.set_crit_paths(std::move(crit_paths_result->paths));
- task->success(std::move(crit_paths_result->report));
+ server_ctx.crit_paths = std::move(crit_paths_result->paths);
+ task->set_success(std::move(crit_paths_result->report));
} else {
std::string msg{"Critical paths report is empty"};
VTR_LOG_ERROR(msg.c_str());
- task->fail(msg);
+ task->set_fail(msg);
}
} else {
std::string msg{"unsupported report details level " + details_level_str};
VTR_LOG_ERROR(msg.c_str());
- task->fail(msg);
+ task->set_fail(msg);
}
} else {
std::string msg{"options errors in get crit path list telegram: " + options.errors_str()};
VTR_LOG_ERROR(msg.c_str());
- task->fail(msg);
+ task->set_fail(msg);
}
}
@@ -130,24 +130,24 @@ void TaskResolver::process_draw_critical_path_task(ezgl::application* app, const
const bool draw_path_contour = options.get_bool(comm::OPTION_DRAW_PATH_CONTOUR, false);
// set critical path elements to render
- server_ctx.set_crit_path_elements(path_elements);
- server_ctx.set_draw_crit_path_contour(draw_path_contour);
+ server_ctx.crit_path_element_indexes = std::move(path_elements);
+ server_ctx.draw_crit_path_contour = draw_path_contour;
// update gtk UI
GtkComboBox* toggle_crit_path = GTK_COMBO_BOX(app->get_object("ToggleCritPath"));
gint high_light_mode_index = get_item_index_by_text(toggle_crit_path, high_light_mode.c_str());
if (high_light_mode_index != -1) {
gtk_combo_box_set_active(toggle_crit_path, high_light_mode_index);
- task->success();
+ task->set_success();
} else {
std::string msg{"cannot find ToggleCritPath qcombobox index for item " + high_light_mode};
VTR_LOG_ERROR(msg.c_str());
- task->fail(msg);
+ task->set_fail(msg);
}
} else {
std::string msg{"options errors in highlight crit path telegram: " + options.errors_str()};
VTR_LOG_ERROR(msg.c_str());
- task->fail(msg);
+ task->set_fail(msg);
}
}
diff --git a/vpr/src/server/taskresolver.h b/vpr/src/server/taskresolver.h
index 9ae91f5e64a..eca06bc1b74 100644
--- a/vpr/src/server/taskresolver.h
+++ b/vpr/src/server/taskresolver.h
@@ -20,23 +20,47 @@ namespace server {
*
* Process and resolve server task, store result and status for processed task.
*/
-
class TaskResolver {
public:
+ /**
+ * @brief Default constructor for TaskResolver.
+ */
TaskResolver()=default;
+
~TaskResolver()=default;
int tasks_num() const { return m_tasks.size(); }
- /* own task to process */
- void own_task(TaskPtr&&);
-
- /* process tasks */
- bool update(ezgl::application*);
-
- /* extract finished tasks */
- void take_finished_tasks(std::vector&);
-
+ /**
+ * @brief Takes ownership of a task.
+ *
+ * This method takes ownership of a task by moving it into the TaskResolver's internal task queue.
+ * After calling this method, the task will be owned and managed by the TaskResolver.
+ *
+ * @param task The task to take ownership of. After calling this method, the task object will be in a valid but unspecified state.
+ *
+ * @note After calling this method, the caller should avoid accessing or modifying the task object.
+ */
+ void own_task(TaskPtr&& task);
+
+ /**
+ * @brief Resolve queued tasks.
+ *
+ * @param app A pointer to the ezgl::application object representing the application instance.
+ */
+ bool update(ezgl::application* app);
+
+ /**
+ * @brief Extracts finished tasks from the internal task queue.
+ *
+ * This function removes finished tasks from the internal task queue and appends them to the provided vector.
+ * After this operation, the internal task queue will no longer hold the extracted tasks.
+ *
+ * @param tasks A reference to a vector where the finished tasks will be appended.
+ */
+ void take_finished_tasks(std::vector& tasks);
+
+ // helper method used in tests
const std::vector& tasks() const { return m_tasks; }
private:
diff --git a/vpr/src/server/telegrambuffer.cpp b/vpr/src/server/telegrambuffer.cpp
index 27a4e80cf3b..0aab6af8be1 100644
--- a/vpr/src/server/telegrambuffer.cpp
+++ b/vpr/src/server/telegrambuffer.cpp
@@ -44,14 +44,14 @@ void TelegramBuffer::take_telegram_frames(std::vector& r
std::size_t expected_telegram_size = TelegramHeader::size() + header.body_bytes_num();
if (m_raw_buffer.size() >= expected_telegram_size) {
// checksum validation
- ByteArray data(m_raw_buffer.begin() + TelegramHeader::size(), m_raw_buffer.begin() + expected_telegram_size);
- uint32_t actual_check_sum = data.calc_check_sum();
+ ByteArray body(m_raw_buffer.begin() + TelegramHeader::size(), m_raw_buffer.begin() + expected_telegram_size);
+ uint32_t actual_check_sum = body.calc_check_sum();
if (actual_check_sum == header.body_check_sum()) {
// construct telegram frame if checksum matches
TelegramFramePtr telegram_frame_ptr = std::make_shared();
telegram_frame_ptr->header = header;
- telegram_frame_ptr->data = std::move(data);
- data.clear(); // post std::move safety step
+ telegram_frame_ptr->body = std::move(body);
+ body.clear(); // post std::move safety step
result.push_back(telegram_frame_ptr);
} else {
@@ -65,12 +65,6 @@ void TelegramBuffer::take_telegram_frames(std::vector& r
}
}
-std::vector TelegramBuffer::take_telegram_frames() {
- std::vector result;
- take_telegram_frames(result);
- return result;
-}
-
void TelegramBuffer::take_errors(std::vector& errors) {
errors.reserve(errors.size() + m_errors.size());
std::move(std::begin(m_errors), std::end(m_errors), std::back_inserter(errors));
diff --git a/vpr/src/server/telegrambuffer.h b/vpr/src/server/telegrambuffer.h
index c781ab6dccd..b5822e9a5c6 100644
--- a/vpr/src/server/telegrambuffer.h
+++ b/vpr/src/server/telegrambuffer.h
@@ -16,15 +16,20 @@ namespace comm {
/**
* @brief Implements Telegram Buffer as a wrapper over BytesArray
*
- * It aggregates received bytes and return only well filled frames.
+ * It aggregates received bytes and assists in extracting telegram frames ( @ref TelegramFrame ) from the raw byte buffer.
*/
class TelegramBuffer
{
- static const std::size_t DEFAULT_SIZE_HINT = 1024;
+ inline static const std::size_t DEFAULT_SIZE_HINT = 1024;
public:
- TelegramBuffer(): m_raw_buffer(DEFAULT_SIZE_HINT) {}
- explicit TelegramBuffer(std::size_t sizeHint): m_raw_buffer(sizeHint) {}
+ /**
+ * @brief Constructs a TelegramBuffer object with a specified size hint.
+ *
+ * This constructor initializes a TelegramBuffer object with a specified size hint for the raw buffer.
+ */
+ explicit TelegramBuffer(std::size_t size_hint = DEFAULT_SIZE_HINT): m_raw_buffer(size_hint) {}
+
~TelegramBuffer()=default;
/**
@@ -44,21 +49,14 @@ class TelegramBuffer
*
* @param data The byte array whose contents will be appended to internal byte buffer.
*/
- void append(const ByteArray&);
+ void append(const ByteArray& data);
/**
* @brief Extracts well-formed telegram frames from the internal byte buffer.
*
* @param frames A reference to a vector where the extracted telegram frames will be stored.
*/
- void take_telegram_frames(std::vector&);
-
- /**
- * @brief Extracts well-formed telegram frames from the internal byte buffer.
- *
- * @return std::vector A vector containing pointers to the extracted telegram frames.
- */
- std::vector take_telegram_frames();
+ void take_telegram_frames(std::vector& frames);
/**
* @brief Takes errors from the internal storage.
@@ -70,7 +68,7 @@ class TelegramBuffer
*
* @note After calling this function, the internal error storage will be cleared.
*/
- void take_errors(std::vector&);
+ void take_errors(std::vector& errors);
/**
* @brief Retrieves a constant reference to the internal byte buffer.
@@ -84,6 +82,15 @@ class TelegramBuffer
std::vector m_errors;
std::optional m_header_opt;
+ /**
+ * @brief Checks for the presence of the telegram header in the buffer.
+ *
+ * This function searches for the telegram header signature in the raw buffer.
+ * If the signature is found, any bytes preceding the header start position
+ * are discarded from the buffer.
+ *
+ * @return true if the telegram header signature is found, false otherwise.
+ */
bool check_telegram_header_presence();
};
diff --git a/vpr/src/server/telegramframe.h b/vpr/src/server/telegramframe.h
index c542d41d1ee..e2237de3e36 100644
--- a/vpr/src/server/telegramframe.h
+++ b/vpr/src/server/telegramframe.h
@@ -10,18 +10,21 @@
namespace comm {
-
/**
* @brief Structure representing a TelegramFrame.
*
* A TelegramFrame consists of a TelegramHeader followed by data.
-*
-* @var header The TelegramHeader containing metadata about the telegram message. @see TelegramHeader
-* @var data The actual data of the telegram message.
*/
struct TelegramFrame {
+ /**
+ * @brief header The TelegramHeader containing metadata about the telegram message.
+ */
TelegramHeader header;
- ByteArray data;
+
+ /**
+ * @brief body The actual data of the telegram message.
+ */
+ ByteArray body;
};
using TelegramFramePtr = std::shared_ptr;
diff --git a/vpr/src/server/telegramheader.cpp b/vpr/src/server/telegramheader.cpp
index 344e8fe7422..f1f05a4864e 100644
--- a/vpr/src/server/telegramheader.cpp
+++ b/vpr/src/server/telegramheader.cpp
@@ -73,7 +73,7 @@ std::string TelegramHeader::info() const {
return ss.str();
}
-comm::TelegramHeader TelegramHeader::construct_from_data(const std::string_view& body, uint8_t compressor_id) {
+comm::TelegramHeader TelegramHeader::construct_from_body(const std::string_view& body, uint8_t compressor_id) {
uint32_t body_check_sum = ByteArray::calc_check_sum(body);
return comm::TelegramHeader{static_cast(body.size()), body_check_sum, compressor_id};
}
diff --git a/vpr/src/server/telegramheader.h b/vpr/src/server/telegramheader.h
index 1a3f990ddb1..5190a3ac7e7 100644
--- a/vpr/src/server/telegramheader.h
+++ b/vpr/src/server/telegramheader.h
@@ -11,19 +11,17 @@
namespace comm {
/**
- * @brief The fixed size bytes sequence where the metadata of a telegram message is stored.
+ * @brief The fixed size byte sequence where the metadata of a telegram message is stored.
*
* This structure is used to describe the message frame sequence in order to successfully extract it.
* The TelegramHeader structure follows this format:
- * ------------------------------------------------------
- * [ 4 bytes ][ 4 bytes ][ 4 bytes ][ 1 byte ]
- * [SIGNATURE][DATA_LENGTH][DATA_CHECKSUM][COMPRESSOR_ID]
- * ------------------------------------------------------
+ * - [ 4 bytes ]: SIGNATURE - A 4-byte constant sequence "I", "P", "A", "\0" which indicates the valid start of a TelegramHeader.
+ * - [ 4 bytes ]: DATA_LENGTH - A 4-byte field where the data length is stored, allowing for proper identification of the start and end of the TelegramFrame sequence.
+ * - [ 4 bytes ]: DATA_CHECKSUM - A 4-byte field where the data checksum is stored to validate the attached data.
+ * - [ 1 byte ]: COMPRESSOR_ID - A 1-byte field where the compressor ID is stored. If it's null, it means the telegram body is not compressed (in text/json format).
+ * Otherwise, the telegram body is compressed. Currently, only zlib compression for the telegram body is supported, which is specified with COMPRESSOR_ID='z'.
*
- * The SIGNATURE is a 4-byte constant sequence "I", "P", "A", "\0" which indicates the valid start of a TelegramHeader.
- * The DATA_LENGTH is a 4-byte field where the data length is stored, allowing for proper identification of the start and end of the TelegramFrame sequence.
- * The DATA_CHECKSUM is a 4-byte field where the data checksum is stored to validate the attached data.
- * The COMPRESSOR_ID is a 1-byte field where the compressor id is stored. If it's NULL, it means the data is not compressed (in text/json format).
+ * @note: The DATA_CHECKSUM field can be used to check the integrity of the telegram body on the client app side.
*/
class TelegramHeader {
public:
@@ -38,26 +36,96 @@ class TelegramHeader {
static constexpr size_t COMPRESSORID_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
TelegramHeader()=default;
- explicit TelegramHeader(uint32_t length, uint32_t checkSum, uint8_t compressorId = 0);
- explicit TelegramHeader(const ByteArray& body);
- ~TelegramHeader()=default;
- static comm::TelegramHeader construct_from_data(const std::string_view& body, uint8_t compressor_id = 0);
+ /**
+ * @brief Constructs a TelegramHeader object with the specified length, checksum, and optional compressor ID.
+ *
+ * @param length The length of the telegram body.
+ * @param check_sum The checksum of the telegram body.
+ * @param compressor_id The compressor ID used for compressing the telegram body (default is 0).
+ */
+ explicit TelegramHeader(uint32_t length, uint32_t check_sum, uint8_t compressor_id = 0);
+
+ /**
+ * @brief Constructs a TelegramHeader object from the provided byte buffer.
+ *
+ * This constructor initializes a TelegramHeader object using the length and checksum information taken from the provided byte buffer.
+ *
+ * @param buffer The ByteArray containing the header data of the telegram.
+ */
+ explicit TelegramHeader(const ByteArray& buffer);
+
+ ~TelegramHeader()=default;
+ /**
+ * @brief Constructs a TelegramHeader based on the provided body data.
+ *
+ * @param body The body data used to calculate the size and checksum.
+ * @param compressor_id The ID of the compressor used for compression (default is 0, means no compressor is used).
+ * @return A TelegramHeader object constructed from the provided body data.
+ */
+ static comm::TelegramHeader construct_from_body(const std::string_view& body, uint8_t compressor_id = 0);
+
+ /**
+ * @brief Returns the total size of the TelegramHeader.
+ *
+ * This static constexpr method returns the total size of the TelegramHeader, including all its components.
+ *
+ * @return The total size of the TelegramHeader.
+ */
static constexpr size_t size() {
return SIGNATURE_SIZE + LENGTH_SIZE + CHECKSUM_SIZE + COMPRESSORID_SIZE;
}
+ /**
+ * @brief To checks if the TelegramHeader is valid.
+ *
+ * @return True if the TelegramHeader is valid, false otherwise.
+ */
bool is_valid() const { return m_is_valid; }
+ /**
+ * @brief Retrieves the buffer associated with the TelegramHeader.
+ *
+ * This method returns a constant reference to the buffer associated with the TelegramHeader.
+ *
+ * @return A constant reference to the buffer.
+ */
const ByteArray& buffer() const { return m_buffer; }
+ /**
+ * @brief Retrieves the number of bytes in the telegram body.
+ *
+ * @return The number of bytes in the telegram body.
+ */
uint32_t body_bytes_num() const { return m_body_bytes_num; }
+
+ /**
+ * @brief Retrieves the checksum of telegram body.
+ *
+ * @return The checksum of telegram body.
+ */
uint32_t body_check_sum() const { return m_body_check_sum; }
+
+ /**
+ * @brief Retrieves the compressor ID used for compressing telegram body.
+ *
+ * @return The compressor ID of the telegram body. 0 if the telegram body is not compressed.
+ */
uint8_t compressor_id() const { return m_compressor_id; }
+ /**
+ * @brief Checks if the telegram body is compressed.
+ *
+ * @return True if the telegram body is compressed; otherwise, false.
+ */
bool is_body_compressed() const { return m_compressor_id != 0; }
+ /**
+ * @brief Retrieves information about the telegram header.
+ *
+ * @return A string containing information about the telegram header.
+ */
std::string info() const;
private:
diff --git a/vpr/src/server/telegramoptions.h b/vpr/src/server/telegramoptions.h
index 2d3a00b8952..41237cdde2e 100644
--- a/vpr/src/server/telegramoptions.h
+++ b/vpr/src/server/telegramoptions.h
@@ -13,7 +13,7 @@ namespace server {
/**
* @brief Option class Parser
- *
+ *
* Parse the string of options in the format "TYPE:KEY1:VALUE1;TYPE:KEY2:VALUE2",
* for example "int:path_num:11;string:path_type:debug;int:details_level:3;bool:is_flat_routing:0".
* It provides a simple interface to check value presence and access them.
@@ -34,19 +34,85 @@ class TelegramOptions {
};
public:
+ /**
+ * @brief Constructs a TelegramOptions object with the provided data and expected keys.
+ *
+ * This constructor initializes a TelegramOptions object with the given data string
+ * and a vector of expected keys. It parses the data string and validates that such data has all required keys.
+ * If some keys are absent, it collects the errors.
+ *
+ * @param data The data string containing the options.
+ * @param expected_keys A vector of strings representing the expected keys in the options.
+ */
TelegramOptions(const std::string& data, const std::vector& expected_keys);
~TelegramOptions()=default;
+ /**
+ * @brief Checks if there are any errors present.
+ *
+ * This function returns true if there are errors present in the error container,
+ * otherwise it returns false.
+ *
+ * @return True if there are errors present, false otherwise.
+ */
bool has_errors() const { return !m_errors.empty(); }
- std::map> get_map_of_sets(const std::string& name);
-
- std::string get_string(const std::string& name);
-
- int get_int(const std::string& name, int fail_value);
-
- bool get_bool(const std::string& name, bool fail_value);
-
+ /**
+ * @brief Retrieves a map of sets associated with the specified key.
+ *
+ * This function retrieves a map of sets associated with the specified key.
+ *
+ * @note The map of sets is used to store the critical path index (map key) and the associated set of selected sub-path element indexes (map value).
+ *
+ * @param key The key of the map of sets to retrieve.
+ * @return The map of sets associated with the specified key.
+ */
+ std::map> get_map_of_sets(const std::string& key);
+
+ /**
+ * @brief Retrieves the string associated with the specified key.
+ *
+ * This function retrieves the string associated with the specified key.
+ * The key is used to identify the desired string value.
+ *
+ * @param key The key of the string to retrieve.
+ * @return The string associated with the specified key.
+ */
+ std::string get_string(const std::string& key);
+
+ /**
+ * @brief Retrieves the integer value associated with the specified key.
+ *
+ * This function retrieves the integer value associated with the specified key.
+ * If the key is found, its corresponding integer value is returned.
+ * If the key is not found, the specified fail_value is returned instead.
+ *
+ * @param key The key whose associated integer value is to be retrieved.
+ * @param fail_value The value to return if the key is not found.
+ * @return The integer value associated with the specified key, or fail_value if the key is not found.
+ */
+ int get_int(const std::string& key, int fail_value);
+
+ /**
+ * @brief Retrieves the boolean value associated with the specified key.
+ *
+ * This function retrieves the boolean value associated with the specified key.
+ *
+ * @param key The key whose associated boolean value is to be retrieved.
+ * @param fail_value The value to return if the key is not found.
+ * @return The boolean value associated with the specified key, or fail_value if the key is not found.
+ */
+ bool get_bool(const std::string& key, bool fail_value);
+
+ /**
+ * @brief Retrieves a concatenated string of all errors stored in the container.
+ *
+ * This function retrieves a concatenated string of all errors stored in the container.
+ * It concatenates all error strings stored in the container and returns the result.
+ * If there are no errors stored in the container, an empty string is returned.
+ *
+ * @return A concatenated string of all errors stored in the container.
+ */
std::string errors_str() const;
private:
diff --git a/vpr/src/server/telegramparser.h b/vpr/src/server/telegramparser.h
index 8ebb49955f2..23e942f1d9d 100644
--- a/vpr/src/server/telegramparser.h
+++ b/vpr/src/server/telegramparser.h
@@ -9,17 +9,71 @@
namespace comm {
/**
- * @brief Dummy JSON parser using regular expressions.
+ * @brief Dummy JSON parser.
*
- * This module provides helper methods to extract values for a keys as "JOB_ID", "CMD", or "OPTIONS"
- * from a JSON schema structured as follows: {JOB_ID:num, CMD:enum, OPTIONS:string}.
+ * This class provides helper methods to extract values for a keys as "JOB_ID", "CMD", "OPTIONS", "DATA", or "STATUS
+ * from a JSON schema structured as follows: {JOB_ID:num, CMD:enum, OPTIONS:string, DATA:string, STATUS:num}.
*/
class TelegramParser {
public:
+ /**
+ * @brief Attempts to extract the JOB_ID field from a given message.
+ *
+ * This function parses the provided message and attempts to extract the JOB_ID field from it.
+ * If the JOB_ID field is found and successfully extracted, it is returned as an optional integer.
+ * If the JOB_ID field is not found or cannot be parsed as an integer, an empty optional is returned.
+ *
+ * @param message The message from which to extract the JOB_ID field.
+ * @return An optional integer containing the extracted JOB_ID if successful, otherwise an empty optional.
+ */
static std::optional try_extract_field_job_id(const std::string& message);
+
+ /**
+ * @brief Attempts to extract the CMD field from a given message.
+ *
+ * This function parses the provided message and attempts to extract the CMD field from it.
+ * If the CMD field is found and successfully extracted, it is returned as an optional integer.
+ * If the CMD field is not found or cannot be parsed as an integer, an empty optional is returned.
+ *
+ * @param message The message from which to extract the CMD field.
+ * @return An optional integer containing the extracted CMD if successful, otherwise an empty optional.
+ */
static std::optional try_extract_field_cmd(const std::string& message);
+
+ /**
+ * @brief Attempts to extract the OPTIONS field from a given message.
+ *
+ * This function parses the provided message and attempts to extract the OPTIONS field from it.
+ * If the OPTIONS field is found and successfully extracted, it is returned as an optional string.
+ * If the OPTIONS field is not found an empty optional is returned.
+ *
+ * @param message The message from which to extract the OPTIONS field.
+ * @return An optional string containing the extracted OPTIONS if successful, otherwise an empty optional.
+ */
static std::optional try_extract_field_options(const std::string& message);
+
+ /**
+ * @brief Attempts to extract the DATA field from a given message.
+ *
+ * This function parses the provided message and attempts to extract the DATA field from it.
+ * If the DATA field is found and successfully extracted, it is returned as an optional string.
+ * If the DATA field is not found an empty optional is returned.
+ *
+ * @param message The message from which to extract the DATA field.
+ * @return An optional string containing the extracted DATA if successful, otherwise an empty optional.
+ */
static std::optional try_extract_field_data(const std::string& message);
+
+ /**
+ * @brief Attempts to extract the STATUS field from a given message.
+ *
+ * This function parses the provided message and attempts to extract the STATUS field from it.
+ * If the STATUS field is found and successfully extracted, it is returned as an optional integer.
+ * If the STATUS field is not found or cannot be parsed as an integer, an empty optional is returned.
+ *
+ * @param message The message from which to extract the STATUS field.
+ * @return An optional integer containing the extracted STATUS if successful, otherwise an empty optional.
+ */
static std::optional try_extract_field_status(const std::string& message);
private:
diff --git a/vpr/test/test_server_taskresolver.cpp b/vpr/test/test_server_taskresolver.cpp
index 4e9ff388341..eda8d5ae82f 100644
--- a/vpr/test/test_server_taskresolver.cpp
+++ b/vpr/test/test_server_taskresolver.cpp
@@ -8,7 +8,7 @@
TEST_CASE("test_server_taskresolver_cmdSpamFilter", "[vpr]") {
server::TaskResolver resolver;
- const int cmd = 10;
+ const comm::CMD cmd = comm::CMD::GET_PATH_LIST_ID;
{
server::TaskPtr task0 = std::make_unique(1, cmd);
@@ -43,7 +43,7 @@ TEST_CASE("test_server_taskresolver_cmdSpamFilter", "[vpr]") {
TEST_CASE("test_server_taskresolver_cmdOverrideFilter", "[vpr]") {
server::TaskResolver resolver;
- const int cmd = 10;
+ const comm::CMD cmd = comm::CMD::GET_PATH_LIST_ID;
{
server::TaskPtr task0 = std::make_unique(1, cmd, "1");
@@ -75,14 +75,17 @@ TEST_CASE("test_server_taskresolver_cmdOverrideFilter", "[vpr]") {
TEST_CASE("test_server_taskresolver_cmdSpamAndOverrideOptions", "[vpr]") {
server::TaskResolver resolver;
+ const comm::CMD cmd1 = comm::CMD::GET_PATH_LIST_ID;
+ const comm::CMD cmd2 = comm::CMD::DRAW_PATH_ID;
+
{
- server::TaskPtr task0 = std::make_unique(1, 2, "1");
- server::TaskPtr task1 = std::make_unique(2, 2, "11");
- server::TaskPtr task2 = std::make_unique(3, 2, "222");
- server::TaskPtr task3 = std::make_unique(4, 2, "222");
- server::TaskPtr task4 = std::make_unique(5, 1);
- server::TaskPtr task5 = std::make_unique(6, 1);
- server::TaskPtr task6 = std::make_unique(7, 1);
+ server::TaskPtr task0 = std::make_unique(1, cmd2, "1");
+ server::TaskPtr task1 = std::make_unique(2, cmd2, "11");
+ server::TaskPtr task2 = std::make_unique(3, cmd2, "222");
+ server::TaskPtr task3 = std::make_unique(4, cmd2, "222");
+ server::TaskPtr task4 = std::make_unique(5, cmd1);
+ server::TaskPtr task5 = std::make_unique(6, cmd1);
+ server::TaskPtr task6 = std::make_unique(7, cmd1);
resolver.own_task(std::move(task0));
resolver.own_task(std::move(task1));
@@ -101,11 +104,11 @@ TEST_CASE("test_server_taskresolver_cmdSpamAndOverrideOptions", "[vpr]") {
const server::TaskPtr& task1 = resolver.tasks().at(1);
REQUIRE(task0->job_id() == 3);
- REQUIRE(task0->cmd() == 2);
+ REQUIRE(task0->cmd() == cmd2);
REQUIRE(task0->options() == "222");
REQUIRE(task1->job_id() == 5);
- REQUIRE(task1->cmd() == 1);
+ REQUIRE(task1->cmd() == cmd1);
REQUIRE(task1->options() == "");
}
diff --git a/vpr/test/test_server_telegrambuffer.cpp b/vpr/test/test_server_telegrambuffer.cpp
index 767b4892030..6c5c793c3d2 100644
--- a/vpr/test/test_server_telegrambuffer.cpp
+++ b/vpr/test/test_server_telegrambuffer.cpp
@@ -40,7 +40,8 @@ TEST_CASE("test_server_telegrambuffer_oneOpened", "[vpr]") {
buff.append(comm::ByteArray{"111"});
buff.append(comm::ByteArray{"222"});
- auto frames = buff.take_telegram_frames();
+ std::vector frames;
+ buff.take_telegram_frames(frames);
REQUIRE(frames.size() == 0);
REQUIRE(std::string_view{buff.data()} == "111222");
@@ -52,12 +53,13 @@ TEST_CASE("test_server_telegrambuffer_notFilledTelegramButWithPrependedRubish",
const comm::ByteArray rubbish{"#@!"};
const comm::ByteArray msgBody{"some message"};
- const comm::TelegramHeader msgHeader{comm::TelegramHeader::construct_from_data(msgBody)};
+ const comm::TelegramHeader msgHeader{comm::TelegramHeader::construct_from_body(msgBody)};
tBuff.append(rubbish);
tBuff.append(msgHeader.buffer());
- auto frames = tBuff.take_telegram_frames();
+ std::vector frames;
+ tBuff.take_telegram_frames(frames);
REQUIRE(0 == frames.size());
REQUIRE(msgHeader.buffer() == tBuff.data()); // the rubbish prefix fragment will be absent here
@@ -70,8 +72,8 @@ TEST_CASE("test_server_telegrambuffer__oneFinishedOneOpened", "[vpr]")
const comm::ByteArray msgBody1{"message1"};
const comm::ByteArray msgBody2{"message2"};
- const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_data(msgBody1)};
- const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_data(msgBody2)};
+ const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_body(msgBody1)};
+ const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_body(msgBody2)};
comm::ByteArray t1(msgHeader1.buffer());
t1.append(msgBody1);
@@ -83,10 +85,11 @@ TEST_CASE("test_server_telegrambuffer__oneFinishedOneOpened", "[vpr]")
tBuff.append(t1);
tBuff.append(t2);
- auto frames = tBuff.take_telegram_frames();
+ std::vector frames;
+ tBuff.take_telegram_frames(frames);
REQUIRE(1 == frames.size());
- REQUIRE(msgBody1 == frames[0]->data);
+ REQUIRE(msgBody1 == frames[0]->body);
REQUIRE(t2 == tBuff.data());
}
@@ -98,8 +101,8 @@ TEST_CASE("test_server_telegrambuffer_twoFinished", "[vpr]")
const comm::ByteArray msgBody1{"message1"};
const comm::ByteArray msgBody2{"message2"};
- const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_data(msgBody1)};
- const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_data(msgBody2)};
+ const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_body(msgBody1)};
+ const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_body(msgBody2)};
comm::ByteArray t1(msgHeader1.buffer());
t1.append(msgBody1);
@@ -110,11 +113,12 @@ TEST_CASE("test_server_telegrambuffer_twoFinished", "[vpr]")
tBuff.append(t1);
tBuff.append(t2);
- auto frames = tBuff.take_telegram_frames();
+ std::vector frames;
+ tBuff.take_telegram_frames(frames);
REQUIRE(2 == frames.size());
- REQUIRE(msgBody1 == frames[0]->data);
- REQUIRE(msgBody2 == frames[1]->data);
+ REQUIRE(msgBody1 == frames[0]->body);
+ REQUIRE(msgBody2 == frames[1]->body);
REQUIRE(comm::ByteArray{} == tBuff.data());
}
@@ -126,8 +130,8 @@ TEST_CASE("test_server_telegrambuffer_clear", "[vpr]")
const comm::ByteArray msgBody1{"message1"};
const comm::ByteArray msgBody2{"message2"};
- const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_data(msgBody1)};
- const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_data(msgBody2)};
+ const comm::TelegramHeader msgHeader1{comm::TelegramHeader::construct_from_body(msgBody1)};
+ const comm::TelegramHeader msgHeader2{comm::TelegramHeader::construct_from_body(msgBody2)};
comm::ByteArray t1(msgHeader1.buffer());
t1.append(msgBody1);
@@ -137,7 +141,8 @@ TEST_CASE("test_server_telegrambuffer_clear", "[vpr]")
tBuff.clear();
- auto frames = tBuff.take_telegram_frames();
+ std::vector frames;
+ tBuff.take_telegram_frames(frames);
REQUIRE(0 == frames.size());
REQUIRE(comm::ByteArray{} == tBuff.data());