LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
line_cli.cpp File Reference
#include <algorithm>
#include <chrono>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
#include "line/util/line_console.h"
#include "line/api/sn/sn_node_metrics.h"
#include "line/solvers/solver_node_tables.h"
#include "line/api/sn/sn_state.h"
#include "line/api/sym/sym_engines.h"
#include "line/io/docker_image.h"
#include "line/io/environment_reader.h"
#include "line/io/jmt_writer.h"
#include "line/io/jsim_reader.h"
#include "line/io/network_reader.h"
#include "line/io/pnml.h"
#include "line/io/lqn_json_reader.h"
#include "line/gen/layered_network_generator.h"
#include "line/gen/network_generator.h"
#include "line/lang/lqn/lqn_reader.h"
#include "line/lang/lqn/lqn_writer.h"
#include "line/num/number.h"
#include "line/reg/api_dispatch.h"
#include "line/reg/registry.h"
#include "line/util/method_type.h"
#include "line/solvers/auto/auto_methods.h"
#include "line/solvers/auto/solver_auto.h"
#include "line/solvers/ba/solver_ba_runner.h"
#include "line/solvers/solver_default_cdf.h"
#include "line/solvers/ctmc/solver_ctmc_analyzer.h"
#include "line/solvers/ctmc/solver_ctmc_cdf.h"
#include "line/solvers/nc/solver_nc_cftp.h"
#include "line/solvers/ctmc/solver_ctmc_getters.h"
#include "line/solvers/ctmc/solver_ctmc_mdd_analyzer.h"
#include "line/solvers/ctmc/solver_ctmc_prob.h"
#include "line/solvers/ctmc/solver_ctmc_reward.h"
#include "line/solvers/ctmc/solver_ctmc_sample.h"
#include "line/solvers/ctmc/solver_ctmc_sens.h"
#include "line/solvers/ctmc/solver_ctmc_waitq.h"
#include "line/solvers/env/env_dispatch.h"
#include "line/solvers/fluid/fluid_jacobian.h"
#include "line/solvers/fluid/fluid_runner.h"
#include "line/solvers/fluid/solver_fluid.h"
#include "line/solvers/ldes/ldes_ln_engine.h"
#include "line/solvers/ln/solver_ln.h"
#include "line/solvers/ag/ag_dispatch.h"
#include "line/solvers/mam/solver_mam_runner.h"
#include "line/solvers/map_env.h"
#include "line/solvers/map_env_stages.h"
#include "line/solvers/mva/solver_mva_prob.h"
#include "line/solvers/mva/solver_mva_runner.h"
#include "line/solvers/nc/solver_nc_busyp.h"
#include "line/solvers/nc/solver_nc_cdf.h"
#include "line/solvers/nc/solver_nc_prob.h"
#include "line/solvers/nc/solver_nc_runner.h"
#include "line/solvers/sens/solver_sens_table.h"
#include "line/solvers/solver_chain_tables.h"
#include "line/solvers/ssa/solver_ssa_getters.h"
#include "line/solvers/ssa/ssa_dispatch.h"
#include "line/solvers/uq/uq_dispatch.h"
#include "line/solvers/wrappers/ldes/solver_ldes.h"
#include "line/solvers/wrappers/jmt/jmt_logs.h"
#include "line/solvers/wrappers/jmt/solver_jmt.h"
#include "line/solvers/wrappers/lqns/solver_lqns.h"
#include "line/solvers/wrappers/lqns/lqns_qnsolver.h"
#include "line/cli/cli_run.h"
#include "line/io/marshal.h"
#include "line/util/error.h"
#include "line/util/websocket.h"

Go to the source code of this file.

Classes

class  FdCapture
 Redirect a file descriptor into a temporary file for a scope, and give back what was written to it. More...

Namespaces

namespace  line
 Conservation laws of a layered queueing network, enumerated from its structure.
namespace  line::cli

Macros

#define LINE_CLI_TABLE_LADDER(FN)

Functions

int find_solver_report (const Options &o)
 Everything one invocation does once the arguments are in hand.
int run_invocation (Options o)
std::string run_invocation_captured (Options o, int &rc)
 Run one invocation with stdout captured, and return what it printed.
int run_server (const Options &base)
 -p/--port: serve solve requests over a WebSocket, as LineWebSocketServer does.
int run_generate (const Options &o)
 --generate: draw a random model and print it, solving nothing.
int dispatch (const Options &in, bool allow_server, bool no_args)
 Everything main did, with the arguments already in hand.
Response line::cli::run (const Request &req)
 Run one invocation and return what it produced.
int line::cli::main_body (int argc, char **argv)
 The binary's main, so line_cli_main.cpp stays ten lines.

Macro Definition Documentation

◆ LINE_CLI_TABLE_LADDER

#define LINE_CLI_TABLE_LADDER ( FN)
Value:
do { \
if (arith == "double") return FN<double>(file, k, eng); \
if (arith == "exact") return FN<line::Rational>(file, k, eng); \
if (arith == "real:16") return FN<line::Real<16> >(file, k, eng); \
if (arith == "real" || arith == "real:32") return FN<line::Real<32> >(file, k, eng); \
if (arith == "real:64") return FN<line::Real<64> >(file, k, eng); \
if (arith == "real:128") return FN<line::Real<128> >(file, k, eng); \
if (arith == "real:256") return FN<line::Real<256> >(file, k, eng); \
} while (0)
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52

Function Documentation

◆ dispatch()

int dispatch ( const Options & in,
bool allow_server,
bool no_args )

Everything main did, with the arguments already in hand.

SPLIT OUT SO A HOST CAN CALL IT. The binary's main is now ten lines in its own translation unit, and this is the body both it and the C ABI run, so a command line and an in-process call take the same path by construction rather than by review.

no_args replaces the argc == 1 that decided the brief help, because an in-process caller has no argv[0] to count and would otherwise never see it.

Definition at line 12099 of file line_cli.cpp.

References line::util::DEBUG, dispatch(), find_solver_report(), run_generate(), run_invocation(), run_server(), line::util::LineConsole::set_verbose(), line::util::SILENT, and line::util::STD.

Referenced by dispatch(), line::cli::main_body(), and line::cli::run().

◆ find_solver_report()

int find_solver_report ( const Options & o)

Everything one invocation does once the arguments are in hand.

SPLIT OUT OF main FOR SERVER MODE, which runs it once per request with a different -f and a captured stdout. Keeping one body means a request served over the socket takes exactly the path the same command line takes at the shell – the failure this avoids is a server that answers slightly differently from the CLI it is supposed to BE. --find-solver: which solvers and methods can analyze the model named by -f.

It reports rather than solves, so it stops before the solver ladder in solve_model_dispatch and before every knob that describes a run. The answer is arithmetic-independent – auto_find_solver asks feature sets, shapes and gates, never numbers – so the model is read at double whatever –arith says, and a caller who passed one is told rather than silently obeyed.

The layered path is not covered: auto_find_solver narrows the flat Network families, and a LayeredNetwork's are ln and lqns, which this port reaches through solve_lqn_dispatch and not through an AUTO of its own.

Definition at line 11602 of file line_cli.cpp.

References line::autosolver::auto_find_solver(), line::autosolver::auto_find_solver_table(), find_solver_report(), line::qn::Network< T >::get_struct(), line::io::is_layered_json(), and line::io::is_layered_json_text().

Referenced by dispatch(), and find_solver_report().

◆ run_generate()

int run_generate ( const Options & o)

--generate: draw a random model and print it, solving nothing.

{"kind":"network", ...} emits the line-model JSON document that every reader in the project already takes, so the generated model round-trips through -f and through load_model in R and Python without a second format. {"kind":"layered", ...} emits the .lqnx document instead, because that is the only interchange the layered readers all share; it is plain text on standard output rather than a collected JSON document, since an XML string is not one.

THE ARITHMETIC IS ALWAYS double. Both generators draw from java.util.Random, whose output is a double by definition, so generating at --arith exact would fabricate an exactness the draw never had. A caller who wants the model solved in another arithmetic reads it back with that –arith.

Definition at line 12012 of file line_cli.cpp.

References line::lqn::LqnBuilder< T >::build(), line::gen::Cyclic, line::gen::LayeredNetworkGenerator< T >::generate(), line::gen::NetworkGenerator< T >::generate(), line::qn::Network< T >::get_struct(), line::lqn::lqnx_to_string(), line::lqn::LqnBuilder< T >::model(), line::gen::LayeredNetworkGenerator< T >::model_name(), line::io::network_json_envelope(), line::gen::Rand, run_generate(), line::gen::NetworkGenerator< T >::set_cclass_job_load(), line::gen::NetworkGenerator< T >::set_distribution(), line::gen::LayeredNetworkGenerator< T >::set_host_demand_range(), line::gen::LayeredNetworkGenerator< T >::set_model_name(), line::gen::NetworkGenerator< T >::set_model_name(), line::gen::NetworkGenerator< T >::set_multi_chain_cs(), line::gen::NetworkGenerator< T >::set_multi_server_queues(), line::gen::LayeredNetworkGenerator< T >::set_population_range(), line::gen::LayeredNetworkGenerator< T >::set_proc_inf_probability(), line::gen::LayeredNetworkGenerator< T >::set_proc_multi_range(), line::gen::NetworkGenerator< T >::set_random_cs_nodes(), line::gen::NetworkGenerator< T >::set_routing_strat(), line::gen::NetworkGenerator< T >::set_sched_strat(), line::gen::LayeredNetworkGenerator< T >::set_seed(), line::gen::NetworkGenerator< T >::set_seed(), line::gen::LayeredNetworkGenerator< T >::set_synch_call_range(), line::gen::LayeredNetworkGenerator< T >::set_task_inf_probability(), line::gen::LayeredNetworkGenerator< T >::set_task_multi_range(), line::gen::LayeredNetworkGenerator< T >::set_think_time_range(), line::gen::NetworkGenerator< T >::set_topology(), and line::gen::NetworkGenerator< T >::set_varying_service_rates().

Referenced by dispatch(), and run_generate().

◆ run_invocation()

◆ run_invocation_captured()

std::string run_invocation_captured ( Options o,
int & rc )

Run one invocation with stdout captured, and return what it printed.

SERVER MODE'S ONE PIECE OF MACHINERY. Every arm of this CLI writes its answer with printf, which is the right thing for a command-line tool and leaves a server nothing to send. Redirecting fd 1 around the call means the arms need no server-aware variant and cannot drift from the command-line behaviour; stderr is deliberately NOT captured, so a warning still reaches the operator's console rather than being folded into the client's answer.

Definition at line 11871 of file line_cli.cpp.

References FdCapture::active(), run_invocation(), run_invocation_captured(), and FdCapture::take().

Referenced by run_invocation_captured(), and run_server().

◆ run_server()

int run_server ( const Options & base)

-p/--port: serve solve requests over a WebSocket, as LineWebSocketServer does.

THE PROTOCOL IS THE JAR's, unchanged: one text message per connection, whose FIRST LINE is the comma-separated argument list and whose remainder is the model document. The JAR overwrites the first two arguments with --file and the path it staged the document at, so the client's own first two tokens are placeholders; the same substitution happens here, which is what lets an existing client talk to this server without knowing which binary answered.

Definition at line 11909 of file line_cli.cpp.

References run_invocation_captured(), run_server(), and line::ws::Server::serve_one().

Referenced by dispatch(), and run_server().