diff --git a/.vscode/launch.json b/.vscode/launch.json index bebac72505c..8117283bbde 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,25 +19,6 @@ "ignoreFailures": true } ] - }, - { - "name": "(gdb) traffic_manager", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/${env:ATS_VSCODE_BUILDDIR}/src/traffic_manager/.libs/traffic_manager", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] } ] } diff --git a/CMakeLists.txt b/CMakeLists.txt index 918ff24e1c5..76a45a1136a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,6 @@ CC_EXEC(traffic_ctl src/traffic_ctl) CC_EXEC(traffic_layout src/traffic_layout) CC_EXEC(traffic_logcat src/traffic_logcat) CC_EXEC(traffic_logstats src/traffic_logstats) -CC_EXEC(traffic_manager src/traffic_manager) CC_EXEC(traffic_server src/traffic_server) target_sources(traffic_server PRIVATE src/shared/overridable_txn_vars.cc) CC_EXEC(traffic_top src/traffic_top) diff --git a/Makefile.am b/Makefile.am index 7ead576fcec..219c3d6d7c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,7 @@ export CCACHE_BASEDIR # and mgmt, hence we have to build proxy/hdrs first. # depends on the generates ts/ts.h include file. -SUBDIRS = include src/tscpp/util lib src/tscore iocore proxy mgmt mgmt2 src plugins tools example rc configs tests +SUBDIRS = include src/tscpp/util lib src/tscore iocore proxy mgmt src plugins tools example rc configs tests if BUILD_DOCS SUBDIRS += doc include @@ -156,7 +156,6 @@ clang-format-lib: clang-format-mgmt: @$(top_srcdir)/tools/clang-format.sh $(top_srcdir)/mgmt - @$(top_srcdir)/tools/clang-format.sh $(top_srcdir)/mgmt2 clang-format-plugins: @$(top_srcdir)/tools/clang-format.sh $(top_srcdir)/plugins diff --git a/README b/README index dee536d71a2..82a6f05cd46 100644 --- a/README +++ b/README @@ -29,10 +29,10 @@ plugins to build large scale web applications. |-- quic/ ......... QUIC implementation |-- utils/ ............ Utilities |-- lib/ .................. - |-- perl/ ............. Perl libraries for e.g. mgmt access and configurations + |-- perl/ ............. Perl libraries for configurations |-- records/ .......... Library for config files |-- yamlcpp/ .......... Library for YAML of C++ - |-- mgmt/ ................. Management server and tools + |-- mgmt/ ................. JSONRPC server/management and tools |-- plugins/ .............. Stable core plugins |-- experimental/ ..... Experimental core plugins |-- proxy/ ................ HTTP proxy logic @@ -50,7 +50,6 @@ plugins to build large scale web applications. |-- traffic_layout/ ... Display information on the build and runtime directory structure |-- traffic_logcat/ ... Convert binary log file to plain text |-- traffic_logstats/ . Log parsing and metrics calculation utility - |-- traffic_manager/ .. The manager process for Traffic Server |-- traffic_server/ ... Main proxy server |-- traffic_top/ ...... Top like tool for viewing Traffic Server statistics |-- traffic_via/ ...... Tool for decoding the Traffic Server Via header codes diff --git a/ci/jenkins/ats_conf.pl b/ci/jenkins/ats_conf.pl index 38c73093ed6..2d5599b405e 100755 --- a/ci/jenkins/ats_conf.pl +++ b/ci/jenkins/ats_conf.pl @@ -27,7 +27,6 @@ $recedit->append(line => ""); $recedit->append(line => "# My local stuff"); -$recedit->append(line => "CONFIG proxy.config.proxy_binary_opts STRING -M --disable_freelist"); #$recedit->append(line => "CONFIG proxy.config.crash_log_helper STRING /home/admin/bin/invoker_wrap.sh"); # Port setup diff --git a/configure.ac b/configure.ac index cedeadaef0a..acecbf0eba3 100644 --- a/configure.ac +++ b/configure.ac @@ -554,18 +554,6 @@ AC_ARG_ENABLE([example-plugins], AC_MSG_RESULT([$enable_example_plugins]) AM_CONDITIONAL([BUILD_EXAMPLE_PLUGINS], [ test "x${enable_example_plugins}" = "xyes" ]) -# -# JSONRPC 2.0 build options. -# -AC_MSG_CHECKING([whether to build & install non jsonrpc traffic_ctl]) -AC_ARG_ENABLE([legacy-traffic_ctl], - [AS_HELP_STRING([--enable-legacy-traffic_ctl],[build and install legacy traffic_ctl. No jsonrpc will be supported through traffic_ctl])], - [], - [enable_legacy_tc=no] -) -AC_MSG_RESULT([$enable_legacy_tc]) -AM_CONDITIONAL([BUILD_LEGACY_TC], [ test "x${enable_legacy_tc}" = "xyes" ]) - # # Test tools. The test tools are always built, but not always installed. Installing # them is useful for QA, but not useful for most users, so we default this to disabled. @@ -2338,10 +2326,9 @@ AC_CONFIG_FILES([ mgmt/api/Makefile mgmt/api/include/Makefile mgmt/utils/Makefile + mgmt/rpc/Makefile + mgmt/config/Makefile plugins/Makefile - mgmt2/Makefile - mgmt2/rpc/Makefile - mgmt2/config/Makefile proxy/Makefile proxy/hdrs/Makefile proxy/http/Makefile diff --git a/contrib/install_trafficserver.sh b/contrib/install_trafficserver.sh index 528ccf85969..8da53cd49be 100644 --- a/contrib/install_trafficserver.sh +++ b/contrib/install_trafficserver.sh @@ -66,7 +66,6 @@ SLACKWARE="slackware" function killAll() { killall traffic_cop - killall traffic_manager killall traffic_server } diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 881b9ec71f8..23500c422c5 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -152,7 +152,7 @@ not be affected by future configuration changes made in For example, we could override the `proxy.config.product_company`_ variable like this:: - $ PROXY_CONFIG_PRODUCT_COMPANY=example traffic_manager & + $ PROXY_CONFIG_PRODUCT_COMPANY=example traffic_server & $ traffic_ctl config get proxy.config.product_company .. _configuration-variables: @@ -189,25 +189,21 @@ System Variables .. ts:cv:: CONFIG proxy.config.proxy_binary STRING traffic_server - The name of the executable that runs the :program:`traffic_server` process. + .. important:: - If you want to set Environment Variables for :program:`traffic_server` process, use a wrapper script like below. :: - - CONFIG proxy.config.proxy_binary STRING start_traffic_server.sh - - :: - - #!/bin/sh - export ASAN_OPTIONS=detect_leaks=1 - /opt/ats/bin/traffic_server "$@" + This is now deprecated. traffic_manager is no longer supported. .. ts:cv:: CONFIG proxy.config.proxy_binary_opts STRING -M - The :ref:`command-line options ` for starting |TS|. + .. important:: + + This is now deprecated .. ts:cv:: CONFIG proxy.config.manager_binary STRING traffic_manager - The name of the executable that runs the :program:`traffic_manager` process. + .. important:: + + This is now deprecated. traffic_manager is no longer supported. .. ts:cv:: CONFIG proxy.config.memory.max_usage INT 0 :units: bytes @@ -217,8 +213,9 @@ System Variables .. ts:cv:: CONFIG proxy.config.env_prep STRING - The script executed before the :program:`traffic_manager` process spawns - the :program:`traffic_server` process. + .. important:: + + This is now deprecated. traffic_manager is no longer supported. .. ts:cv:: CONFIG proxy.config.syslog_facility STRING LOG_DAEMON @@ -231,7 +228,7 @@ System Variables This is used for log rolling configuration so |TS| knows the path of the output file that should be rolled. This configuration takes the name of the - file receiving :program:`traffic_server` and :program:`traffic_manager` + file receiving :program:`traffic_server` process output that is set via the ``--bind_stdout`` and ``--bind_stderr`` :ref:`command-line options `. :ts:cv:`proxy.config.output.logfile` is used only to identify the name of @@ -389,8 +386,9 @@ Thread Variables .. ts:cv:: CONFIG proxy.config.restart.active_client_threshold INT 0 :reloadable: - This setting specifies the number of active client connections - for use by :option:`traffic_ctl server restart --drain`. + .. important:: + + Deprecated. traffic_manager is no longer supported. .. ts:cv:: CONFIG proxy.config.restart.stop_listening INT 0 :reloadable: @@ -556,16 +554,14 @@ Network When we trigger a throttling scenario, this how long our accept() are delayed. -Local Manager -============= +Management +========== .. ts:cv:: CONFIG proxy.node.config.manager_log_filename STRING manager.log - The name of the file to which :program:`traffic_manager` logs will be emitted. - - If this is set to ``stdout`` or ``stderr``, then all :program:`traffic_manager` - logging will go to the stdout or stderr stream, respectively. + .. important:: + This is now deprecated. traffic_manager is no longer supported. .. ts:cv:: CONFIG proxy.config.admin.user_id STRING nobody @@ -591,31 +587,8 @@ Local Manager .. ts:cv:: CONFIG proxy.config.admin.api.restricted INT 0 - This setting specifies whether the management API should be restricted to - root processes. If this is set to ``0``, then on platforms that support - passing process credentials, non-root processes will be allowed to make - read-only management API calls. Any management API calls that modify server - state (eg. setting a configuration variable) will still be restricted to - root processes. - - This setting is not reloadable, since it is must be applied when - :program:`traffic_manager` initializes. - -.. ts:cv:: CONFIG proxy.node.config.manager_exponential_sleep_ceiling INT 60 - - In case of :program:`traffic_manager` is unable to start :program:`traffic_server`, - this setting specifies the maximum amount of seconds that the :program:`traffic_manager` - process should wait until it tries again to restart :program:`traffic_server`. - In case of :program:`traffic_manager` failing to start :program:`traffic_server`, it will - retry exponentially until it reaches the ceiling time. - -.. ts:cv:: CONFIG proxy.node.config.manager_retry_cap INT 5 - - This setting specifies the number of times that :program:`traffic_manager` will retry - to restart :program:`traffic_server` once the maximum ceiling time is reached. - -.. note:: - If set to ``0``, no cap will take place. + This is now deprecated, please refer to :ref:`admin-jsonrpc-configuration` to find + out about the new admin API mechanism. Alarm Configuration =================== @@ -4654,7 +4627,7 @@ SOCKS Processor Enables (1) or disables (0) the SOCKS proxy option. As a SOCKS proxy, |TS| receives SOCKS traffic (usually on port - 1080) and forwards all requests directly to the SOCKS server. + 1) and forwards all requests directly to the SOCKS server. .. ts:cv:: CONFIG proxy.config.socks.accept_port INT 1080 diff --git a/doc/admin-guide/installation/index.en.rst b/doc/admin-guide/installation/index.en.rst index fed6f8a4593..20dce5c220b 100644 --- a/doc/admin-guide/installation/index.en.rst +++ b/doc/admin-guide/installation/index.en.rst @@ -226,7 +226,7 @@ Stop Traffic Server To stop Traffic Server, always use the :program:`trafficserver` command, passing in the attribute ``stop``. This command stops all the Traffic -Server processes (:program:`traffic_manager` and :program:`traffic_server`). +Server processes (:program:`traffic_server`). Do not manually stop processes, as this can lead to unpredictable results. :: bin/trafficserver stop diff --git a/doc/admin-guide/introduction.en.rst b/doc/admin-guide/introduction.en.rst index 25d5c79f3ba..c988ba18af0 100644 --- a/doc/admin-guide/introduction.en.rst +++ b/doc/admin-guide/introduction.en.rst @@ -165,28 +165,14 @@ bindings in memory, DNS traffic is reduced. |TS| Processes -------------- -|TS| contains two processes that work together to serve -requests and manage, control, and monitor the health of the system. +|TS| contains a single processes to serve requests, manage administrative +calls(JSONRPC) and handle configuration. #. The :program:`traffic_server` process is the transaction processing engine of |TS|. It is responsible for accepting connections, processing protocol requests, and serving documents from the cache or origin server. -#. The :program:`traffic_manager` process is the command and control facility - of the |TS|, responsible for launching, monitoring, and - reconfiguring the :program:`traffic_server` process. The :program:`traffic_manager` - process is also responsible for the proxy autoconfiguration port, the - statistics interface, and virtual IP failover. - - If the :program:`traffic_manager` process detects a :program:`traffic_server` - process failure, it instantly restarts the process but also maintains - a connection queue of all incoming requests. All incoming connections - that arrive in the several seconds before full server restart are - saved in the connection queue and processed in first-come, - first-served order. This connection queueing shields users from any - server restart downtime. - Administration Tools -------------------- @@ -201,9 +187,9 @@ Administration Tools changes you make through :program:`traffic_ctl` are automatically made to the configuration files as well. -- Finally, there is a clean C API which can be put to good use from a - multitude of languages. The |TS| Admin Client demonstrates - this for Perl. +- Finally, there is a JSONRPC 2.0 interface which provides access to the JSONRPC 2.0 + Administrative endpoint which allow you to implement your own tool by just using + JSON or YAML. Check :ref:`jsonrpc-node` for more information. Traffic Analysis Options ======================== diff --git a/doc/admin-guide/logging/understanding.en.rst b/doc/admin-guide/logging/understanding.en.rst index b789315068a..1544be9668e 100644 --- a/doc/admin-guide/logging/understanding.en.rst +++ b/doc/admin-guide/logging/understanding.en.rst @@ -82,8 +82,7 @@ specifies where these messages are logged. A typical location is ``/var/log/messages`` (Linux). The :manpage:`syslog(8)` process works on a system-wide basis, so it serves as -the single repository for messages from all |TS| processes (including -:program:`traffic_server` and :program:`traffic_manager`). +the single repository for messages from |TS| process (:program:`traffic_server`). System information logs observe a static format. Each log entry in the log contains information about the date and time the error was logged, the hostname diff --git a/doc/admin-guide/monitoring/error-messages.en.rst b/doc/admin-guide/monitoring/error-messages.en.rst index 94225695423..6aa414fb7b2 100644 --- a/doc/admin-guide/monitoring/error-messages.en.rst +++ b/doc/admin-guide/monitoring/error-messages.en.rst @@ -118,11 +118,6 @@ Alarm Messages Check your custom log configuration file; there could be syntax errors. Refer to :ref:`admin-logging-fields` for correct custom log format fields. -``vip_config binary is not setuid root, manager will be unable to enable virtual ip addresses`` - The :program:`traffic_manager` process is not able to set virtual IP - addresses. You must ``setuid root`` for the ``vip_config`` file in - the Traffic Server ``bin`` directory. - .. _body-factory: HTML Messages Sent to Clients diff --git a/doc/admin-guide/monitoring/statistics/core/general.en.rst b/doc/admin-guide/monitoring/statistics/core/general.en.rst index 7ead32c2a84..01446038ea6 100644 --- a/doc/admin-guide/monitoring/statistics/core/general.en.rst +++ b/doc/admin-guide/monitoring/statistics/core/general.en.rst @@ -34,6 +34,8 @@ General .. ts:stat:: global proxy.node.config.restart_required.manager integer :type: flag + This metric is now deprecated. traffic_manager is no longer supported. + .. ts:stat:: global proxy.node.config.restart_required.proxy integer :type: flag @@ -55,8 +57,7 @@ General :type: gauge :units: seconds - Unix epoch-time value indicating the time at which the currently-running - :program:`traffic_manager` process was started. + This metric is now deprecated. traffic_manager is no longer supported. .. ts:stat:: global proxy.node.restarts.proxy.cache_ready_time integer :type: gauge @@ -66,13 +67,6 @@ General .. ts:stat:: global proxy.node.restarts.proxy.start_time integer .. ts:stat:: global proxy.node.restarts.proxy.stop_time integer .. ts:stat:: global proxy.process.user_agent_total_bytes integer -.. ts:stat:: global proxy.node.version.manager.build_date string -.. ts:stat:: global proxy.node.version.manager.build_machine string -.. ts:stat:: global proxy.node.version.manager.build_number integer -.. ts:stat:: global proxy.node.version.manager.build_person string -.. ts:stat:: global proxy.node.version.manager.build_time string -.. ts:stat:: global proxy.node.version.manager.long string -.. ts:stat:: global proxy.node.version.manager.short float .. ts:stat:: global proxy.process.http.tunnels integer .. ts:stat:: global proxy.process.update.fails integer .. ts:stat:: global proxy.process.update.no_actions integer diff --git a/doc/admin-guide/security/index.en.rst b/doc/admin-guide/security/index.en.rst index d93b918f739..97ddb6c92c6 100644 --- a/doc/admin-guide/security/index.en.rst +++ b/doc/admin-guide/security/index.en.rst @@ -150,7 +150,7 @@ Client/|TS| connections, you must do the following: CONFIG proxy.config.ssl.CA.cert.path STRING /opt/CA/certs/private-ca.pem -#. Run the command :option:`traffic_ctl server restart` to restart |TS|. +#. Restart Traffic Server. .. _traffic-server-and-origin-server-connections: @@ -235,7 +235,7 @@ and origin server connections, you must do the following: CONFIG proxy.config.ssl.client.CA.cert.path STRING /opt/ts/etc/ssl/certs/ CONFIG proxy.config.ssl.client.CA.cert.filename STRING CAs.pem -#. Run the command :option:`traffic_ctl server restart` to restart |TS|. +#. Restart Traffic Server. :doc:`mtls.en` ============== diff --git a/doc/appendices/command-line/traffic_ctl.en.rst b/doc/appendices/command-line/traffic_ctl.en.rst index 644ffcbbae2..19d250f0299 100644 --- a/doc/appendices/command-line/traffic_ctl.en.rst +++ b/doc/appendices/command-line/traffic_ctl.en.rst @@ -13,7 +13,12 @@ .. include:: ../../common.defs -.. _traffic_ctl: +.. |RPC| replace:: JSONRPC 2.0 + +.. _JSONRPC: https://www.jsonrpc.org/specification +.. _JSON: https://www.json.org/json-en.html + +.. _traffic_ctl_jsonrpc: traffic_ctl *********** @@ -23,17 +28,19 @@ Synopsis :program:`traffic_ctl` [OPTIONS] SUBCOMMAND [OPTIONS] -.. _traffic-ctl-commands: + +.. important:: + + :program:`traffic_ctl` uses a `JSONRPC`_ protocol to communicate with :program:`traffic_server`. Description =========== -:program:`traffic_ctl` is used to display and manipulate configure +:program:`traffic_ctl` is used to display, manipulate and configure a running Traffic Server. :program:`traffic_ctl` includes a number of subcommands that control different aspects of Traffic Server: -:program:`traffic_ctl alarm` - Display and manipulate Traffic Server alarms + :program:`traffic_ctl config` Manipulate and display configuration records :program:`traffic_ctl metric` @@ -46,8 +53,11 @@ of subcommands that control different aspects of Traffic Server: Interact with plugins. :program:`traffic_ctl host` Manipulate host status. parents for now but will be expanded to origins. +:program:`traffic_ctl rpc` + Interact directly with the |RPC| server in |TS| + + -To use :program:`traffic_ctl`, :ref:`traffic_manager` needs to be running. Options ======= @@ -61,34 +71,81 @@ Options Print version information and exit. +.. option:: -f, --format + + Specify the output print style. + + =================== ======================================================================== + Options Description + =================== ======================================================================== + ``legacy`` Will honour the old :program:`traffic_ctl` output messages. This is the default format type. + ``pretty`` will print a different output, a prettier output. This depends on the implementation, + it's not required to always implement a pretty output + ``json`` It will show the response message formatted to `JSON`_ This is ideal if you want to redirect the stdout to a different source. + It will only stream the json response, no other messages. + ``data:`` This is an addon to the default format style, data can be: ``{req|resp|all}`` which will make :program:`traffic_ctl` + to print in json format the request or response or both. + =================== ======================================================================== + + In case of a record request(config) ``--records`` overrides this flag. + + Default: ``legacy`` + + Example: + + .. code-block:: + + traffic_ctl config get variable --format data:req + --> {request} + + .. code-block:: + + $ traffic_ctl config get variable --format data:resp + <-- {response} + + .. code-block:: + + $ traffic_ctl config get variable --format data:all + --> {request} + <-- {response} + + .. code-block:: + + $ traffic_ctl config get variable --format json + {response} + + There will be no print out beside the json response. This is ideal to redirect to a file. + + +.. option:: --records + + Option available only for records request. + +.. option:: --run-root + + Path to the runroot file. + Subcommands =========== +.. _traffic-control-command-alarm: + traffic_ctl alarm ----------------- -.. program:: traffic_ctl alarm -.. option:: list - - List all alarm events that have not been acknowledged (cleared). -.. program:: traffic_ctl alarm -.. option:: clear +.. warning:: - Clear (acknowledge) all current alarms. + Option not available in the |RPC| version. -.. program:: traffic_ctl alarm -.. option:: resolve ALARM [ALARM...] - - Clear (acknowledge) an alarm event. The arguments are a specific - alarm number (e.g. ''1''), or an alarm string identifier (e.g. - ''MGMT_ALARM_PROXY_CONFIG_ERROR''). +.. _traffic-control-command-config: traffic_ctl config ------------------ + .. program:: traffic_ctl config .. option:: defaults [--records] - Display the default values for all configuration records. The --records* flag has the same + Display the default values for all configuration records. The ``--records`` flag has the same behavior as :option:`traffic_ctl config get --records`. .. program:: traffic_ctl config @@ -97,10 +154,12 @@ traffic_ctl config Display all the known information about a configuration record. This includes the current and default values, the data type, the record class and syntax checking expression. + Error output available if ``--format pretty`` is specified. + .. program:: traffic_ctl config .. option:: diff [--records] - Display configuration records that have non-default values. The --records* flag has the same + Display configuration records that have non-default values. The ``--records`` flag has the same behavior as :option:`traffic_ctl config get --records`. .. program:: traffic_ctl config @@ -108,6 +167,8 @@ traffic_ctl config Display the current value of a configuration record. + Error output available if ``--format pretty`` is specified. + .. program:: traffic_ctl config get .. option:: --records @@ -118,7 +179,7 @@ traffic_ctl config .. option:: match [--records] REGEX [REGEX...] Display the current values of all configuration variables whose names match the given regular - expression. The *--records* flag has the same behavior as :option:`traffic_ctl config get + expression. The ``--records`` flag has the same behavior as :option:`traffic_ctl config get --records`. .. program:: traffic_ctl config @@ -145,14 +206,23 @@ traffic_ctl config information, whether the internal configuration store is current and whether any daemon processes should be restarted. -.. _traffic-ctl-metric: +.. program:: traffic_ctl config +.. option:: registry + + Display information about the registered files in |TS|. This includes the full file path, config record name, parent config (if any) + if needs root access and if the file is required in |TS|. This command uses :ref:`filemanager.get_files_registry` + + +.. _traffic-control-command-metric: traffic_ctl metric ------------------ .. program:: traffic_ctl metric .. option:: get METRIC [METRIC...] - Display the current value of the specifies statistics. + Display the current value of the specified statistics. + + Error output available if ``--format pretty`` is specified. .. program:: traffic_ctl metric .. option:: match REGEX [REGEX...] @@ -165,55 +235,30 @@ traffic_ctl metric Reset the named statistics to zero. -traffic_ctl server ------------------- -.. program:: traffic_ctl server -.. option:: restart - - Shut down and immediately restart Traffic Server - -.. program:: traffic_ctl server restart -.. option:: --drain +.. program:: traffic_ctl metric +.. option:: describe RECORD [RECORD...] - This option modifies the behavior of :option:`traffic_ctl server restart` such that - :program:`traffic_server` is not shut down until the number of active client connections drops to - the number given by the :ts:cv:`proxy.config.restart.active_client_threshold` configuration - variable. + Display all the known information about a metric record. -.. option:: --manager + Error output available if ``--format pretty`` is specified. - The default behavior of :option:`traffic_ctl server restart` is to restart - :program:`traffic_server`. If this option is specified, :program:`traffic_manager` is also - restarted. +.. _traffic-control-command-server: +traffic_ctl server +------------------ .. program:: traffic_ctl server -.. option:: start - - Start :program:`traffic_server` if it is already running. - -.. program:: traffic_ctl server start -.. option:: --clear-cache - - Clear the disk cache upon startup. - -.. option:: --clear-hostdb - - Clear the DNS resolver cache upon startup. .. program:: traffic_ctl server -.. option:: status +.. option:: drain - Show the current proxy server status, indicating if we're running or not. + Drop the number of active client connections.{ .. program:: traffic_ctl server -.. option:: stop - - Stop the running :program:`traffic_server` process. +.. option:: status -.. program:: traffic_ctl server -.. option:: backtrace + Option not yet available - Show a full stack trace of all the :program:`traffic_server` threads. +.. _traffic-control-command-storage: traffic_ctl storage ------------------- @@ -226,18 +271,20 @@ traffic_ctl storage effect as a disk failure for that storage. This does not persist across restarts of the :program:`traffic_server` process. +.. _traffic-control-command-plugin: + traffic_ctl plugin ------------------- .. program:: traffic_ctl plugin .. option:: msg TAG DATA Send a message to plugins. All plugins that have hooked the - :cpp:enumerator:`TSLifecycleHookID::TS_LIFECYCLE_MSG_HOOK` will receive a callback for that hook. + ``TSLifecycleHookID::TS_LIFECYCLE_MSG_HOOK`` will receive a callback for that hook. The :arg:`TAG` and :arg:`DATA` will be available to the plugin hook processing. It is expected that plugins will use :arg:`TAG` to select relevant messages and determine the format of the - :arg:`DATA`. The :arg:`DATA` is optional and may not be available to consume, if not available then size will be 0 - and the data will be NULL. Any extra passed value beside the tag and the optional data will be ignored. - Check :c:type:`TSPluginMsg` for more info. + :arg:`DATA`. + +.. _traffic-control-command-host: traffic_ctl host ---------------- @@ -302,32 +349,211 @@ endpoint. Supports :option:`--reason`. +.. _traffic_ctl_rpc: + +traffic_ctl rpc +--------------- +.. program:: traffic_ctl rpc + +A mechanism to interact directly with the |TS| |RPC| endpoint. This means that this is not tied to any particular API +but rather to the rpc endpoint, so you can directly send requests and receive responses from the server. + +.. option:: file + + Reads a file or a set of files from the disc, use the content of the files as message(s) to the |RPC| endpoint. All jsonrpc messages + will be validated before sending them. If the file contains invalid json|yaml format the message will not be send, in + case of a set of files, if a particular file is not a proper json/yaml format then that particular file will be skipped. + + Example: + + .. code-block:: bash + + traffic_ctl rpc file jsonrpc_cmd1.json jsonrpc_cmd2.yaml + +.. option:: get-api + + Request the entire admin api. This will retrieve all the registered methods and notifications on the server side. + + Example: + + .. code-block:: bash + + $ traffic_ctl rpc get-api + Methods: + - admin_host_set_status + - admin_server_stop_drain + - admin_server_start_drain + - admin_clear_metrics_records + - admin_clear_all_metrics_records + - admin_plugin_send_basic_msg + - admin_lookup_records + - admin_config_set_records + - admin_storage_get_device_status + - admin_storage_set_device_offline + - admin_config_reload + - show_registered_handlers + Notifications: + - some_registered_notification_handler + + +.. option:: input + + Input mode, traffic_ctl will provide a control input from a stream buffer. Once the content is written the terminal :program:`traffic_ctl` + will wait for the user to press Control-D to send the request to the rpc endpoint. + This feature allows you to directly interact with the jsonrpc endpoint and test your API easily and without the need to know the low level + implementation details of the transport layer. + :program:`traffic_ctl` will validate the input format, not the message content. The message content will be validated by the server. + See example `input_example_2`_. + + .. option:: --raw, -r + + No json/yaml parse validation will take place, the input content will be directly send to the server. + + Example: + + .. code-block:: + + $ traffic_ctl rpc input + >> Ctrl-D to fire the request + { + "id":"86e59b43-185b-4a0b-b1c1-babb1a3d5401", + "jsonrpc":"2.0", + "method":"admin_lookup_records", + "params":[ + { + "record_name":"proxy.config.diags.debug.tags", + "rec_types":[ + "1", + "16" + ] + } + ] + } + + + <-- Server's response. + { + "jsonrpc":"2.0", + "result":{ + "recordList":[ + { + "record":{ + "record_name":"proxy.config.diags.debug.tags", + "record_type":"3", + "version":"0", + "raw_stat_block":"0", + "order":"423", + "config_meta":{ + "access_type":"0", + "update_status":"0", + "update_type":"1", + "checktype":"0", + "source":"3", + "check_expr":"null" + }, + "record_class":"1", + "overridable":"false", + "data_type":"STRING", + "current_value":"rpc", + "default_value":"http|dns" + } + } + ] + }, + "id":"86e59b43-185b-4a0b-b1c1-babb1a3d5401" + } + + +.. _input_example_2: + + Example 2: + + You can see a valid json ``{}`` but an invalid |RPC| message. In this case the server is responding. + + .. code-block:: + + $ traffic_ctl rpc input + >> Ctrl-D to fire the request + {} + + < -- Server's response + { + "jsonrpc":"2.0", + "error":{ + "code":-32600, + "message":"Invalid Request" + } + } + Examples ======== Mark down a host with `traffic_ctl` and view the associated host stats:: - $ traffic_ctl host down cdn-cache-02.foo.com --reason manual + .. code-block:: bash - $ /opt/trafficserver/bin/traffic_ctl metric match host_status - proxy.process.host_status.cdn-cache-01.foo.com HOST_STATUS_DOWN,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:DOWN:1556896844:0,SELF_DETECT:UP:0 - proxy.process.host_status.cdn-cache-02.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 - proxy.process.host_status.cdn-cache-origin-01.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 + # traffic_ctl host down cdn-cache-02.foo.com --reason manual + + # traffic_ctl metric match host_status + proxy.process.host_status.cdn-cache-01.foo.com HOST_STATUS_DOWN,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:DOWN:1556896844:0,SELF_DETECT:UP:0 + proxy.process.host_status.cdn-cache-02.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 + proxy.process.host_status.cdn-cache-origin-01.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 In the example above, 'cdn-cache-01.foo.com' is unavailable, `HOST_STATUS_DOWN` and was marked down for the `manual` reason, `MANUAL:DOWN:1556896844:0`, at the time indicated by the UNIX time stamp -`1556896844`. To make the host available, one would have to clear the `manual` reason using :: +`1556896844`. To make the host available, one would have to clear the `manual` reason using: + + .. code-block:: bash + + # traffic_ctl host up cdn-cache-01.foo.com --reason manual + +Configure Traffic Server to insert ``Via`` header in the response to the client + + .. code-block:: bash + + # traffic_ctl config set proxy.config.http.insert_response_via_str 1 + # traffic_ctl config reload + +Autest +====== + +If you want to interact with |TS| under a unit test, then a few things need to be considered. + +- Runroot needs to be configured in order to let `traffic_ctl` knows where to find the socket. + + There are currently two ways to do this: + + 1. Using `run-root` param. + + 1. Let `Test.MakeATSProcess` to create the runroot file under the |TS| config directory. This can be done by passing `dump_runroot=True` to the above function: + + .. code-block:: python + + ts = Test.MakeATSProcess(..., dump_runroot=True) + + + `dump_runroot` will write out some of the keys inside the runroot file, in this case the `runtimedir`. + + 2. Then you should specify the :option:`traffic_ctl --run-root` when invoking the command: + + .. code-block:: python + + tr.Processes.Default.Command = f'traffic_ctl config reload --run-root {ts.Disk.runroot_yaml.Name}' + + 2. Setting up the `TS_RUNROOT` environment variable. + This is very similar to `1` but, instead of passing the `--run-root` param to `traffic_ctl`, you just need to specify the + `TS_RUNROOT` environment variable. To do that, just do as 1.1 shows and then: - $ traffic_ctl host up cdn-cache-01.foo.com --reason manual + .. code-block:: python -Configure Traffic Server to insert ``Via`` header in the response to -the client:: + ts.SetRunRootEnv() - $ traffic_ctl config set proxy.config.http.insert_response_via_str 1 - $ traffic_ctl config reload + The above call will set the variable, please be aware that this variable will also be read by TS. See also ======== :manpage:`records.config(5)`, -:manpage:`storage.config(5)` +:manpage:`storage.config(5)`, +:ref:`admin-jsonrpc-configuration`, +:ref:`jsonrpc-protocol` diff --git a/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst b/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst deleted file mode 100644 index 94f0e5667fd..00000000000 --- a/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst +++ /dev/null @@ -1,608 +0,0 @@ -.. Licensed to the Apache Software Foundation (ASF) under one or more contributor license - agreements. See the NOTICE file distributed with this work for additional information regarding - copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the License - is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - or implied. See the License for the specific language governing permissions and limitations - under the License. - -.. include:: ../../common.defs - -.. |RPC| replace:: JSONRPC 2.0 - -.. _JSONRPC: https://www.jsonrpc.org/specification -.. _JSON: https://www.json.org/json-en.html - -.. _traffic_ctl_jsonrpc: - -traffic_ctl -*********** - -Synopsis -======== - -:program:`traffic_ctl` [OPTIONS] SUBCOMMAND [OPTIONS] - - -.. note:: - - :program:`traffic_ctl` now uses a `JSONRPC`_ endpoint instead of ``traffic_manager``. ``traffic_manager`` is not - required. To build this version of :program:`traffic_ctl` ``--enable-jsonrpc-tc`` should be passed when configure the build. - -Description -=========== - -:program:`traffic_ctl` is used to display,manipulate and configure -a running Traffic Server. :program:`traffic_ctl` includes a number -of subcommands that control different aspects of Traffic Server: - - -:program:`traffic_ctl config` - Manipulate and display configuration records -:program:`traffic_ctl metric` - Manipulate performance and status metrics -:program:`traffic_ctl server` - Stop, restart and examine the server -:program:`traffic_ctl storage` - Manipulate cache storage -:program:`traffic_ctl plugin` - Interact with plugins. -:program:`traffic_ctl host` - Manipulate host status. parents for now but will be expanded to origins. -:program:`traffic_ctl rpc` - Interact directly with the |RPC| server in |TS| - - - - -Options -======= - -.. program:: traffic_ctl -.. option:: --debug - - Enable debugging output. - -.. option:: -V, --version - - Print version information and exit. - -.. option:: -f, --format - - Specify the output print style. - - =================== ======================================================================== - Options Description - =================== ======================================================================== - ``legacy`` Will honour the old :program:`traffic_ctl` output messages. This is the default format type. - ``pretty`` will print a different output, a prettier output. This depends on the implementation, - it's not required to always implement a pretty output - ``json`` It will show the response message formatted to `JSON`_. This is ideal if you want to redirect the stdout to a different source. - It will only stream the json response, no other messages. - ``rpc`` Show the JSONRPC request and response + the default output. - =================== ======================================================================== - - In case of a record request(config) ``--records`` overrides this flag. - - Default: ``legacy`` - - Example: - - .. code-block:: - - $ traffic_ctl config get variable --format rpc - --> {request} - <-- {response} - variable 1234 - - .. code-block:: - - $ traffic_ctl config get variable --format json - {response} - - There will be no print out beside the json response. This is ideal to redirect to a file. - - -.. option:: --records - - Option available only for records request. - -.. option:: --run-root - - Path to the runroot file. - -Subcommands -=========== - -.. _traffic-control-command-alarm: - -traffic_ctl alarm ------------------ - -.. warning:: - - Option not available in the |RPC| version. - -.. _traffic-control-command-config: - -traffic_ctl config ------------------- - -.. program:: traffic_ctl config -.. option:: defaults [--records] - - :ref:`admin_lookup_records` - - Display the default values for all configuration records. The ``--records`` flag has the same - behavior as :option:`traffic_ctl config get --records`. - -.. program:: traffic_ctl config -.. option:: describe RECORD [RECORD...] - - :ref:`admin_lookup_records` - - Display all the known information about a configuration record. This includes the current and - default values, the data type, the record class and syntax checking expression. - - Error output available if ``--format pretty`` is specified. - -.. program:: traffic_ctl config -.. option:: diff [--records] - - :ref:`admin_lookup_records` - - Display configuration records that have non-default values. The ``--records`` flag has the same - behavior as :option:`traffic_ctl config get --records`. - -.. program:: traffic_ctl config -.. option:: get [--records] RECORD [RECORD...] - - :ref:`admin_lookup_records` - - Display the current value of a configuration record. - - Error output available if ``--format pretty`` is specified. - -.. program:: traffic_ctl config get -.. option:: --records - - If this flag is provided, :option:`traffic_ctl config get` will emit results in - :file:`records.config` format. - -.. program:: traffic_ctl config -.. option:: match [--records] REGEX [REGEX...] - - :ref:`admin_lookup_records` - - Display the current values of all configuration variables whose names match the given regular - expression. The ``--records`` flag has the same behavior as :option:`traffic_ctl config get - --records`. - -.. program:: traffic_ctl config -.. option:: reload - - :ref:`admin_config_reload` - - Initiate a Traffic Server configuration reload. Use this command to update the running - configuration after any configuration file modification. If no configuration files have been - modified since the previous configuration load, this command is a no-op. - - The timestamp of the last reconfiguration event (in seconds since epoch) is published in the - `proxy.node.config.reconfigure_time` metric. - -.. program:: traffic_ctl config -.. option:: set RECORD VALUE - - :ref:`admin_config_set_records` - - Set the named configuration record to the specified value. Refer to the :file:`records.config` - documentation for a list of the configuration variables you can specify. Note that this is not a - synchronous operation. - -.. program:: traffic_ctl config -.. option:: status - - :ref:`admin_lookup_records` - - Display detailed status about the Traffic Server configuration system. This includes version - information, whether the internal configuration store is current and whether any daemon processes - should be restarted. - -.. program:: traffic_ctl config -.. option:: registry - - :ref:`filemanager.get_files_registry` - - Display information about the registered files in |TS|. This includes the full file path, config record name, parent config (if any) - if needs root access and if the file is required in |TS|. - -.. _traffic-control-command-metric: - -traffic_ctl metric ------------------- - -.. program:: traffic_ctl metric -.. option:: get METRIC [METRIC...] - - :ref:`admin_lookup_records` - - Display the current value of the specified statistics. - - Error output available if ``--format pretty`` is specified. - -.. program:: traffic_ctl metric -.. option:: match REGEX [REGEX...] - - :ref:`admin_lookup_records` - - Display the current values of all statistics whose names match - the given regular expression. - -.. program:: traffic_ctl metric -.. option:: zero METRIC [METRIC...] - - :ref:`admin_clear_metrics_records` - - Reset the named statistics to zero. - -.. program:: traffic_ctl metric -.. option:: describe RECORD [RECORD...] - - :ref:`admin_lookup_records` - - Display all the known information about a metric record. - - Error output available if ``--format pretty`` is specified. - -.. _traffic-control-command-server: - -traffic_ctl server ------------------- - -.. program:: traffic_ctl server - -.. program:: traffic_ctl server -.. option:: drain - - :ref:`admin_server_start_drain` - - :ref:`admin_server_stop_drain` - - Drop the number of active client connections. - -.. program:: traffic_ctl server -.. option:: status - - Option not yet available - -.. _traffic-control-command-storage: - -traffic_ctl storage -------------------- - -.. program:: traffic_ctl storage -.. option:: offline PATH [PATH ...] - - :ref:`admin_storage_set_device_offline` - - Mark a cache storage device as offline. The storage is identified by :arg:`PATH` which must match - exactly a path specified in :file:`storage.config`. This removes the storage from the cache and - redirects requests that would have used this storage to other storage. This has exactly the same - effect as a disk failure for that storage. This does not persist across restarts of the - :program:`traffic_server` process. - -.. program:: traffic_ctl storage -.. option:: status PATH [PATH ...] - - :ref:`admin_storage_get_device_status` - - Show the storage configuration status. - -.. _traffic-control-command-plugin: - -traffic_ctl plugin -------------------- - -.. program:: traffic_ctl plugin -.. option:: msg TAG DATA - - :ref:`admin_plugin_send_basic_msg` - - Send a message to plugins. All plugins that have hooked the - ``TSLifecycleHookID::TS_LIFECYCLE_MSG_HOOK`` will receive a callback for that hook. - The :arg:`TAG` and :arg:`DATA` will be available to the plugin hook processing. It is expected - that plugins will use :arg:`TAG` to select relevant messages and determine the format of the - :arg:`DATA`. - -.. _traffic-control-command-host: - -traffic_ctl host ----------------- -.. program:: traffic_ctl host - -A record to track status is created for each host. The name is the host fqdn. The value of the -record when retrieved, is a serialized string representation of the status. -This contains the overall status and the status for each reason. The -records may be viewed using the :program:`traffic_ctl host status` command. - -.. option:: --time count - - Set the duration of an operation to ``count`` seconds. A value of ``0`` means no duration, the - condition persists until explicitly changed. The default is ``0`` if an operation requires a time - and none is provided by this option. - -.. option:: --reason active | local | manual - - Sets the reason for the operation. - - ``active`` - Set the active health check reason. - - ``local`` - Set the local health check reason. - - ``manual`` - Set the administrative reason. This is the default reason if a reason is needed and not - provided by this option. - - Internally the reason can be ``self_detect`` if - :ts:cv:`proxy.config.http.parent_proxy.self_detect` is set to the value 2 (the default). This is - used to prevent parent selection from creating a loop by selecting itself as the upstream by - marking this reason as "down" in that case. - - .. note:: - - The up / down status values are independent, and a host is consider available if and only if - all of the statuses are "up". - -.. option:: status HOSTNAME [HOSTNAME ...] - - :ref:`admin_lookup_records` - - Get the current status of the specified hosts with respect to their use as targets for parent - selection. If the HOSTNAME arguments are omitted, all host records available are returned. - -.. option:: down HOSTNAME [HOSTNAME ...] - - :ref:`admin_host_set_status` - - Marks the listed hosts as down so that they will not be chosen as a next hop parent. If - :option:`--time` is included the host is marked down for the specified number of seconds after - which the host will automatically be marked up. A host is not marked up until all reason codes - are cleared by marking up the host for the specified reason code. - - Supports :option:`--time`, :option:`--reason`. - -.. option:: up HOSTNAME [HOSTNAME ...] - - :ref:`admin_host_set_status` - - Marks the listed hosts as up so that they will be available for use as a next hop parent. Use - :option:`--reason` to mark the host reason code. The 'self_detect' is an internal reason code - used by parent selection to mark down a parent when it is identified as itself and - - - Supports :option:`--reason`. - -.. _traffic_ctl_rpc: - -traffic_ctl rpc ---------------- -.. program:: traffic_ctl rpc - -A mechanism to interact directly with the |TS| |RPC| endpoint. This means that this is not tied to any particular API -but rather to the rpc endpoint, so you can directly send requests and receive responses from the server. - -.. option:: file - - Reads a file or a set of files from the disc, use the content of the files as message(s) to the |RPC| endpoint. All jsonrpc messages - will be validated before sending them. If the file contains invalid json|yaml format the message will not be send, in - case of a set of files, if a particular file is not a proper json/yaml format then that particular file will be skipped. - - Example: - - .. code-block:: bash - - traffic_ctl rpc file jsonrpc_cmd1.json jsonrpc_cmd2.yaml - -.. option:: get-api - - :ref:`show_registered_handlers` - - Request the entire admin api. This will retrieve all the registered methods and notifications on the server side. - - Example: - - .. code-block:: bash - - $ traffic_ctl rpc get-api - Methods: - - admin_host_set_status - - admin_server_stop_drain - - admin_server_start_drain - - admin_clear_metrics_records - - admin_clear_all_metrics_records - - admin_plugin_send_basic_msg - - admin_lookup_records - - admin_config_set_records - - admin_storage_get_device_status - - admin_storage_set_device_offline - - admin_config_reload - - show_registered_handlers - Notifications: - - some_registered_notification_handler - - -.. option:: input - - Input mode, traffic_ctl will provide a control input from a stream buffer. Once the content is written the terminal :program:`traffic_ctl` - will wait for the user to press Control-D to send the request to the rpc endpoint. - This feature allows you to directly interact with the jsonrpc endpoint and test your API easily and without the need to know the low level - implementation details of the transport layer. - :program:`traffic_ctl` will validate the input format, not the message content. The message content will be validated by the server. - See example `input_example_2`_. - - .. option:: --raw, -r - - No json/yaml parse validation will take place, the input content will be directly send to the server. - - Example: - - .. code-block:: - - $ traffic_ctl rpc input - >> Ctrl-D to fire the request - { - "id":"86e59b43-185b-4a0b-b1c1-babb1a3d5401", - "jsonrpc":"2.0", - "method":"admin_lookup_records", - "params":[ - { - "record_name":"proxy.config.diags.debug.tags", - "rec_types":[ - "1", - "16" - ] - } - ] - } - - - <-- Server's response. - { - "jsonrpc":"2.0", - "result":{ - "recordList":[ - { - "record":{ - "record_name":"proxy.config.diags.debug.tags", - "record_type":"3", - "version":"0", - "raw_stat_block":"0", - "order":"423", - "config_meta":{ - "access_type":"0", - "update_status":"0", - "update_type":"1", - "checktype":"0", - "source":"3", - "check_expr":"null" - }, - "record_class":"1", - "overridable":"false", - "data_type":"STRING", - "current_value":"rpc", - "default_value":"http|dns" - } - } - ] - }, - "id":"86e59b43-185b-4a0b-b1c1-babb1a3d5401" - } - - -.. _input_example_2: - - Example 2: - - You can see a valid json ``{}`` but an invalid |RPC| message. In this case the server is responding. - - .. code-block:: - - $ traffic_ctl rpc input - >> Ctrl-D to fire the request - {} - - < -- Server's response - { - "jsonrpc":"2.0", - "error":{ - "code":-32600, - "message":"Invalid Request" - } - } - - -.. option:: invoke - - Invoke a remote call by using the method name as parameter. This could be a handy option if you are developing a new handler or you - just don't want to expose the method in :program:`traffic_ctl`, for instance when implementing a custom handler inside a proprietary plugin. - - .. option:: --params, -p - - Parameters to be passed in the request, YAML or JSON format are accepted. If JSON is passed as param it should not - be mixed with YAML. It's important that you follow the :ref:`jsonrpc-protocol` specs. If the passed param does not - follows the specs the server will reject the request. - -.. _rpc_invoke_example_1: - - Example 1: - - Call a jsonrpc method with no parameter. - - .. code-block:: - - $ traffic_ctl rpc invoke some_jsonrpc_handler - --> {"id": "0dbab88d-b78f-4ebf-8aa3-f100031711a5", "jsonrpc": "2.0", "method": "some_jsonrpc_handler"} - <-- { response } - -.. _rpc_invoke_example_2: - - Example 2: - - Call a jsonrpc method with parameters. - - .. code-block:: - - $ traffic_ctl rpc invoke reload_files_from_folder --params 'filenames: ["file1", "file2"]' 'folder: "/path/to/folder"' - --> {"id": "9ac68652-5133-4d5f-8260-421baca4c67f", "jsonrpc": "2.0", "method": "reload_files_from_folder", "params": {"filenames": ["file1", "file2"], "folder": "/path/to/folder"}} - <-- { response } - -Examples -======== - -Mark down a host with `traffic_ctl` and view the associated host stats:: - - .. code-block:: bash - - # traffic_ctl host down cdn-cache-02.foo.com --reason manual - - # traffic_ctl metric match host_status - proxy.process.host_status.cdn-cache-01.foo.com HOST_STATUS_DOWN,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:DOWN:1556896844:0,SELF_DETECT:UP:0 - proxy.process.host_status.cdn-cache-02.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 - proxy.process.host_status.cdn-cache-origin-01.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0 - -In the example above, 'cdn-cache-01.foo.com' is unavailable, `HOST_STATUS_DOWN` and was marked down -for the `manual` reason, `MANUAL:DOWN:1556896844:0`, at the time indicated by the UNIX time stamp -`1556896844`. To make the host available, one would have to clear the `manual` reason using: - - .. code-block:: bash - - # traffic_ctl host up cdn-cache-01.foo.com --reason manual - -Configure Traffic Server to insert ``Via`` header in the response to the client - - .. code-block:: bash - - # traffic_ctl config set proxy.config.http.insert_response_via_str 1 - # traffic_ctl config reload - -Autest -====== - -Runroot needs to be configured in order to let `traffic_ctl` know where to find the socket. This is done by default -and there is no change you have to do to interact with it, but make sure that you are not overriding the `dump_runroot=False` -when creating the ATS Process, otherwise the `runroot.yaml` will not be set. - -See also -======== - -:manpage:`records.config(5)`, -:manpage:`storage.config(5)`, -:ref:`admin-jsonrpc-configuration`, -:ref:`jsonrpc-protocol` diff --git a/doc/appendices/command-line/traffic_layout.en.rst b/doc/appendices/command-line/traffic_layout.en.rst index f4fa104afa8..2ad1a3be3a8 100644 --- a/doc/appendices/command-line/traffic_layout.en.rst +++ b/doc/appendices/command-line/traffic_layout.en.rst @@ -50,12 +50,12 @@ First we need to create a runroot. It can be created simply by calling command ` A runroot will be created in ``/path/to/runroot``, available for other programs to use. If the path is not specified, the current working directory will be used. -For example, to run traffic_manager, using the runroot, there are several ways: - #. ``/path/to/runroot/bin/traffic_manager`` - #. ``traffic_manager --run-root=/path/to/runroot`` - #. ``traffic_manager --run-root=/path/to/runroot/runroot.yaml`` - #. Set :envvar:`TS_RUNROOT` to ``/path/to/runroot`` and run ``traffic_manager`` - #. Run ``traffic_manager`` with ``/path/to/runroot`` as current working directory +For example, to run traffic_server, using the runroot, there are several ways: + #. ``/path/to/runroot/bin/traffic_server`` + #. ``traffic_server --run-root=/path/to/runroot`` + #. ``traffic_server --run-root=/path/to/runroot/runroot.yaml`` + #. Set :envvar:`TS_RUNROOT` to ``/path/to/runroot`` and run ``traffic_server`` + #. Run ``traffic_server`` with ``/path/to/runroot`` as current working directory .. Note:: diff --git a/doc/appendices/command-line/traffic_manager.en.rst b/doc/appendices/command-line/traffic_manager.en.rst index 90ae56d2047..bf2141385e1 100644 --- a/doc/appendices/command-line/traffic_manager.en.rst +++ b/doc/appendices/command-line/traffic_manager.en.rst @@ -22,65 +22,9 @@ traffic_manager *************** -.. program:: traffic_manager - -Description -=========== - -.. option:: --aconfPort PORT -.. option:: --action TAGS -.. option:: --debug TAGS -.. option:: --groupAddr ADDRESS -.. option:: --help -.. option:: --nosyslog -.. option:: --path FILE -.. option:: --proxyOff -.. option:: --listenOff -.. option:: --proxyPort PORT -.. option:: --recordsConf FILE -.. option:: --tsArgs ARGUMENTS -.. option:: --maxRecords RECORDS -.. option:: --bind_stdout FILE - -The file to which the stdout stream for :program:`traffic_manager` will be bound. - -.. option:: --bind_stderr FILE - -The file to which the stderr stream for :program:`traffic_manager` will be bound. - -.. option:: --version - -Signals -======= - -SIGHUP - This signal causes a reconfiguration event, equivalent to running :program:`traffic_ctl config reload`. - -SIGINT, SIGTERM - These signals cause :program:`traffic_manager` to exit after also shutting down :program:`traffic_server`. - -SIGUSR2 - This signal causes the :program:`traffic_manager` and :program:`traffic_server` processes to close - and reopen their file descriptors for all of their log files. This allows the use of external - tools to handle log rotation and retention. For instance, logrotate(8) can be configured to rotate - the various |ATS| logs and, via the logrotate postrotate script, send a `-SIGUSR2` to the - :program:`traffic_manager` process. After the signal is received, |ATS| will stop logging to the - now-rolled files and will reopen log files with the originally configured log names. - -Exponential Back-off Delay -========================== - - If :program:`traffic_server` has issues communicating with :program:`traffic_manager` after a crash, - :program:`traffic_manager` will retry to start :program:`traffic_server` using an exponential back-off delay, - which will make :program:`traffic_manager` to retry starting :program:`traffic_server` from ``1s`` until it - reaches the max ceiling time. The ceiling time is configurable as well as the number of times that - :program:`traffic_manager` will keep trying to start :program:`traffic_server`. *A random variance will be - added to the sleep time on every retry* - -.. note:: - For more information about this configuration please check :file:`records.config` - +.. important:: + traffic_manager is deprecated. :program:`traffic_server` must be used instead. See also ======== diff --git a/doc/appendices/command-line/traffic_server.en.rst b/doc/appendices/command-line/traffic_server.en.rst index edcd51d57c1..af88c6d33a8 100644 --- a/doc/appendices/command-line/traffic_server.en.rst +++ b/doc/appendices/command-line/traffic_server.en.rst @@ -119,11 +119,6 @@ the available tests. The maximum number of entries in metrics and configuration variables. The default is 1600, which is also the minimum. This may need to be increased if running plugins that create metrics. -.. option:: -M, --remote_management - -Indicates the process should expect to be managed by :ref:`traffic_manager`. This option should not -be used except by that process. - .. option:: -n COUNT, --net_threads COUNT .. option:: -k, --clear_hostdb @@ -149,11 +144,6 @@ be used except by that process. Environment =========== -.. envvar:: PROXY_REMOTE_MGMT - -This environment variable forces :program:`traffic_server` to believe that it is being managed by -:program:`traffic_manager`. - .. envvar:: PROXY_AUTO_EXIT When this environment variable is set to an integral number of @@ -176,4 +166,3 @@ See also ======== :manpage:`traffic_ctl(8)`, -:manpage:`traffic_manager(8)` diff --git a/doc/appendices/faq.en.rst b/doc/appendices/faq.en.rst index 1cca514e4a4..bdb861c0d3b 100644 --- a/doc/appendices/faq.en.rst +++ b/doc/appendices/faq.en.rst @@ -329,31 +329,14 @@ You are unable to execute Traffic Control commands :program:`traffic_ctl` commands do not execute under the following conditions: -**When the traffic_manager process is not running** - Check to see if the :program:`traffic_manager` process is running by entering the - following command:: - - pgrep -l traffic_manager - - If the :program:`traffic_manager` process is not running, then enter the - following command from the Traffic Server ``bin`` directory to start it:: - - ./traffic_manager - -.. XXX: this is wrong - - You should always start and stop Traffic Server with the - :program:`trafficserver start` and :program:`trafficserver stop` commands to ensure - that all the processes start and stop correctly. For more information, - refer to :ref:`getting-started`. - -**When you are not executing the command from $TSHome/bin** - If the Traffic Server ``bin`` directory is not in your path, then prepend the - Traffic Control commands with ``./`` (for example, ``./traffic_ctl -h``). - -**When multiple Traffic Server installations are present and you are not -executing the Traffic Control command from the active Traffic Server path -specified in ``/etc/trafficserver``** +**When the traffic_server process is not running** + :program:`traffic_ctl` needs traffic_server to be running, the former needs + the later to be running in order to connect to the jsonrpc endpoint. You can + check this :ref:`jsonrpc-node` for more information. + +**When :program:`traffic_ctl` is unable to locate the jsonrpc socket.** + The program needs to know where the path is located, this could be the default + build folder or the one specified by the runroot file. Web browsers display an error document with a 'data missing' message diff --git a/doc/developer-guide/api/types/TSMgmtTypes.en.rst b/doc/developer-guide/api/types/TSMgmtTypes.en.rst index 40526f1a385..8bd72e0d118 100644 --- a/doc/developer-guide/api/types/TSMgmtTypes.en.rst +++ b/doc/developer-guide/api/types/TSMgmtTypes.en.rst @@ -23,6 +23,10 @@ TSMgmt Synopsis ======== +.. important:: + + This is now deprecated. All new RPC communication is now done by :ref:`jsonrpc-protocol` + Macros used for RPC communications. Management Signals diff --git a/doc/developer-guide/api/types/TSRecordUpdateType.en.rst b/doc/developer-guide/api/types/TSRecordUpdateType.en.rst index af6c1c2d23a..b378aca353f 100644 --- a/doc/developer-guide/api/types/TSRecordUpdateType.en.rst +++ b/doc/developer-guide/api/types/TSRecordUpdateType.en.rst @@ -47,7 +47,7 @@ Enumeration Members .. c:member:: TSRecordUpdateType TS_RECORDUPDATE_RESTART_TM - The value is updated if the :program:`traffic_manager` process is restarted. + Deprecated. Description =========== diff --git a/doc/developer-guide/config-vars.en.rst b/doc/developer-guide/config-vars.en.rst index a234a0e5322..59cadd8fc80 100644 --- a/doc/developer-guide/config-vars.en.rst +++ b/doc/developer-guide/config-vars.en.rst @@ -124,7 +124,7 @@ update:``RecUpdateT`` The :program:`traffic_server` process must be restarted for a new value to take effect. ``RECD_RESTART_TM`` - The :program:`traffic_manager` process must be restarted for a new value to take effect. + Deprecated. required:``RecordRequiredType`` Effectively a boolean that specifies if the record is required to be present, diff --git a/doc/developer-guide/core-architecture/index.en.rst b/doc/developer-guide/core-architecture/index.en.rst index 97f59712d72..133483ba147 100644 --- a/doc/developer-guide/core-architecture/index.en.rst +++ b/doc/developer-guide/core-architecture/index.en.rst @@ -27,5 +27,4 @@ Core Architecture heap.en hostdb.en - rpc.en url_rewrite_architecture.en.rst diff --git a/doc/developer-guide/core-architecture/rpc.en.rst b/doc/developer-guide/core-architecture/rpc.en.rst deleted file mode 100644 index f447b10e7f8..00000000000 --- a/doc/developer-guide/core-architecture/rpc.en.rst +++ /dev/null @@ -1,279 +0,0 @@ -.. Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - -.. include:: ../../common.defs - -.. highlight:: cpp -.. default-domain:: cpp - -.. _developer-doc-rpc: - -.. |TServer| replace:: :program:`traffic_server` -.. |TManager| replace:: :program:`traffic_manager` -.. |TCtl| replace:: :program:`traffic_ctl` -.. |LM| replace:: :class:`LocalManager` -.. |PM| replace:: :class:`ProcessManager` - -RPC -*** - -======== -Overview -======== - -In order for programs in different address spaces (remote clients and |TManager|) to communicate with |TServer|, there is a RPC mechanism in :ts:git:`mgmt/`. - -This is a simple serialization style RPC which runs over unix domain sockets. The following sections will detail the runtime structure, serialization mechanisms and how messages are passed from remote clients to |TServer|. - - -================= -Runtime Structure -================= - -.. uml:: - :align: center - - hide empty members - - node "traffic_manager" - node "traffic_server" - - [traffic_ctl] <-d-> [traffic_manager] : Remote RPC - [other remote clients] <-u-> [traffic_manager] : Remote RPC - [traffic_manager] <-r-> [traffic_server] : Local RPC - [traffic_server] <-r-> [plugin] : Hook - -|TManager| opens a unix domain socket to receive commands from remote clients. |TManager| also has a unix domain socket connection with |TServer| to communicate. - -=============== -Message Passing -=============== - -Sequence diagram for a command sent from |TCtl| to when it is received by a plugin. - -.. figure:: ../../uml/images/RPC-sequence-diagram.svg - -.. note:: - - Currently a fire and forget model. traffic_manager sends out an asynchronous signal without any acknowledgment. It then proceeds to send a response itself. - -======================= -Remote RPC vs Local RPC -======================= - -The RPC API for remote clients, such as |TCtl|, etc, is different from the RPC API used between |TManager| and |TServer|. - -|TManager| acts like a bridge for remote clients to interact with |TServer|. Thus, it is currently impossible to do things like have |TCtl| directly send messages to |TServer|. Classes suffixed with "Remote", ie. :ts:git:`CoreAPIRemote.cc`, and classes suffixed with "Local", ie. :ts:git:`NetworkUtilsLocal.cc` are for remote and local clients, respectively. The following sections will note which set of RPC's are relevant. - -======================= -Serialization Mechanism -======================= - -.. class:: MgmtMarshall - - This is the class used to marshall data objects. It provides functions to marshall and unmarshall data. Each data object is associated with a field. Fields are of :type:`MgmtMarshallType`: - - - **MGMT_MARSHALL_INT** : 4 bytes. - - **MGMT_MARSHALL_LONG** : 8 bytes. - - **MGMT_MARSHALL_STRING** : 4 bytes to indicate the string size in bytes, followed by the entire string and NULL terminator. - - **MGMT_MARSHALL_DATA** : 4 byt es to indicate data size in bytes, followed by the entire data object. - -When data is actually sent over a connection it must first be serialized. This is the general serialization mechanism for RPC communication. - -Generally, for remote clients sending messages to |TServer|, the message is serialized using remote RPC APIs. The serialized message is sent to |TManager| and |TManager| then simply relays the message to |TServer|. |TServer| eventually unserializes the message. - -Details for how |TManager| and |TServer| communicate are documented in the next section. - -Marshalling: -============ - - .. function:: ssize_t mgmt_message_marshall(void *buf, size_t remain, const MgmtMarshallType *fields, unsigned count, ...) - - Variable argument wrapper for ``mgmt_message_marshall_v``. Allows for different data types to be marshalled together as long as a field is specified for each data object. Arguments should be references to objects to be marshalled. - - .. function:: ssize_t mgmt_message_marshall_v(void *buf, size_t remain, const MgmtMarshallType *fields, unsigned count, va_list ap) - - This function goes through all the data objects and serializes them together into a buffer. Based on the field, the number of bytes is determined and if there is enough space, it is written into the buffer. - -Unmarshalling: -============== - - .. function:: ssize_t mgmt_message_parse(const void *buf, size_t len, const MgmtMarshallType *fields, unsigned count, ...) - - Variable argument wrapper for ``mgmt_message_parse_v``. Reference to data object to store unmarshalled message needed for variable arguments. - - .. function:: ssize_t mgmt_message_parse_v(const void *buf, size_t len, const MgmtMarshallType *fields, unsigned count, va_list ap) - - This function parses all the serialized. Based on the field, the number of bytes to be read is determined and copied into a ``MgmtMarshallAnyPtr``. - -=================== -Local Serialization -=================== - -A RPC message is sent as a :class:`MgmtMessageHdr` followed by the serialized data in bytes. Serialization is very simple as the interface for communication between |TManager| and |TServer| only allows for :class:`MgmtMessageHdr`, which is a fixed size, and raw data in the form of :code:`char*` to be sent. A header specifies a :arg:`msg_id` and the :arg:`data_len`. On a read, the header is *always* first read. Based on the length of the data payload, the correct number of bytes is then read from the socket. On a write, the header is first populated and sent on the socket, followed by the raw data. - -.. class:: MgmtMessageHdr - - .. member:: int msg_id - - ID for the event or signal to be sent. - - .. member:: int data_len - - Length in bytes of the message. - -.. uml:: - - |Write| - start - :populate msg_id; - :populate data_len; - |#LightGreen|Socket| - :send MgmtMessageHdr; - |Write| - :get the raw data; - note left : casts from\nchar* to void* - |Socket| - :send raw data; - |Read| - :different address space; - : ...\nsome time later; - |Socket| - :read MgmtMessageHdr; - |Read| - :get data_len; - |Socket| - :read data_len bytes; - |Read| - :choose callback based on msg_id\nand send raw data; - stop - -========================== -RPC API for remote clients -========================== - -:ts:git:`NetworkMessage.cc` provides a set of APIs for remote clients to communicate with |TManager|. - -|TManager| will then send a response with the return value. The return value only indicates if the request was successfully propagated to |TServer|. Thus, there is no way currently for |TServer| to send information back to remote clients. - -.. function:: TSMgmtError send_mgmt_request(const mgmt_message_sender &snd, OpType optype, ...) -.. function:: TSMgmtError send_mgmt_request(int fd, OpType optype, ...) - - Send a request from a remote client to |TManager|. - -.. function:: TSMgmtError send_mgmt_response(int fd, OpType optype, ...) - - Send a response from |TManager| to remote client. - -.. function:: TSMgmtError send_mgmt_error(int fd, OpType optype, TSMgmtError error) - - Send err from |TManager| to remote client. - -.. function:: TSMgmtError recv_mgmt_request(void *buf, size_t buflen, OpType optype, ...) - - Read request from remote client. Used by |TManager|. - -.. function:: TSMgmtError recv_mgmt_response(void *buf, size_t buflen, OpType optype, ...) - - Read response from |TManager|. Used by remote clients. - -Using Remote RPC API Example -============================ - -This details how a remote client may use the :ts:git:`NetworkMessage.cc` interface to send messages to |TManager|. Leveraging :func:`send_mgmt_request` with a :class:`mgmt_message_sender` which specifies how *send* a message, a remote client can implement its own way to send messages to |TManager| to allow for things such as preprocessing messages. - -.. class:: mgmt_message_sender - -.. class:: mgmtapi_sender : public mgmt_message_sender - - .. function:: TSMgmtError send(void *msg, size_t msglen) const override - - Specifies how the message is to be sent. Can do things such as serialization or preprocessing based on parameters. - -.. code-block:: cpp - - #define MGMTAPI_SEND_MESSAGE(fd, optype, ...) send_mgmt_request(mgmtapi_sender(fd), (optype), __VA_ARGS__) - -Now, using this macro, messages can easily be sent. For example: - -.. code-block:: cpp - - TSMgmtError ret; - MgmtMarshallData reply = {nullptr, 0}; - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &optype); - if (ret != TS_ERR_OKAY) { - goto done; - } - - // get a response - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - goto done; - } - -==================================== -RPC API for |TServer| and |TManager| -==================================== - -.. figure:: ../../uml/images/RPC-states.svg - :align: center - -|LM| and |PM| follow similar workflows. A manager will poll the socket for any messages. If it is able to read a message, it will handle it based on the :arg:`msg_id` from the :class:`MgmtMessageHdr` and select a callback to run asynchoronously. The async callback will add a response, if any, to an outgoing event queue within the class. A manager will continue to poll and read on the socket as long as there are messages available. Two things can stop a manager from polling. - -1. there are no longer any messages on the socket for a *timeout* time period. - -#. an external event, for example, a |TCtl| command, triggers an ``eventfd`` to tell the manager to stop polling. In the case of an external event, the manager will finish reading anything on the socket, but it will not wait for any timeout period. So, if there are three pending events on the socket, all three will be processed and then immediately after, the manager will stop polling. - -Once a manager is done polling, it will begin to send out messages from it's outgoing event queue. It continues to do this until there are no more messages left. Note that as a manager is polling, it is unable to write anything on the socket itself so the number of messages read will always be exhaustive. - -.. class:: BaseManager - -LocalManager -============ - -.. class:: LocalManager : public BaseManager - - This class is used by |TManager| to communicate with |TServer| - - .. function:: void pollMgmtProcessServer() - - This function watches the socket and handles incoming messages from processes. Used in the main event loop of |TManager|. - - .. function:: void sendMgmtMsgToProcesses(MgmtMessageHdr *mh) - - This function is used by |TManager| to process the messages based on :arg:`msg_id`. It then sends the message to |TServer| over sockets. - -ProcessManager -============== - -.. class:: ProcessManager : public BaseManager - - This class is used by |TServer| to communicate with |TManager| - - .. function:: int pollLMConnection() - - This function periodically polls the socket to see if there are any messages from the |LM|. - - .. function:: void signalManager (int msg_id, const char *data_raw, int data_len) - - This function sends messages to the |LM| using sockets. - -.. note:: - - 1. Both :func:`LocalManager::pollMgmtProcessServer` and :func:`ProcessManager::pollLMConnection` actually use ``select``, not ``poll`` or ``epoll``, underneath. diff --git a/doc/developer-guide/introduction/header-file-structure.en.rst b/doc/developer-guide/introduction/header-file-structure.en.rst index edee3b16665..ae7490c2862 100644 --- a/doc/developer-guide/introduction/header-file-structure.en.rst +++ b/doc/developer-guide/introduction/header-file-structure.en.rst @@ -34,14 +34,14 @@ are available to plugins. same directory). These provide functionality that is used inside the |TS| core logic but has been demonstrated to be useful for plugins as well [#]_. The functions are in the library ``libtscpputil.so``, although many of the utilities are header only. This library is linked in to - the ``traffic_server`` and ``traffic_manager`` binaries and so linkage may not be needed for a plugin. + the ``traffic_server`` binary and so linkage may not be needed for a plugin. This library is independent of the C++ API and can be used with or without that library. "tscore" |TS| core header files. These can only be used inside |TS| itself because they either depend on internal - data structures either directly or operationally. This is linked in to the ``traffic_server`` and - ``traffic_manager`` binaries therefore has no explicit linkage when used in the core. + data structures either directly or operationally. This is linked in to the ``traffic_server`` binary therefore + has no explicit linkage when used in the core. Historical ========== diff --git a/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst index 91489c5e980..5f860545606 100644 --- a/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst +++ b/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst @@ -116,7 +116,7 @@ you also can find this information in the `JSONRPC`_ link. Requests -------- -Please find the `jsonrpc 2.0 request` schema for reference ( `mgmt2/rpc/schema/jsonrpc_request_schema.json` ). +Please find the `jsonrpc 2.0 request` schema for reference ( `mgmt/rpc/schema/jsonrpc_request_schema.json` ). * Mandatory fields. @@ -209,7 +209,7 @@ Responses Although each individual API call will describe the response details and some specific errors, in this section we will describe a high level protocol response, some defined by the `JSONRPC`_ specs and some by |TS| -Please find the `jsonrpc 2.0 response` schema for reference( `mgmt2/rpc/schema/jsonrpc_response_schema.json` ). +Please find the `jsonrpc 2.0 response` schema for reference( `mgmt/rpc/schema/jsonrpc_response_schema.json` ). diff --git a/doc/developer-guide/layout/runroot.en.rst b/doc/developer-guide/layout/runroot.en.rst index 07c73bf9391..9ad2e129e3d 100644 --- a/doc/developer-guide/layout/runroot.en.rst +++ b/doc/developer-guide/layout/runroot.en.rst @@ -52,7 +52,7 @@ Work flow: #. Compiler defaults in layout class Right now, the following programs are integrated with the runroot logic: -**traffic_server**, **traffic_manager**, **traffic_ctl**, **traffic_layout**, **traffic_crashlog**, **traffic_logcat**, **traffic_logstat**. +**traffic_server**, **traffic_ctl**, **traffic_layout**, **traffic_crashlog**, **traffic_logcat**, **traffic_logstat**. The YAML file ============= diff --git a/doc/manpages.py b/doc/manpages.py index 66644997edf..6ef5e096279 100644 --- a/doc/manpages.py +++ b/doc/manpages.py @@ -35,8 +35,6 @@ u'Traffic Server log spooler', None, '8'), ('appendices/command-line/traffic_logstats.en', 'traffic_logstats', u'Traffic Server analyzer', None, '8'), - ('appendices/command-line/traffic_manager.en', 'traffic_manager', - u'Traffic Server process manager', None, '8'), ('appendices/command-line/traffic_server.en', 'traffic_server', u'Traffic Server', None, '8'), ('appendices/command-line/traffic_top.en', 'traffic_top', diff --git a/include/shared/rpc/README.md b/include/shared/rpc/README.md index 23a72ef9cae..f4b616c9c44 100644 --- a/include/shared/rpc/README.md +++ b/include/shared/rpc/README.md @@ -5,5 +5,5 @@ are looking to interact with it in a different C++ application, like traffic_ctl and traffic_top. All this definitions under the shared::rpc namespace are a client lightweight version of the ones used internally by the JSONRPC node server/handlers, they -should not be mixed with the ones defined in `mgmt2/rpc/jsonrpc` which are for +should not be mixed with the ones defined in `mgmt/rpc/jsonrpc` which are for internal use only. diff --git a/include/ts/experimental.h b/include/ts/experimental.h index deef0ab3f6c..309909022f7 100644 --- a/include/ts/experimental.h +++ b/include/ts/experimental.h @@ -327,6 +327,7 @@ tsapi char *TSMatcherLineValue(TSMatcherLine ml, int element); /**************************************************************************** * Set a records.config integer variable ****************************************************************************/ +// DEPRECATED tsapi TSReturnCode TSMgmtConfigIntSet(const char *var_name, TSMgmtInt value); tsapi TSReturnCode TSMgmtConfigFileAdd(const char *parent, const char *fileName); diff --git a/include/tscore/DiagsTypes.h b/include/tscore/DiagsTypes.h index e1e8fd32122..e199bdcc547 100644 --- a/include/tscore/DiagsTypes.h +++ b/include/tscore/DiagsTypes.h @@ -114,7 +114,7 @@ class DiagsConfigState // * debugging tags to selectively enable & disable diagnostics // * action tags to selectively enable & disable code paths // * configurable output to stdout, stderr, syslog, error logs -// * traffic_manager interface supporting on-the-fly reconfiguration +// * interface to supporting on-the-fly reconfiguration // ////////////////////////////////////////////////////////////////////////////// diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index 22b502aac89..4f5c0a2daeb 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -2020,12 +2020,10 @@ AIO_Callback_handler::handle_disk_failure(int /* event ATS_UNUSED */, void *data if (!DISK_BAD(d)) { snprintf(message, sizeof(message), "Error accessing Disk %s [%d/%d]", d->path, d->num_errors, cache_config_max_disk_errors); Warning("%s", message); - RecSignalManager(REC_SIGNAL_CACHE_WARNING, message); } else if (!DISK_BAD_SIGNALLED(d)) { snprintf(message, sizeof(message), "too many errors accessing disk %s [%d/%d]: declaring disk bad", d->path, d->num_errors, cache_config_max_disk_errors); Warning("%s", message); - RecSignalManager(REC_SIGNAL_CACHE_ERROR, message); cacheProcessor.mark_storage_offline(d); // take it out of service } break; diff --git a/iocore/cache/CacheHosting.cc b/iocore/cache/CacheHosting.cc index 36e8afd5952..cbe665c0f17 100644 --- a/iocore/cache/CacheHosting.cc +++ b/iocore/cache/CacheHosting.cc @@ -286,8 +286,7 @@ CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_bu errPtr = parseConfigLine(const_cast(tmp), current, &config_tags); if (errPtr != nullptr) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : %s", matcher_name, config_file_path, - line_num, errPtr); + Warning("%s discarding %s entry at line %d : %s", matcher_name, config_file_path, line_num, errPtr); ats_free(current); } else { // Line parsed ok. Figure out what the destination @@ -366,8 +365,7 @@ CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_bu hostMatch->NewEntry(current); } } else { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry with unknown type at line %d", matcher_name, - config_file_path, current->line_num); + Warning("%s discarding %s entry with unknown type at line %d", matcher_name, config_file_path, current->line_num); } // Deallocate the parsing structure @@ -380,9 +378,7 @@ CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_bu if (!generic_rec_initd) { const char *cache_type = (type == CACHE_HTTP_TYPE) ? "http" : "mixt"; - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, - "No Volumes specified for Generic Hostnames for %s documents: %s cache will be disabled", cache_type, - cache_type); + Warning("No Volumes specified for Generic Hostnames for %s documents: %s cache will be disabled", cache_type, cache_type); } ink_assert(second_pass == numEntries); @@ -436,7 +432,7 @@ CacheHostRecord::Init(CacheType typ) } } if (!num_cachevols) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "error: No volumes found for Cache Type %d", type); + Warning("error: No volumes found for Cache Type %d", type); return -1; } vols = static_cast(ats_malloc(num_vols * sizeof(Vol *))); @@ -485,16 +481,18 @@ CacheHostRecord::Init(matcher_line *line_info, CacheType typ) s++; if (!(*s)) { const char *errptr = "A volume number expected"; - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d :%s", "[CacheHosting]", config_file, - line_info->line_num, errptr); - ats_free(val); + Warning("%s discarding %s entry at line %d :%s", "[CacheHosting]", config_file, line_info->line_num, errptr); + if (val != nullptr) { + ats_free(val); + } return -1; } } if ((*s < '0') || (*s > '9')) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : bad token [%c]", "[CacheHosting]", - config_file, line_info->line_num, *s); - ats_free(val); + Warning("%s discarding %s entry at line %d : bad token [%c]", "[CacheHosting]", config_file, line_info->line_num, *s); + if (val != nullptr) { + ats_free(val); + } return -1; } s++; @@ -528,9 +526,11 @@ CacheHostRecord::Init(matcher_line *line_info, CacheType typ) } } if (!is_vol_present) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : bad volume number [%d]", - "[CacheHosting]", config_file, line_info->line_num, volume_number); - ats_free(val); + Warning("%s discarding %s entry at line %d : bad volume number [%d]", "[CacheHosting]", config_file, + line_info->line_num, volume_number); + if (val != nullptr) { + ats_free(val); + } return -1; } if (c == '\0') { @@ -545,14 +545,12 @@ CacheHostRecord::Init(matcher_line *line_info, CacheType typ) break; } - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : bad token [%s]", "[CacheHosting]", config_file, - line_info->line_num, label); + Warning("%s discarding %s entry at line %d : bad token [%s]", "[CacheHosting]", config_file, line_info->line_num, label); return -1; } if (i == MATCHER_MAX_TOKENS) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : No volumes specified", "[CacheHosting]", - config_file, line_info->line_num); + Warning("%s discarding %s entry at line %d : No volumes specified", "[CacheHosting]", config_file, line_info->line_num); return -1; } @@ -758,8 +756,7 @@ ConfigVolumes::BuildListFromString(char *config_file_path, char *file_buf) } if (err) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s discarding %s entry at line %d : %s", matcher_name, config_file_path, line_num, - err); + Warning("%s discarding %s entry at line %d : %s", matcher_name, config_file_path, line_num, err); } else if (volume_number && size && scheme) { /* add the config */ diff --git a/iocore/cache/Store.cc b/iocore/cache/Store.cc index 85a9d556b6d..d9e4cd6cfc9 100644 --- a/iocore/cache/Store.cc +++ b/iocore/cache/Store.cc @@ -386,7 +386,6 @@ Store::read_config() Debug("cache_init", "Store::read_config - ns = new Span; ns->init(\"%s\",%" PRId64 "), forced volume=%d%s%s", pp.c_str(), size, volume_num, seed ? " id=" : "", seed ? seed : ""); if ((err = ns->init(pp.c_str(), size))) { - RecSignalWarning(REC_SIGNAL_SYSTEM_ERROR, "could not initialize storage \"%s\" [%s]", pp.c_str(), err); Debug("cache_init", "Store::read_config - could not initialize storage \"%s\" [%s]", pp.c_str(), err); delete ns; continue; diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc index 0095fd70f80..d8982c49325 100644 --- a/iocore/hostdb/HostDB.cc +++ b/iocore/hostdb/HostDB.cc @@ -29,6 +29,7 @@ #include "tscore/ts_file.h" #include "tscore/ink_apidefs.h" #include "tscore/bwf_std_format.h" +#include "MgmtDefs.h" // MgmtInt, MgmtFloat, etc #include #include diff --git a/iocore/net/P_SSLCertLookup.h b/iocore/net/P_SSLCertLookup.h index a36aba9dba7..e8ddf627d11 100644 --- a/iocore/net/P_SSLCertLookup.h +++ b/iocore/net/P_SSLCertLookup.h @@ -25,6 +25,8 @@ #include #include +#include +#include #include "ProxyConfig.h" diff --git a/iocore/net/P_UnixNet.h b/iocore/net/P_UnixNet.h index cff9439e9a4..676b28f0c9e 100644 --- a/iocore/net/P_UnixNet.h +++ b/iocore/net/P_UnixNet.h @@ -432,7 +432,7 @@ check_shedding_warning() ink_hrtime t = Thread::get_hrtime(); if (t - last_shedding_warning > NET_THROTTLE_MESSAGE_EVERY) { last_shedding_warning = t; - RecSignalWarning(REC_SIGNAL_SYSTEM_ERROR, "number of connections reaching shedding limit"); + Warning("number of connections reaching shedding limit"); } } @@ -454,9 +454,8 @@ check_throttle_warning(ThrottleType type) if (t - last_throttle_warning > NET_THROTTLE_MESSAGE_EVERY) { last_throttle_warning = t; int connections = net_connections_to_throttle(type); - RecSignalWarning(REC_SIGNAL_SYSTEM_ERROR, - "too many connections, throttling. connection_type=%s, current_connections=%d, net_connections_throttle=%d", - type == ACCEPT ? "ACCEPT" : "CONNECT", connections, net_connections_throttle); + Warning("too many connections, throttling. connection_type=%s, current_connections=%d, net_connections_throttle=%d", + type == ACCEPT ? "ACCEPT" : "CONNECT", connections, net_connections_throttle); } } diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index 22f170ce8ca..3a0c8d0a07a 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -2060,8 +2060,7 @@ SSLMultiCertConfigLoader::load(SSLCertLookup *lookup) errPtr = parseConfigLine(line, &line_info, &sslCertTags); Debug("ssl", "currently parsing %s", line); if (errPtr != nullptr) { - RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s: discarding %s entry at line %d: %s", __func__, params->configFilePath, - line_num, errPtr); + Warning("%s: discarding %s entry at line %d: %s", __func__, params->configFilePath, line_num, errPtr); } else { if (ssl_extract_certificate(&line_info, sslMultiCertSettings.get())) { // There must be a certificate specified unless the tunnel action is set diff --git a/iocore/net/libinknet_stub.cc b/iocore/net/libinknet_stub.cc index d9771d902a4..64c5efee15e 100644 --- a/iocore/net/libinknet_stub.cc +++ b/iocore/net/libinknet_stub.cc @@ -139,30 +139,6 @@ SslAPIHooks *ssl_hooks = nullptr; LifecycleAPIHooks *lifecycle_hooks = nullptr; StatPagesManager statPagesManager; -#include "ProcessManager.h" -ProcessManager *pmgmt = nullptr; - -int -BaseManager::registerMgmtCallback(int, MgmtCallback const &) -{ - ink_assert(false); - return 0; -} - -void -ProcessManager::signalManager(int, char const *, int) -{ - ink_assert(false); - return; -} - -void -ProcessManager::signalManager(int, char const *) -{ - ink_assert(false); - return; -} - #include "PreWarmManager.h" void PreWarmManager::reconfigure() diff --git a/iocore/net/test_certlookup.cc b/iocore/net/test_certlookup.cc index fa1d793d208..1c0e7430473 100644 --- a/iocore/net/test_certlookup.cc +++ b/iocore/net/test_certlookup.cc @@ -43,11 +43,11 @@ REGRESSION_TEST(SSLCertificateLookup)(RegressionTest *t, int /* atype ATS_UNUSED box = REGRESSION_TEST_PASSED; - assert(wild != nullptr); - assert(notwild != nullptr); - assert(b_notwild != nullptr); - assert(foo != nullptr); - assert(all_com != nullptr); + ink_assert(wild != nullptr); + ink_assert(notwild != nullptr); + ink_assert(b_notwild != nullptr); + ink_assert(foo != nullptr); + ink_assert(all_com != nullptr); box.check(lookup.insert("www.foo.com", foo_cc) >= 0, "insert host context"); // Insert the same SSL_CTX instance under another name too diff --git a/lib/perl/MANIFEST b/lib/perl/MANIFEST index 51aeb642d7a..f8a23d6ada1 100644 --- a/lib/perl/MANIFEST +++ b/lib/perl/MANIFEST @@ -2,8 +2,6 @@ Makefile.PL README examples/forw_proxy_conf.pl MANIFEST -t/Apache-TS-AdminClient.t lib/Apache/TS.pm lib/Apache/TS/Config/Records.pm -lib/Apache/TS/AdminClient.pm lib/Apache/TS/Config.pm diff --git a/lib/perl/README b/lib/perl/README index 0b10953f5d7..766abd94052 100644 --- a/lib/perl/README +++ b/lib/perl/README @@ -4,9 +4,6 @@ Apache-TS version 3.4.0 Apache::TS - a set of perl interfaces to manage an Apache Traffic Server instance. This includes the following sub-modules - Apache::TS::AdminClient - access the statistics and configuration - settings stored within Apache Traffic Server - Apache::TS::Config - Manage Apache Traffic Server configs Apache::TS::Config::Records - Manage records.config settings. diff --git a/lib/perl/lib/Apache/TS.pm.in b/lib/perl/lib/Apache/TS.pm.in index f492fea8bd9..e6ca7bbd743 100644 --- a/lib/perl/lib/Apache/TS.pm.in +++ b/lib/perl/lib/Apache/TS.pm.in @@ -50,17 +50,19 @@ Apache::TS - a collection of Perl interfaces to manage Apache Traffic Server ins =head1 SYNOPSIS #!/usr/bin/perl - use Apache::TS::AdminClient; + use Apache::TS::Config::Records; - my $cli = Apache::TS::AdminClient->new(%input); - my $string = $cli->get_stat("proxy.config.product_company"); - print "$string\n"; + my $recedit = new Apache::TS::Config::Records(file => "etc/trafficserver/records.config.default"); + # Threads + $recedit->set(conf => "proxy.config.exec_thread.autoconfig", val => "0"); + # ... + # Write it all out + $recedit->write(file => "etc/trafficserver/records.config"); =head1 DESCRIPTION This is the main module for Apache::TS, in includes the following sub-modules - Apache::TS::AdminClient Apache::TS::Config Apache::TS::Config::Records diff --git a/lib/perl/lib/Apache/TS/AdminClient.pm b/lib/perl/lib/Apache/TS/AdminClient.pm deleted file mode 100644 index 5c3410f93be..00000000000 --- a/lib/perl/lib/Apache/TS/AdminClient.pm +++ /dev/null @@ -1,625 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -package Apache::TS::AdminClient; - -use warnings; -use strict; - -require 5.006; - -use Carp; -use IO::Socket::UNIX; -use IO::Select; - -use Apache::TS; - -# Mgmt API command constants, should track ts/mgmtapi.h -use constant { - TS_RECORD_SET => 0, - TS_RECORD_GET => 1, - TS_PROXY_STATE_GET => 2, - TS_PROXY_STATE_SET => 3, - TS_RECONFIGURE => 4, - TS_RESTART => 5, - TS_BOUNCE => 6, - TS_EVENT_RESOLVE => 7, - TS_EVENT_GET_MLT => 8, - TS_EVENT_ACTIVE => 9, - TS_EVENT_REG_CALLBACK => 10, - TS_EVENT_UNREG_CALLBACK => 11, - TS_EVENT_NOTIFY => 12, - TS_STATS_RESET_NODE => 13, - TS_STORAGE_DEVICE_CMD_OFFLINE => 14, - TS_RECORD_MATCH_GET => 15, - TS_API_PING => 16, - TS_SERVER_BACKTRACE => 17, - TS_RECORD_DESCRIBE_CONFIG => 18, - TS_LIFECYCLE_MESSAGE => 19, - TS_UNDEFINED_OP => 20 -}; - -use constant { - TS_REC_INT => 0, - TS_REC_COUNTER => 1, - TS_REC_FLOAT => 2, - TS_REC_STRING => 3 -}; - -use constant { - TS_ERR_OKAY => 0, - TS_ERR_READ_FILE => 1, - TS_ERR_WRITE_FILE => 2, - TS_ERR_PARSE_CONFIG_RULE => 3, - TS_ERR_INVALID_CONFIG_RULE => 4, - TS_ERR_NET_ESTABLISH => 5, - TS_ERR_NET_READ => 6, - TS_ERR_NET_WRITE => 7, - TS_ERR_NET_EOF => 8, - TS_ERR_NET_TIMEOUT => 9, - TS_ERR_SYS_CALL => 10, - TS_ERR_PARAMS => 11, - TS_ERR_FAIL => 12 -}; - -# Semi-intelligent way of finding the mgmtapi socket. -sub _find_socket -{ - my $path = shift || ""; - my $name = shift || "mgmtapi.sock"; - my @sockets_def = ( - $path, Apache::TS::PREFIX . '/' . Apache::TS::REL_RUNTIMEDIR . '/' . 'mgmtapi.sock', - '/usr/local/var/trafficserver', '/usr/local/var/run/trafficserver', - '/usr/local/var/run', '/var/trafficserver', - '/var/run/trafficserver', '/var/run', - '/opt/ats/var/trafficserver', - ); - - foreach my $socket (@sockets_def) { - return $socket if (-S $socket); - return "${socket}/${name}" if (-S "${socket}/${name}"); - - } - return undef; -} - -# -# Constructor -# -sub new -{ - my ($class, %args) = @_; - my $self = {}; - - $self->{_socket_path} = _find_socket($args{socket_path}); - $self->{_socket} = undef; - croak "Unable to locate socket, please pass socket_path with the management api socket location to Apache::TS::AdminClient" - if (!$self->{_socket_path}); - if ((!-r $self->{_socket_path}) or (!-w $self->{_socket_path}) or (!-S $self->{_socket_path})) { - croak "Unable to open $self->{_socket_path} for reads or writes"; - } - - $self->{_select} = IO::Select->new(); - bless $self, $class; - - $self->open_socket(); - - return $self; -} - -# -# Destructor -# -sub DESTROY -{ - my $self = shift; - return $self->close_socket(); -} - -# -# Open the socket (Unix domain) -# -sub open_socket -{ - my $self = shift; - my %args = @_; - - if (defined($self->{_socket})) { - if ($args{force} || $args{reopen}) { - $self->close_socket(); - } else { - return undef; - } - } - - $self->{_socket} = IO::Socket::UNIX->new( - Type => SOCK_STREAM, - Peer => $self->{_socket_path} - ) or croak("Error opening socket - $@"); - - return undef unless defined($self->{_socket}); - $self->{_select}->add($self->{_socket}); - - return $self; -} - -sub close_socket -{ - my $self = shift; - - # if socket doesn't exist, return as there's nothing to do. - return unless defined($self->{_socket}); - - # gracefully close socket. - $self->{_select}->remove($self->{_socket}); - $self->{_socket}->close(); - $self->{_socket} = undef; - - return $self; -} - -# -# Do reads()'s on our Unix domain socket, takes an optional timeout, in ms's. -# -sub _do_read -{ - my $self = shift; - my $timeout = shift || 1 / 1000.0; # 1ms by default - my $res = ""; - - while ($self->{_select}->can_read($timeout)) { - my $rc = $self->{_socket}->sysread($res, 1024, length($res)); - - # If the server dies we get into a infinite loop because - # IO::Select::can_read keeps returning true - # In this condition sysread returns 0 or undef - # Also, we want to return an undef rather than a partial response - # to avoid unmarshalling errors in the callers - if (!defined($rc) || ($rc == 0)) { - $res = undef; - last; - } - } - - return $res || undef; -} - -# -# Get (read) a stat out of the local manager. Note that the assumption is -# that you are calling this with an existing stats "name". -# -sub get_stat -{ - my ($self, $stat) = @_; - my $res = ""; - - return undef unless defined($self->{_socket}); - return undef unless $self->{_select}->can_write(10); - - # This is a total hack for now, we need to wrap this into the proper mgmt API library. - # The request format is: - # MGMT_MARSHALL_INT: message length - # MGMT_MARSHALL_INT: TS_RECORD_GET - # MGMT_MARSHALL_STRING: record name - my $msg = pack("ll/Z", TS_RECORD_GET, $stat); - $self->{_socket}->print(pack("l/a", $msg)); - $res = $self->_do_read(); - return undef unless defined($res); # Don't proceed on read failure. - - # The response format is: - # MGMT_MARSHALL_INT: message length - # MGMT_MARSHALL_INT: error code - # MGMT_MARSHALL_INT: record class - # MGMT_MARSHALL_INT: record type - # MGMT_MARSHALL_STRING: record name - # MGMT_MARSHALL_DATA: record data - ($msg) = unpack("l/a", $res); - my ($ecode, $rclass, $type, $name, $value) = unpack("l l l l/Z l/a", $msg); - - if ($ecode == TS_ERR_OKAY) { - if ($type == TS_REC_INT || $type == TS_REC_COUNTER) { - my ($ival) = unpack("q", $value); - return $ival; - } elsif ($type == TS_REC_FLOAT) { - my ($fval) = unpack("f", $value); - return $fval; - } elsif ($type == TS_REC_STRING) { - my ($sval) = unpack("Z*", $value); - return $sval; - } - } - - return undef; -} -*get_config = \&get_stat; - -1; - -__END__ - -#-=-=-=-=-=-=-=-= Give us some POD please =-=-=-=-=-=-=-=- - -=head1 NAME: - -Apache::TS::AdminClient - a perl interface to the statistics and configuration settings stored within Apache Traffic Server. - -=head1 SYNOPSIS - - #!/usr/bin/perl - use Apache::TS::AdminClient; - - my $cli = Apache::TS::AdminClient->new(%input); - my $string = $cli->get_stat("proxy.config.product_company"); - print "$string\n"; - - -=head1 DESCRIPTION: - -AdminClient opens a TCP connection to a unix domain socket on local disk. When the connection is established, -AdminClient will write requests to the socket and wait for Apache Traffic Server to return a response. Valid -request strings can be found in RecordsConfig.cc which is included with Apache Traffic Server source. -A list of valid request strings are included with this documentation, but this included list may not be complete -as future releases of Apache Traffic Server may include new request strings or remove existing ones. - -=head1 CONSTRUCTOR - -When the object is created for this module, it assumes the 'Unix Domain Socket' is at the default location from -the Apache Traffic Server installation. This can be changed when creating the object by setting B<'socket_path'>. -For example: - -=over 4 - -=item my $cli = AdminClient->new(socket_path=> "/var/trafficserver"); - - -This would make the module look for the 'Unix Domain Socket' in the directory '/var/trafficserver'. The path -can optionally include the name of the Socket file, without it the constructor defaults to 'mgmtapi.sock'. - -=back - -=head1 PUBLIC METHODS - -To read a single metric (or configuration), two APIs are available: - -=over 4 - -=item $cli->get_stat($stats_name); - -=item $cli->get_config($config_name); - -This will return a (scalar) value for this metric or configuration. - -=back - -=head1 traffic_ctl - -There is a command line tool included with Apache Traffic Server called traffic_ctl which overlaps with this module. traffic_ctl -can be used to read and write statistics or config settings that this module can. Hence if you don't want to write a perl one-liner to -get to this information, traffic_ctl is your tool. - -=head1 List of configurations - -The Apache Traffic Server Administration Manual will explain what these strings represent. (https://docs.trafficserver.apache.org/en/latest/) - - proxy.config.accept_threads - proxy.config.task_threads - proxy.config.admin.synthetic_port - proxy.config.admin.cli_path - proxy.config.admin.user_id - proxy.config.alarm.abs_path - proxy.config.alarm.bin - proxy.config.alarm.script_runtime - proxy.config.bandwidth_mgmt.filename - proxy.config.bin_path - proxy.config.body_factory.enable_customizations - proxy.config.body_factory.enable_logging - proxy.config.body_factory.response_max_size - proxy.config.body_factory.response_suppression_mode - proxy.config.body_factory.template_sets_dir - proxy.config.cache.agg_write_backlog - proxy.config.cache.alt_rewrite_max_size - proxy.config.cache.control.filename - proxy.config.cache.dir.sync_frequency - proxy.config.cache.enable_checksum - proxy.config.cache.enable_read_while_writer - proxy.config.cache.hostdb.disable_reverse_lookup - proxy.config.cache.hostdb.sync_frequency - proxy.config.cache.hosting_filename - proxy.config.cache.ip_allow.filename - proxy.config.cache.limits.http.max_alts - proxy.config.cache.log.alternate.eviction - proxy.config.cache.max_disk_errors - proxy.config.cache.max_doc_size - proxy.config.cache.min_average_object_size - proxy.config.cache.volume_filename - proxy.config.cache.permit.pinning - proxy.config.cache.ram_cache_cutoff - proxy.config.cache.ram_cache.size - proxy.config.cache.select_alternate - proxy.config.cache.threads_per_disk - proxy.config.cache.mutex_retry_delay - proxy.config.cop.core_signal - proxy.config.cop.linux_min_memfree_kb - proxy.config.cop.linux_min_swapfree_kb - proxy.config.core_limit - proxy.config.diags.action.enabled - proxy.config.diags.action.tags - proxy.config.diags.debug.enabled - proxy.config.diags.debug.tags - proxy.config.diags.output.alert - proxy.config.diags.output.debug - proxy.config.diags.output.diag - proxy.config.diags.output.emergency - proxy.config.diags.output.error - proxy.config.diags.output.fatal - proxy.config.diags.output.note - proxy.config.diags.output.status - proxy.config.diags.output.warning - proxy.config.diags.show_location - proxy.config.dns.failover_number - proxy.config.dns.failover_period - proxy.config.dns.lookup_timeout - proxy.config.dns.max_dns_in_flight - proxy.config.dns.nameservers - proxy.config.dns.resolv_conf - proxy.config.dns.retries - proxy.config.dns.round_robin_nameservers - proxy.config.dns.search_default_domains - proxy.config.dns.splitDNS.enabled - proxy.config.dns.splitdns.filename - proxy.config.dump_mem_info_frequency - proxy.config.env_prep - proxy.config.exec_thread.autoconfig - proxy.config.exec_thread.autoconfig.scale - proxy.config.exec_thread.limit - proxy.config.header.parse.no_host_url_redirect - proxy.config.hostdb - proxy.config.hostdb.fail.timeout - proxy.config.hostdb.filename - proxy.config.hostdb.lookup_timeout - proxy.config.hostdb.migrate_on_demand - proxy.config.hostdb.re_dns_on_reload - proxy.config.hostdb.serve_stale_for - proxy.config.hostdb.size - proxy.config.hostdb.storage_path - proxy.config.hostdb.storage_size - proxy.config.hostdb.strict_round_robin - proxy.config.hostdb.timeout - proxy.config.hostdb.ttl_mode - proxy.config.hostdb.verify_after - proxy.config.http.accept_encoding_filter.filename - proxy.config.http.accept_no_activity_timeout - proxy.config.http.insert_client_ip - proxy.config.http.anonymize_other_header_list - proxy.config.http.anonymize_remove_client_ip - proxy.config.http.anonymize_remove_cookie - proxy.config.http.anonymize_remove_from - proxy.config.http.anonymize_remove_referer - proxy.config.http.anonymize_remove_user_agent - proxy.config.http.background_fill_active_timeout - proxy.config.http.background_fill_completed_threshold - proxy.config.http.cache.cache_responses_to_cookies - proxy.config.http.cache.cache_urls_that_look_dynamic - proxy.config.http.cache.guaranteed_max_lifetime - proxy.config.http.cache.guaranteed_min_lifetime - proxy.config.http.cache.heuristic_lm_factor - proxy.config.http.cache.heuristic_max_lifetime - proxy.config.http.cache.heuristic_min_lifetime - proxy.config.http.cache.http - proxy.config.http.cache.ignore_accept_charset_mismatch - proxy.config.http.cache.ignore_accept_encoding_mismatch - proxy.config.http.cache.ignore_accept_language_mismatch - proxy.config.http.cache.ignore_accept_mismatch - proxy.config.http.cache.ignore_authentication - proxy.config.http.cache.ignore_client_cc_max_age - proxy.config.http.cache.ignore_client_no_cache - proxy.config.http.cache.ignore_server_no_cache - proxy.config.http.cache.ims_on_client_no_cache - proxy.config.http.cache.max_open_read_retries - proxy.config.http.cache.max_open_write_retries - proxy.config.http.cache.max_stale_age - proxy.config.http.cache.open_read_retry_time - proxy.config.http.cache.range.lookup - proxy.config.http.cache.range.write - proxy.config.http.cache.required_headers - proxy.config.http.cache.when_to_revalidate - proxy.config.http.chunking_enabled - proxy.config.http.connect_attempts_max_retries - proxy.config.http.connect_attempts_max_retries_dead_server - proxy.config.http.connect_attempts_rr_retries - proxy.config.http.connect_attempts_timeout - proxy.config.http.connect_ports - proxy.config.http.default_buffer_size - proxy.config.http.default_buffer_water_mark - proxy.config.http.doc_in_cache_skip_dns - proxy.config.http.down_server.cache_time - proxy.config.http.enabled - proxy.config.http.enable_http_info - proxy.config.http.enable_http_stats - proxy.config.http.errors.log_error_pages - proxy.config.http.forward.proxy_auth_to_parent - proxy.config.http.global_user_agent_header - proxy.config.http.insert_age_in_response - proxy.config.http.insert_request_via_str - proxy.config.http.insert_response_via_str - proxy.config.http.insert_squid_x_forwarded_for - proxy.config.http.keep_alive_enabled_in - proxy.config.http.keep_alive_enabled_out - proxy.config.http.keep_alive_no_activity_timeout_in - proxy.config.http.keep_alive_no_activity_timeout_out - proxy.config.http.keep_alive_post_out - proxy.config.http.negative_caching_enabled - proxy.config.http.negative_caching_list - proxy.config.http.negative_caching_lifetime - proxy.config.http.negative_revalidating_enabled - proxy.config.http.negative_revalidating_lifetime - proxy.config.http.no_dns_just_forward_to_parent - proxy.config.http.no_origin_server_dns - proxy.config.http.normalize_ae_gzip - proxy.config.http.number_of_redirections - proxy.config.http.per_server.connection.max - proxy.config.http.origin_min_keep_alive_connections - proxy.config.http.parent_proxies - proxy.config.http.parent_proxy.fail_threshold - proxy.config.http.parent_proxy.file - proxy.config.http.parent_proxy.per_parent_connect_attempts - proxy.config.http.parent_proxy.retry_time - proxy.config.http.parent_proxy.total_connect_attempts - proxy.config.http.post_copy_size - proxy.config.http.push_method_enabled - proxy.config.http.quick_filter.mask - proxy.config.http.record_heartbeat - proxy.config.http.referer_default_redirect - proxy.config.http.referer_filter - proxy.config.http.referer_format_redirect - proxy.config.http.request_header_max_size - proxy.config.http.request_via_str - proxy.config.http.response_header_max_size - proxy.config.http.response_server_enabled - proxy.config.http.response_server_str - proxy.config.http.response_via_str - proxy.config.http.send_http11_requests - proxy.config.http.server_max_connections - proxy.config.http.server_port - proxy.config.http.slow.log.threshold - proxy.config.http.connect_ports - proxy.config.http.transaction_active_timeout_in - proxy.config.http.transaction_active_timeout_out - proxy.config.http.transaction_no_activity_timeout_in - proxy.config.http.transaction_no_activity_timeout_out - proxy.config.http_ui_enabled - proxy.config.http.uncacheable_requests_bypass_parent - proxy.config.io.max_buffer_size - proxy.config.lm.pserver_timeout_msecs - proxy.config.lm.pserver_timeout_secs - proxy.config.local_state_dir - proxy.config.log.ascii_buffer_size - proxy.config.log.auto_delete_rolled_files - proxy.config.log.file_stat_frequency - proxy.config.log.hostname - proxy.config.log.log_buffer_size - proxy.config.log.logfile_dir - proxy.config.log.logfile_perm - proxy.config.log.logging_enabled - proxy.config.log.max_line_size - proxy.config.log.max_secs_per_buffer - proxy.config.log.max_space_mb_for_logs - proxy.config.log.max_space_mb_headroom - proxy.config.log.overspill_report_count - proxy.config.log.rolling_enabled - proxy.config.log.rolling_interval_sec - proxy.config.log.rolling_offset_hr - proxy.config.log.rolling_size_mb - proxy.config.log.sampling_frequency - proxy.config.log.space_used_frequency - proxy.config.log.config.filename - proxy.config.manager_binary - proxy.config.net.connections_throttle - proxy.config.net.listen_backlog - proxy.config.net.sock_mss_in - proxy.config.net.sock_option_flag_in - proxy.config.net.sock_option_flag_out - proxy.config.net.sock_recv_buffer_size_in - proxy.config.net.sock_recv_buffer_size_out - proxy.config.net.sock_send_buffer_size_in - proxy.config.net.sock_send_buffer_size_out - proxy.config.net.defer_accept - proxy.config.output.logfile - proxy.config.plugin.plugin_dir - proxy.config.process_manager.mgmt_port - proxy.config.process_manager.timeout - proxy.config.product_company - proxy.config.product_name - proxy.config.product_vendor - proxy.config.proxy.authenticate.basic.realm - proxy.config.proxy_binary - proxy.config.proxy_binary_opts - proxy.config.proxy_name - proxy.config.remap.num_remap_threads - proxy.config.res_track_memory - proxy.config.reverse_proxy.enabled - proxy.config.reverse_proxy.oldasxbehavior - proxy.config.socks.accept_enabled - proxy.config.socks.accept_port - proxy.config.socks.connection_attempts - proxy.config.socks.default_servers - proxy.config.socks.http_port - proxy.config.socks.per_server_connection_attempts - proxy.config.socks.server_connect_timeout - proxy.config.socks.server_fail_threshold - proxy.config.socks.server_retry_time - proxy.config.socks.server_retry_timeout - proxy.config.socks.socks_config_file - proxy.config.socks.socks_needed - proxy.config.socks.socks_timeout - proxy.config.socks.socks_version - proxy.config.srv_enabled - proxy.config.ssl.CA.cert.filename - proxy.config.ssl.CA.cert.path - proxy.config.ssl.client.CA.cert.filename - proxy.config.ssl.client.CA.cert.path - proxy.config.ssl.client.cert.filename - proxy.config.ssl.client.certification_level - proxy.config.ssl.client.cert.path - proxy.config.ssl.client.private_key.filename - proxy.config.ssl.client.private_key.path - proxy.config.ssl.server.cert_chain.filename - proxy.config.ssl.server.cert.path - proxy.config.ssl.server.cipher_suite - proxy.config.ssl.server.honor_cipher_order - proxy.config.ssl.server.dhparams_file - proxy.config.ssl.TLSv1 - proxy.config.ssl.TLSv1_1 - proxy.config.ssl.TLSv1_2 - proxy.config.ssl.TLSv1_3 - proxy.config.ssl.server.multicert.filename - proxy.config.ssl.server.private_key.path - proxy.config.ssl.keylog_file - proxy.config.stat_collector.interval - proxy.config.stat_collector.port - proxy.config.syslog_facility - proxy.config.system.file_max_pct - proxy.config.thread.default.stacksize - proxy.config.udp.free_cancelled_pkts_sec - proxy.config.udp.periodic_cleanup - proxy.config.udp.send_retries - proxy.config.url_remap.filename - proxy.config.url_remap.pristine_host_hdr - proxy.config.url_remap.remap_required - -=head1 LICENSE - - Simple Apache Traffic Server client object, to communicate with the local manager. - - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=cut - -#-=-=-=-=-=-=-=-= No more POD for you =-=-=-=-=-=-=-=- diff --git a/lib/perl/t/Apache-TS-AdminClient.t b/lib/perl/t/Apache-TS-AdminClient.t deleted file mode 100644 index 53aeacee92a..00000000000 --- a/lib/perl/t/Apache-TS-AdminClient.t +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl Apache-TS-AdminClient.t' - -######################### - -# change 'tests => 1' to 'tests => last_test_to_print'; - - -use Test::More tests => 2; -BEGIN { use_ok('Apache::TS::AdminClient') }; - -######################### - -# Insert your test code below, the Test::More module is use()ed here so read -# its man page ( perldoc Test::More ) for help writing this test script. - -#----- is this right or do we need to use Test::MockObject as well? -our @methods = qw(new DESTROY open_socket close_socket get_stat); -can_ok('Apache::TS::AdminClient', @methods); diff --git a/lib/records/I_RecAlarms.h b/lib/records/I_RecAlarms.h deleted file mode 100644 index f4843c9bb93..00000000000 --- a/lib/records/I_RecAlarms.h +++ /dev/null @@ -1,37 +0,0 @@ -/** @file - - Public REC_ALARM defines - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -// copy from mgmt/Alarms.h -#define REC_ALARM_UNDEFINED 0 - -#define REC_ALARM_PROXY_PROCESS_DIED 1 -#define REC_ALARM_PROXY_PROCESS_BORN 2 -#define REC_ALARM_PROXY_CONFIG_ERROR 3 -#define REC_ALARM_PROXY_SYSTEM_ERROR 4 -#define REC_ALARM_PROXY_CACHE_ERROR 5 -#define REC_ALARM_PROXY_CACHE_WARNING 6 -#define REC_ALARM_PROXY_LOGGING_ERROR 7 -#define REC_ALARM_PROXY_LOGGING_WARNING 8 -#define REC_ALARM_CONFIG_UPDATE_FAILED 9 diff --git a/lib/records/I_RecCore.h b/lib/records/I_RecCore.h index 061ebb8dbb7..90b0a03dfcf 100644 --- a/lib/records/I_RecCore.h +++ b/lib/records/I_RecCore.h @@ -28,9 +28,6 @@ #include "tscore/Diags.h" #include "I_RecDefs.h" -#include "I_RecAlarms.h" -#include "I_RecSignals.h" -#include "I_RecEvents.h" #include "tscpp/util/MemSpan.h" struct RecRecord; @@ -176,22 +173,6 @@ RecErrT RecGetRecordSource(const char *name, RecSourceT *source, bool lock = tru RecErrT RecGetRecordAccessType(const char *name, RecAccessT *secure, bool lock = true); RecErrT RecSetRecordAccessType(const char *name, RecAccessT secure, bool lock = true); -//------------------------------------------------------------------------ -// Signal and Alarms -//------------------------------------------------------------------------ - -// RecSignalManager always sends a management signal up to traffic_manager. -void RecSignalManager(int id, const char *, size_t); - -static inline void -RecSignalManager(int id, const char *str) -{ - RecSignalManager(id, str, strlen(str) + 1); -} - -// Format a message, and send it to the manager and to the Warning diagnostic. -void RecSignalWarning(int sig, const char *fmt, ...) TS_PRINTFLIKE(2, 3); - /// Generate a warning if any configuration name/value is not registered. void RecConfigWarnIfUnregistered(); @@ -300,9 +281,3 @@ RecErrT RecResetStatRecord(RecT type = RECT_NULL, bool all = false); // Set RecRecord attributes //------------------------------------------------------------------------ RecErrT RecSetSyncRequired(char *name, bool lock = true); - -//------------------------------------------------------------------------ -// Manager Callback -//------------------------------------------------------------------------ -using RecManagerCb = std::function)>; -int RecRegisterManagerCb(int _signal, RecManagerCb const &_fn); diff --git a/lib/records/I_RecDefs.h b/lib/records/I_RecDefs.h index cfe9206347e..5baf5d9687e 100644 --- a/lib/records/I_RecDefs.h +++ b/lib/records/I_RecDefs.h @@ -100,7 +100,7 @@ enum RecUpdateT { RECU_NULL, // default: don't know the behavior RECU_DYNAMIC, // config can be updated dynamically w/ "traffic_ctl config reload" RECU_RESTART_TS, // config requires TS to be restarted to take effect - RECU_RESTART_TM, // config requires TM/TS to be restarted to take effect + RECU_RESTART_TM, // deprecated }; enum RecCheckT { @@ -125,7 +125,7 @@ enum RecModeT { RECM_NULL, RECM_CLIENT, RECM_SERVER, - RECM_STAND_ALONE, + RECM_STAND_ALONE, ///< The only option now as traffic_manager is no longer supported. }; enum RecAccessT { diff --git a/lib/records/I_RecEvents.h b/lib/records/I_RecEvents.h deleted file mode 100644 index 3e3c47680f4..00000000000 --- a/lib/records/I_RecEvents.h +++ /dev/null @@ -1,37 +0,0 @@ -/** @file - - Public REC_EVENT defines - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -// copy from mgmt/BaseManager.h -#define REC_EVENT_SYNC_KEY 10000 -#define REC_EVENT_SHUTDOWN 10001 -#define REC_EVENT_RESTART 10002 -#define REC_EVENT_BOUNCE 10003 -#define REC_EVENT_CLEAR_STATS 10004 -#define REC_EVENT_CONFIG_FILE_UPDATE 10005 -#define REC_EVENT_PLUGIN_CONFIG_UPDATE 10006 -#define REC_EVENT_ROLL_LOG_FILES 10008 -#define REC_EVENT_LIBRECORDS 10009 - -#define REC_EVENT_CACHE_DISK_CONTROL 10011 diff --git a/lib/records/I_RecSignals.h b/lib/records/I_RecSignals.h deleted file mode 100644 index 2f1d5ab3c9b..00000000000 --- a/lib/records/I_RecSignals.h +++ /dev/null @@ -1,41 +0,0 @@ -/** @file - - Public REC_SIGNAL defines - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -// copy from mgmt/BaseManager.h -#define REC_SIGNAL_PID 0 - -#define REC_SIGNAL_PROXY_PROCESS_DIED 1 -#define REC_SIGNAL_PROXY_PROCESS_BORN 2 -#define REC_SIGNAL_CONFIG_ERROR 3 -#define REC_SIGNAL_SYSTEM_ERROR 4 -#define REC_SIGNAL_CACHE_ERROR 5 -#define REC_SIGNAL_CACHE_WARNING 6 -#define REC_SIGNAL_LOGGING_ERROR 7 -#define REC_SIGNAL_LOGGING_WARNING 8 -#define REC_SIGNAL_PLUGIN_SET_CONFIG 9 - -// This are additional on top of the ones defined in Alarms.h. Que? -#define REC_SIGNAL_LIBRECORDS 10 -#define REC_SIGNAL_CONFIG_FILE_CHILD 11 diff --git a/lib/records/Makefile.am b/lib/records/Makefile.am index 2dd0ca5304e..426b2bc9c0f 100644 --- a/lib/records/Makefile.am +++ b/lib/records/Makefile.am @@ -30,16 +30,13 @@ AM_CPPFLAGS += \ -I$(abs_top_srcdir)/lib \ $(TS_INCLUDES) -noinst_LIBRARIES = librecords_lm.a librecords_p.a +noinst_LIBRARIES = librecords_p.a librecords_COMMON = \ - I_RecAlarms.h \ I_RecCore.h \ I_RecDefs.h \ - I_RecEvents.h \ I_RecHttp.h \ I_RecMutex.h \ - I_RecSignals.h \ P_RecCore.cc \ P_RecCore.h \ P_RecDefs.h \ @@ -56,12 +53,6 @@ librecords_COMMON = \ RecRawStats.cc \ RecUtils.cc -librecords_lm_a_SOURCES = \ - $(librecords_COMMON) \ - I_RecLocal.h \ - P_RecLocal.h \ - RecLocal.cc - librecords_p_a_SOURCES = \ $(librecords_COMMON) \ I_RecProcess.h \ diff --git a/lib/records/P_RecCore.cc b/lib/records/P_RecCore.cc index 717011daf49..d768f25cead 100644 --- a/lib/records/P_RecCore.cc +++ b/lib/records/P_RecCore.cc @@ -38,228 +38,6 @@ RecModeT g_mode_type = RECM_NULL; -//------------------------------------------------------------------------- -// send_reset_message -//------------------------------------------------------------------------- -static RecErrT -send_reset_message(RecRecord *record) -{ - RecMessage *m; - - rec_mutex_acquire(&(record->lock)); - m = RecMessageAlloc(RECG_RESET); - m = RecMessageMarshal_Realloc(m, record); - RecDebug(DL_Note, "[send] RECG_RESET [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - RecMessageSend(m); - RecMessageFree(m); - rec_mutex_release(&(record->lock)); - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// send_set_message -//------------------------------------------------------------------------- -static RecErrT -send_set_message(RecRecord *record) -{ - RecMessage *m; - - rec_mutex_acquire(&(record->lock)); - m = RecMessageAlloc(RECG_SET); - m = RecMessageMarshal_Realloc(m, record); - RecDebug(DL_Note, "[send] RECG_SET [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - RecMessageSend(m); - RecMessageFree(m); - rec_mutex_release(&(record->lock)); - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// send_register_message -//------------------------------------------------------------------------- -RecErrT -send_register_message(RecRecord *record) -{ - RecMessage *m; - - rec_mutex_acquire(&(record->lock)); - m = RecMessageAlloc(RECG_REGISTER); - m = RecMessageMarshal_Realloc(m, record); - RecDebug(DL_Note, "[send] RECG_REGISTER [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - RecMessageSend(m); - RecMessageFree(m); - rec_mutex_release(&(record->lock)); - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// send_push_message -//------------------------------------------------------------------------- -RecErrT -send_push_message() -{ - RecRecord *r; - RecMessage *m; - int i, num_records; - bool send_msg = false; - - m = RecMessageAlloc(RECG_PUSH); - num_records = g_num_records; - for (i = 0; i < num_records; i++) { - r = &(g_records[i]); - rec_mutex_acquire(&(r->lock)); - if (i_am_the_record_owner(r->rec_type)) { - if (r->sync_required & REC_PEER_SYNC_REQUIRED) { - m = RecMessageMarshal_Realloc(m, r); - r->sync_required &= ~REC_PEER_SYNC_REQUIRED; - send_msg = true; - } - } - rec_mutex_release(&(r->lock)); - } - if (send_msg) { - RecDebug(DL_Note, "[send] RECG_PUSH [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - RecMessageSend(m); - } - RecMessageFree(m); - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// send_pull_message -//------------------------------------------------------------------------- -RecErrT -send_pull_message(RecMessageT msg_type) -{ - RecRecord *r; - RecMessage *m; - int i, num_records; - - m = RecMessageAlloc(msg_type); - switch (msg_type) { - case RECG_PULL_REQ: - // We're requesting all of the records from our peer. No payload - // here, just send the message. - RecDebug(DL_Note, "[send] RECG_PULL_REQ [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - break; - - case RECG_PULL_ACK: - // Respond to a RECG_PULL_REQ message from our peer. Send ALL - // records! Also be sure to send a response even if it has no - // payload. Our peer may be blocking and waiting for a response! - num_records = g_num_records; - for (i = 0; i < num_records; i++) { - r = &(g_records[i]); - if (i_am_the_record_owner(r->rec_type) || (REC_TYPE_IS_STAT(r->rec_type) && !(r->registered)) || - (REC_TYPE_IS_STAT(r->rec_type) && (r->stat_meta.persist_type == RECP_NON_PERSISTENT))) { - rec_mutex_acquire(&(r->lock)); - m = RecMessageMarshal_Realloc(m, r); - r->sync_required &= ~REC_PEER_SYNC_REQUIRED; - rec_mutex_release(&(r->lock)); - } - } - RecDebug(DL_Note, "[send] RECG_PULL_ACK [%d bytes]", sizeof(RecMessageHdr) + m->o_write - m->o_start); - break; - - default: - RecMessageFree(m); - return REC_ERR_FAIL; - } - - RecMessageSend(m); - RecMessageFree(m); - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// recv_message_cb -//------------------------------------------------------------------------- -RecErrT -recv_message_cb(RecMessage *msg, RecMessageT msg_type, void * /* cookie */) -{ - RecRecord *r; - RecMessageItr itr; - - switch (msg_type) { - case RECG_SET: - - RecDebug(DL_Note, "[recv] RECG_SET [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - if (RecMessageUnmarshalFirst(msg, &itr, &r) != REC_ERR_FAIL) { - do { - if (REC_TYPE_IS_STAT(r->rec_type)) { - RecSetRecord(r->rec_type, r->name, r->data_type, &(r->data), &(r->stat_meta.data_raw), REC_SOURCE_EXPLICIT); - } else { - RecSetRecord(r->rec_type, r->name, r->data_type, &(r->data), nullptr, REC_SOURCE_EXPLICIT); - } - } while (RecMessageUnmarshalNext(msg, &itr, &r) != REC_ERR_FAIL); - } - break; - - case RECG_RESET: - - RecDebug(DL_Note, "[recv] RECG_RESET [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - if (RecMessageUnmarshalFirst(msg, &itr, &r) != REC_ERR_FAIL) { - do { - if (REC_TYPE_IS_STAT(r->rec_type)) { - RecResetStatRecord(r->name); - } else { - RecSetRecord(r->rec_type, r->name, r->data_type, &(r->data), nullptr, REC_SOURCE_EXPLICIT); - } - } while (RecMessageUnmarshalNext(msg, &itr, &r) != REC_ERR_FAIL); - } - break; - - case RECG_REGISTER: - RecDebug(DL_Note, "[recv] RECG_REGISTER [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - if (RecMessageUnmarshalFirst(msg, &itr, &r) != REC_ERR_FAIL) { - do { - if (REC_TYPE_IS_STAT(r->rec_type)) { - RecRegisterStat(r->rec_type, r->name, r->data_type, r->data_default, r->stat_meta.persist_type); - } else if (REC_TYPE_IS_CONFIG(r->rec_type)) { - RecRegisterConfig(r->rec_type, r->name, r->data_type, r->data_default, r->config_meta.update_type, - r->config_meta.check_type, r->config_meta.check_expr, r->config_meta.source, - r->config_meta.access_type); - } - } while (RecMessageUnmarshalNext(msg, &itr, &r) != REC_ERR_FAIL); - } - break; - - case RECG_PUSH: - RecDebug(DL_Note, "[recv] RECG_PUSH [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - if (RecMessageUnmarshalFirst(msg, &itr, &r) != REC_ERR_FAIL) { - do { - RecForceInsert(r); - } while (RecMessageUnmarshalNext(msg, &itr, &r) != REC_ERR_FAIL); - } - break; - - case RECG_PULL_ACK: - RecDebug(DL_Note, "[recv] RECG_PULL_ACK [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - if (RecMessageUnmarshalFirst(msg, &itr, &r) != REC_ERR_FAIL) { - do { - RecForceInsert(r); - } while (RecMessageUnmarshalNext(msg, &itr, &r) != REC_ERR_FAIL); - } - break; - - case RECG_PULL_REQ: - RecDebug(DL_Note, "[recv] RECG_PULL_REQ [%d bytes]", sizeof(RecMessageHdr) + msg->o_end - msg->o_start); - send_pull_message(RECG_PULL_ACK); - break; - - default: - ink_assert(!"Unexpected RecG type"); - return REC_ERR_FAIL; - } - - return REC_ERR_OKAY; -} - //------------------------------------------------------------------------- // RecRegisterStatXXX //------------------------------------------------------------------------- @@ -271,8 +49,6 @@ recv_message_cb(RecMessage *msg, RecMessageT msg_type, void * /* cookie */) if ((r = RecRegisterStat(rec_type, name, B, my_data_default, persist_type)) != nullptr) { \ if (i_am_the_record_owner(r->rec_type)) { \ r->sync_required = r->sync_required | REC_PEER_SYNC_REQUIRED; \ - } else { \ - send_register_message(r); \ } \ return REC_ERR_OKAY; \ } else { \ @@ -314,8 +90,6 @@ _RecRegisterStatCounter(RecT rec_type, const char *name, RecCounter data_default nullptr) { \ if (i_am_the_record_owner(r->rec_type)) { \ r->sync_required = r->sync_required | REC_PEER_SYNC_REQUIRED; \ - } else { \ - send_register_message(r); \ } \ return REC_ERR_OKAY; \ } else { \ @@ -400,23 +174,6 @@ RecSetRecord(RecT rec_type, const char *name, RecDataT data_type, RecData *data, } } rec_mutex_release(&(r1->lock)); - } else { - // We don't need to ats_strdup() here as we will make copies of any - // strings when we marshal them into our RecMessage buffer. - RecRecord r2; - - RecRecordInit(&r2); - r2.rec_type = rec_type; - r2.name = name; - r2.data_type = (data_type != RECD_NULL) ? data_type : r1->data_type; - r2.data = *data; - if (REC_TYPE_IS_STAT(r2.rec_type) && (data_raw != nullptr)) { - r2.stat_meta.data_raw = *data_raw; - } else if (REC_TYPE_IS_CONFIG(r2.rec_type)) { - r2.config_meta.source = source; - } - err = send_set_message(&r2); - RecRecordFree(&r2); } } else { // Add the record but do not set the 'registered' flag, as this @@ -437,9 +194,8 @@ RecSetRecord(RecT rec_type, const char *name, RecDataT data_type, RecData *data, } if (i_am_the_record_owner(r1->rec_type)) { r1->sync_required = r1->sync_required | REC_PEER_SYNC_REQUIRED; - } else { - err = send_set_message(r1); } + // else, error if from rec_type? g_records_ht.emplace(name, r1); } @@ -693,24 +449,13 @@ RecExecConfigUpdateCbs(unsigned int update_required_type) static RecErrT reset_stat_record(RecRecord *rec) { - RecErrT err; + RecErrT err = REC_ERR_FAIL; if (i_am_the_record_owner(rec->rec_type)) { rec_mutex_acquire(&(rec->lock)); ++(rec->version); err = RecDataSet(rec->data_type, &(rec->data), &(rec->data_default)) ? REC_ERR_OKAY : REC_ERR_FAIL; rec_mutex_release(&(rec->lock)); - } else { - RecRecord r2; - - RecRecordInit(&r2); - r2.rec_type = rec->rec_type; - r2.name = rec->name; - r2.data_type = rec->data_type; - r2.data = rec->data_default; - - err = send_reset_message(&r2); - RecRecordFree(&r2); } return err; @@ -785,24 +530,6 @@ RecSetSyncRequired(char *name, bool lock) } rec_mutex_release(&(r1->lock)); err = REC_ERR_OKAY; - } else { - // No point of doing the following because our peer will - // set the value with RecDataSet. However, since - // r2.name == r1->name, the sync_required bit will not be - // set. - - /* - RecRecord r2; - - RecRecordInit(&r2); - r2.rec_type = r1->rec_type; - r2.name = r1->name; - r2.data_type = r1->data_type; - r2.data = r1->data_default; - - err = send_set_message(&r2); - RecRecordFree(&r2); - */ } } diff --git a/lib/records/P_RecCore.h b/lib/records/P_RecCore.h index 5840f5d7ef6..9613222d82b 100644 --- a/lib/records/P_RecCore.h +++ b/lib/records/P_RecCore.h @@ -84,10 +84,6 @@ RecErrT RecReadConfigFile(); //------------------------------------------------------------------------- bool i_am_the_record_owner(RecT rec_type); -RecErrT send_push_message(); -RecErrT send_pull_message(RecMessageT msg_type); -RecErrT send_register_message(RecRecord *record); -RecErrT recv_message_cb(RecMessage *msg, RecMessageT msg_type, void *cookie); RecUpdateT RecExecConfigUpdateCbs(unsigned int update_required_type); void RecDumpRecordsHt(RecT rec_type = RECT_NULL); diff --git a/lib/records/P_RecLocal.h b/lib/records/P_RecLocal.h index e9caf32c346..1a838126480 100644 --- a/lib/records/P_RecLocal.h +++ b/lib/records/P_RecLocal.h @@ -22,5 +22,3 @@ */ #pragma once - -#include "I_RecLocal.h" diff --git a/lib/records/P_RecMessage.h b/lib/records/P_RecMessage.h index 24930feb5f6..802c7b3c4cb 100644 --- a/lib/records/P_RecMessage.h +++ b/lib/records/P_RecMessage.h @@ -43,9 +43,7 @@ RecMessage *RecMessageMarshal_Realloc(RecMessage *msg, const RecRecord *record); int RecMessageUnmarshalFirst(RecMessage *msg, RecMessageItr *itr, RecRecord **record); int RecMessageUnmarshalNext(RecMessage *msg, RecMessageItr *itr, RecRecord **record); -int RecMessageSend(RecMessage *msg); int RecMessageRegisterRecvCb(RecMessageRecvCb recv_cb, void *cookie); -void RecMessageRecvThis(ts::MemSpan); RecMessage *RecMessageReadFromDisk(const char *fpath); int RecMessageWriteToDisk(RecMessage *msg, const char *fpath); diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index 4fa791d1e6d..23de562d3ee 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -1262,22 +1262,6 @@ RecConfigReadPersistentStatsPath() return Layout::relative_to(rundir, ts::filename::RECORDS_STATS); } -void -RecSignalWarning(int sig, const char *fmt, ...) -{ - char msg[1024]; - va_list args; - - va_start(args, fmt); - WarningV(fmt, args); - va_end(args); - - va_start(args, fmt); - vsnprintf(msg, sizeof(msg), fmt, args); - RecSignalManager(sig, msg); - va_end(args); -} - //------------------------------------------------------------------------- // RecConfigWarnIfUnregistered //------------------------------------------------------------------------- diff --git a/lib/records/RecLocal.cc b/lib/records/RecLocal.cc deleted file mode 100644 index 4604ef2b0c9..00000000000 --- a/lib/records/RecLocal.cc +++ /dev/null @@ -1,214 +0,0 @@ -/** @file - - Record local definitions - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "ConfigManager.h" -#include "tscore/ParseRules.h" -#include "P_RecCore.h" -#include "P_RecLocal.h" -#include "P_RecMessage.h" -#include "P_RecUtils.h" -#include "P_RecFile.h" -#include "LocalManager.h" -#include "FileManager.h" -#include - -// Marks whether the message handler has been initialized. -static bool message_initialized_p = false; - -//------------------------------------------------------------------------- -// i_am_the_record_owner, only used for libreclocal.a -//------------------------------------------------------------------------- -bool -i_am_the_record_owner(RecT rec_type) -{ - switch (rec_type) { - case RECT_CONFIG: - case RECT_NODE: - case RECT_LOCAL: - return true; - case RECT_PROCESS: - case RECT_PLUGIN: - return false; - default: - ink_assert(!"Unexpected RecT type"); - return false; - } -} - -//------------------------------------------------------------------------- -// sync_thr -//------------------------------------------------------------------------- -static void * -sync_thr(void *data) -{ - FileManager *configFiles = static_cast(data); - - while (!TSSystemState::is_event_system_shut_down()) { - RecBool check = true; - - send_push_message(); - RecSyncStatsFile(); - - // If we didn't successfully sync to disk, check whether we need to update .... - if (check) { - if (configFiles->isConfigStale()) { - RecSetRecordInt("proxy.node.config.reconfigure_required", 1, REC_SOURCE_DEFAULT); - } - } - - usleep(REC_REMOTE_SYNC_INTERVAL_MS * 1000); - } - - return nullptr; -} - -//------------------------------------------------------------------------- -// config_update_thr -//------------------------------------------------------------------------- -static void * -config_update_thr(void * /* data */) -{ - while (!TSSystemState::is_event_system_shut_down()) { - switch (RecExecConfigUpdateCbs(REC_LOCAL_UPDATE_REQUIRED)) { - case RECU_RESTART_TS: - RecSetRecordInt("proxy.node.config.restart_required.proxy", 1, REC_SOURCE_DEFAULT); - break; - case RECU_RESTART_TM: - RecSetRecordInt("proxy.node.config.restart_required.proxy", 1, REC_SOURCE_DEFAULT); - RecSetRecordInt("proxy.node.config.restart_required.manager", 1, REC_SOURCE_DEFAULT); - break; - case RECU_NULL: - case RECU_DYNAMIC: - break; - } - - usleep(REC_CONFIG_UPDATE_INTERVAL_MS * 1000); - } - return nullptr; -} - -//------------------------------------------------------------------------- -// RecMessageInit -//------------------------------------------------------------------------- -void -RecMessageInit() -{ - ink_assert(g_mode_type != RECM_NULL); - lmgmt->registerMgmtCallback(MGMT_SIGNAL_LIBRECORDS, &RecMessageRecvThis); - message_initialized_p = true; -} - -//------------------------------------------------------------------------- -// RecLocalInit -//------------------------------------------------------------------------- -int -RecLocalInit(Diags *_diags) -{ - static bool initialized_p = false; - ; - - if (initialized_p) { - return REC_ERR_OKAY; - } - - g_mode_type = RECM_SERVER; - - if (RecCoreInit(RECM_SERVER, _diags) == REC_ERR_FAIL) { - return REC_ERR_FAIL; - } - - initialized_p = true; - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// RecLocalInitMessage -//------------------------------------------------------------------------- -int -RecLocalInitMessage() -{ - static bool initialized_p = false; - - if (initialized_p) { - return REC_ERR_OKAY; - } - - RecMessageInit(); - if (RecMessageRegisterRecvCb(recv_message_cb, nullptr)) { - return REC_ERR_FAIL; - } - - initialized_p = true; - - return REC_ERR_OKAY; -} - -//------------------------------------------------------------------------- -// RecLocalStart -//------------------------------------------------------------------------- -int -RecLocalStart(FileManager *configFiles) -{ - ink_thread_create(nullptr, sync_thr, configFiles, 0, 0, nullptr); - ink_thread_create(nullptr, config_update_thr, nullptr, 0, 0, nullptr); - return REC_ERR_OKAY; -} - -int -RecRegisterManagerCb(int id, RecManagerCb const &_fn) -{ - return lmgmt->registerMgmtCallback(id, _fn); -} - -void -RecSignalManager(int id, const char *, size_t) -{ - // Signals are messages sent across the management pipe, so by definition, - // you can't send a signal if you are a local process manager. - RecDebug(DL_Debug, "local manager dropping signal %d", id); -} - -//------------------------------------------------------------------------- -// RecMessageSend -//------------------------------------------------------------------------- - -int -RecMessageSend(RecMessage *msg) -{ - int msg_size; - - if (!message_initialized_p) { - return REC_ERR_OKAY; - } - - // Make a copy of the record, but truncate it to the size actually used - if (g_mode_type == RECM_CLIENT || g_mode_type == RECM_SERVER) { - msg->o_end = msg->o_write; - msg_size = sizeof(RecMessageHdr) + (msg->o_write - msg->o_start); - lmgmt->signalEvent(MGMT_EVENT_LIBRECORDS, reinterpret_cast(msg), msg_size); - } - - return REC_ERR_OKAY; -} diff --git a/lib/records/RecMessage.cc b/lib/records/RecMessage.cc index b51aa4d59d5..a4afd8e8c6e 100644 --- a/lib/records/RecMessage.cc +++ b/lib/records/RecMessage.cc @@ -240,17 +240,6 @@ RecMessageRegisterRecvCb(RecMessageRecvCb recv_cb, void *cookie) return REC_ERR_OKAY; } -//------------------------------------------------------------------------- -// RecMessageRecvThis -//------------------------------------------------------------------------- - -void -RecMessageRecvThis(ts::MemSpan span) -{ - RecMessage *msg = static_cast(span.data()); - g_recv_cb(msg, msg->msg_type, g_recv_cookie); -} - //------------------------------------------------------------------------- // RecMessageReadFromDisk //------------------------------------------------------------------------- diff --git a/lib/records/RecProcess.cc b/lib/records/RecProcess.cc index 970f2284b9b..c1bbe72bbb3 100644 --- a/lib/records/RecProcess.cc +++ b/lib/records/RecProcess.cc @@ -33,9 +33,6 @@ #include "P_RecUtils.h" #include "P_RecFile.h" -#include "mgmtapi.h" -#include "ProcessManager.h" - // Marks whether the message handler has been initialized. static bool message_initialized_p = false; static bool g_started = false; @@ -53,20 +50,7 @@ static Event *sync_cont_event; bool i_am_the_record_owner(RecT rec_type) { - if (g_mode_type == RECM_CLIENT) { - switch (rec_type) { - case RECT_PROCESS: - case RECT_PLUGIN: - return true; - case RECT_CONFIG: - case RECT_NODE: - case RECT_LOCAL: - return false; - default: - ink_assert(!"Unexpected RecT type"); - return false; - } - } else if (g_mode_type == RECM_STAND_ALONE) { + if (g_mode_type == RECM_STAND_ALONE) { switch (rec_type) { case RECT_CONFIG: case RECT_PROCESS: @@ -117,24 +101,6 @@ RecProcess_set_remote_sync_interval_ms(int ms) } } -//------------------------------------------------------------------------- -// recv_message_cb__process -//------------------------------------------------------------------------- -static RecErrT -recv_message_cb__process(RecMessage *msg, RecMessageT msg_type, void *cookie) -{ - RecErrT err; - - if ((err = recv_message_cb(msg, msg_type, cookie)) == REC_ERR_OKAY) { - if (msg_type == RECG_PULL_ACK) { - g_force_req_notify.lock(); - g_force_req_notify.signal(); - g_force_req_notify.unlock(); - } - } - return err; -} - //------------------------------------------------------------------------- // raw_stat_sync_cont //------------------------------------------------------------------------- @@ -188,7 +154,6 @@ struct sync_cont : public Continuation { int sync(int /* event */, Event * /* e */) { - send_push_message(); RecSyncStatsFile(); Debug("statsproc", "sync_cont() processed"); @@ -224,10 +189,8 @@ void RecMessageInit() { ink_assert(g_mode_type != RECM_NULL); - pmgmt->registerMgmtCallback(MGMT_EVENT_LIBRECORDS, &RecMessageRecvThis); message_initialized_p = true; } - //------------------------------------------------------------------------- // RecProcessInitMessage //------------------------------------------------------------------------- @@ -241,17 +204,6 @@ RecProcessInitMessage(RecModeT mode_type) } RecMessageInit(); - if (RecMessageRegisterRecvCb(recv_message_cb__process, nullptr)) { - return REC_ERR_FAIL; - } - - if (mode_type == RECM_CLIENT) { - send_pull_message(RECG_PULL_REQ); - g_force_req_notify.lock(); - g_force_req_notify.wait(); - g_force_req_notify.unlock(); - } - initialized_p = true; return REC_ERR_OKAY; @@ -284,39 +236,3 @@ RecProcessStart() return REC_ERR_OKAY; } - -void -RecSignalManager(int id, const char *msg, size_t msgsize) -{ - ink_assert(pmgmt); - pmgmt->signalManager(id, msg, msgsize); -} - -int -RecRegisterManagerCb(int _signal, RecManagerCb const &_fn) -{ - return pmgmt->registerMgmtCallback(_signal, _fn); -} - -//------------------------------------------------------------------------- -// RecMessageSend -//------------------------------------------------------------------------- - -int -RecMessageSend(RecMessage *msg) -{ - int msg_size; - - if (!message_initialized_p) { - return REC_ERR_OKAY; - } - - // Make a copy of the record, but truncate it to the size actually used - if (g_mode_type == RECM_CLIENT || g_mode_type == RECM_SERVER) { - msg->o_end = msg->o_write; - msg_size = sizeof(RecMessageHdr) + (msg->o_write - msg->o_start); - pmgmt->signalManager(MGMT_SIGNAL_LIBRECORDS, reinterpret_cast(msg), msg_size); - } - - return REC_ERR_OKAY; -} diff --git a/lib/records/RecRawStats.cc b/lib/records/RecRawStats.cc index 9d87cbaa898..84030832730 100644 --- a/lib/records/RecRawStats.cc +++ b/lib/records/RecRawStats.cc @@ -267,8 +267,6 @@ _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDa r->rsb_id = id; // This is the index within the RSB raw block for this stat, used for lookups by name. if (i_am_the_record_owner(r->rec_type)) { r->sync_required = r->sync_required | REC_PEER_SYNC_REQUIRED; - } else { - send_register_message(r); } // store a pointer to our record->stat_meta.data_raw in our rsb diff --git a/lib/records/test_I_RecLocal.cc b/lib/records/test_I_RecLocal.cc index 056f1d1c1ea..4cba95a87de 100644 --- a/lib/records/test_I_RecLocal.cc +++ b/lib/records/test_I_RecLocal.cc @@ -21,7 +21,6 @@ limitations under the License. */ -#include "I_RecLocal.h" #include "P_RecUtils.h" #include "test_RecordsConfig.h" diff --git a/lib/records/test_RecProcess.i b/lib/records/test_RecProcess.i index e9c3c918ed9..70c756b9603 100644 --- a/lib/records/test_RecProcess.i +++ b/lib/records/test_RecProcess.i @@ -593,8 +593,6 @@ main(int argc, char **argv) eventProcessor.start(4); RecProcessStart(); - RecSignalManager(1, "This is a signal, signaled by RecSignalManager"); - // See if we're sync'd okay RecDumpRecordsHt(RECT_NULL); diff --git a/mgmt/Alarms.cc b/mgmt/Alarms.cc deleted file mode 100644 index 35f7d641569..00000000000 --- a/mgmt/Alarms.cc +++ /dev/null @@ -1,391 +0,0 @@ -/** @file - - Function defs for the Alarms keeper. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/ink_string.h" -#include "tscore/ink_file.h" -#include "tscore/ink_time.h" -#include "MgmtUtils.h" -#include "Alarms.h" - -#include "records/P_RecCore.h" - -const char *alarmText[] = { - "Unknown Alarm", // 0 - "[TrafficManager] Traffic Server process was reset.", // 1 - "[TrafficManager] Traffic Server process established.", // 2 - "Invalid Configuration", // 3 - "System Error", // 4 - "Cache Error", // 5 - "Cache Warning", // 6 - "Logging Error", // 7 - "Logging Warning", // 8 - "Alarms configuration update failed", // 9 - "Librecords", // 10 (unclear if needed / used) - "Plugin set configuration", // 11 (unclear if needed / used) -}; - -const int alarmTextNum = sizeof(alarmText) / sizeof(char *); - -// Return the alarm script directory. Use proxy.config.alarm.abs_path if it is -// set, falling back to proxy.config.bin_path otherwise. -static char * -alarm_script_dir() -{ - char *path; - - path = REC_readString("proxy.config.alarm.abs_path", nullptr); - if (path && *path) { - return path; - } - - return ats_stringdup(RecConfigReadBinDir()); -} - -Alarms::Alarms() -{ - cur_cb = 0; - ink_mutex_init(&mutex); -} /* End Alarms::Alarms */ - -Alarms::~Alarms() -{ - for (auto &&it : local_alarms) { - ats_free(it.second); - } - for (auto &&it : remote_alarms) { - ats_free(it.second); - } - ink_mutex_destroy(&mutex); -} /* End Alarms::Alarms */ - -void -Alarms::registerCallback(AlarmCallbackFunc func) -{ - char cb_buf[80]; - - ink_mutex_acquire(&mutex); - snprintf(cb_buf, sizeof(cb_buf), "%d", cur_cb++); - Debug("alarm", "[Alarms::registerCallback] Registering Alarms callback"); - cblist.emplace(cb_buf, func); - ink_mutex_release(&mutex); -} /* End Alarms::registerCallback */ - -bool -Alarms::isCurrentAlarm(alarm_t a, char *ip) -{ - bool ret = false; - char buf[80]; - - ink_mutex_acquire(&mutex); - if (!ip) { - snprintf(buf, sizeof(buf), "%d", a); - } else { - snprintf(buf, sizeof(buf), "%d-%s", a, ip); - } - - if (!ip && local_alarms.find(buf) != local_alarms.end()) { - ret = true; - } else if (ip && remote_alarms.find(buf) != remote_alarms.end()) { - ret = true; - } - ink_mutex_release(&mutex); - return ret; -} /* End Alarms::isCurrentAlarm */ - -void -Alarms::resolveAlarm(alarm_t a, char *ip) -{ - char buf[80]; - - ink_mutex_acquire(&mutex); - if (!ip) { - snprintf(buf, sizeof(buf), "%d", a); - } else { - snprintf(buf, sizeof(buf), "%d-%s", a, ip); - } - - if (!ip && local_alarms.find(buf) != local_alarms.end()) { - Alarm *hash_value = local_alarms[buf]; - local_alarms.erase(buf); - ats_free(hash_value->description); - ats_free(hash_value); - } else if (ip && remote_alarms.find(buf) != remote_alarms.end()) { - Alarm *hash_value = remote_alarms[buf]; - remote_alarms.erase(buf); - ats_free(hash_value->description); - ats_free(hash_value); - } - ink_mutex_release(&mutex); - - return; -} /* End Alarms::resolveAlarm */ - -void -Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip) -{ - static time_t last_sent = 0; - static char prev_alarm_text[2048] = ""; - - int priority; - char buf[80]; - Alarm *atmp; - - /* Assign correct priorities */ - switch (a) { - case MGMT_ALARM_PROXY_CACHE_ERROR: - priority = 1; // INKqa07595 - break; - case MGMT_ALARM_PROXY_CACHE_WARNING: - return; - case MGMT_ALARM_PROXY_PROCESS_DIED: - priority = 1; - break; - case MGMT_ALARM_PROXY_PROCESS_BORN: - mgmt_log("[Alarms::signalAlarm] Server Process born\n"); - return; - default: - priority = 2; - break; - } - - /* Quick hack to buffer repeat alarms and only send every 15 min */ - if (desc && (priority == 1 || priority == 2) && !ip) { - if (strcmp(prev_alarm_text, desc) == 0) { /* a repeated alarm */ - time_t time_delta = time(nullptr) - last_sent; - if (time_delta < 900) { - mgmt_log("[Alarms::signalAlarm] Skipping Alarm: '%s'\n", desc); - return; - } else { - last_sent = time(nullptr); - } - } else { - ink_strlcpy(prev_alarm_text, desc, sizeof(prev_alarm_text)); - last_sent = time(nullptr); - } - } - - Debug("alarm", "[Alarms::signalAlarm] Sending Alarm: '%s'", desc); - - if (!desc) { - desc = const_cast(getAlarmText(a)); - } - - /* - * Exec alarm bin for priority alarms every time, regardless if they are - * potentially duplicates. However, only exec this for you own alarms, - * don't want every node in the cluster reporting the same alarm. - */ - if (priority == 1 && !ip) { - execAlarmBin(desc); - } - - ink_mutex_acquire(&mutex); - if (!ip) { - snprintf(buf, sizeof(buf), "%d", a); - if (local_alarms.find(buf) != local_alarms.end()) { - ink_mutex_release(&mutex); - return; - } - } else { - snprintf(buf, sizeof(buf), "%d-%s", a, ip); - if (auto it = remote_alarms.find(buf); it != remote_alarms.end()) { - // Reset the seen flag so that we know the remote alarm is - // still active - atmp = it->second; - atmp->seen = true; - ink_mutex_release(&mutex); - return; - } - } - - atmp = static_cast(ats_malloc(sizeof(Alarm))); - atmp->type = a; - atmp->linger = true; - atmp->seen = true; - atmp->priority = priority; - atmp->description = nullptr; - - if (!ip) { - atmp->local = true; - atmp->inet_address = 0; - local_alarms.emplace(buf, atmp); - } else { - atmp->local = false; - atmp->inet_address = inet_addr(ip); - local_alarms.emplace(buf, atmp); - } - - // Swap desc with time-stamped description. Kinda hackish - // Temporary until we get a new - // alarm system in place. TS 5.0.0, 02/08/2001 - time_t my_time_t; - char my_ctime_str[32]; - time(&my_time_t); - ink_ctime_r(&my_time_t, my_ctime_str); - char *p = my_ctime_str; - while (*p != '\n' && *p != '\0') { - p++; - } - if (*p == '\n') { - *p = '\0'; - } - const size_t sz = sizeof(char) * (strlen(desc) + strlen(my_ctime_str) + 4); - ats_free(atmp->description); - atmp->description = static_cast(ats_malloc(sz)); - snprintf(atmp->description, sz, "[%s] %s", my_ctime_str, desc); - - ink_mutex_release(&mutex); - - for (auto &&it : cblist) { - AlarmCallbackFunc func = it.second; - Debug("alarm", "[Alarms::signalAlarm] invoke callback for %d", a); - (*(func))(a, ip, desc); - } - - /* Priority 2 alarms get signaled if they are the first unsolved occurrence. */ - if (priority == 2 && !ip) { - execAlarmBin(desc); - } - -} /* End Alarms::signalAlarm */ - -/* - * resetSeenFlag(...) - * Function resets the "seen" flag for a given peer's alarms. This allows - * us to flush alarms that may have expired naturally or were dealt. - */ -void -Alarms::resetSeenFlag(char *ip) -{ - ink_mutex_acquire(&mutex); - for (auto &&it : remote_alarms) { - std::string const &key = it.first; - Alarm *tmp = it.second; - if (key.find(ip) != std::string::npos) { - tmp->seen = false; - } - } - ink_mutex_release(&mutex); - return; -} /* End Alarms::resetSeenFlag */ - -/* - * clearUnSeen(...) - * This function is a sweeper function to clean up those alarms that have - * been taken care of through other local managers or at the peer itself. - */ -void -Alarms::clearUnSeen(char *ip) -{ - ink_mutex_acquire(&mutex); - for (auto &&it : remote_alarms) { - std::string const &key = it.first; - Alarm *tmp = it.second; - - if (key.find(ip) != std::string::npos) { /* Make sure alarm is for correct ip */ - if (!tmp->seen) { /* Make sure we did not see it in peer's report */ - remote_alarms.erase(key); - ats_free(tmp->description); - ats_free(tmp); - } - } - } - ink_mutex_release(&mutex); - return; -} /* End Alarms::clearUnSeen */ - -void -Alarms::execAlarmBin(const char *desc) -{ - ats_scoped_str bindir(alarm_script_dir()); - char cmd_line[MAXPATHLEN]; - - ats_scoped_str alarm_bin(REC_readString("proxy.config.alarm.bin", nullptr)); - ats_scoped_str alarm_email_from_name; - ats_scoped_str alarm_email_from_addr; - ats_scoped_str alarm_email_to_addr; - - pid_t pid; - - // If there's no alarm script configured, don't even bother. - if (!alarm_bin || *alarm_bin == '\0') { - return; - } - - ink_filepath_make(cmd_line, sizeof(cmd_line), bindir, alarm_bin); - -#ifdef POSIX_THREAD - if ((pid = fork()) < 0) -#else - if ((pid = fork1()) < 0) -#endif - { - mgmt_elog(errno, "[Alarms::execAlarmBin] Unable to fork1 process\n"); - } else if (pid > 0) { /* Parent */ - int status; - bool script_done = false; - time_t timeout = static_cast(REC_readInteger("proxy.config.alarm.script_runtime", nullptr)); - if (!timeout) { - timeout = 5; // default time = 5 secs - } - time_t time_delta = 0; - time_t first_time = time(nullptr); - while (time_delta <= timeout) { - // waitpid will return child's pid if status is available - // or -1 if there is some problem; returns 0 if child status - // is not available - if (waitpid(pid, &status, WNOHANG) != 0) { - Debug("alarm", "[Alarms::execAlarmBin] child pid %" PRId64 " has status", (int64_t)pid); - script_done = true; - break; - } - time_delta = time(nullptr) - first_time; - } - // need to kill the child script process if it's not complete - if (!script_done) { - Debug("alarm", "[Alarms::execAlarmBin] kill child pid %" PRId64 "", (int64_t)pid); - kill(pid, SIGKILL); - waitpid(pid, &status, 0); // to reap the thread - } - } else { - int res = execl(cmd_line, (const char *)alarm_bin, desc, (char *)nullptr); - - _exit(res); - } -} - -// -// getAlarmText -// -// returns the corresponding text for the alarm id -// -const char * -Alarms::getAlarmText(alarm_t id) -{ - if (id < alarmTextNum) { - return alarmText[id]; - } else { - return alarmText[0]; // "Unknown Alarm"; - } -} diff --git a/mgmt/Alarms.h b/mgmt/Alarms.h deleted file mode 100644 index d42da3105e5..00000000000 --- a/mgmt/Alarms.h +++ /dev/null @@ -1,103 +0,0 @@ -/** @file - - Class definitions for alarms keeper, class keeps a queue of Alarm - objects. Can be polled on status of alarms. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "tscore/ink_mutex.h" -#include -#include - -class AppVersionInfo; - -/*********************************************************************** - * - * MODULARIZATION: if you are adding new alarms, please be sure to add - * the corresponding alarms in lib/records/I_RecAlarms.h - * - ***********************************************************************/ - -// When adding new alarms, please make sure add the -// corresponding alarm text -// -#define MGMT_ALARM_UNDEFINED 0 - -#define MGMT_ALARM_PROXY_PROCESS_DIED 1 -#define MGMT_ALARM_PROXY_PROCESS_BORN 2 -#define MGMT_ALARM_PROXY_CONFIG_ERROR 3 -#define MGMT_ALARM_PROXY_SYSTEM_ERROR 4 -#define MGMT_ALARM_PROXY_CACHE_ERROR 5 -#define MGMT_ALARM_PROXY_CACHE_WARNING 6 -#define MGMT_ALARM_PROXY_LOGGING_ERROR 7 -#define MGMT_ALARM_PROXY_LOGGING_WARNING 8 -#define MGMT_ALARM_CONFIG_UPDATE_FAILED 9 - -extern const char *alarmText[]; -extern const int alarmTextNum; - -typedef int alarm_t; -typedef void (*AlarmCallbackFunc)(alarm_t, const char *, const char *); - -typedef struct _alarm { - alarm_t type; - int priority; - bool linger; - bool local; - bool seen; - unsigned long inet_address; /* If not local */ - char *description; -} Alarm; - -class Alarms -{ -public: - Alarms(); - ~Alarms(); - - void registerCallback(AlarmCallbackFunc func); - bool isCurrentAlarm(alarm_t a, char *ip = nullptr); - - void signalAlarm(alarm_t t, const char *desc, const char *ip = nullptr); - void resolveAlarm(alarm_t a, char *ip = nullptr); - - void constructAlarmMessage(const AppVersionInfo &version, char *ip, char *message, int max); - void resetSeenFlag(char *ip); - void clearUnSeen(char *ip); - - void execAlarmBin(const char *desc); - - const char *getAlarmText(alarm_t id); - std::unordered_map const & - getLocalAlarms() - { - return local_alarms; - } - -private: - int cur_cb; - ink_mutex mutex; - - std::unordered_map cblist; - std::unordered_map local_alarms; - std::unordered_map remote_alarms; -}; /* End class Alarms */ diff --git a/mgmt/BaseManager.cc b/mgmt/BaseManager.cc deleted file mode 100644 index 0f3d8a1e0d9..00000000000 --- a/mgmt/BaseManager.cc +++ /dev/null @@ -1,83 +0,0 @@ -/** @file - - Member function definitions for Base Manager class. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. - See the NOTICE file distributed with this work for additional information regarding copyright - ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance with the License. You may obtain a - copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the License - is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - or implied. See the License for the specific language governing permissions and limitations under - the License. - */ - -#include "tscore/ink_memory.h" -#include "tscore/ink_mutex.h" -#include "BaseManager.h" - -BaseManager::BaseManager() -{ - ink_sem_init(&q_sem, 0); -} - -BaseManager::~BaseManager() -{ - while (!queue.empty()) { - ats_free(queue.front()); - queue.pop(); - } -} - -void -BaseManager::enqueue(MgmtMessageHdr *mh) -{ - std::lock_guard lock(q_mutex); - queue.emplace(mh); - ink_sem_post(&q_sem); -} - -bool -BaseManager::queue_empty() -{ - std::lock_guard lock(q_mutex); - return queue.empty(); -} - -MgmtMessageHdr * -BaseManager::dequeue() -{ - MgmtMessageHdr *msg{nullptr}; - - ink_sem_wait(&q_sem); - { - std::lock_guard lock(q_mutex); - msg = queue.front(); - queue.pop(); - } - return msg; -} - -int -BaseManager::registerMgmtCallback(int msg_id, MgmtCallback const &cb) -{ - auto &cb_list{mgmt_callback_table[msg_id]}; - cb_list.emplace_back(cb); - return msg_id; -} - -void -BaseManager::executeMgmtCallback(int msg_id, ts::MemSpan span) -{ - if (auto it = mgmt_callback_table.find(msg_id); it != mgmt_callback_table.end()) { - for (auto &&cb : it->second) { - cb(span); - } - } -} diff --git a/mgmt/BaseManager.h b/mgmt/BaseManager.h deleted file mode 100644 index 322b6542ee5..00000000000 --- a/mgmt/BaseManager.h +++ /dev/null @@ -1,145 +0,0 @@ -/** @file - - Base Manager Class, base class for all managers. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include - -#include "tscore/ink_thread.h" -#include "tscore/ink_mutex.h" -#include "tscpp/util/MemSpan.h" - -#include "MgmtDefs.h" -#include "MgmtMarshall.h" - -/* - * MgmtEvent defines. - */ - -// Event flows: traffic manager -> traffic server -#define MGMT_EVENT_SYNC_KEY 10000 -#define MGMT_EVENT_SHUTDOWN 10001 -#define MGMT_EVENT_RESTART 10002 -#define MGMT_EVENT_BOUNCE 10003 -#define MGMT_EVENT_CLEAR_STATS 10004 -#define MGMT_EVENT_CONFIG_FILE_UPDATE 10005 -#define MGMT_EVENT_PLUGIN_CONFIG_UPDATE 10006 -#define MGMT_EVENT_ROLL_LOG_FILES 10008 -#define MGMT_EVENT_LIBRECORDS 10009 -// 10010 is unused -// cache storage operations - each is a distinct event. -// this is done because the code paths share nothing but boilerplate logic -// so it's easier to do this than to try to encode an opcode and yet another -// case statement. -#define MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE 10011 -#define MGMT_EVENT_LIFECYCLE_MESSAGE 10012 -#define MGMT_EVENT_DRAIN 10013 -#define MGMT_EVENT_HOST_STATUS_UP 10014 -#define MGMT_EVENT_HOST_STATUS_DOWN 10015 - -/*********************************************************************** - * - * MODULARIZATION: if you are adding new signals, please ensure to add - * the corresponding signals in librecords/I_RecSignals.h - * - * - ***********************************************************************/ - -// Signal flows: traffic server -> traffic manager -#define MGMT_SIGNAL_PID 0 - -#define MGMT_SIGNAL_PROXY_PROCESS_DIED 1 -#define MGMT_SIGNAL_PROXY_PROCESS_BORN 2 -#define MGMT_SIGNAL_CONFIG_ERROR 3 -#define MGMT_SIGNAL_SYSTEM_ERROR 4 -#define MGMT_SIGNAL_CACHE_ERROR 5 -#define MGMT_SIGNAL_CACHE_WARNING 6 -#define MGMT_SIGNAL_LOGGING_ERROR 7 -#define MGMT_SIGNAL_LOGGING_WARNING 8 -#define MGMT_SIGNAL_PLUGIN_SET_CONFIG 9 - -// This are additional on top of the ones defined in Alarms.h. Que? -#define MGMT_SIGNAL_LIBRECORDS 10 -#define MGMT_SIGNAL_CONFIG_FILE_CHILD 11 - -struct MgmtMessageHdr { - int msg_id; - int data_len; - ts::MemSpan - payload() - { - return {this + 1, static_cast(data_len)}; - } -}; - -class BaseManager -{ - using MgmtCallbackList = std::list; - -public: - BaseManager(); - - ~BaseManager(); - - /** Associate a callback function @a func with message identifier @a msg_id. - * - * @param msg_id Message identifier for the callback. - * @param func The callback function. - * @return @a msg_id on success, -1 on failure. - * - * @a msg_id should be one of the @c MGMT_EVENT_... values. - * - * If a management message with @a msg is received, the callbacks for that message id - * are invoked and passed the message payload (not including the header). - */ - int registerMgmtCallback(int msg_id, MgmtCallback const &func); - - /// Add a @a msg to the queue. - /// This must be the entire message as read off the wire including the header. - void enqueue(MgmtMessageHdr *msg); - - /// Current size of the queue. - /// @note This does not block on the semaphore. - bool queue_empty(); - - /// Dequeue a msg. - /// This waits on the semaphore for a message to arrive. - MgmtMessageHdr *dequeue(); - -protected: - void executeMgmtCallback(int msg_id, ts::MemSpan span); - - /// The mapping from an event type to a list of callbacks to invoke. - std::unordered_map mgmt_callback_table; - - /// Message queue. - // These holds the entire message object, including the header. - std::queue queue; - /// Locked access to the queue. - std::mutex q_mutex; - /// Semaphore to signal queue state. - ink_semaphore q_sem; -}; diff --git a/mgmt/ConfigManager.cc b/mgmt/ConfigManager.cc deleted file mode 100644 index 2f2a8306327..00000000000 --- a/mgmt/ConfigManager.cc +++ /dev/null @@ -1,127 +0,0 @@ -/** @file - - This file contains code for class to allow management of configuration files - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/ink_memory.h" -#include "tscore/ink_time.h" -#include "Alarms.h" -#include "LocalManager.h" -#include "ConfigManager.h" -#include "WebMgmtUtils.h" -#include "ExpandingArray.h" -#include "MgmtSocket.h" -#include "tscore/I_Layout.h" -#include "FileManager.h" -#include "ProxyConfig.h" - -#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC -#define TS_ARCHIVE_STAT_MTIME(t) ((t).st_mtime * 1000000000 + (t).st_mtimespec.tv_nsec) -#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC -#define TS_ARCHIVE_STAT_MTIME(t) ((t).st_mtime * 1000000000 + (t).st_mtim.tv_nsec) -#else -#define TS_ARCHIVE_STAT_MTIME(t) ((t).st_mtime * 1000000000) -#endif - -ConfigManager::ConfigManager(const char *fileName_, const char *configName_, bool root_access_needed_, bool isRequired_, - ConfigManager *parentConfig_) - : root_access_needed(root_access_needed_), isRequired(isRequired_), parentConfig(parentConfig_) -{ - ExpandingArray existVer(25, true); // Existing versions - struct stat fileInfo; - ink_assert(fileName_ != nullptr); - - // parent must not also have a parent - if (parentConfig) { - ink_assert(parentConfig->parentConfig == nullptr); - } - - // Copy the file name. - fileName = std::string{fileName_}; - configName = std::string{configName_}; - - ink_mutex_init(&fileAccessLock); - // Check to make sure that our configuration file exists - // - if (statFile(&fileInfo) < 0) { - mgmt_log("[ConfigManager::ConfigManager] %s Unable to load: %s", fileName.c_str(), strerror(errno)); - - if (isRequired) { - mgmt_fatal(0, "[ConfigManager::ConfigManager] Unable to open required configuration file %s.\n\tStat failed : %s\n", - fileName.c_str(), strerror(errno)); - } - } else { - fileLastModified = TS_ARCHIVE_STAT_MTIME(fileInfo); - } -} - -// -// -// int ConfigManager::statFile() -// -// A wrapper for stat() -// -int -ConfigManager::statFile(struct stat *buf) -{ - int statResult; - std::string sysconfdir(RecConfigReadConfigDir()); - std::string filePath = Layout::get()->relative_to(sysconfdir, fileName); - - statResult = root_access_needed ? elevating_stat(filePath.c_str(), buf) : stat(filePath.c_str(), buf); - - return statResult; -} - -// bool ConfigManager::checkForUserUpdate(RollBackCheckType how) -// -// Called to check if the file has been changed by the user. -// Timestamps are compared to see if a change occurred -bool -ConfigManager::checkForUserUpdate(RollBackCheckType how) -{ - struct stat fileInfo; - bool result; - - ink_mutex_acquire(&fileAccessLock); - - if (this->statFile(&fileInfo) < 0) { - ink_mutex_release(&fileAccessLock); - return false; - } - - if (fileLastModified < TS_ARCHIVE_STAT_MTIME(fileInfo)) { - if (how == ROLLBACK_CHECK_AND_UPDATE) { - fileLastModified = TS_ARCHIVE_STAT_MTIME(fileInfo); - if (!this->isChildManaged()) { - configFiles->fileChanged(fileName.c_str(), configName.c_str()); - } - mgmt_log("User has changed config file %s\n", fileName.c_str()); - } - result = true; - } else { - result = false; - } - - ink_mutex_release(&fileAccessLock); - return result; -} diff --git a/mgmt/ConfigManager.h b/mgmt/ConfigManager.h deleted file mode 100644 index f9210616a1d..00000000000 --- a/mgmt/ConfigManager.h +++ /dev/null @@ -1,132 +0,0 @@ -/** @file - - Interface for class to allow management of configuration files - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "tscore/ink_mutex.h" -#include "tscore/List.h" - -#include - -class FileManager; -class TextBuffer; - -class ExpandingArray; - -enum RollBackCheckType { - ROLLBACK_CHECK_AND_UPDATE, - ROLLBACK_CHECK_ONLY, -}; - -// -// class ConfigManager -// -// public functions -// -// checkForUserUpdate() - compares the last known modification time -// of the active version of the file with that files current modification -// time. Returns true if the file has been changed manually or false -// if it hasn't -// -// private functions -// -// statFile(struct stat*) - a wrapper for stat(), using layout engine -// -class ConfigManager -{ -public: - // fileName_ should be rooted or a base file name. - ConfigManager(const char *fileName_, const char *configName_, bool root_access_needed, bool isRequired_, - ConfigManager *parentConfig_); - ~ConfigManager() = default; - - // Manual take out of lock required - void - acquireLock() - { - ink_mutex_acquire(&fileAccessLock); - }; - - void - releaseLock() - { - ink_mutex_release(&fileAccessLock); - }; - - // Check if a file has changed, automatically holds the lock. Used by FileManager. - bool checkForUserUpdate(RollBackCheckType); - - // These are getters, for FileManager to get info about a particular configuration. - const char * - getFileName() const - { - return fileName.c_str(); - } - - const char * - getConfigName() const - { - return configName.c_str(); - } - - bool - isChildManaged() const - { - return parentConfig != nullptr; - } - - ConfigManager * - getParentConfig() const - { - return parentConfig; - } - - bool - rootAccessNeeded() const - { - return root_access_needed; - } - - bool - getIsRequired() const - { - return isRequired; - } - - FileManager *configFiles = nullptr; // Manager to notify on an update. - - // noncopyable - ConfigManager(const ConfigManager &) = delete; - ConfigManager &operator=(const ConfigManager &) = delete; - -private: - int statFile(struct stat *buf); - - ink_mutex fileAccessLock; - std::string fileName; - std::string configName; - bool root_access_needed; - bool isRequired; - ConfigManager *parentConfig; - time_t fileLastModified = 0; -}; diff --git a/mgmt/DerivativeMetrics.cc b/mgmt/DerivativeMetrics.cc index 16572db439e..3a3987517bc 100644 --- a/mgmt/DerivativeMetrics.cc +++ b/mgmt/DerivativeMetrics.cc @@ -30,7 +30,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This currently only supports one type of derivative metrics: Sums() of other, existing metrics. It's ok to add -// additional metrics here, and we prefer to call them proxy.process (since, hopefully in the future, traffic_manager dies). +// additional metrics here, and we prefer to call them proxy.process now that traffic_manager died. // static const std::vector sum_metrics = { // Total bytes of client request body + headers diff --git a/mgmt/DerivativeMetrics.h b/mgmt/DerivativeMetrics.h index 2109f02ee87..cc8db1bdc27 100644 --- a/mgmt/DerivativeMetrics.h +++ b/mgmt/DerivativeMetrics.h @@ -24,8 +24,7 @@ #pragma once #include - -#include "records/I_RecLocal.h" +#include "records/I_RecDefs.h" using DerivativeSum = std::tuple>; diff --git a/mgmt/FileManager.cc b/mgmt/FileManager.cc deleted file mode 100644 index fce09a0dcf2..00000000000 --- a/mgmt/FileManager.cc +++ /dev/null @@ -1,265 +0,0 @@ -/** @file - - Code for class to manage configuration updates - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "FileManager.h" -#include "tscore/ink_platform.h" -#include "tscore/ink_file.h" -#include "ConfigManager.h" -#include "WebMgmtUtils.h" - -#include -#include - -FileManager::FileManager() -{ - ink_mutex_init(&accessLock); - ink_mutex_init(&cbListLock); -} - -// FileManager::~FileManager -// -// There is only FileManager object in the process and it -// should never need to be destructed except at -// program exit -// -FileManager::~FileManager() -{ - callbackListable *cb; - - // Let other operations finish and do not start any new ones - ink_mutex_acquire(&accessLock); - - for (cb = cblist.pop(); cb != nullptr; cb = cblist.pop()) { - delete cb; - } - for (auto &&it : bindings) { - delete it.second; - } - - ink_mutex_release(&accessLock); - ink_mutex_destroy(&accessLock); - ink_mutex_destroy(&cbListLock); -} - -// void FileManager::registerCallback(FileCallbackFunc func) -// -// Adds a new callback function -// callbacks are made whenever a configuration file has -// changed -// -// The callback function is responsible for free'ing -// the string the string it is passed -// -void -FileManager::registerCallback(FileCallbackFunc func) -{ - callbackListable *newcb = new callbackListable(); - ink_assert(newcb != nullptr); - newcb->func = func; - ink_mutex_acquire(&cbListLock); - cblist.push(newcb); - ink_mutex_release(&cbListLock); -} - -// void FileManager::addFile(char* fileName, const configFileInfo* file_info, -// ConfigManager* parentConfig) -// -// for the baseFile, creates a ConfigManager object for it -// -// if file_info is not null, a WebFileEdit object is also created for -// the file -// -// Pointers to the new objects are stored in the bindings hashtable -// -void -FileManager::addFile(const char *fileName, const char *configName, bool root_access_needed, bool isRequired, - ConfigManager *parentConfig) -{ - ink_mutex_acquire(&accessLock); - addFileHelper(fileName, configName, root_access_needed, isRequired, parentConfig); - ink_mutex_release(&accessLock); -} - -// caller must hold the lock -void -FileManager::addFileHelper(const char *fileName, const char *configName, bool root_access_needed, bool isRequired, - ConfigManager *parentConfig) -{ - ink_assert(fileName != nullptr); - - ConfigManager *rb = new ConfigManager(fileName, configName, root_access_needed, isRequired, parentConfig); - rb->configFiles = this; - - bindings.emplace(rb->getFileName(), rb); -} - -// bool FileManager::getConfigManagerObj(char* fileName, ConfigManager** rbPtr) -// -// Sets rbPtr to the ConfigManager object associated -// with the passed in fileName. -// -// If there is no binding, false is returned -// -bool -FileManager::getConfigObj(const char *fileName, ConfigManager **rbPtr) -{ - ink_mutex_acquire(&accessLock); - auto it = bindings.find(fileName); - bool found = it != bindings.end(); - ink_mutex_release(&accessLock); - - *rbPtr = found ? it->second : nullptr; - return found; -} - -// bool FileManager::fileChanged(const char* fileName) -// -// Called by the ConfigManager class whenever a config has changed -// Initiates callbacks -// -// -void -FileManager::fileChanged(const char *fileName, const char *configName) -{ - callbackListable *cb; - char *filenameCopy, *confignameCopy; - Debug("lm", "filename changed %s", fileName); - ink_mutex_acquire(&cbListLock); - - for (cb = cblist.head; cb != nullptr; cb = cb->link.next) { - // Dup the string for each callback to be - // defensive in case it's modified when it's not supposed to be - confignameCopy = ats_strdup(configName); - filenameCopy = ats_strdup(fileName); - (*cb->func)(filenameCopy, confignameCopy); - ats_free(filenameCopy); - ats_free(confignameCopy); - } - ink_mutex_release(&cbListLock); -} - -// void FileManger::rereadConfig() -// -// Iterates through the list of managed files and -// calls ConfigManager::checkForUserUpdate on them -// -// although it is tempting, DO NOT CALL FROM SIGNAL HANDLERS -// This function is not Async-Signal Safe. It -// is thread safe -void -FileManager::rereadConfig() -{ - ConfigManager *rb; - - std::vector changedFiles; - std::vector parentFileNeedChange; - size_t n; - ink_mutex_acquire(&accessLock); - for (auto &&it : bindings) { - rb = it.second; - // ToDo: rb->isVersions() was always true before, because numberBackups was always >= 1. So ROLLBACK_CHECK_ONLY could not - // happen at all... - if (rb->checkForUserUpdate(ROLLBACK_CHECK_AND_UPDATE)) { - changedFiles.push_back(rb); - if (rb->isChildManaged()) { - if (std::find(parentFileNeedChange.begin(), parentFileNeedChange.end(), rb->getParentConfig()) == - parentFileNeedChange.end()) { - parentFileNeedChange.push_back(rb->getParentConfig()); - } - } - } - } - - std::vector childFileNeedDelete; - n = changedFiles.size(); - for (size_t i = 0; i < n; i++) { - if (changedFiles[i]->isChildManaged()) { - continue; - } - // for each parent file, if it is changed, then delete all its children - for (auto &&it : bindings) { - rb = it.second; - if (rb->getParentConfig() == changedFiles[i]) { - if (std::find(childFileNeedDelete.begin(), childFileNeedDelete.end(), rb) == childFileNeedDelete.end()) { - childFileNeedDelete.push_back(rb); - } - } - } - } - n = childFileNeedDelete.size(); - for (size_t i = 0; i < n; i++) { - bindings.erase(childFileNeedDelete[i]->getFileName()); - delete childFileNeedDelete[i]; - } - ink_mutex_release(&accessLock); - - n = parentFileNeedChange.size(); - for (size_t i = 0; i < n; i++) { - if (std::find(changedFiles.begin(), changedFiles.end(), parentFileNeedChange[i]) == changedFiles.end()) { - fileChanged(parentFileNeedChange[i]->getFileName(), parentFileNeedChange[i]->getConfigName()); - } - } - // INKqa11910 - // need to first check that enable_customizations is enabled - bool found; - int enabled = static_cast(REC_readInteger("proxy.config.body_factory.enable_customizations", &found)); - - if (found && enabled) { - fileChanged("proxy.config.body_factory.template_sets_dir", "proxy.config.body_factory.template_sets_dir"); - } - fileChanged("proxy.config.ssl.server.ticket_key.filename", "proxy.config.ssl.server.ticket_key.filename"); -} - -bool -FileManager::isConfigStale() -{ - ConfigManager *rb; - bool stale = false; - - ink_mutex_acquire(&accessLock); - for (auto &&it : bindings) { - rb = it.second; - if (rb->checkForUserUpdate(ROLLBACK_CHECK_ONLY)) { - stale = true; - break; - } - } - - ink_mutex_release(&accessLock); - return stale; -} - -// void configFileChild(const char *parent, const char *child) -// -// Add child to the bindings with parentConfig -void -FileManager::configFileChild(const char *parent, const char *child) -{ - ConfigManager *parentConfig = nullptr; - ink_mutex_acquire(&accessLock); - if (auto it = bindings.find(parent); it != bindings.end()) { - parentConfig = it->second; - addFileHelper(child, "", parentConfig->rootAccessNeeded(), parentConfig->getIsRequired(), parentConfig); - } - ink_mutex_release(&accessLock); -} diff --git a/mgmt/FileManager.h b/mgmt/FileManager.h deleted file mode 100644 index 64725b620a7..00000000000 --- a/mgmt/FileManager.h +++ /dev/null @@ -1,101 +0,0 @@ -/** @file - - Interface for class to manage configuration updates - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "tscore/ink_mutex.h" -#include "tscore/List.h" - -#include - -class ExpandingArray; -class ConfigManager; - -typedef void (*FileCallbackFunc)(char *, char *); - -struct callbackListable { -public: - FileCallbackFunc func; - LINK(callbackListable, link); -}; - -enum lockAction_t { - ACQUIRE_LOCK, - RELEASE_LOCK, -}; - -// class FileManager -// -// public functions: -// -// addFile(char*, char *, bool, configFileInfo*) - adds a new config file to be -// managed. A ConfigManager object is created for the file. -// if the file_info ptr is not NULL, a WebFileEdit object -// is also created -// -// getRollbckObj(char* , ConfigManagerPtr**) - sets *rbPtr to ConfigManager -// object bound to fileName. Returns true if there is -// a binding and false otherwise -// -// getWFEObj(char*, WebFileEdit**) - sets *wfePtr to WebFileEdit -// object bound to fileName. Returns true if there is -// a binding and false otherwise -// -// registerCallback(FileCallbackFunc) - registers a callback function -// which will get called every time a managed file changes. The -// callback function should NOT use the calling thread to -// access any ConfigManager objects or block for a long time -// -// fileChanged(const char* fileName, const char *configName) - called by ConfigManager objects -// when their contents change. Triggers callbacks to FileCallbackFuncs -// -// isConfigStale() - returns whether the in-memory files might be stale -// compared to what is on disk. -// -// rereadConfig() - Checks all managed files to see if they have been -// updated -// addConfigFileGroup(char* data_str, int data_size) - update config file group infos -class FileManager -{ -public: - FileManager(); - ~FileManager(); - void addFile(const char *fileName, const char *configName, bool root_access_needed, bool isRequired, - ConfigManager *parentConfig = nullptr); - bool getConfigObj(const char *fileName, ConfigManager **rbPtr); - void registerCallback(FileCallbackFunc func); - void fileChanged(const char *fileName, const char *configName); - void rereadConfig(); - bool isConfigStale(); - void configFileChild(const char *parent, const char *child); - -private: - ink_mutex accessLock; // Protects bindings hashtable - ink_mutex cbListLock; // Protects the CallBack List - DLL cblist; - std::unordered_map bindings; - void addFileHelper(const char *fileName, const char *configName, bool root_access_needed, bool isRequired, - ConfigManager *parentConfig); -}; - -void initializeRegistry(); // implemented in AddConfigFilesHere.cc diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc deleted file mode 100644 index 9a1a0d2f4b8..00000000000 --- a/mgmt/LocalManager.cc +++ /dev/null @@ -1,1124 +0,0 @@ -/** @file - - The Local Manager process of the management system. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/ink_sock.h" -#include "tscore/ink_file.h" -#include "tscore/ink_error.h" -#include "Alarms.h" -#include "MgmtUtils.h" -#include "tscore/I_Layout.h" -#include "tscore/runroot.h" -#include "LocalManager.h" -#include "MgmtSocket.h" -#include "tscore/ink_cap.h" -#include "FileManager.h" -#include -#include -#include "tscpp/util/TextView.h" -#include "tscore/BufferWriter.h" -#include "tscore/bwf_std_format.h" -#include "tscore/Filenames.h" - -#if TS_USE_POSIX_CAP -#include -#endif - -using namespace std::literals; -static const std::string_view MGMT_OPT{"-M"}; -static const std::string_view RUNROOT_OPT{"--run-root="}; - -void -LocalManager::mgmtCleanup() -{ - close_socket(process_server_sockfd); - process_server_sockfd = ts::NO_FD; - -#if HAVE_EVENTFD - if (wakeup_fd != ts::NO_FD) { - close_socket(wakeup_fd); - wakeup_fd = ts::NO_FD; - } -#endif - - // fix me for librecords - - closelog(); - return; -} - -void -LocalManager::mgmtShutdown() -{ - mgmt_log("[LocalManager::mgmtShutdown] Executing shutdown request.\n"); - processShutdown(true); - // WCCP TBD: Send a shutdown message to routers. - - if (processRunning()) { - waitpid(watched_process_pid, nullptr, 0); -#if defined(linux) - /* Avert race condition, wait for the thread to complete, - before getting one more restart process */ - /* Workaround for bugid INKqa10060 */ - mgmt_sleep_msec(1); -#endif - } - mgmtCleanup(); -} - -void -LocalManager::processShutdown(bool mainThread) -{ - mgmt_log("[LocalManager::processShutdown] Executing process shutdown request.\n"); - if (mainThread) { - sendMgmtMsgToProcesses(MGMT_EVENT_SHUTDOWN, "processShutdown[main]"); - } else { - signalEvent(MGMT_EVENT_SHUTDOWN, "processShutdown"); - } - return; -} - -void -LocalManager::processRestart() -{ - mgmt_log("[LocalManager::processRestart] Executing process restart request.\n"); - signalEvent(MGMT_EVENT_RESTART, "processRestart"); - return; -} - -void -LocalManager::processBounce() -{ - mgmt_log("[LocalManager::processBounce] Executing process bounce request.\n"); - signalEvent(MGMT_EVENT_BOUNCE, "processBounce"); - return; -} - -void -LocalManager::processDrain(int to_drain) -{ - mgmt_log("[LocalManager::processDrain] Executing process drain request.\n"); - signalEvent(MGMT_EVENT_DRAIN, to_drain ? "1" : "0"); - return; -} - -void -LocalManager::rollLogFiles() -{ - mgmt_log("[LocalManager::rollLogFiles] Log files are being rolled.\n"); - signalEvent(MGMT_EVENT_ROLL_LOG_FILES, "rollLogs"); - return; -} - -void -LocalManager::hostStatusSetDown(const char *marshalled_req, int len) -{ - signalEvent(MGMT_EVENT_HOST_STATUS_DOWN, marshalled_req, len); - return; -} - -void -LocalManager::hostStatusSetUp(const char *marshalled_req, int len) -{ - signalEvent(MGMT_EVENT_HOST_STATUS_UP, marshalled_req, len); - return; -} - -void -LocalManager::clearStats(const char *name) -{ - // Clear our records and then send the signal. There is a race condition - // here where our stats could get re-updated from the proxy - // before the proxy clears them, but this should be rare. - // - // Doing things in the opposite order prevents that race - // but exacerbates the race between the node and cluster - // stats getting cleared by propagation of clearing the - // cluster stats - // - if (name && *name) { - RecResetStatRecord(name); - } else { - RecResetStatRecord(RECT_NULL, true); - } - - // If the proxy is not running, sending the signal does - // not do anything. Remove the stats file to make sure - // that operation works even when the proxy is off - // - if (this->proxy_running == 0) { - ats_scoped_str statsPath(RecConfigReadPersistentStatsPath()); - if (unlink(statsPath) < 0) { - if (errno != ENOENT) { - mgmt_log("[LocalManager::clearStats] Unlink of %s failed : %s\n", (const char *)statsPath, strerror(errno)); - } - } - } -} - -bool -LocalManager::processRunning() -{ - if (watched_process_fd != ts::NO_FD && watched_process_pid != -1) { - return true; - } else { - return false; - } -} - -LocalManager::LocalManager(bool proxy_on, bool listen) : BaseManager(), run_proxy(proxy_on), listen_for_proxy(listen) -{ - bool found; - std::string bindir(RecConfigReadBinDir()); - std::string sysconfdir(RecConfigReadConfigDir()); - - manager_started_at = time(nullptr); - - RecRegisterStatInt(RECT_NODE, "proxy.node.proxy_running", 0, RECP_NON_PERSISTENT); - - RecInt http_enabled = REC_readInteger("proxy.config.http.enabled", &found); - ink_assert(found); - if (http_enabled && found) { - HttpProxyPort::loadConfig(m_proxy_ports); - } - HttpProxyPort::loadDefaultIfEmpty(m_proxy_ports); - - // Get the default IP binding values. - RecHttpLoadIp("proxy.local.incoming_ip_to_bind", m_inbound_ip4, m_inbound_ip6); - - if (access(sysconfdir.c_str(), R_OK) == -1) { - mgmt_log("[LocalManager::LocalManager] unable to access() directory '%s': %d, %s\n", sysconfdir.c_str(), errno, - strerror(errno)); - mgmt_fatal(0, "[LocalManager::LocalManager] please set the 'TS_ROOT' environment variable\n"); - } - -#if TS_HAS_WCCP - // Bind the WCCP address if present. - ats_scoped_str wccp_addr_str(REC_readString("proxy.config.wccp.addr", &found)); - if (found && wccp_addr_str && *wccp_addr_str) { - wccp_cache.setAddr(inet_addr(wccp_addr_str)); - mgmt_log("[LocalManager::LocalManager] WCCP identifying address set to %s.\n", static_cast(wccp_addr_str)); - } - - ats_scoped_str wccp_config_str(RecConfigReadConfigPath("proxy.config.wccp.services")); - if (wccp_config_str && strlen(wccp_config_str) > 0) { - bool located = true; - if (access(wccp_config_str, R_OK) == -1) { - located = false; - } - - if (located) { - wccp_cache.loadServicesFromFile(wccp_config_str); - } else { // not located - mgmt_log("[LocalManager::LocalManager] WCCP service configuration file '%s' was specified but could not be found in the file " - "system.\n", - static_cast(wccp_config_str)); - } - } -#endif - - process_server_timeout_secs = REC_readInteger("proxy.config.lm.pserver_timeout_secs", &found); - process_server_timeout_msecs = REC_readInteger("proxy.config.lm.pserver_timeout_msecs", &found); - proxy_name = REC_readString("proxy.config.proxy_name", &found); - proxy_binary = REC_readString("proxy.config.proxy_binary", &found); - env_prep = REC_readString("proxy.config.env_prep", &found); - - // Calculate proxy_binary from the absolute bin_path - absolute_proxy_binary = ats_stringdup(Layout::relative_to(bindir, proxy_binary)); - - // coverity[fs_check_call] - if (access(absolute_proxy_binary, R_OK | X_OK) == -1) { - mgmt_log("[LocalManager::LocalManager] Unable to access() '%s': %d, %s\n", absolute_proxy_binary, errno, strerror(errno)); - mgmt_fatal(0, "[LocalManager::LocalManager] please set bin path 'proxy.config.bin_path' \n"); - } - - return; -} - -LocalManager::~LocalManager() -{ - delete alarm_keeper; - ats_free(absolute_proxy_binary); - ats_free(proxy_name); - ats_free(proxy_binary); - ats_free(env_prep); -} - -void -LocalManager::initAlarm() -{ - alarm_keeper = new Alarms(); -} - -/* - * initMgmtProcessServer() - * sets up the server socket that proxy processes connect to. - */ -void -LocalManager::initMgmtProcessServer() -{ - std::string rundir(RecConfigReadRuntimeDir()); - std::string sockpath(Layout::relative_to(rundir, LM_CONNECTION_SERVER)); - mode_t oldmask = umask(0); - -#if TS_HAS_WCCP - if (wccp_cache.isConfigured()) { - if (0 > wccp_cache.open()) - mgmt_log("Failed to open WCCP socket\n"); - } -#endif - - process_server_sockfd = bind_unix_domain_socket(sockpath.c_str(), 00700); - if (process_server_sockfd == -1) { - mgmt_fatal(errno, "[LocalManager::initMgmtProcessServer] failed to bind socket at %s\n", sockpath.c_str()); - } - -#if HAVE_EVENTFD - wakeup_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (wakeup_fd < 0) { - mgmt_fatal(errno, "[LocalManager::initMgmtProcessServer] failed to create eventfd. errno : %s\n", strerror(errno)); - } -#endif - - umask(oldmask); - RecSetRecordInt("proxy.node.restarts.manager.start_time", manager_started_at, REC_SOURCE_DEFAULT); -} - -/* - * pollMgmtProcessServer() - * - Function checks the mgmt process server for new processes - * and any requests sent from processes. It handles processes sent. - */ -void -LocalManager::pollMgmtProcessServer() -{ - struct timeval timeout; - fd_set fdlist; - - while (true) { -#if TS_HAS_WCCP - int wccp_fd = wccp_cache.getSocket(); -#endif - - timeout.tv_sec = process_server_timeout_secs; - timeout.tv_usec = process_server_timeout_msecs * 1000; - - FD_ZERO(&fdlist); - - if (process_server_sockfd != ts::NO_FD) { - FD_SET(process_server_sockfd, &fdlist); - } - - if (watched_process_fd != ts::NO_FD) { - FD_SET(watched_process_fd, &fdlist); - } - -#if TS_HAS_WCCP - // Only run WCCP housekeeping while we have a server process. - // Note: The WCCP socket is opened iff WCCP is configured. - if (wccp_fd != ts::NO_FD && watched_process_fd != ts::NO_FD) { - wccp_cache.housekeeping(); - time_t wccp_wait = wccp_cache.waitTime(); - if (wccp_wait < process_server_timeout_secs) - timeout.tv_sec = wccp_wait; - - if (wccp_fd != ts::NO_FD) { - FD_SET(wccp_fd, &fdlist); - } - } -#endif - -#if HAVE_EVENTFD - if (wakeup_fd != ts::NO_FD) { - FD_SET(wakeup_fd, &fdlist); - } -#endif - - int num = mgmt_select(FD_SETSIZE, &fdlist, nullptr, nullptr, &timeout); - - switch (num) { - case 0: - // Timed out, nothing to do. - return; - case -1: - if (mgmt_transient_error()) { - continue; - } - - mgmt_log("[LocalManager::pollMgmtProcessServer] select failed: %s (%d)\n", ::strerror(errno), errno); - return; - - default: - // if we get a wakeup_fd event, we may not want to follow it - // because there may be more data to be read on the socket. - bool keep_polling = false; -#if TS_HAS_WCCP - if (wccp_fd != ts::NO_FD && FD_ISSET(wccp_fd, &fdlist)) { - wccp_cache.handleMessage(); - --num; - keep_polling = true; - } -#endif - - if (process_server_sockfd != ts::NO_FD && FD_ISSET(process_server_sockfd, &fdlist)) { /* New connection */ - struct sockaddr_in clientAddr; - socklen_t clientLen = sizeof(clientAddr); - int new_sockfd = mgmt_accept(process_server_sockfd, reinterpret_cast(&clientAddr), &clientLen); - - mgmt_log("[LocalManager::pollMgmtProcessServer] New process connecting fd '%d'\n", new_sockfd); - - if (new_sockfd < 0) { - mgmt_elog(errno, "[LocalManager::pollMgmtProcessServer] ==> "); - } else if (!processRunning()) { - watched_process_fd = new_sockfd; - } else { - close_socket(new_sockfd); - } - --num; - keep_polling = true; - } - - if (ts::NO_FD != watched_process_fd && FD_ISSET(watched_process_fd, &fdlist)) { - int res; - MgmtMessageHdr mh_hdr; - - keep_polling = true; - - // read the message - if ((res = mgmt_read_pipe(watched_process_fd, reinterpret_cast(&mh_hdr), sizeof(MgmtMessageHdr))) > 0) { - MgmtMessageHdr *mh_full = static_cast(malloc(sizeof(MgmtMessageHdr) + mh_hdr.data_len)); - memcpy(mh_full, &mh_hdr, sizeof(MgmtMessageHdr)); - char *data_raw = reinterpret_cast(mh_full) + sizeof(MgmtMessageHdr); - if ((res = mgmt_read_pipe(watched_process_fd, data_raw, mh_hdr.data_len)) > 0) { - handleMgmtMsgFromProcesses(mh_full); - } else if (res < 0) { - mgmt_fatal(0, "[LocalManager::pollMgmtProcessServer] Error in read (errno: %d)\n", -res); - } - free(mh_full); - } else if (res < 0) { - mgmt_fatal(0, "[LocalManager::pollMgmtProcessServer] Error in read (errno: %d)\n", -res); - } - - // handle EOF - if (res == 0) { - int estatus; - pid_t tmp_pid = watched_process_pid; - - Debug("lm", "[LocalManager::pollMgmtProcessServer] Lost process EOF!"); - - close_socket(watched_process_fd); - - waitpid(watched_process_pid, &estatus, 0); /* Reap child */ - if (WIFSIGNALED(estatus)) { - int sig = WTERMSIG(estatus); - mgmt_log("[LocalManager::pollMgmtProcessServer] Server Process terminated due to Sig %d: %s\n", sig, strsignal(sig)); - } else if (WIFEXITED(estatus)) { - int return_code = WEXITSTATUS(estatus); - - // traffic_server's exit code will be UNRECOVERABLE_EXIT if it calls - // ink_emergency() or ink_emergency_va(). The call signals that traffic_server - // cannot be recovered with a reboot. In other words, catastrophic failure. - if (return_code == UNRECOVERABLE_EXIT) { - proxy_recoverable = false; - } - } - - if (lmgmt->run_proxy) { - mgmt_log("[Alarms::signalAlarm] Server Process was reset\n"); - lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_PROCESS_DIED, nullptr); - } else { - mgmt_log("[TrafficManager] Server process shutdown\n"); - } - - watched_process_fd = watched_process_pid = -1; - if (tmp_pid != -1) { /* Incremented after a pid: message is sent */ - proxy_running--; - } - proxy_started_at = -1; - RecSetRecordInt("proxy.node.proxy_running", 0, REC_SOURCE_DEFAULT); - } - - --num; - } - -#if HAVE_EVENTFD - if (wakeup_fd != ts::NO_FD && FD_ISSET(wakeup_fd, &fdlist)) { - if (!keep_polling) { - // read or else fd will always be set. - uint64_t ignore; - ATS_UNUSED_RETURN(read(wakeup_fd, &ignore, sizeof(uint64_t))); - return; - } - --num; - } -#else - (void)keep_polling; // suppress compiler warning -#endif - - ink_assert(num == 0); /* Invariant */ - } - } -} - -void -LocalManager::handleMgmtMsgFromProcesses(MgmtMessageHdr *mh) -{ - char *data_raw = reinterpret_cast(mh) + sizeof(MgmtMessageHdr); - switch (mh->msg_id) { - case MGMT_SIGNAL_PID: - watched_process_pid = *(reinterpret_cast(data_raw)); - lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_PROCESS_BORN, nullptr); - proxy_running++; - proxy_launch_pid = -1; - proxy_launch_outstanding = false; - RecSetRecordInt("proxy.node.proxy_running", 1, REC_SOURCE_DEFAULT); - break; - - // FIX: This is very messy need to correlate mgmt signals and - // alarms better - case MGMT_SIGNAL_CONFIG_ERROR: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_CONFIG_ERROR, data_raw); - break; - case MGMT_SIGNAL_SYSTEM_ERROR: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_SYSTEM_ERROR, data_raw); - break; - case MGMT_SIGNAL_CACHE_ERROR: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_CACHE_ERROR, data_raw); - break; - case MGMT_SIGNAL_CACHE_WARNING: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_CACHE_WARNING, data_raw); - break; - case MGMT_SIGNAL_LOGGING_ERROR: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_LOGGING_ERROR, data_raw); - break; - case MGMT_SIGNAL_LOGGING_WARNING: - alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_LOGGING_WARNING, data_raw); - break; - case MGMT_SIGNAL_PLUGIN_SET_CONFIG: { - char var_name[256]; - char var_value[256]; - MgmtType stype; - // stype is an enum type, so cast to an int* to avoid warnings. /leif - int tokens = sscanf(data_raw, "%255s %d %255s", var_name, reinterpret_cast(&stype), var_value); - if (tokens != 3) { - stype = MGMT_INVALID; - } - switch (stype) { - case MGMT_INT: - RecSetRecordInt(var_name, ink_atoi64(var_value), REC_SOURCE_EXPLICIT); - break; - case MGMT_COUNTER: - case MGMT_FLOAT: - case MGMT_STRING: - case MGMT_INVALID: - default: - mgmt_log("[LocalManager::handleMgmtMsgFromProcesses] " - "Invalid plugin set-config msg '%s'\n", - data_raw); - break; - } - } break; - case MGMT_SIGNAL_LIBRECORDS: - if (mh->data_len > 0) { - executeMgmtCallback(MGMT_SIGNAL_LIBRECORDS, {data_raw, static_cast(mh->data_len)}); - } else { - executeMgmtCallback(MGMT_SIGNAL_LIBRECORDS, {}); - } - break; - case MGMT_SIGNAL_CONFIG_FILE_CHILD: { - static const MgmtMarshallType fields[] = {MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING}; - char *parent = nullptr; - char *child = nullptr; - if (mgmt_message_parse(data_raw, mh->data_len, fields, countof(fields), &parent, &child) != -1) { - configFiles->configFileChild(parent, child); - } else { - mgmt_log("[LocalManager::handleMgmtMsgFromProcesses] " - "MGMT_SIGNAL_CONFIG_FILE_CHILD mgmt_message_parse error\n"); - } - // Output pointers are guaranteed to be NULL or valid. - ats_free_null(parent); - ats_free_null(child); - } break; - - default: - break; - } -} - -void -LocalManager::sendMgmtMsgToProcesses(int msg_id, const char *data_str) -{ - sendMgmtMsgToProcesses(msg_id, data_str, strlen(data_str) + 1); - return; -} - -void -LocalManager::sendMgmtMsgToProcesses(int msg_id, const char *data_raw, int data_len) -{ - MgmtMessageHdr *mh; - - mh = static_cast(alloca(sizeof(MgmtMessageHdr) + data_len)); - mh->msg_id = msg_id; - mh->data_len = data_len; - memcpy(reinterpret_cast(mh) + sizeof(MgmtMessageHdr), data_raw, data_len); - sendMgmtMsgToProcesses(mh); - return; -} - -void -LocalManager::sendMgmtMsgToProcesses(MgmtMessageHdr *mh) -{ - switch (mh->msg_id) { - case MGMT_EVENT_SHUTDOWN: { - run_proxy = false; - this->closeProxyPorts(); - break; - } - case MGMT_EVENT_RESTART: - run_proxy = true; - listenForProxy(); - return; - case MGMT_EVENT_BOUNCE: /* Just bouncing the cluster, have it exit well restart */ - mh->msg_id = MGMT_EVENT_SHUTDOWN; - break; - case MGMT_EVENT_ROLL_LOG_FILES: - mgmt_log("[LocalManager::SendMgmtMsgsToProcesses]Event is being constructed .\n"); - break; - case MGMT_EVENT_CONFIG_FILE_UPDATE: - bool found; - char *fname = nullptr; - ConfigManager *rb; - char *data_raw; - - data_raw = reinterpret_cast(mh) + sizeof(MgmtMessageHdr); - fname = REC_readString(data_raw, &found); - - RecT rec_type; - if (RecGetRecordType(data_raw, &rec_type) == REC_ERR_OKAY && rec_type == RECT_CONFIG) { - RecSetSyncRequired(data_raw); - } else { - mgmt_log("[LocalManager:sendMgmtMsgToProcesses] Unknown file change: '%s'\n", data_raw); - } - ink_assert(found); - if (!(fname && configFiles && configFiles->getConfigObj(fname, &rb)) && - (strcmp(data_raw, "proxy.config.body_factory.template_sets_dir") != 0) && - (strcmp(data_raw, "proxy.config.ssl.server.ticket_key.filename") != 0)) { - mgmt_fatal(0, "[LocalManager::sendMgmtMsgToProcesses] " - "Invalid 'data_raw' for MGMT_EVENT_CONFIG_FILE_UPDATE\n"); - } - ats_free(fname); - break; - } - - if (watched_process_fd != -1) { - if (mgmt_write_pipe(watched_process_fd, reinterpret_cast(mh), sizeof(MgmtMessageHdr) + mh->data_len) <= 0) { - // In case of Linux, sometimes when the TS dies, the connection between TS and TM - // is not closed properly. the socket does not receive an EOF. So, the TM does - // not detect that the connection and hence TS has gone down. Hence it still - // tries to send a message to TS, but encounters an error and enters here - // Also, ensure that this whole thing is done only once because there will be a - // deluge of message in the traffic.log otherwise - - static pid_t check_prev_pid = watched_process_pid; - static pid_t check_current_pid = watched_process_pid; - if (check_prev_pid != watched_process_pid) { - check_prev_pid = watched_process_pid; - check_current_pid = watched_process_pid; - } - - if (check_prev_pid == check_current_pid) { - check_current_pid = -1; - int lerrno = errno; - mgmt_elog(errno, "[LocalManager::sendMgmtMsgToProcesses] Error writing message\n"); - if (lerrno == ECONNRESET || lerrno == EPIPE) { // Connection closed by peer or Broken pipe - if ((kill(watched_process_pid, 0) < 0) && (errno == ESRCH)) { - // TS is down - pid_t tmp_pid = watched_process_pid; - close_socket(watched_process_fd); - mgmt_log("[LocalManager::pollMgmtProcessServer] " - "Server Process has been terminated\n"); - if (lmgmt->run_proxy) { - mgmt_log("[Alarms::signalAlarm] Server Process was reset\n"); - lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_PROCESS_DIED, nullptr); - } else { - mgmt_log("[TrafficManager] Server process shutdown\n"); - } - watched_process_fd = watched_process_pid = -1; - if (tmp_pid != -1) { /* Incremented after a pid: message is sent */ - proxy_running--; - } - proxy_started_at = -1; - RecSetRecordInt("proxy.node.proxy_running", 0, REC_SOURCE_DEFAULT); - // End of TS down - } else { - // TS is still up, but the connection is lost - const char *err_msg = "The TS-TM connection is broken for some reason. Either restart TS and TM or correct this error " - "for TM to display TS statistics correctly"; - lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_SYSTEM_ERROR, err_msg); - } - - // check if the TS is down, by checking the pid - // if TS is down, then, - // raise an alarm - // set the variables so that TS is restarted later - // else (TS is still up) - // raise an alarm stating the problem - } - } - } - } -} - -void -LocalManager::signalFileChange(const char *var_name) -{ - signalEvent(MGMT_EVENT_CONFIG_FILE_UPDATE, var_name); - - return; -} - -void -LocalManager::signalEvent(int msg_id, const char *data_str) -{ - signalEvent(msg_id, data_str, strlen(data_str) + 1); - return; -} - -void -LocalManager::signalEvent(int msg_id, const char *data_raw, int data_len) -{ - MgmtMessageHdr *mh; - size_t n = sizeof(MgmtMessageHdr) + data_len; - - mh = static_cast(ats_malloc(n)); - mh->msg_id = msg_id; - mh->data_len = data_len; - auto payload = mh->payload(); - memcpy(payload.data(), data_raw, data_len); - this->enqueue(mh); - // ink_assert(enqueue(mgmt_event_queue, mh)); - -#if HAVE_EVENTFD - // we don't care about the actual value of wakeup_fd, so just keep adding 1. just need to - // wakeup the fd. also, note that wakeup_fd was initialized to non-blocking so we can - // directly write to it without any timeout checking. - // - // don't trigger if MGMT_EVENT_LIBRECORD because they happen all the time - // and don't require a quick response. for MGMT_EVENT_LIBRECORD, rely on timeouts so - // traffic_server can spend more time doing other things - uint64_t one = 1; - if (wakeup_fd != ts::NO_FD && mh->msg_id != MGMT_EVENT_LIBRECORDS) { - ATS_UNUSED_RETURN(write(wakeup_fd, &one, sizeof(uint64_t))); // trigger to stop polling - } -#endif -} - -/* - * processEventQueue() - * Function drains and processes the mgmt event queue - * notifying any registered callback functions and performing - * any mgmt tasks for each event. - */ -void -LocalManager::processEventQueue() -{ - while (!this->queue_empty()) { - bool handled_by_mgmt = false; - - MgmtMessageHdr *mh = this->dequeue(); - auto payload = mh->payload().rebind(); - - // check if we have a local file update - if (mh->msg_id == MGMT_EVENT_CONFIG_FILE_UPDATE) { - // records.config - if (!(strcmp(payload.begin(), ts::filename::RECORDS))) { - if (RecReadConfigFile() != REC_ERR_OKAY) { - mgmt_elog(errno, "[fileUpdated] Config update failed for %s\n", ts::filename::RECORDS); - } else { - RecConfigWarnIfUnregistered(); - } - handled_by_mgmt = true; - } - } - - if (!handled_by_mgmt) { - if (processRunning() == false) { - // Fix INKqa04984 - // If traffic server hasn't completely come up yet, - // we will hold off until next round. - this->enqueue(mh); - return; - } - Debug("lm", "[TrafficManager] ==> Sending signal event '%d' %s payload=%d", mh->msg_id, payload.begin(), int(payload.size())); - lmgmt->sendMgmtMsgToProcesses(mh); - } - ats_free(mh); - } -} - -/* - * startProxy() - * Function fires up a proxy process. - * - * Args: - * onetime_options: one time options that traffic_server should be started with (ie - * these options do not persist across reboots) - */ -static const size_t OPTIONS_SIZE = 16384; // Arbitrary max size for command line option string - -bool -LocalManager::startProxy(const char *onetime_options) -{ - if (proxy_launch_outstanding) { - return false; - } - mgmt_log("[LocalManager::startProxy] Launching ts process\n"); - - pid_t pid; - - // Before we do anything lets check for the existence of - // the traffic server binary along with it's execute permissions - if (access(absolute_proxy_binary, F_OK) < 0) { - // Error can't find traffic_server - mgmt_elog(errno, "[LocalManager::startProxy] Unable to find traffic server at %s\n", absolute_proxy_binary); - return false; - } - // traffic server binary exists, check permissions - else if (access(absolute_proxy_binary, R_OK | X_OK) < 0) { - // Error don't have proper permissions - mgmt_elog(errno, "[LocalManager::startProxy] Unable to access %s due to bad permissions \n", absolute_proxy_binary); - return false; - } - - if (env_prep) { -#ifdef POSIX_THREAD - if ((pid = fork()) < 0) -#else - if ((pid = fork1()) < 0) -#endif - { - mgmt_elog(errno, "[LocalManager::startProxy] Unable to fork1 prep process\n"); - return false; - } else if (pid > 0) { - int estatus; - waitpid(pid, &estatus, 0); - } else { - int res; - - char env_prep_bin[MAXPATHLEN]; - std::string bindir(RecConfigReadBinDir()); - - ink_filepath_make(env_prep_bin, sizeof(env_prep_bin), bindir.c_str(), env_prep); - res = execl(env_prep_bin, env_prep_bin, (char *)nullptr); - _exit(res); - } - } -#ifdef POSIX_THREAD - if ((pid = fork()) < 0) -#else - if ((pid = fork1()) < 0) -#endif - { - mgmt_elog(errno, "[LocalManager::startProxy] Unable to fork1 process\n"); - return false; - } else if (pid > 0) { /* Parent */ - proxy_launch_pid = pid; - proxy_launch_outstanding = true; - proxy_started_at = time(nullptr); - ++proxy_launch_count; - RecSetRecordInt("proxy.node.restarts.proxy.start_time", proxy_started_at, REC_SOURCE_DEFAULT); - RecSetRecordInt("proxy.node.restarts.proxy.restart_count", proxy_launch_count, REC_SOURCE_DEFAULT); - } else { - int i = 0; - char *options[32], *last, *tok; - char options_buffer[OPTIONS_SIZE]; - ts::FixedBufferWriter w{options_buffer, OPTIONS_SIZE}; - - w.clip(1); - w.print("{}{}", ts::bwf::OptionalAffix(proxy_options), ts::bwf::OptionalAffix(onetime_options)); - - // Make sure we're starting the proxy in mgmt mode - if (w.view().find(MGMT_OPT) == std::string_view::npos) { - w.write(MGMT_OPT); - w.write(' '); - } - - // pass the runroot option to traffic_server - std::string_view runroot_arg = get_runroot(); - if (!runroot_arg.empty()) { - w.write(RUNROOT_OPT); - w.write(runroot_arg); - w.write(' '); - } - - // Pass down port/fd information to traffic_server if there are any open ports. - if (std::any_of(m_proxy_ports.begin(), m_proxy_ports.end(), [](HttpProxyPort &p) { return ts::NO_FD != p.m_fd; })) { - char portbuf[128]; - bool need_comma_p = false; - - w.write("--httpport "sv); - for (auto &p : m_proxy_ports) { - if (ts::NO_FD != p.m_fd) { - if (need_comma_p) { - w.write(','); - } - need_comma_p = true; - p.print(portbuf, sizeof(portbuf)); - w.write(portbuf); - } - } - } - - w.extend(1); - w.write('\0'); // null terminate. - - Debug("lm", "[LocalManager::startProxy] Launching %s '%s'", absolute_proxy_binary, w.data()); - - // Unfortunately the normally obnoxious null writing of strtok is in this case a required - // side effect and other alternatives are noticeably more clunky. - ink_zero(options); - options[0] = absolute_proxy_binary; - i = 1; - tok = strtok_r(options_buffer, " ", &last); - Debug("lm", "opt %d = '%s'", i, tok); - options[i++] = tok; - while (i < 32 && (tok = strtok_r(nullptr, " ", &last))) { - Debug("lm", "opt %d = '%s'", i, tok); - options[i++] = tok; - } - - EnableDeathSignal(SIGTERM); - - execv(absolute_proxy_binary, options); - mgmt_fatal(errno, "[LocalManager::startProxy] Exec of %s failed\n", absolute_proxy_binary); - } - return true; -} - -/** Close all open ports. - */ -void -LocalManager::closeProxyPorts() -{ - for (auto &p : lmgmt->m_proxy_ports) { - if (ts::NO_FD != p.m_fd) { - close_socket(p.m_fd); - p.m_fd = ts::NO_FD; - } - } -} -/* - * listenForProxy() - * Function listens on the accept port of the proxy, so users aren't dropped. - */ -void -LocalManager::listenForProxy() -{ - if (!run_proxy || !listen_for_proxy) { - return; - } - - // We are not already bound, bind the port - for (auto &p : lmgmt->m_proxy_ports) { - if (ts::NO_FD == p.m_fd) { - // Check the protocol (TCP or UDP) and create an appropriate socket - if (p.isQUIC()) { - this->bindUdpProxyPort(p); - } else { - this->bindTcpProxyPort(p); - } - } - - std::string_view fam{ats_ip_family_name(p.m_family)}; - if (p.isQUIC()) { - // Can we do something like listen backlog for QUIC(UDP) ?? - // Do nothing for now - } else { - // read backlog configuration value and overwrite the default value if found - bool found; - RecInt backlog = REC_readInteger("proxy.config.net.listen_backlog", &found); - backlog = (found && backlog >= 0) ? backlog : ats_tcp_somaxconn(); - - if ((listen(p.m_fd, backlog)) < 0) { - mgmt_fatal(errno, "[LocalManager::listenForProxy] Unable to listen on port: %d (%.*s)\n", p.m_port, fam.size(), fam.data()); - } - } - - mgmt_log("[LocalManager::listenForProxy] Listening on port: %d (%.*s)\n", p.m_port, fam.size(), fam.data()); - } - return; -} - -/* - * bindUdpProxyPort() - * Function binds the accept port of the proxy - */ -void -LocalManager::bindUdpProxyPort(HttpProxyPort &port) -{ - int one = 1; - int priv = (port.m_port < 1024 && 0 != geteuid()) ? ElevateAccess::LOW_PORT_PRIVILEGE : 0; - - ElevateAccess access(priv); - - if ((port.m_fd = socket(port.m_family, SOCK_DGRAM, 0)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to create socket : %s\n", strerror(errno)); - } - - if (port.m_family == AF_INET6) { - if (setsockopt(port.m_fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) { - mgmt_log("[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno)); - } - } - if (setsockopt(port.m_fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&one), sizeof(int)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno)); - } - - IpEndpoint ip; - if (port.m_inbound_ip.isValid()) { - ip.assign(port.m_inbound_ip); - } else if (AF_INET6 == port.m_family) { - if (m_inbound_ip6.isValid()) { - ip.assign(m_inbound_ip6); - } else { - ip.setToAnyAddr(AF_INET6); - } - } else if (AF_INET == port.m_family) { - if (m_inbound_ip4.isValid()) { - ip.assign(m_inbound_ip4); - } else { - ip.setToAnyAddr(AF_INET); - } - } else { - mgmt_fatal(0, "[bindProxyPort] Proxy port with invalid address type %d\n", port.m_family); - } - ip.network_order_port() = htons(port.m_port); - if (bind(port.m_fd, &ip.sa, ats_ip_size(&ip)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to bind socket: %d : %s\n", port.m_port, strerror(errno)); - } - - Debug("lm", "[bindProxyPort] Successfully bound proxy port %d", port.m_port); -} - -/* - * bindTcpProxyPort() - * Function binds the accept port of the proxy - */ -void -LocalManager::bindTcpProxyPort(HttpProxyPort &port) -{ - int one = 1; - int priv = (port.m_port < 1024 && 0 != geteuid()) ? ElevateAccess::LOW_PORT_PRIVILEGE : 0; - - ElevateAccess access(priv); - - /* Setup reliable connection, for large config changes */ - if ((port.m_fd = socket(port.m_family, SOCK_STREAM, 0)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to create socket : %s\n", strerror(errno)); - } - - if (port.m_type == HttpProxyPort::TRANSPORT_DEFAULT) { - int should_filter_int = 0; - bool found; - should_filter_int = REC_readInteger("proxy.config.net.defer_accept", &found); - if (found && should_filter_int > 0) { -#if defined(SOL_FILTER) && defined(FIL_ATTACH) - (void)setsockopt(port.m_fd, SOL_FILTER, FIL_ATTACH, "httpfilt", 9); -#endif - } - } - - if (port.m_mptcp) { -#if MPTCP_ENABLED - int err; - - err = setsockopt(port.m_fd, IPPROTO_TCP, MPTCP_ENABLED, &one, sizeof(one)); - if (err < 0) { - mgmt_log("[bindProxyPort] Unable to enable MPTCP: %s\n", strerror(errno)); - Debug("lm_mptcp", "[bindProxyPort] Unable to enable MPTCP: %s", strerror(errno)); - } else { - mgmt_log("[bindProxyPort] Successfully enabled MPTCP on %d\n", port.m_port); - Debug("lm_mptcp", "[bindProxyPort] Successfully enabled MPTCP on %d\n", port.m_port); - } -#else - Debug("lm_mptcp", "[bindProxyPort] Multipath TCP requested but not configured on this host"); -#endif - } - - if (port.m_family == AF_INET6) { - if (setsockopt(port.m_fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) { - mgmt_log("[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno)); - } - } - if (setsockopt(port.m_fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&one), sizeof(int)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno)); - } - - if (port.m_proxy_protocol) { - Debug("lm", "[bindProxyPort] Proxy Protocol enabled"); - } - - if (port.m_inbound_transparent_p) { -#if TS_USE_TPROXY - Debug("http_tproxy", "Listen port %d inbound transparency enabled.", port.m_port); - if (setsockopt(port.m_fd, SOL_IP, TS_IP_TRANSPARENT, &one, sizeof(one)) == -1) { - mgmt_fatal(0, "[bindProxyPort] Unable to set transparent socket option [%d] %s\n", errno, strerror(errno)); - } -#else - Debug("lm", "[bindProxyPort] Transparency requested but TPROXY not configured"); -#endif - } - - IpEndpoint ip; - if (port.m_inbound_ip.isValid()) { - ip.assign(port.m_inbound_ip); - } else if (AF_INET6 == port.m_family) { - if (m_inbound_ip6.isValid()) { - ip.assign(m_inbound_ip6); - } else { - ip.setToAnyAddr(AF_INET6); - } - } else if (AF_INET == port.m_family) { - if (m_inbound_ip4.isValid()) { - ip.assign(m_inbound_ip4); - } else { - ip.setToAnyAddr(AF_INET); - } - } else { - mgmt_fatal(0, "[bindProxyPort] Proxy port with invalid address type %d\n", port.m_family); - } - ip.network_order_port() = htons(port.m_port); - if (bind(port.m_fd, &ip.sa, ats_ip_size(&ip)) < 0) { - mgmt_fatal(0, "[bindProxyPort] Unable to bind socket: %d : %s\n", port.m_port, strerror(errno)); - } - - Debug("lm", "[bindProxyPort] Successfully bound proxy port %d", port.m_port); -} - -void -LocalManager::signalAlarm(int alarm_id, const char *desc, const char *ip) -{ - if (alarm_keeper) { - alarm_keeper->signalAlarm(static_cast(alarm_id), desc, ip); - } -} diff --git a/mgmt/LocalManager.h b/mgmt/LocalManager.h deleted file mode 100644 index f5121a41e63..00000000000 --- a/mgmt/LocalManager.h +++ /dev/null @@ -1,141 +0,0 @@ -/** @file - - Definitions for the LocalManager class. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include - -#include "BaseManager.h" -#include "records/I_RecHttp.h" -#include "tscore/I_Version.h" - -#include -#if TS_HAS_WCCP -#include -#endif -#if HAVE_EVENTFD -#include -#endif - -class Alarms; -class FileManager; - -enum ManagementPendingOperation { - MGMT_PENDING_NONE, // Do nothing - MGMT_PENDING_RESTART, // Restart TS and TM - MGMT_PENDING_BOUNCE, // Restart TS - MGMT_PENDING_STOP, // Stop TS - MGMT_PENDING_DRAIN, // Drain TS - MGMT_PENDING_IDLE_RESTART, // Restart TS and TM when TS is idle - MGMT_PENDING_IDLE_BOUNCE, // Restart TS when TS is idle - MGMT_PENDING_IDLE_STOP, // Stop TS when TS is idle - MGMT_PENDING_IDLE_DRAIN, // Drain TS when TS is idle from new connections - MGMT_PENDING_UNDO_DRAIN, // Recover TS from drain -}; - -class LocalManager : public BaseManager -{ -public: - explicit LocalManager(bool proxy_on, bool listen); - ~LocalManager(); - - void initAlarm(); - void initCCom(const AppVersionInfo &version, FileManager *files, int mcport, char *addr, int rsport); - void initMgmtProcessServer(); - void pollMgmtProcessServer(); - void handleMgmtMsgFromProcesses(MgmtMessageHdr *mh); - void sendMgmtMsgToProcesses(int msg_id, const char *data_str); - void sendMgmtMsgToProcesses(int msg_id, const char *data_raw, int data_len); - void sendMgmtMsgToProcesses(MgmtMessageHdr *mh); - - void signalFileChange(const char *var_name); - void signalEvent(int msg_id, const char *data_str); - void signalEvent(int msg_id, const char *data_raw, int data_len); - void signalAlarm(int alarm_id, const char *desc = nullptr, const char *ip = nullptr); - - void processEventQueue(); - bool startProxy(const char *onetime_options); - void listenForProxy(); - void bindUdpProxyPort(HttpProxyPort &); - void bindTcpProxyPort(HttpProxyPort &); - void closeProxyPorts(); - - void mgmtCleanup(); - void mgmtShutdown(); - void processShutdown(bool mainThread = false); - void processRestart(); - void processBounce(); - void processDrain(int to_drain = 1); - void rollLogFiles(); - void clearStats(const char *name = nullptr); - void hostStatusSetDown(const char *marshalled_req, int len); - void hostStatusSetUp(const char *marshalled_req, int len); - - bool processRunning(); - - bool run_proxy; - bool listen_for_proxy; - bool proxy_recoverable = true; // false if traffic_server cannot recover with a reboot - time_t manager_started_at; - time_t proxy_started_at = -1; - int proxy_launch_count = 0; - bool proxy_launch_outstanding = false; - ManagementPendingOperation mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - time_t mgmt_shutdown_triggered_at; - time_t mgmt_drain_triggered_at; - int proxy_running = 0; - HttpProxyPort::Group m_proxy_ports; - // Local inbound addresses to bind, if set. - IpAddr m_inbound_ip4; - IpAddr m_inbound_ip6; - - int process_server_timeout_secs; - int process_server_timeout_msecs; - - char *absolute_proxy_binary; - char *proxy_name; - char *proxy_binary; - std::string proxy_options; // These options should persist across proxy reboots - char *env_prep; - - int process_server_sockfd = ts::NO_FD; - int watched_process_fd = ts::NO_FD; -#if HAVE_EVENTFD - int wakeup_fd = ts::NO_FD; // external trigger to stop polling -#endif - pid_t proxy_launch_pid = -1; - - Alarms *alarm_keeper = nullptr; - FileManager *configFiles = nullptr; - - pid_t watched_process_pid = -1; - - int syslog_facility = LOG_DAEMON; - -#if TS_HAS_WCCP - wccp::Cache wccp_cache; -#endif -private: -}; /* End class LocalManager */ - -extern LocalManager *lmgmt; diff --git a/mgmt/Makefile.am b/mgmt/Makefile.am index b200946a76f..93a26fe57e6 100644 --- a/mgmt/Makefile.am +++ b/mgmt/Makefile.am @@ -17,19 +17,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -SUBDIRS = utils api +SUBDIRS = utils api config rpc # Decoder ring: # libmgmt_c.la Configuration records (defaults). -# libmgmt_lm.la libmgmt for Local Manager applications (traffic_manager) # libmgmt_p.la libmgmt for Process Manager applications (everything else) -noinst_LTLIBRARIES = libmgmt_c.la libmgmt_p.la libmgmt_lm.la +noinst_LTLIBRARIES = libmgmt_c.la libmgmt_p.la AM_CPPFLAGS += \ $(iocore_include_dirs) \ -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/lib \ - -I$(abs_top_srcdir)/mgmt/api/include \ -I$(abs_top_srcdir)/mgmt/utils \ -I$(abs_top_srcdir)/proxy \ -I$(abs_top_srcdir)/proxy/http \ @@ -42,39 +40,16 @@ libmgmt_c_la_SOURCES = \ RecordsConfig.h libmgmt_COMMON = \ - BaseManager.cc \ - BaseManager.h \ MgmtDefs.h \ RecordsConfigUtils.cc libmgmt_p_la_SOURCES = \ $(libmgmt_COMMON) \ - ProcessManager.cc \ - ProcessManager.h \ ProxyConfig.cc \ ProxyConfig.h \ YamlCfg.cc \ YamlCfg.h -libmgmt_lm_la_SOURCES = \ - $(libmgmt_COMMON) \ - Alarms.cc \ - Alarms.h \ - DerivativeMetrics.cc \ - DerivativeMetrics.h \ - FileManager.cc \ - FileManager.h \ - LocalManager.cc \ - LocalManager.h \ - ConfigManager.cc \ - ConfigManager.h \ - WebMgmtUtils.cc \ - WebMgmtUtils.h - -libmgmt_lm_la_LIBADD = \ - libmgmt_c.la \ - $(top_builddir)/mgmt/utils/libutils_lm.la - libmgmt_p_la_LIBADD = \ libmgmt_c.la \ $(top_builddir)/mgmt/utils/libutils_p.la diff --git a/mgmt/MgmtDefs.h b/mgmt/MgmtDefs.h index 2245ee5b9db..b62588ff299 100644 --- a/mgmt/MgmtDefs.h +++ b/mgmt/MgmtDefs.h @@ -39,15 +39,6 @@ typedef int8_t MgmtByte; typedef float MgmtFloat; typedef char *MgmtString; -enum MgmtType { - MGMT_INVALID = -1, - MGMT_INT = 0, - MGMT_FLOAT = 1, - MGMT_STRING = 2, - MGMT_COUNTER = 3, - MGMT_TYPE_MAX = 4, -}; - /// Management callback signature. /// The memory span is the message payload for the callback. /// This can be a lambda, which should be used if additional context information is needed. @@ -145,5 +136,3 @@ inline MgmtConverter::MgmtConverter(MgmtInt (*_load_int)(const void *), void (*_ store_string(_store_string) { } - -constexpr ts::TextView LM_CONNECTION_SERVER{"processerver.sock"}; diff --git a/mgmt/ProcessManager.cc b/mgmt/ProcessManager.cc deleted file mode 100644 index b8661eebbb2..00000000000 --- a/mgmt/ProcessManager.cc +++ /dev/null @@ -1,512 +0,0 @@ -/** @file - - File contains the member function defs and thread loop for the process manager. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "InkAPIInternal.h" -#include "ProcessManager.h" - -#include "tscore/ink_apidefs.h" -#include "tscore/TSSystemState.h" -#include "MgmtSocket.h" -#include "tscore/I_Layout.h" - -/* - * Global ProcessManager - */ -ProcessManager *pmgmt = nullptr; - -// read_management_message attempts to read a message from the management -// socket. Returns -errno on error, otherwise 0. If a message was read the -// *msg pointer will be filled in with the message that was read. -static int -read_management_message(int sockfd, MgmtMessageHdr **msg) -{ - MgmtMessageHdr hdr; - int ret; - - *msg = nullptr; - - // We have a message, try to read the message header. - ret = mgmt_read_pipe(sockfd, reinterpret_cast(&hdr), sizeof(MgmtMessageHdr)); - switch (ret) { - case 0: - // Received EOF. - return 0; - case sizeof(MgmtMessageHdr): - break; - default: - // Received -errno. - return -errno; - } - - size_t msg_size = sizeof(MgmtMessageHdr) + hdr.data_len; - MgmtMessageHdr *full_msg = static_cast(ats_malloc(msg_size)); - - memcpy(full_msg, &hdr, sizeof(MgmtMessageHdr)); - char *data_raw = reinterpret_cast(full_msg) + sizeof(MgmtMessageHdr); - - ret = mgmt_read_pipe(sockfd, data_raw, hdr.data_len); - if (ret == 0) { - // Received EOF. - ats_free(full_msg); - return 0; - } else if (ret < 0) { - // Received -errno. - ats_free(full_msg); - return ret; - } else { - ink_release_assert(ret == hdr.data_len); - // Received the message. - *msg = full_msg; - return 0; - } -} - -void -ProcessManager::start(std::function const &cb_init, std::function const &cb_destroy) -{ - Debug("pmgmt", "starting process manager"); - - init = cb_init; - destroy = cb_destroy; - - ink_release_assert(running == 0); - ink_atomic_increment(&running, 1); - ink_thread_create(&poll_thread, processManagerThread, nullptr, 0, 0, nullptr); -} - -void -ProcessManager::stop() -{ - Debug("pmgmt", "stopping process manager"); - - ink_release_assert(running == 1); - ink_atomic_decrement(&running, 1); - - int tmp; - - if (local_manager_sockfd != ts::NO_FD) { - tmp = local_manager_sockfd; - local_manager_sockfd = ts::NO_FD; - close_socket(tmp); - } - -#if HAVE_EVENTFD - if (wakeup_fd != ts::NO_FD) { - tmp = wakeup_fd; - wakeup_fd = ts::NO_FD; - close_socket(tmp); - } -#endif - - ink_thread_kill(poll_thread, SIGINT); - - ink_thread_join(poll_thread); - poll_thread = ink_thread_null(); - - while (!queue_is_empty(mgmt_signal_queue)) { - char *sig = static_cast(::dequeue(mgmt_signal_queue)); - ats_free(sig); - } - - LLQ *tmp_queue = mgmt_signal_queue; - mgmt_signal_queue = nullptr; - delete_queue(tmp_queue); -} - -/* - * processManagerThread(...) - * The start function and thread loop for the process manager. - */ -void * -ProcessManager::processManagerThread(void *arg) -{ - void *ret = arg; - - while (!pmgmt) { /* Avert race condition, thread spun during constructor */ - Debug("pmgmt", "waiting for initialization"); - mgmt_sleep_sec(1); - } - - if (pmgmt->require_lm) { /* Allow p. process to run w/o a lm */ - pmgmt->initLMConnection(); - } else { - return ret; - } - - if (pmgmt->init) { - pmgmt->managerThread = pmgmt->init(); - } - - // Start pumping messages between the local process and the process - // manager. This will terminate when the process manager terminates - // or the local process calls stop(). In either case, it is likely - // that we will first notice because we got a socket error, but in - // the latter case, the `running` flag has already been toggled so - // we know that we are really doing a shutdown. - while (pmgmt->running) { - int ret; - - if (pmgmt->require_lm) { - ret = pmgmt->pollLMConnection(); - if (ret < 0 && pmgmt->running && !TSSystemState::is_event_system_shut_down()) { - Alert("exiting with read error from process manager: %s", strerror(-ret)); - } - } - - ret = pmgmt->processSignalQueue(); - if (ret < 0 && pmgmt->running && !TSSystemState::is_event_system_shut_down()) { - Alert("exiting with write error from process manager: %s", strerror(-ret)); - } - } - - if (pmgmt->destroy && pmgmt->managerThread != nullptr) { - pmgmt->destroy(pmgmt->managerThread); - pmgmt->managerThread = nullptr; - } - - return ret; -} - -ProcessManager::ProcessManager(bool rlm) - : BaseManager(), require_lm(rlm), pid(getpid()), local_manager_sockfd(0), cbtable(nullptr), max_msgs_in_a_row(1) -{ - mgmt_signal_queue = create_queue(); - - local_manager_sockfd = ts::NO_FD; -#if HAVE_EVENTFD - wakeup_fd = ts::NO_FD; -#endif - - // Set temp. process/manager timeout. Will be reconfigure later. - // Making the process_manager thread a spinning thread to start traffic server - // as quickly as possible. Will reset this timeout when reconfigure() - timeout = 0; -} - -ProcessManager::~ProcessManager() -{ - if (running) { - stop(); - } -} - -void -ProcessManager::reconfigure() -{ - max_msgs_in_a_row = MAX_MSGS_IN_A_ROW; - - if (RecGetRecordInt("proxy.config.process_manager.timeout", &timeout) != REC_ERR_OKAY) { - // Default to 5sec if the timeout is unspecified. - timeout = 5; - } -} - -void -ProcessManager::signalConfigFileChild(const char *parent, const char *child) -{ - static const MgmtMarshallType fields[] = {MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING}; - - size_t len = mgmt_message_length(fields, countof(fields), &parent, &child); - void *buffer = ats_malloc(len); - - mgmt_message_marshall(buffer, len, fields, countof(fields), &parent, &child); - signalManager(MGMT_SIGNAL_CONFIG_FILE_CHILD, static_cast(buffer), len); - - ats_free(buffer); -} - -void -ProcessManager::signalManager(int msg_id, const char *data_str) -{ - signalManager(msg_id, data_str, strlen(data_str) + 1); -} - -void -ProcessManager::signalManager(int msg_id, const char *data_raw, int data_len) -{ - MgmtMessageHdr *mh; - - mh = static_cast(ats_malloc(sizeof(MgmtMessageHdr) + data_len)); - mh->msg_id = msg_id; - mh->data_len = data_len; - memcpy(reinterpret_cast(mh) + sizeof(MgmtMessageHdr), data_raw, data_len); - this->signalManager(mh); -} - -void -ProcessManager::signalManager(int msg_id, std::string_view text) -{ - MgmtMessageHdr *mh; - - // Make space for the extra null terminator. - mh = static_cast(ats_malloc(sizeof(MgmtMessageHdr) + text.size() + 1)); - auto body = reinterpret_cast(mh + 1); // start of the message body. - mh->msg_id = msg_id; - mh->data_len = text.size() + 1; - memcpy(body, text.data(), text.size()); - body[text.size()] = '\0'; - - this->signalManager(mh); -} - -void -ProcessManager::signalManager(MgmtMessageHdr *mh) -{ - if (!this->running) { - Warning("MgmtMessageHdr is ignored. Because ProcessManager is not running"); - return; - } - ink_release_assert(::enqueue(mgmt_signal_queue, mh)); - -#if HAVE_EVENTFD - // we don't care about the actual value of wakeup_fd, so just keep adding 1. just need to - // wakeup the fd. also, note that wakeup_fd was initialized to non-blocking so we can - // directly write to it without any timeout checking. - // - // don't trigger if MGMT_EVENT_LIBRECORD because they happen all the time - // and don't require a quick response. for MGMT_EVENT_LIBRECORD, rely on timeouts so - // traffic_server can spend more time doing other things/ - uint64_t one = 1; - if (wakeup_fd != ts::NO_FD && mh->msg_id != MGMT_SIGNAL_LIBRECORDS) { - ATS_UNUSED_RETURN(write(wakeup_fd, &one, sizeof(uint64_t))); // trigger to stop polling - } -#endif -} - -int -ProcessManager::processSignalQueue() -{ - while (!queue_is_empty(mgmt_signal_queue)) { - MgmtMessageHdr *mh = static_cast(::dequeue(mgmt_signal_queue)); - - Debug("pmgmt", "signaling local manager with message ID %d", mh->msg_id); - - if (require_lm) { - int ret = mgmt_write_pipe(local_manager_sockfd, reinterpret_cast(mh), sizeof(MgmtMessageHdr) + mh->data_len); - ats_free(mh); - - if (ret < 0) { - return ret; - } - } - } - - return 0; -} - -void -ProcessManager::initLMConnection() -{ - std::string rundir(RecConfigReadRuntimeDir()); - std::string sockpath(Layout::relative_to(rundir, LM_CONNECTION_SERVER)); - - MgmtMessageHdr *mh_full; - int data_len; - - int servlen; - struct sockaddr_un serv_addr; - - if (sockpath.length() > sizeof(serv_addr.sun_path) - 1) { - errno = ENAMETOOLONG; - Fatal("Unable to create socket '%s': %s", sockpath.c_str(), strerror(errno)); - } - - /* Setup Connection to LocalManager */ - memset(reinterpret_cast(&serv_addr), 0, sizeof(serv_addr)); - serv_addr.sun_family = AF_UNIX; - - ink_strlcpy(serv_addr.sun_path, sockpath.c_str(), sizeof(serv_addr.sun_path)); -#if defined(darwin) || defined(freebsd) - servlen = sizeof(sockaddr_un); -#else - servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); -#endif - - if ((local_manager_sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - Fatal("Unable to create socket '%s': %s", sockpath.c_str(), strerror(errno)); - } - - if (fcntl(local_manager_sockfd, F_SETFD, FD_CLOEXEC) < 0) { - Fatal("unable to set close-on-exec flag: %s", strerror(errno)); - } - - if ((connect(local_manager_sockfd, reinterpret_cast(&serv_addr), servlen)) < 0) { - Fatal("failed to connect management socket '%s': %s", sockpath.c_str(), strerror(errno)); - } - -#if HAVE_EVENTFD - wakeup_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (wakeup_fd < 0) { - Fatal("unable to create wakeup eventfd. errno: %s", strerror(errno)); - } -#endif - - data_len = sizeof(pid_t); - mh_full = static_cast(alloca(sizeof(MgmtMessageHdr) + data_len)); - mh_full->msg_id = MGMT_SIGNAL_PID; - mh_full->data_len = data_len; - - memcpy(reinterpret_cast(mh_full) + sizeof(MgmtMessageHdr), &(pid), data_len); - - if (mgmt_write_pipe(local_manager_sockfd, reinterpret_cast(mh_full), sizeof(MgmtMessageHdr) + data_len) <= 0) { - Fatal("error writing message: %s", strerror(errno)); - } -} - -int -ProcessManager::pollLMConnection() -{ - int count; - int ready; - struct timeval timeout; - fd_set fdlist; - - // Avoid getting stuck enqueuing too many requests in a row, limit to MAX_MSGS_IN_A_ROW. - for (count = 0; running && count < max_msgs_in_a_row; ++count) { - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - FD_ZERO(&fdlist); - - if (local_manager_sockfd != ts::NO_FD) { - FD_SET(local_manager_sockfd, &fdlist); - } - -#if HAVE_EVENTFD - if (wakeup_fd != ts::NO_FD) { - FD_SET(wakeup_fd, &fdlist); - } -#endif - - // wait for data on socket - ready = mgmt_select(FD_SETSIZE, &fdlist, nullptr, nullptr, &timeout); - - switch (ready) { - case 0: - // Timed out. - return 0; - case -1: - if (mgmt_transient_error()) { - continue; - } - return -errno; - } - - if (local_manager_sockfd != ts::NO_FD && FD_ISSET(local_manager_sockfd, &fdlist)) { /* Message from manager */ - MgmtMessageHdr *msg; - - int ret = read_management_message(local_manager_sockfd, &msg); - if (ret < 0) { - return ret; - } - - // No message, we are done polling. */ - if (msg == nullptr) { - return 0; - } - - Debug("pmgmt", "received message ID %d", msg->msg_id); - handleMgmtMsgFromLM(msg); - } -#if HAVE_EVENTFD - else if (wakeup_fd != ts::NO_FD && FD_ISSET(wakeup_fd, &fdlist)) { /* if msg, keep polling for more */ - // read or else fd will always be set. - uint64_t ignore; - ATS_UNUSED_RETURN(read(wakeup_fd, &ignore, sizeof(uint64_t))); - break; - } -#endif - } - Debug("pmgmt", "enqueued %d of max %d messages in a row", count, max_msgs_in_a_row); - return 0; -} - -void -ProcessManager::handleMgmtMsgFromLM(MgmtMessageHdr *mh) -{ - ink_assert(mh != nullptr); - - auto payload = mh->payload(); - - Debug("pmgmt", "processing event id '%d' payload=%d", mh->msg_id, mh->data_len); - switch (mh->msg_id) { - case MGMT_EVENT_SHUTDOWN: - executeMgmtCallback(MGMT_EVENT_SHUTDOWN, {}); - Alert("exiting on shutdown message"); - break; - case MGMT_EVENT_RESTART: - executeMgmtCallback(MGMT_EVENT_RESTART, {}); - break; - case MGMT_EVENT_DRAIN: - executeMgmtCallback(MGMT_EVENT_DRAIN, payload); - break; - case MGMT_EVENT_CLEAR_STATS: - executeMgmtCallback(MGMT_EVENT_CLEAR_STATS, {}); - break; - case MGMT_EVENT_HOST_STATUS_UP: - executeMgmtCallback(MGMT_EVENT_HOST_STATUS_UP, payload); - break; - case MGMT_EVENT_HOST_STATUS_DOWN: - executeMgmtCallback(MGMT_EVENT_HOST_STATUS_DOWN, payload); - break; - case MGMT_EVENT_ROLL_LOG_FILES: - executeMgmtCallback(MGMT_EVENT_ROLL_LOG_FILES, {}); - break; - case MGMT_EVENT_PLUGIN_CONFIG_UPDATE: { - auto msg{payload.rebind()}; - if (!msg.empty() && msg[0] != '\0' && this->cbtable) { - this->cbtable->invoke(msg.data()); - } - } break; - case MGMT_EVENT_CONFIG_FILE_UPDATE: - /* - librecords -- we don't do anything in here because we are traffic_server - and we are not the owner of proxy.config.* variables. - Even if we trigger the sync_required bit, by - RecSetSynRequired, the sync. message will send back to - traffic_manager. And traffic_manager founds out that, the - actual value of the config variable didn't changed. - At the end, the sync_required bit is not set and we will - never get notified and callbacks are never invoked. - - The solution is to set the sync_required bit on the - manager side. See LocalManager::sendMgmtMsgToProcesses() - for details. - */ - break; - case MGMT_EVENT_LIBRECORDS: - executeMgmtCallback(MGMT_EVENT_LIBRECORDS, payload); - break; - case MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE: - executeMgmtCallback(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, payload); - break; - case MGMT_EVENT_LIFECYCLE_MESSAGE: - executeMgmtCallback(MGMT_EVENT_LIFECYCLE_MESSAGE, payload); - break; - default: - Warning("received unknown message ID %d\n", mh->msg_id); - break; - } - - ats_free(mh); -} diff --git a/mgmt/ProcessManager.h b/mgmt/ProcessManager.h deleted file mode 100644 index 926d2290427..00000000000 --- a/mgmt/ProcessManager.h +++ /dev/null @@ -1,115 +0,0 @@ -/** @file - - Process Manager Class, derived from BaseManager. Class provides callback - registration for management events as well as the interface to the outside - world. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include -#include - -#include - -#include "MgmtUtils.h" -#include "BaseManager.h" -#include "tscore/ink_sock.h" -#include "tscore/ink_llqueue.h" -#include "tscore/ink_apidefs.h" - -#if HAVE_EVENTFD -#include -#endif - -class ConfigUpdateCbTable; - -class ProcessManager : public BaseManager -{ -public: - ProcessManager(bool rlm); - ~ProcessManager(); - - // Start a thread for the process manager. If @a cb is set then it - // is called after the thread is started and before any messages are - // processed. - void start(std::function const &cb_init = std::function(), - std::function const &cb_destroy = std::function()); - - // Stop the process manager, dropping any unprocessed messages. - void stop(); - - void signalConfigFileChild(const char *parent, const char *child); - void signalManager(int msg_id, const char *data_str); - void signalManager(int msg_id, const char *data_raw, int data_len); - - /** Send a management message of type @a msg_id with @a text. - * - * @param msg_id ID for the message. - * @param text Content for the message. - * - * A terminating null character is added automatically. - */ - void signalManager(int msg_id, std::string_view text); - - void signalManager(MgmtMessageHdr *mh); - - void reconfigure(); - void initLMConnection(); - void handleMgmtMsgFromLM(MgmtMessageHdr *mh); - - void - registerPluginCallbacks(ConfigUpdateCbTable *_cbtable) - { - cbtable = _cbtable; - } - -private: - int pollLMConnection(); - int processSignalQueue(); - bool processEventQueue(); - - bool require_lm; - RecInt timeout; - LLQ *mgmt_signal_queue; - pid_t pid; - - ink_thread poll_thread = ink_thread_null(); - int running = 0; - - /// Thread initialization callback. - /// This allows @c traffic_server and @c traffic_manager to perform different initialization in the thread. - std::function init; - std::function destroy; - TSThread managerThread = nullptr; - - int local_manager_sockfd; -#if HAVE_EVENTFD - int wakeup_fd; // external trigger to stop polling -#endif - ConfigUpdateCbTable *cbtable; - int max_msgs_in_a_row; - - static const int MAX_MSGS_IN_A_ROW = 10000; - static void *processManagerThread(void *arg); -}; - -extern ProcessManager *pmgmt; diff --git a/mgmt/ProxyConfig.h b/mgmt/ProxyConfig.h index 493dec230e2..e55be717824 100644 --- a/mgmt/ProxyConfig.h +++ b/mgmt/ProxyConfig.h @@ -25,23 +25,10 @@ #include -#include "ProcessManager.h" #include "I_Tasks.h" class ProxyMutex; -// -// Macros that spin waiting for the data to be bound -// -#define SignalManager(_n, _d) pmgmt->signalManager(_n, (char *)_d) -#define SignalWarning(_n, _s) \ - { \ - Warning("%s", _s); \ - SignalManager(_n, _s); \ - } - -#define RegisterMgmtCallback(_signal, _fn, _data) pmgmt->registerMgmtCallback(_signal, _fn, _data) - #define MAX_CONFIGS 100 typedef RefCountObj ConfigInfo; diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 73d6b519e47..bb80a5745c5 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -53,12 +53,6 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.bin_path", RECD_STRING, TS_BUILD_BINDIR, RECU_NULL, RR_REQUIRED, RECC_NULL, nullptr, RECA_READ_ONLY} , - {RECT_CONFIG, "proxy.config.proxy_binary", RECD_STRING, "traffic_server", RECU_NULL, RR_REQUIRED, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.config.manager_binary", RECD_STRING, "traffic_manager", RECU_NULL, RR_REQUIRED, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.config.proxy_binary_opts", RECD_STRING, "-M", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , {RECT_CONFIG, "proxy.config.env_prep", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , // Jira TS-21 @@ -246,22 +240,11 @@ static const RecordElement RecordsConfig[] = //############################################################################## //# - //# Local Manager + //# Management //# //############################################################################## - {RECT_CONFIG, "proxy.config.lm.pserver_timeout_secs", RECD_INT, "1", RECU_RESTART_TM, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.config.lm.pserver_timeout_msecs", RECD_INT, "0", RECU_RESTART_TM, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.config.admin.autoconf.localhost_only", RECD_INT, "1", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} - , {RECT_CONFIG, "proxy.config.admin.user_id", RECD_STRING, TS_PKGSYSUSER, RECU_NULL, RR_REQUIRED, RECC_NULL, nullptr, RECA_READ_ONLY} , - {RECT_CONFIG, "proxy.config.admin.cli_path", RECD_STRING, "cli", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.config.admin.api.restricted", RECD_INT, "0", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} - , - //############################################################################## //# //# UDP configuration stuff: hidden variables @@ -276,14 +259,6 @@ static const RecordElement RecordsConfig[] = {RECT_CONFIG, "proxy.config.udp.threads", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - //############################################################################## - //# - //# Process Manager - //# - //############################################################################## - {RECT_CONFIG, "proxy.config.process_manager.timeout", RECD_INT, "5", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - //############################################################################## //# //# Alarm Configuration @@ -1284,8 +1259,6 @@ static const RecordElement RecordsConfig[] = //# //# Restart Stats //# - {RECT_NODE, "proxy.node.restarts.manager.start_time", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , {RECT_NODE, "proxy.node.restarts.proxy.start_time", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_NODE, "proxy.node.restarts.proxy.cache_ready_time", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} @@ -1294,32 +1267,6 @@ static const RecordElement RecordsConfig[] = , {RECT_NODE, "proxy.node.restarts.proxy.restart_count", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - //# - //# Manager Version Info - //# - {RECT_NODE, "proxy.node.version.manager.short", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.long", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.build_number", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.build_time", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.build_date", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.build_machine", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_NODE, "proxy.node.version.manager.build_person", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - //# manager: backoff configuration. - {RECT_CONFIG, "proxy.node.config.manager_exponential_sleep_ceiling", RECD_INT, "60", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - {RECT_CONFIG, "proxy.node.config.manager_retry_cap", RECD_INT, "5", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , - //# manager: log filename - {RECT_CONFIG, "proxy.node.config.manager_log_filename", RECD_STRING, "manager.log", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[^[:space:]]+$", RECA_NULL} - , - //# //# SSL parent proxying info //# diff --git a/mgmt/WebMgmtUtils.cc b/mgmt/WebMgmtUtils.cc index da3458c655f..b587ab6dc90 100644 --- a/mgmt/WebMgmtUtils.cc +++ b/mgmt/WebMgmtUtils.cc @@ -28,76 +28,6 @@ #include "WebMgmtUtils.h" #include "tscore/Regex.h" -// bool varSetFromStr(const char*, const char* ) -// -// Sets the named local manager variable from the value string -// passed in. Does the appropriate type conversion on -// value string to get it to the type of the local manager -// variable -// -// returns true if the variable was successfully set -// and false otherwise -// -bool -varSetFromStr(const char *varName, const char *value) -{ - RecDataT varDataType = RECD_NULL; - bool found = true; - int err = REC_ERR_FAIL; - RecData data; - - memset(&data, 0, sizeof(RecData)); - - err = RecGetRecordDataType(const_cast(varName), &varDataType); - if (err != REC_ERR_OKAY) { - return found; - } - // Use any empty string if we get a NULL so - // sprintf does puke. However, we need to - // switch this back to NULL for STRING types - if (value == nullptr) { - value = ""; - } - - switch (varDataType) { - case RECD_INT: - if (sscanf(value, "%" PRId64 "", &data.rec_int) == 1) { - RecSetRecordInt(const_cast(varName), data.rec_int, REC_SOURCE_EXPLICIT); - } else { - found = false; - } - break; - case RECD_COUNTER: - if (sscanf(value, "%" PRId64 "", &data.rec_counter) == 1) { - RecSetRecordCounter(const_cast(varName), data.rec_counter, REC_SOURCE_EXPLICIT); - } else { - found = false; - } - break; - case RECD_FLOAT: - // coverity[secure_coding] - if (sscanf(value, "%f", &data.rec_float) == 1) { - RecSetRecordFloat(const_cast(varName), data.rec_float, REC_SOURCE_EXPLICIT); - } else { - found = false; - } - break; - case RECD_STRING: - if (*value == '\0') { - RecSetRecordString(const_cast(varName), nullptr, REC_SOURCE_EXPLICIT); - } else { - RecSetRecordString(const_cast(varName), const_cast(value), REC_SOURCE_EXPLICIT); - } - break; - case RECD_NULL: - default: - found = false; - break; - } - - return found; -} - // bool varSetFloat(const char* varName, RecFloat value) // // Sets the variable specified by varName to value. varName @@ -292,154 +222,6 @@ varDataFromName(RecDataT varType, const char *varName, RecData *value) return (err == REC_ERR_OKAY); } -// bool varCounterFromName (const char*, RecFloat* ) -// -// Sets the *value to value of the varName. -// -// return true if bufVal was successfully set -// and false otherwise -// -bool -varCounterFromName(const char *varName, RecCounter *value) -{ - RecDataT varDataType = RECD_NULL; - bool found = true; - int err = REC_ERR_FAIL; - - err = RecGetRecordDataType(const_cast(varName), &varDataType); - - if (err == REC_ERR_FAIL) { - return false; - } - - switch (varDataType) { - case RECD_INT: { - RecInt tempInt = 0; - RecGetRecordInt(const_cast(varName), &tempInt); - *value = static_cast(tempInt); - break; - } - case RECD_COUNTER: { - *value = 0; - RecGetRecordCounter(const_cast(varName), value); - break; - } - case RECD_FLOAT: { - RecFloat tempFloat = 0.0; - RecGetRecordFloat(const_cast(varName), &tempFloat); - *value = static_cast(tempFloat); - break; - } - case RECD_STRING: - case RECD_NULL: - default: - *value = -1; - found = false; - break; - } - - return found; -} - -// bool varFloatFromName (const char*, RecFloat* ) -// -// Sets the *value to value of the varName. -// -// return true if bufVal was successfully set -// and false otherwise -// -bool -varFloatFromName(const char *varName, RecFloat *value) -{ - RecDataT varDataType = RECD_NULL; - bool found = true; - - int err = REC_ERR_FAIL; - - err = RecGetRecordDataType(const_cast(varName), &varDataType); - - if (err == REC_ERR_FAIL) { - return false; - } - - switch (varDataType) { - case RECD_INT: { - RecInt tempInt = 0; - RecGetRecordInt(const_cast(varName), &tempInt); - *value = static_cast(tempInt); - break; - } - case RECD_COUNTER: { - RecCounter tempCounter = 0; - RecGetRecordCounter(const_cast(varName), &tempCounter); - *value = static_cast(tempCounter); - break; - } - case RECD_FLOAT: { - *value = 0.0; - RecGetRecordFloat(const_cast(varName), value); - break; - } - case RECD_STRING: - case RECD_NULL: - default: - *value = -1.0; - found = false; - break; - } - - return found; -} - -// bool varIntFromName (const char*, RecInt* ) -// -// Sets the *value to value of the varName. -// -// return true if bufVal was successfully set -// and false otherwise -// -bool -varIntFromName(const char *varName, RecInt *value) -{ - RecDataT varDataType = RECD_NULL; - bool found = true; - int err = REC_ERR_FAIL; - - err = RecGetRecordDataType(const_cast(varName), &varDataType); - - if (err != REC_ERR_OKAY) { - return false; - } - - switch (varDataType) { - case RECD_INT: { - *value = 0; - RecGetRecordInt(const_cast(varName), value); - break; - } - case RECD_COUNTER: { - RecCounter tempCounter = 0; - RecGetRecordCounter(const_cast(varName), &tempCounter); - *value = static_cast(tempCounter); - break; - } - case RECD_FLOAT: { - RecFloat tempFloat = 0.0; - RecGetRecordFloat(const_cast(varName), &tempFloat); - *value = static_cast(tempFloat); - break; - } - case RECD_STRING: - case RECD_NULL: - default: - *value = -1; - found = false; - break; - } - - return found; -} - // void percentStrFromFloat(MgmtFloat, char* bufVal) // // Converts a float to a percent string @@ -543,252 +325,6 @@ bytesFromInt(RecInt bytes, char *bufVal) } } -// bool varStrFromName (const char*, char*, int) -// -// Sets the bufVal string to the value of the local manager -// named by varName. bufLen is size of bufVal -// -// return true if bufVal was successfully set -// and false otherwise -// -// EVIL ALERT: overviewRecord::varStrFromName is extremely -// similar to this function except in how it gets it's -// data. Changes to this function must be propagated -// to its twin. Cut and Paste sucks but there is not -// an easy way to merge the functions -// -bool -varStrFromName(const char *varNameConst, char *bufVal, int bufLen) -{ - char *varName = nullptr; - RecDataT varDataType = RECD_NULL; - bool found = true; - int varNameLen = 0; - char formatOption = '\0'; - RecData data; - int err = REC_ERR_FAIL; - - memset(&data, 0, sizeof(RecData)); - - // Check to see if there is a \ option on the end of variable - // \ options indicate that we need special formatting - // of the results. Supported \ options are - // - /// b - bytes. Ints and Counts only. Amounts are - // transformed into one of GB, MB, KB, or B - // - varName = ats_strdup(varNameConst); - varNameLen = strlen(varName); - if (varNameLen > 3 && varName[varNameLen - 2] == '\\') { - formatOption = varName[varNameLen - 1]; - - // Now that we know the format option, terminate the string - // to make the option disappear - varName[varNameLen - 2] = '\0'; - - // Return not found for unknown format options - if (formatOption != 'b' && formatOption != 'm' && formatOption != 'c' && formatOption != 'p') { - ats_free(varName); - return false; - } - } - - err = RecGetRecordDataType(varName, &varDataType); - if (err == REC_ERR_FAIL) { - ats_free(varName); - return false; - } - - switch (varDataType) { - case RECD_INT: - RecGetRecordInt(varName, &data.rec_int); - if (formatOption == 'b') { - bytesFromInt(data.rec_int, bufVal); - } else if (formatOption == 'm') { - MbytesFromInt(data.rec_int, bufVal); - } else if (formatOption == 'c') { - commaStrFromInt(data.rec_int, bufVal); - } else { - snprintf(bufVal, bufLen, "%" PRId64 "", data.rec_int); - } - break; - - case RECD_COUNTER: - RecGetRecordCounter(varName, &data.rec_counter); - if (formatOption == 'b') { - bytesFromInt(static_cast(data.rec_counter), bufVal); - } else if (formatOption == 'm') { - MbytesFromInt(static_cast(data.rec_counter), bufVal); - } else if (formatOption == 'c') { - commaStrFromInt(data.rec_counter, bufVal); - } else { - snprintf(bufVal, bufLen, "%" PRId64 "", data.rec_counter); - } - break; - case RECD_FLOAT: - RecGetRecordFloat(varName, &data.rec_float); - if (formatOption == 'p') { - percentStrFromFloat(data.rec_float, bufVal); - } else { - snprintf(bufVal, bufLen, "%.2f", data.rec_float); - } - break; - case RECD_STRING: - RecGetRecordString_Xmalloc(varName, &data.rec_string); - if (data.rec_string == nullptr) { - bufVal[0] = '\0'; - } else if (strlen(data.rec_string) < static_cast(bufLen - 1)) { - ink_strlcpy(bufVal, data.rec_string, bufLen); - } else { - ink_strlcpy(bufVal, data.rec_string, bufLen); - } - ats_free(data.rec_string); - break; - default: - found = false; - break; - } - - ats_free(varName); - return found; -} - -// bool MgmtData::setFromName(const char*) -// -// Fills in class variables from the given -// variable name -// -// Returns true if the information could be set -// and false otherwise -// -bool -MgmtData::setFromName(const char *varName) -{ - bool found = true; - int err; - - err = RecGetRecordDataType(const_cast(varName), &this->type); - - if (err == REC_ERR_FAIL) { - return found; - } - - switch (this->type) { - case RECD_INT: - RecGetRecordInt(const_cast(varName), &this->data.rec_int); - break; - case RECD_COUNTER: - RecGetRecordCounter(const_cast(varName), &this->data.rec_counter); - break; - case RECD_FLOAT: - RecGetRecordFloat(const_cast(varName), &this->data.rec_float); - break; - case RECD_STRING: - RecGetRecordString_Xmalloc(const_cast(varName), &this->data.rec_string); - break; - case RECD_NULL: - default: - found = false; - break; - } - - return found; -} - -MgmtData::MgmtData() -{ - type = RECD_NULL; - memset(&data, 0, sizeof(RecData)); -} - -MgmtData::~MgmtData() -{ - if (type == RECD_STRING) { - ats_free(data.rec_string); - } -} - -// MgmtData::compareFromString(const char* str, strLen) -// -// Compares the value of string converted to -// data type of this_>type with value -// held in this->data -// -bool -MgmtData::compareFromString(const char *str) -{ - RecData compData; - bool compare = false; - float floatDiff; - - switch (this->type) { - case RECD_INT: - // TODO: Add SI decimal multipliers rule ? - if (str && recordRegexCheck("^[0-9]+$", str)) { - compData.rec_int = ink_atoi64(str); - if (data.rec_int == compData.rec_int) { - compare = true; - } - } - break; - case RECD_COUNTER: - if (str && recordRegexCheck("^[0-9]+$", str)) { - compData.rec_counter = ink_atoi64(str); - if (data.rec_counter == compData.rec_counter) { - compare = true; - } - } - break; - case RECD_FLOAT: - compData.rec_float = atof(str); - // HACK - There are some rounding problems with - // floating point numbers so say we have a match if there difference - // is small - floatDiff = data.rec_float - compData.rec_float; - if (floatDiff > -0.001 && floatDiff < 0.001) { - compare = true; - } - break; - case RECD_STRING: - if (str == nullptr || *str == '\0') { - if (data.rec_string == nullptr) { - compare = true; - } - } else { - if ((data.rec_string != nullptr) && (strcmp(str, data.rec_string) == 0)) { - compare = true; - } - } - break; - case RECD_NULL: - default: - compare = false; - break; - } - - return compare; -} - -// void RecDataT varType(const char* varName) -// -// Simply return the variable type -// -RecDataT -varType(const char *varName) -{ - RecDataT data_type; - int err; - - err = RecGetRecordDataType(const_cast(varName), &data_type); - - if (err == REC_ERR_FAIL) { - return RECD_NULL; - } - - Debug("RecOp", "[varType] %s is of type %d", varName, data_type); - return data_type; -} - // // Removes any cr/lf line breaks from the text data // @@ -899,209 +435,3 @@ substituteForHTMLChars(const char *buffer) *safeCurrent = '\0'; return safeBuf; } - -// -// -// Sets the LocalManager variable: proxy.node.hostname -// -// To the fully qualified hostname for the machine -// that we are running on -int -setHostnameVar() -{ - char ourHostName[MAXDNAME]; - char *firstDot; - - // Get Our HostName - if (gethostname(ourHostName, MAXDNAME) < 0) { - mgmt_fatal(errno, "[setHostnameVar] Can not determine our hostname"); - } - - res_init(); - appendDefaultDomain(ourHostName, MAXDNAME); - - // FQ is a Fully Qualified hostname (ie: proxydev.example.com) - varSetFromStr("proxy.node.hostname_FQ", ourHostName); - - // non-FQ is just the hostname (ie: proxydev) - firstDot = strchr(ourHostName, '.'); - if (firstDot != nullptr) { - *firstDot = '\0'; - } - varSetFromStr("proxy.node.hostname", ourHostName); - - return 0; -} - -// void appendDefaultDomain(char* hostname, int bufLength) -// -// Appends the pasted in hostname with the default -// domain if the hostname is an unqualified name -// -// The default domain is obtained from the resolver libraries -// data structure -// -// Truncates the domain name if bufLength is too small -// -// -void -appendDefaultDomain(char *hostname, int bufLength) -{ - int len = strlen(hostname); - const char msg[] = "Nodes will be know by their unqualified host name"; - static int error_before = 0; // Race ok since effect is multiple error msg - - ink_assert(len < bufLength); - ink_assert(bufLength >= 64); - - // Ensure null termination of the result string - hostname[bufLength - 1] = '\0'; - - if (strchr(hostname, '.') == nullptr) { - if (_res.defdname[0] != '\0') { - if (bufLength - 2 >= static_cast(strlen(hostname) + strlen(_res.defdname))) { - ink_strlcat(hostname, ".", bufLength); - ink_strlcat(hostname, _res.defdname, bufLength); - } else { - if (error_before == 0) { - mgmt_log("%s %s\n", "[appendDefaultDomain] Domain name is too long.", msg); - error_before++; - } - } - } else { - if (error_before == 0) { - mgmt_log("%s %s\n", "[appendDefaultDomain] Unable to determine default domain name.", msg); - error_before++; - } - } - } -} - -bool -recordValidityCheck(const char *varName, const char *value) -{ - RecCheckT check_t; - char *pattern; - - if (RecGetRecordCheckType(const_cast(varName), &check_t) != REC_ERR_OKAY) { - return false; - } - if (RecGetRecordCheckExpr(const_cast(varName), &pattern) != REC_ERR_OKAY) { - return false; - } - - switch (check_t) { - case RECC_STR: - if (recordRegexCheck(pattern, value)) { - return true; - } - break; - case RECC_INT: - if (recordRangeCheck(pattern, value)) { - return true; - } - break; - case RECC_IP: - if (recordIPCheck(pattern, value)) { - return true; - } - break; - case RECC_NULL: - // skip checking - return true; - default: - // unknown RecordCheckType... - mgmt_log("[WebMgmtUtil] error, unknown RecordCheckType for record %s\n", varName); - } - - return false; -} - -bool -recordRegexCheck(const char *pattern, const char *value) -{ - pcre *regex; - const char *error; - int erroffset; - - regex = pcre_compile(pattern, 0, &error, &erroffset, nullptr); - if (!regex) { - return false; - } else { - int r = pcre_exec(regex, nullptr, value, strlen(value), 0, 0, nullptr, 0); - - pcre_free(regex); - return (r != -1) ? true : false; - } - - return false; // no-op -} - -bool -recordRangeCheck(const char *pattern, const char *value) -{ - char *p = const_cast(pattern); - Tokenizer dashTok("-"); - - if (recordRegexCheck("^[0-9]+$", value)) { - while (*p != '[') { - p++; - } // skip to '[' - if (dashTok.Initialize(++p, COPY_TOKS) == 2) { - int l_limit = atoi(dashTok[0]); - int u_limit = atoi(dashTok[1]); - int val = atoi(value); - if (val >= l_limit && val <= u_limit) { - return true; - } - } - } - return false; -} - -bool -recordIPCheck(const char *pattern, const char *value) -{ - // regex_t regex; - // int result; - bool check; - const char *range_pattern = R"(\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\])"; - const char *ip_pattern = "[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9]"; - - Tokenizer dotTok1("."); - Tokenizer dotTok2("."); - - check = true; - if (recordRegexCheck(range_pattern, pattern) && recordRegexCheck(ip_pattern, value)) { - if (dotTok1.Initialize(const_cast(pattern), COPY_TOKS) == 4 && - dotTok2.Initialize(const_cast(value), COPY_TOKS) == 4) { - for (int i = 0; i < 4 && check; i++) { - if (!recordRangeCheck(dotTok1[i], dotTok2[i])) { - check = false; - } - } - if (check) { - return true; - } - } - } else if (strcmp(value, "") == 0) { - return true; - } - return false; -} - -bool -recordRestartCheck(const char *varName) -{ - RecUpdateT update_t; - - if (RecGetRecordUpdateType(const_cast(varName), &update_t) != REC_ERR_OKAY) { - return false; - } - - if (update_t == RECU_RESTART_TS || update_t == RECU_RESTART_TM) { - return true; - } - - return false; -} diff --git a/mgmt/WebMgmtUtils.h b/mgmt/WebMgmtUtils.h index 26cb01d915a..ce76303817c 100644 --- a/mgmt/WebMgmtUtils.h +++ b/mgmt/WebMgmtUtils.h @@ -26,20 +26,6 @@ #include "MgmtDefs.h" #include "records/P_RecCore.h" -// class MgmtData - stores information from local manager -// variables in its native type -// -class MgmtData -{ -public: - MgmtData(); - ~MgmtData(); - bool compareFromString(const char *str); - bool setFromName(const char *varName); - RecDataT type; - RecData data; -}; - // Convert to byte units (GB, MB, KB) void bytesFromInt(RecInt bytes, char *bufVal); @@ -52,14 +38,7 @@ void commaStrFromInt(RecInt bytes, char *bufVal); // Create percent string from float void percentStrFromFloat(RecFloat val, char *bufVal); -// All types converted to/from strings where appropriate -bool varStrFromName(const char *varName, char *bufVal, int bufLen); -bool varSetFromStr(const char *varName, const char *value); - // Converts where applicable to specified type -bool varIntFromName(const char *varName, RecInt *value); -bool varFloatFromName(const char *varName, RecFloat *value); -bool varCounterFromName(const char *varName, RecCounter *value); bool varDataFromName(RecDataT varType, const char *varName, RecData *value); // No conversion done. varName must represent a value of the appropriate @@ -70,18 +49,6 @@ bool varSetCounter(const char *varName, RecCounter value, bool convert = false); bool varSetFloat(const char *varName, RecFloat value, bool convert = false); bool varSetData(RecDataT varType, const char *varName, RecData value); -// Return the type of the variable named -RecDataT varType(const char *varName); - int convertHtmlToUnix(char *buffer); int substituteUnsafeChars(char *buffer); char *substituteForHTMLChars(const char *buffer); - -int setHostnameVar(); -void appendDefaultDomain(char *hostname, int bufLength); - -bool recordValidityCheck(const char *varName, const char *value); -bool recordRegexCheck(const char *pattern, const char *value); -bool recordRangeCheck(const char *pattern, const char *value); -bool recordIPCheck(const char *pattern, const char *value); -bool recordRestartCheck(const char *varName); diff --git a/mgmt/api/APITestCliRemote.cc b/mgmt/api/APITestCliRemote.cc deleted file mode 100644 index 8778b20286f..00000000000 --- a/mgmt/api/APITestCliRemote.cc +++ /dev/null @@ -1,1026 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: APITestCliRemote.cc - * Purpose: An interactive cli to test remote mgmt API; UNIT TEST for mgmtAPI - * Created: lant - * - ***************************************************************************/ - -/*************************************************************************** - * Possible Commands: - *************************************************************************** - * Control Operations: - * ------------------- - * state: returns ON (proxy is on) or OFF (proxy is off) - * start: - turns Proxy on, the tsArgs is optional; - * it can either be "hostdb" or "all", - * eg. start, start:hostdb, start:all - * stop: turns Proxy off - * restart: restarts Traffic Manager (Traffic Cop must be running) - * - * File operations: - * --------------- - * read_file: reads hosting.config file - * proxy.config.xxx (a records.config variable): returns value of that record - * records: tests get/set/get a record of each different type - * (int, float, counter, string) - * err_recs: stress test record get/set functions by purposely entering - * invalid record names and/or values - * get_mlt: tests TSRecordGetMlt - * set_mlt: tests TSRecordSetMlt - * - * read_url: tests TSReadFromUrl works by retrieving two valid urls - * test_url: tests robustness of TSReadFromUrl using invalid urls - * - * Event Operations: - * ---------------- - * active_events: lists the names of all currently active events - * MGMT_ALARM_xxx (event_name specified in CoreAPIShared.h or Alarms.h): - * resolves the specified event - * register: registers a generic callback (=eventCallbackFn) which - * prints out the event name whenever an event is signalled - * unregister: unregisters the generic callback function eventCallbackFn - * - * Diags - * ---- - * diags - uses STATUS, NOTE, FATAL, ERROR diags - * - * Statistics - * ---------- - * set_stats - sets dummy values for selected group of NODE, PROCESS - * records - * print_stats - prints the values for the same selected group of records - * reset_stats - resets all statistics to default values - */ - -#include "tscore/ink_config.h" -#include "tscore/ink_defs.h" -#include "tscore/ink_memory.h" -#include -#include -#include -#include -#include "tscore/ink_string.h" - -#include "mgmtapi.h" - -// refer to test_records() function -#define TEST_STRING 1 -#define TEST_FLOAT 1 -#define TEST_INT 1 -#define TEST_COUNTER 1 -#define TEST_REC_SET 1 -#define TEST_REC_GET 0 -#define TEST_REC_GET_2 0 - -#define SET_INT 0 - -/*************************************************************************** - * Printing Helper Functions - ***************************************************************************/ - -/* ------------------------------------------------------------------------ - * print_err - * ------------------------------------------------------------------------ - * used to print the error description associated with the TSMgmtError err - */ -void -print_err(const char *module, TSMgmtError err) -{ - char *err_msg; - - err_msg = TSGetErrorMessage(err); - printf("(%s) ERROR: %s\n", module, err_msg); - - if (err_msg) { - TSfree(err_msg); - } -} - -/*------------------------------------------------------------- - * print_string_list - *-------------------------------------------------------------*/ -void -print_string_list(TSStringList list) -{ - int i, count, buf_pos = 0; - char buf[1000]; - - if (!list) { - return; - } - count = TSStringListLen(list); - for (i = 0; i < count; i++) { - char *str = TSStringListDequeue(list); - snprintf(buf + buf_pos, sizeof(buf) - buf_pos, "%s,", str); - buf_pos = strlen(buf); - TSStringListEnqueue(list, str); - } - printf("%s \n", buf); -} - -/*------------------------------------------------------------- - * print_int_list - *-------------------------------------------------------------*/ -void -print_int_list(TSIntList list) -{ - int i, count, buf_pos = 0; - char buf[1000]; - - count = TSIntListLen(list); - for (i = 0; i < count; i++) { - int *elem = TSIntListDequeue(list); - snprintf(buf + buf_pos, sizeof(buf) - buf_pos, "%d:", *elem); - buf_pos = strlen(buf); - TSIntListEnqueue(list, elem); - } - printf("Int List: %s \n", buf); -} - -/*************************************************************************** - * Control Testing - ***************************************************************************/ -void -print_proxy_state() -{ - TSProxyStateT state = TSProxyStateGet(); - - switch (state) { - case TS_PROXY_ON: - printf("Proxy State = ON\n"); - break; - case TS_PROXY_OFF: - printf("Proxy State = OFF\n"); - break; - default: - printf("ERROR: Proxy State Undefined!\n"); - break; - } -} - -// starts Traffic Server (turns proxy on) -void -start_TS(char *tsArgs) -{ - TSMgmtError ret; - TSCacheClearT clear = TS_CACHE_CLEAR_NONE; - char *args; - - strtok(tsArgs, ":"); - args = strtok(nullptr, ":"); - if (args) { - if (strcmp(args, "all\n") == 0) { - clear = TS_CACHE_CLEAR_CACHE; - } else if (strcmp(args, "hostdb\n") == 0) { - clear = TS_CACHE_CLEAR_HOSTDB; - } - } else { - clear = TS_CACHE_CLEAR_NONE; - } - - printf("STARTING PROXY with cache: %d\n", clear); - if ((ret = TSProxyStateSet(TS_PROXY_ON, clear)) != TS_ERR_OKAY) { - printf("[TSProxyStateSet] turn on FAILED\n"); - } - print_err("start_TS", ret); -} - -// stops Traffic Server (turns proxy off) -void -stop_TS() -{ - TSMgmtError ret; - - printf("STOPPING PROXY\n"); - if ((ret = TSProxyStateSet(TS_PROXY_OFF, TS_CACHE_CLEAR_NONE)) != TS_ERR_OKAY) { - printf("[TSProxyStateSet] turn off FAILED\n"); - } - print_err("stop_TS", ret); -} - -// restarts Traffic Manager (Traffic Cop must be running) -void -restart() -{ - TSMgmtError ret; - - printf("RESTART\n"); - if ((ret = TSRestart(true)) != TS_ERR_OKAY) { - printf("[TSRestart] FAILED\n"); - } - - print_err("restart", ret); -} - -// rereads all the configuration files -void -reconfigure() -{ - TSMgmtError ret; - - printf("RECONFIGURE\n"); - if ((ret = TSReconfigure()) != TS_ERR_OKAY) { - printf("[TSReconfigure] FAILED\n"); - } - - print_err("reconfigure", ret); -} - -/* ------------------------------------------------------------------------ - * test_action_need - * ------------------------------------------------------------------------ - * tests if correct action need is returned when requested record is set - */ -void -test_action_need() -{ - TSActionNeedT action; - - // RU_NULL record - TSRecordSetString("proxy.config.proxy_name", "proxy_dorky", &action); - printf("[TSRecordSetString] proxy.config.proxy_name \n\tAction Should: [%d]\n\tAction is : [%d]\n", TS_ACTION_UNDEFINED, - action); -} - -/* Bouncer the traffic_server process(es) */ -void -bounce() -{ - TSMgmtError ret; - - printf("BOUNCER\n"); - if ((ret = TSBounce(true)) != TS_ERR_OKAY) { - printf("[TSBounce] FAILED\n"); - } - - print_err("bounce", ret); -} - -/*************************************************************************** - * Record Testing - ***************************************************************************/ - -/* ------------------------------------------------------------------------ - * test_error_records - * ------------------------------------------------------------------------ - * stress test error handling by purposely being dumb; send requests to - * get invalid record names - */ -void -test_error_records() -{ - TSInt port1, new_port = 8080; - TSActionNeedT action; - TSMgmtError ret; - TSCounter ctr1; - - printf("\n"); - // test get integer - fprintf(stderr, "Test invalid record names\n"); - - ret = TSRecordGetInt("proy.config.cop.core_signal", &port1); - if (ret != TS_ERR_OKAY) { - print_err("TSRecordGetInt", ret); - } else { - printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port1); - } - - // test set integer - ret = TSRecordSetInt("proy.config.cop.core_signal", new_port, &action); - print_err("TSRecordSetInt", ret); - - printf("\n"); - if (TSRecordGetCounter("proxy.press.socks.connections_successful", &ctr1) != TS_ERR_OKAY) { - printf("TSRecordGetCounter FAILED!\n"); - } else { - printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr1); - } -} - -/* ------------------------------------------------------------------------ - * test_records - * ------------------------------------------------------------------------ - * stress test record functionality by getting and setting different - * records types; use the #defines defined above to determine which - * type of tests you'd like turned on/off - */ -void -test_records() -{ - TSActionNeedT action; - char *rec_value; - char new_str[] = "new_record_value"; - TSInt port1, port2, new_port = 52432; - TSCounter ctr1, ctr2, new_ctr = 6666; - TSMgmtError err; - - /********************* START TEST SECTION *****************/ - printf("\n\n"); - -#if SET_INT - // test set integer - if (TSRecordSetInt("proxy.config.cop.core_signal", new_port, &action) != TS_ERR_OKAY) - printf("TSRecordSetInt FAILED!\n"); - else - printf("[TSRecordSetInt] proxy.config.cop.core_signal=%" PRId64 " \n", new_port); -#endif - -#if TEST_REC_GET - TSRecordEle *rec_ele; - // retrieve a string value record using generic RecordGet - rec_ele = TSRecordEleCreate(); - if (TSRecordGet("proxy.config.http.cache.vary_default_other", rec_ele) != TS_ERR_OKAY) - printf("TSRecordGet FAILED!\n"); - else - printf("[TSRecordGet] proxy.config.http.cache.vary_default_other=%s\n", rec_ele->string_val); - - TSRecordEleDestroy(rec_ele); - printf("\n\n"); -#endif - -#if TEST_REC_GET_2 - // retrieve a string value record using generic RecordGet - rec_ele = TSRecordEleCreate(); - if (TSRecordGet("proxy.config.proxy_name", rec_ele) != TS_ERR_OKAY) - printf("TSRecordGet FAILED!\n"); - else - printf("[TSRecordGet] proxy.config.proxy_name=%s\n", rec_ele->string_val); - - TSRecordEleDestroy(rec_ele); - printf("\n\n"); -#endif - -#if TEST_STRING - // retrieve an string value record using GetString - err = TSRecordGetString("proxy.config.proxy_name", &rec_value); - if (err != TS_ERR_OKAY) { - print_err("TSRecordGetString", err); - } else { - printf("[TSRecordGetString] proxy.config.proxy_name=%s\n", rec_value); - } - TSfree(rec_value); - rec_value = nullptr; - - // test RecordSet - err = TSRecordSetString("proxy.config.proxy_name", (TSString)new_str, &action); - if (err != TS_ERR_OKAY) { - print_err("TSRecordSetString", err); - } else { - printf("[TSRecordSetString] proxy.config.proxy_name=%s\n", new_str); - } - - // get - err = TSRecordGetString("proxy.config.proxy_name", &rec_value); - if (err != TS_ERR_OKAY) { - print_err("TSRecordGetString", err); - } else { - printf("[TSRecordGetString] proxy.config.proxy_name=%s\n", rec_value); - } - printf("\n"); - TSfree(rec_value); -#endif - -#if TEST_INT - printf("\n"); - // test get integer - if (TSRecordGetInt("proxy.config.cop.core_signal", &port1) != TS_ERR_OKAY) { - printf("TSRecordGetInt FAILED!\n"); - } else { - printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port1); - } - - // test set integer - if (TSRecordSetInt("proxy.config.cop.core_signal", new_port, &action) != TS_ERR_OKAY) { - printf("TSRecordSetInt FAILED!\n"); - } else { - printf("[TSRecordSetInt] proxy.config.cop.core_signal=%" PRId64 " \n", new_port); - } - - if (TSRecordGetInt("proxy.config.cop.core_signal", &port2) != TS_ERR_OKAY) { - printf("TSRecordGetInt FAILED!\n"); - } else { - printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port2); - } - printf("\n"); -#endif - -#if TEST_COUNTER - printf("\n"); - - if (TSRecordGetCounter("proxy.process.socks.connections_successful", &ctr1) != TS_ERR_OKAY) { - printf("TSRecordGetCounter FAILED!\n"); - } else { - printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr1); - } - - if (TSRecordSetCounter("proxy.process.socks.connections_successful", new_ctr, &action) != TS_ERR_OKAY) { - printf("TSRecordSetCounter FAILED!\n"); - } else { - printf("[TSRecordSetCounter] proxy.process.socks.connections_successful=%" PRId64 " \n", new_ctr); - } - - if (TSRecordGetCounter("proxy.process.socks.connections_successful", &ctr2) != TS_ERR_OKAY) { - printf("TSRecordGetCounter FAILED!\n"); - } else { - printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr2); - } - printf("\n"); -#endif -} - -// retrieves the value of the "proxy.config.xxx" record requested at input -void -test_rec_get(char *rec_name) -{ - TSRecordEle *rec_ele; - TSMgmtError ret; - char *name; - - name = ats_strdup(rec_name); - printf("[test_rec_get] Get Record: %s\n", name); - - // retrieve a string value record using generic RecordGet - rec_ele = TSRecordEleCreate(); - if ((ret = TSRecordGet(name, rec_ele)) != TS_ERR_OKAY) { - printf("TSRecordGet FAILED!\n"); - } else { - switch (rec_ele->rec_type) { - case TS_REC_INT: - printf("[TSRecordGet] %s=%" PRId64 "\n", name, rec_ele->valueT.int_val); - break; - case TS_REC_COUNTER: - printf("[TSRecordGet] %s=%" PRId64 "\n", name, rec_ele->valueT.counter_val); - break; - case TS_REC_FLOAT: - printf("[TSRecordGet] %s=%f\n", name, rec_ele->valueT.float_val); - break; - case TS_REC_STRING: - printf("[TSRecordGet] %s=%s\n", name, rec_ele->valueT.string_val); - break; - default: - // Handled here: - // TS_REC_UNDEFINED - break; - } - } - - print_err("TSRecordGet", ret); - - TSRecordEleDestroy(rec_ele); - TSfree(name); -} - -/* ------------------------------------------------------------------------ - * test_record_get_mlt - * ------------------------------------------------------------------------ - * Creates a list of record names to retrieve, and then batch request to - * get list of records - */ -void -test_record_get_mlt() -{ - TSStringList name_list; - TSList rec_list; - int i, num; - char *v1, *v2, *v3, *v6, *v7; - TSMgmtError ret; - - name_list = TSStringListCreate(); - rec_list = TSListCreate(); - - const size_t v1_size = (sizeof(char) * (strlen("proxy.config.proxy_name") + 1)); - v1 = static_cast(TSmalloc(v1_size)); - ink_strlcpy(v1, "proxy.config.proxy_name", v1_size); - const size_t v2_size = (sizeof(char) * (strlen("proxy.config.bin_path") + 1)); - v2 = static_cast(TSmalloc(v2_size)); - ink_strlcpy(v2, "proxy.config.bin_path", v2_size); - const size_t v3_size = (sizeof(char) * (strlen("proxy.config.manager_binary") + 1)); - v3 = static_cast(TSmalloc(v3_size)); - ink_strlcpy(v3, "proxy.config.manager_binary", v3_size); - const size_t v6_size = (sizeof(char) * (strlen("proxy.config.env_prep") + 1)); - v6 = static_cast(TSmalloc(v6_size)); - ink_strlcpy(v6, "proxy.config.env_prep", v6_size); - const size_t v7_size = (sizeof(char) * (strlen("proxy.config.cop.core_signal") + 1)); - v7 = static_cast(TSmalloc(v7_size)); - ink_strlcpy(v7, "proxy.config.cop.core_signal", v7_size); - - // add the names to the get_list - TSStringListEnqueue(name_list, v1); - TSStringListEnqueue(name_list, v2); - TSStringListEnqueue(name_list, v3); - TSStringListEnqueue(name_list, v6); - TSStringListEnqueue(name_list, v7); - - num = TSStringListLen(name_list); - printf("Num Records to Get: %d\n", num); - ret = TSRecordGetMlt(name_list, rec_list); - // free the string list - TSStringListDestroy(name_list); - if (ret != TS_ERR_OKAY) { - print_err("TSStringListDestroy", ret); - } - - for (i = 0; i < num; i++) { - TSRecordEle *rec_ele = static_cast(TSListDequeue(rec_list)); - if (!rec_ele) { - printf("ERROR\n"); - break; - } - printf("Record: %s = ", rec_ele->rec_name); - switch (rec_ele->rec_type) { - case TS_REC_INT: - printf("%" PRId64 "\n", rec_ele->valueT.int_val); - break; - case TS_REC_COUNTER: - printf("%" PRId64 "\n", rec_ele->valueT.counter_val); - break; - case TS_REC_FLOAT: - printf("%f\n", rec_ele->valueT.float_val); - break; - case TS_REC_STRING: - printf("%s\n", rec_ele->valueT.string_val); - break; - default: - // Handled here: - // TS_REC_UNDEFINED - break; - } - TSRecordEleDestroy(rec_ele); - } - - TSListDestroy(rec_list); // must dequeue and free each string individually - - return; -} - -/* ------------------------------------------------------------------------ - * test_record_set_mlt - * ------------------------------------------------------------------------ - * Creates a list of TSRecordEle's, and then batch request to set records - * Also checks to make sure correct action_need type is set. - */ -void -test_record_set_mlt() -{ - TSList list; - TSRecordEle *ele1, *ele2; - TSActionNeedT action = TS_ACTION_UNDEFINED; - TSMgmtError err; - - list = TSListCreate(); - - ele1 = TSRecordEleCreate(); // TS_TYPE_UNDEFINED action - ele1->rec_name = TSstrdup("proxy.config.cli_binary"); - ele1->rec_type = TS_REC_STRING; - ele1->valueT.string_val = TSstrdup(ele1->rec_name); - - ele2 = TSRecordEleCreate(); // undefined action - ele2->rec_name = TSstrdup("proxy.config.cop.core_signal"); - ele2->rec_type = TS_REC_INT; - ele2->valueT.int_val = -4; - - TSListEnqueue(list, ele1); - TSListEnqueue(list, ele2); - - err = TSRecordSetMlt(list, &action); - print_err("TSRecordSetMlt", err); - fprintf(stderr, "[TSRecordSetMlt] Action Required: %d\n", action); - - // cleanup: need to iterate through list and delete each ele - int count = TSListLen(list); - for (int i = 0; i < count; i++) { - TSRecordEle *ele = static_cast(TSListDequeue(list)); - TSRecordEleDestroy(ele); - } - TSListDestroy(list); -} - -/*************************************************************************** - * File I/O Testing - ***************************************************************************/ - -// if valid==true, then use a valid url to read -void -test_read_url(bool valid) -{ - char *header = nullptr; - int headerSize; - char *body = nullptr; - int bodySize; - TSMgmtError err; - - if (!valid) { - // first try - - err = TSReadFromUrlEx("hsdfasdf.com:80/index.html", &header, &headerSize, &body, &bodySize, 50000); - if (err != TS_ERR_OKAY) { - print_err("TSReadFromUrlEx", err); - } else { - printf("--------------------------------------------------------------\n"); - // printf("The header...\n%s\n%d\n", *header, *headerSize); - printf("--------------------------------------------------------------\n"); - printf("The body...\n%s\n%d\n", body, bodySize); - } - if (body) { - TSfree(body); - } - if (header) { - TSfree(header); - } - - err = TSReadFromUrlEx("http://sadfasdfi.com:80/", &header, &headerSize, &body, &bodySize, 50000); - if (err != TS_ERR_OKAY) { - print_err("TSReadFromUrlEx", err); - } else { - printf("---------------------------------------------------------------\n"); - printf("The header...\n%s\n%d\n", header, headerSize); - printf("-------------------------------------------------------------\n"); - printf("The body...\n%s\n%d\n", body, bodySize); - } - if (header) { - TSfree(header); - } - if (body) { - TSfree(body); - } - - } else { // use valid urls - err = TSReadFromUrlEx("lakota.example.com:80/", &header, &headerSize, &body, &bodySize, 50000); - - if (err != TS_ERR_OKAY) { - print_err("TSReadFromUrlEx", err); - } else { - printf("---------------------------------------------------------------\n"); - printf("The header...\n%s\n%d\n", header, headerSize); - printf("-------------------------------------------------------------\n"); - printf("The body...\n%s\n%d\n", body, bodySize); - } - if (header) { - TSfree(header); - } - if (body) { - TSfree(body); - } - - // read second url - err = TSReadFromUrlEx("http://www.apache.org:80/index.html", &header, &headerSize, &body, &bodySize, 50000); - if (err != TS_ERR_OKAY) { - print_err("TSReadFromUrlEx", err); - } else { - printf("---------------------------------------------------------------\n"); - printf("The header...\n%s\n%d\n", header, headerSize); - printf("-------------------------------------------------------------\n"); - printf("The body...\n%s\n%d\n", body, bodySize); - } - if (header) { - TSfree(header); - } - if (body) { - TSfree(body); - } - } -} - -/*************************************************************************** - * Events Testing - ***************************************************************************/ -/* ------------------------------------------------------------------------ - * print_active_events - * ------------------------------------------------------------------------ - * retrieves a list of all active events and prints out each event name, - * one event per line - */ -void -print_active_events() -{ - TSList events; - TSMgmtError ret; - int count, i; - char *name; - - printf("[print_active_events]\n"); - - events = TSListCreate(); - ret = TSActiveEventGetMlt(events); - if (ret != TS_ERR_OKAY) { - print_err("TSActiveEventGetMlt", ret); - goto END; - } else { // successful get - count = TSListLen(events); - for (i = 0; i < count; i++) { - name = static_cast(TSListDequeue(events)); - printf("\t%s\n", name); - TSfree(name); - } - } - -END: - TSListDestroy(events); - return; -} - -/* ------------------------------------------------------------------------ - * check_active - * ------------------------------------------------------------------------ - * returns true if the event named event_name is currently active (unresolved) - * returns false otherwise - */ -bool -check_active(char *event_name) -{ - bool active; - TSMgmtError ret; - - ret = TSEventIsActive(event_name, &active); - print_err("TSEventIsActive", ret); - - if (active) { - printf("%s is ACTIVE\n", event_name); - } else { - printf("%s is NOT-ACTIVE\n", event_name); - } - - return active; -} - -/* ------------------------------------------------------------------------ - * try_resolve - * ------------------------------------------------------------------------ - * checks if the event_name is still unresolved; if it is, it then - * resolves it, and checks the status of the event again to make sure - * the event was actually resolved - * - * NOTE: all the special string manipulation is needed because the CLI - * appends extra newline character to end of the user input; normally - * do not have to do all this special string manipulation - */ -void -try_resolve(char *event_name) -{ - TSMgmtError ret; - char *name; - - name = TSstrdup(event_name); - printf("[try_resolve] Resolving event: %s\n", name); - - if (check_active(name)) { // resolve events - ret = TSEventResolve(name); - print_err("TSEventResolve", ret); - check_active(name); // should be non-active now - } - - TSfree(name); -} - -/* ------------------------------------------------------------------------ - * eventCallbackFn - * ------------------------------------------------------------------------ - * the callback function; when called, it just prints out the name - * of the event that was signalled - */ -void -eventCallbackFn(char *name, char *msg, int /* pri ATS_UNUSED */, void * /* data ATS_UNUSED */) -{ - printf("[eventCallbackFn] EVENT: %s, %s\n", name, msg); - return; -} - -/* ------------------------------------------------------------------------ - * register_event_callback - * ------------------------------------------------------------------------ - * registers the eventCallbackFn above for all events; this just means - * that for any event that's signalled, the callback fn will also be called - */ -void -register_event_callback() -{ - TSMgmtError err; - - printf("\n[register_event_callback] \n"); - err = TSEventSignalCbRegister(nullptr, eventCallbackFn, nullptr); - print_err("TSEventSignalCbRegister", err); -} - -/* ------------------------------------------------------------------------ - * unregister_event_callback - * ------------------------------------------------------------------------ - * unregisters the eventCallbackFn above for all events; this just means - * that it will remove this eventCallbackFn entirely so that for any - * event called, the eventCallbackFn will NOT be called - */ -void -unregister_event_callback() -{ - TSMgmtError err; - - printf("\n[unregister_event_callback]\n"); - err = TSEventSignalCbUnregister(nullptr, eventCallbackFn); - print_err("TSEventSignalCbUnregister", err); -} - -/*************************************************************************** - * Statistics - ***************************************************************************/ - -// generate dummy values for statistics -void -set_stats() -{ - TSActionNeedT action; - - fprintf(stderr, "[set_stats] Set Dummy Stat Values\n"); - - TSRecordSetInt("proxy.process.http.user_agent_response_document_total_size", 100, &action); - TSRecordSetInt("proxy.process.http.user_agent_response_header_total_size", 100, &action); - TSRecordSetInt("proxy.process.http.current_client_connections", 100, &action); - TSRecordSetInt("proxy.process.http.current_client_transactions", 100, &action); - TSRecordSetInt("proxy.process.http.origin_server_response_document_total_size", 100, &action); - TSRecordSetInt("proxy.process.http.origin_server_response_header_total_size", 100, &action); - TSRecordSetInt("proxy.process.http.current_server_connections", 100, &action); - TSRecordSetInt("proxy.process.http.current_server_transactions", 100, &action); - - TSRecordSetInt("proxy.node.proxy_running", 110, &action); - TSRecordSetInt("proxy.node.proxy_running", 110, &action); -} - -void -print_stats() -{ - TSInt i1, i2, i3, i4, i5, i6, i7, i8; - - fprintf(stderr, "[print_stats]\n"); - - TSRecordGetInt("proxy.process.http.user_agent_response_document_total_size", &i1); - TSRecordGetInt("proxy.process.http.user_agent_response_header_total_size", &i2); - TSRecordGetInt("proxy.process.http.current_client_connections", &i3); - TSRecordGetInt("proxy.process.http.current_client_transactions", &i4); - TSRecordGetInt("proxy.process.http.origin_server_response_document_total_size", &i5); - TSRecordGetInt("proxy.process.http.origin_server_response_header_total_size", &i6); - TSRecordGetInt("proxy.process.http.current_server_connections", &i7); - TSRecordGetInt("proxy.process.http.current_server_transactions", &i8); - - fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1, - i2, i3, i4, i5, i6, i7, i8); - - TSRecordGetInt("proxy.node.proxy_running", &i4); - TSRecordGetInt("proxy.node.proxy_running", &i6); - - fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1, i7, i2, i3, i4, - i5, i6); - - fprintf(stderr, "PROCESS stats: \n"); - fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1, i2, i3, i4); -} - -void -reset_stats() -{ - TSMgmtError err = TSStatsReset(nullptr); - print_err("TSStatsReset", err); - return; -} - -void -sync_test() -{ - TSActionNeedT action; - - TSRecordSetString("proxy.config.proxy_name", "dorkface", &action); - printf("[TSRecordSetString] proxy.config.proxy_name \n\tAction Should: [%d]\n\tAction is : [%d]\n", TS_ACTION_UNDEFINED, - action); - - TSMgmtError ret; - if ((ret = TSProxyStateSet(TS_PROXY_OFF, TS_CACHE_CLEAR_NONE)) != TS_ERR_OKAY) { - printf("[TSProxyStateSet] turn off FAILED\n"); - } - print_err("stop_TS", ret); -} - -/* ########################################################################*/ -/* ------------------------------------------------------------------------ - * runInteractive - * ------------------------------------------------------------------------ - * the loop that processes the commands inputted by user - */ -static void -runInteractive() -{ - char buf[512]; // holds request from interactive prompt - - // process input from command line - while (true) { - // Display a prompt - printf("api_cli-> "); - - // get input from command line - ATS_UNUSED_RETURN(fgets(buf, 512, stdin)); - - // check status of 'stdin' after reading - if (feof(stdin) != 0) { - printf("EXIT api_cli_remote\n"); - return; - } else if (ferror(stdin) != 0) { - printf("EXIT api_cli_remote\n"); - return; - } - // continue on newline - if (strcmp(buf, "\n") == 0) { - continue; - } - // exiting/quitting? - if (strcasecmp("quit\n", buf) == 0 || strcasecmp("exit\n", buf) == 0) { - // Don't wait for response LM - // exit(0); - return; - } - // check what operation user typed in - if (strstr(buf, "state")) { - print_proxy_state(); - } else if (strncmp(buf, "start", 5) == 0) { - start_TS(buf); - } else if (strstr(buf, "stop")) { - stop_TS(); - } else if (strstr(buf, "restart")) { - restart(); - } else if (strstr(buf, "reconfig")) { - reconfigure(); - } else if (strstr(buf, "records")) { - test_records(); - } else if (strstr(buf, "err_recs")) { - test_error_records(); - } else if (strstr(buf, "get_mlt")) { - test_record_get_mlt(); - } else if (strstr(buf, "set_mlt")) { - test_record_set_mlt(); - } else if (strstr(buf, "proxy.")) { - test_rec_get(buf); - } else if (strstr(buf, "active_events")) { - print_active_events(); - } else if (strstr(buf, "MGMT_ALARM_")) { - try_resolve(buf); - } else if (strncmp(buf, "register", 8) == 0) { - register_event_callback(); - } else if (strstr(buf, "unregister")) { - unregister_event_callback(); - } else if (strstr(buf, "read_url")) { - test_read_url(true); - } else if (strstr(buf, "test_url")) { - test_read_url(false); - } else if (strstr(buf, "reset_stats")) { - reset_stats(); - } else if (strstr(buf, "set_stats")) { - set_stats(); - } else if (strstr(buf, "print_stats")) { - print_stats(); - } else { - sync_test(); - } - - } // end while(1) - -} // end runInteractive - -/* ------------------------------------------------------------------------ - * main - * ------------------------------------------------------------------------ - * Main entry point which connects the client to the API, does any - * clean up on exit, and gets the interactive command-line running - */ -int -main(int /* argc ATS_UNUSED */, char ** /* argv ATS_UNUSED */) -{ - TSMgmtError ret; - - if ((ret = TSInit(nullptr, TS_MGMT_OPT_DEFAULTS)) == TS_ERR_OKAY) { - runInteractive(); - TSTerminate(); - printf("END REMOTE API TEST\n"); - } else { - print_err("main", ret); - } - - return 0; -} // end main() diff --git a/mgmt/api/CoreAPI.cc b/mgmt/api/CoreAPI.cc deleted file mode 100644 index 35cd8267776..00000000000 --- a/mgmt/api/CoreAPI.cc +++ /dev/null @@ -1,924 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * CoreAPI.cc - * - * Implementation of many of TSMgmtAPI functions, but from local side. - * - * - ***************************************************************************/ -#include - -#include "tscore/ink_platform.h" -#include "tscore/ink_file.h" -#include "tscore/ParseRules.h" -#include "RecordsConfig.h" -#include "Alarms.h" -#include "MgmtUtils.h" -#include "LocalManager.h" -#include "FileManager.h" -#include "ConfigManager.h" -#include "WebMgmtUtils.h" -#include "tscore/Diags.h" -#include "ExpandingArray.h" - -#include "CoreAPI.h" -#include "CoreAPIShared.h" -#include "EventCallback.h" -#include "tscore/I_Layout.h" -#include "tscore/ink_cap.h" - -// global variable -static CallbackTable *local_event_callbacks; - -extern FileManager *configFiles; // global in traffic_manager - -/*------------------------------------------------------------------------- - * Init - *------------------------------------------------------------------------- - * performs any necessary initializations for the local API client, - * eg. set up global structures; called by the TSMgmtAPI::TSInit() - */ -TSMgmtError -Init(const char * /* socket_path ATS_UNUSED */, TSInitOptionT options) -{ - // socket_path should be null; only applies to remote clients - if (0 == (options & TS_MGMT_OPT_NO_EVENTS)) { - local_event_callbacks = create_callback_table("local_callbacks"); - if (!local_event_callbacks) { - return TS_ERR_SYS_CALL; - } - } else { - local_event_callbacks = nullptr; - } - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * Terminate - *------------------------------------------------------------------------- - * performs any necessary cleanup of global structures, etc, - * for the local API client, - */ -TSMgmtError -Terminate() -{ - delete_callback_table(local_event_callbacks); - - return TS_ERR_OKAY; -} - -/*************************************************************************** - * Control Operations - ***************************************************************************/ - -// bool ProxyShutdown() -// -// Attempts to turn the proxy off. Returns -// true if the proxy is off when the call returns -// and false if it is still on -// -static bool -ProxyShutdown() -{ - int i = 0; - - // Check to make sure that we are not already down - if (!lmgmt->processRunning()) { - return true; - } - - lmgmt->processShutdown(false /* only shut down the proxy*/); - - // Wait for awhile for shutdown to happen - do { - mgmt_sleep_sec(1); - i++; - } while (i < 10 && lmgmt->processRunning()); - - // See if we succeeded - if (lmgmt->processRunning()) { - return false; - } else { - return true; - } -} -/*------------------------------------------------------------------------- - * ProxyStateGet - *------------------------------------------------------------------------- - * return TS_PROXY_OFF if Traffic Server is off. - * return TS_PROXY_ON if Traffic Server is on. - */ -TSProxyStateT -ProxyStateGet() -{ - if (!lmgmt->processRunning()) { - return TS_PROXY_OFF; - } else { - return TS_PROXY_ON; - } -} - -/*------------------------------------------------------------------------- - * ProxyStateSet - *------------------------------------------------------------------------- - * If state == TS_PROXY_ON, will turn on TS (unless it's already running). - * If state == TS_PROXY_OFF, will turn off TS (unless it's already off). - * tsArgs - (optional) a string with space delimited options that user - * wants to start traffic Server with - */ -TSMgmtError -ProxyStateSet(TSProxyStateT state, TSCacheClearT clear) -{ - char tsArgs[MAX_BUF_SIZE]; - char *proxy_options; - - ink_zero(tsArgs); - - switch (state) { - case TS_PROXY_OFF: - if (!ProxyShutdown()) { // from WebMgmtUtils - goto Lerror; // unsuccessful shutdown - } - break; - case TS_PROXY_ON: - if (lmgmt->processRunning()) { // already on - break; - } - - // Start with the default options from records.config. - if (RecGetRecordString_Xmalloc("proxy.config.proxy_binary_opts", &proxy_options) == REC_ERR_OKAY) { - if (max_records_entries == - (REC_INTERNAL_RECORDS + REC_DEFAULT_API_RECORDS)) { // Default size, don't need to pass down to _server - snprintf(tsArgs, sizeof(tsArgs), "%s", proxy_options); - } else { - snprintf(tsArgs, sizeof(tsArgs), "%s --maxRecords %d", proxy_options, max_records_entries); - } - ats_free(proxy_options); - } - - if (clear & TS_CACHE_CLEAR_CACHE) { - ink_strlcat(tsArgs, " -K", sizeof(tsArgs)); - } - - if (clear & TS_CACHE_CLEAR_HOSTDB) { - ink_strlcat(tsArgs, " -k", sizeof(tsArgs)); - } - - mgmt_log("[ProxyStateSet] Traffic Server Args: '%s %s'\n", lmgmt->proxy_options.c_str(), tsArgs); - - lmgmt->run_proxy = true; - lmgmt->listenForProxy(); - if (!lmgmt->startProxy(tsArgs)) { - goto Lerror; - } - - break; - - default: - goto Lerror; - } - - return TS_ERR_OKAY; - -Lerror: - return TS_ERR_FAIL; /* failed to set proxy state */ -} - -#if TS_USE_REMOTE_UNWINDING - -#include -#include -#include -#include - -using threadlist = std::vector; - -static threadlist -threads_for_process(pid_t proc) -{ - DIR *dir = nullptr; - struct dirent *entry = nullptr; - - char path[64]; - threadlist threads; - - if (snprintf(path, sizeof(path), "/proc/%ld/task", static_cast(proc)) >= static_cast(sizeof(path))) { - goto done; - } - - dir = opendir(path); - if (dir == nullptr) { - goto done; - } - - while ((entry = readdir(dir))) { - pid_t threadid; - - if (isdot(entry->d_name) || isdotdot(entry->d_name)) { - continue; - } - - threadid = strtol(entry->d_name, nullptr, 10); - if (threadid > 0) { - threads.push_back(threadid); - Debug("backtrace", "found thread %ld", (long)threadid); - } - } - -done: - if (dir) { - closedir(dir); - } - - return threads; -} - -static void -backtrace_for_thread(pid_t threadid, TextBuffer &text) -{ - int status; - unw_addr_space_t addr_space = nullptr; - unw_cursor_t cursor; - void *ap = nullptr; - pid_t target = -1; - unsigned level = 0; - - // First, attach to the child, causing it to stop. - status = ptrace(PTRACE_ATTACH, threadid, 0, 0); - if (status < 0) { - Debug("backtrace", "ptrace(ATTACH, %ld) -> %s (%d)", (long)threadid, strerror(errno), errno); - return; - } - - // Wait for it to stop (XXX should be a timed wait ...) - target = waitpid(threadid, &status, __WALL | WUNTRACED); - Debug("backtrace", "waited for target %ld, found PID %ld, %s", (long)threadid, (long)target, - WIFSTOPPED(status) ? "STOPPED" : "???"); - if (target < 0) { - goto done; - } - - ap = _UPT_create(threadid); - Debug("backtrace", "created UPT %p", ap); - if (ap == nullptr) { - goto done; - } - - addr_space = unw_create_addr_space(&_UPT_accessors, 0 /* byteorder */); - Debug("backtrace", "created address space %p", addr_space); - if (addr_space == nullptr) { - goto done; - } - - status = unw_init_remote(&cursor, addr_space, ap); - Debug("backtrace", "unw_init_remote(...) -> %d", status); - if (status != 0) { - goto done; - } - - while (unw_step(&cursor) > 0) { - unw_word_t ip; - unw_word_t offset; - char buf[256]; - - unw_get_reg(&cursor, UNW_REG_IP, &ip); - - if (unw_get_proc_name(&cursor, buf, sizeof(buf), &offset) == 0) { - int status; - char *name = abi::__cxa_demangle(buf, nullptr, nullptr, &status); - text.format("%-4u 0x%016llx %s + %p\n", level, static_cast(ip), name ? name : buf, (void *)offset); - free(name); - } else { - text.format("%-4u 0x%016llx 0x0 + %p\n", level, static_cast(ip), (void *)offset); - } - - ++level; - } - -done: - if (addr_space) { - unw_destroy_addr_space(addr_space); - } - - if (ap) { - _UPT_destroy(ap); - } - - status = ptrace(PTRACE_DETACH, target, NULL, NULL); - Debug("backtrace", "ptrace(DETACH, %ld) -> %d (errno %d)", (long)target, status, errno); -} - -TSMgmtError -ServerBacktrace(unsigned /* options */, char **trace) -{ - *trace = nullptr; - - // Unfortunately, we need to be privileged here. We either need to be root or to be holding - // the CAP_SYS_PTRACE capability. Even though we are the parent traffic_manager, it is not - // traceable without privilege because the process credentials do not match. - ElevateAccess access(ElevateAccess::TRACE_PRIVILEGE); - threadlist threads(threads_for_process(lmgmt->watched_process_pid)); - TextBuffer text(0); - - Debug("backtrace", "tracing %zd threads for traffic_server PID %ld", threads.size(), (long)lmgmt->watched_process_pid); - - for (auto threadid : threads) { - Debug("backtrace", "tracing thread %ld", (long)threadid); - // Get the thread name using /proc/PID/comm - ats_scoped_fd fd; - char threadname[128]; - - snprintf(threadname, sizeof(threadname), "/proc/%ld/comm", static_cast(threadid)); - fd = open(threadname, O_RDONLY); - if (fd >= 0) { - text.format("Thread %ld, ", static_cast(threadid)); - text.readFromFD(fd); - text.chomp(); - } else { - text.format("Thread %ld", static_cast(threadid)); - } - - text.format(":\n"); - - backtrace_for_thread(threadid, text); - text.format("\n"); - } - - *trace = text.release(); - return TS_ERR_OKAY; -} - -#else /* TS_USE_REMOTE_UNWINDING */ - -TSMgmtError -ServerBacktrace(unsigned /* options */, char **trace) -{ - *trace = nullptr; - return TS_ERR_NOT_SUPPORTED; -} - -#endif - -/*------------------------------------------------------------------------- - * Reconfigure - *------------------------------------------------------------------------- - * Rereads configuration files - */ -TSMgmtError -Reconfigure() -{ - configFiles->rereadConfig(); // TM rereads - lmgmt->signalEvent(MGMT_EVENT_PLUGIN_CONFIG_UPDATE, "*"); // TS rereads - RecSetRecordInt("proxy.node.config.reconfigure_time", time(nullptr), REC_SOURCE_DEFAULT); - RecSetRecordInt("proxy.node.config.reconfigure_required", 0, REC_SOURCE_DEFAULT); - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * Restart - *------------------------------------------------------------------------- - * Restarts Traffic Manager. Traffic Cop must be running in order to - * restart Traffic Manager!! - */ -TSMgmtError -Restart(unsigned options) -{ - lmgmt->mgmt_shutdown_triggered_at = time(nullptr); - lmgmt->mgmt_shutdown_outstanding = (options & TS_RESTART_OPT_DRAIN) ? MGMT_PENDING_IDLE_RESTART : MGMT_PENDING_RESTART; - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * Bouncer - *------------------------------------------------------------------------- - * Bounces traffic_server process(es). - */ -TSMgmtError -Bounce(unsigned options) -{ - lmgmt->mgmt_shutdown_triggered_at = time(nullptr); - lmgmt->mgmt_shutdown_outstanding = (options & TS_RESTART_OPT_DRAIN) ? MGMT_PENDING_IDLE_BOUNCE : MGMT_PENDING_BOUNCE; - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * Stop - *------------------------------------------------------------------------- - * Stops traffic_server process(es). - */ -TSMgmtError -Stop(unsigned options) -{ - lmgmt->mgmt_shutdown_triggered_at = time(nullptr); - lmgmt->mgmt_shutdown_outstanding = (options & TS_STOP_OPT_DRAIN) ? MGMT_PENDING_IDLE_STOP : MGMT_PENDING_STOP; - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * Drain - *------------------------------------------------------------------------- - * Drain requests of traffic_server - */ -TSMgmtError -Drain(unsigned options) -{ - switch (options) { - case TS_DRAIN_OPT_NONE: - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_DRAIN; - break; - case TS_DRAIN_OPT_IDLE: - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_IDLE_DRAIN; - break; - case TS_DRAIN_OPT_UNDO: - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_UNDO_DRAIN; - break; - default: - ink_release_assert(!"Not expected to reach here"); - } - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * StorageDeviceCmdOffline - *------------------------------------------------------------------------- - * Disable a storage device. - * [amc] I don't think this is called but is required because of the way the - * CoreAPI is linked (it must match the remote CoreAPI signature so compiling - * this source or CoreAPIRemote.cc yields the same set of symbols). - */ -TSMgmtError -StorageDeviceCmdOffline(const char *dev) -{ - lmgmt->signalEvent(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, dev); - return TS_ERR_OKAY; -} -/*------------------------------------------------------------------------- - * Lifecycle Message - *------------------------------------------------------------------------- - * Signal plugins. - */ -TSMgmtError -LifecycleMessage(const char *tag, void const *data, size_t data_size) -{ - ink_release_assert(!"Not expected to reach here"); - lmgmt->signalEvent(MGMT_EVENT_LIFECYCLE_MESSAGE, tag); - return TS_ERR_OKAY; -} -/************************************************************************** - * RECORD OPERATIONS - *************************************************************************/ -/*------------------------------------------------------------------------- - * MgmtRecordGet - *------------------------------------------------------------------------- - * rec_ele has allocated memory already but with all empty fields. - * The record info associated with rec_name will be returned in rec_ele. - */ -TSMgmtError -MgmtRecordGet(const char *rec_name, TSRecordEle *rec_ele) -{ - RecDataT rec_type; - char rec_val[MAX_BUF_SIZE]; - char *str_val; - MgmtIntCounter counter_val; - MgmtInt int_val; - - Debug("RecOp", "[MgmtRecordGet] Start"); - - // initialize the record name - rec_ele->rec_name = ats_strdup(rec_name); - memset(rec_val, 0, MAX_BUF_SIZE); - - // get variable type; returns INVALID if invalid rec_name - rec_type = varType(rec_name); - switch (rec_type) { - case RECD_COUNTER: - rec_ele->rec_type = TS_REC_COUNTER; - if (!varCounterFromName(rec_name, &(counter_val))) { - return TS_ERR_FAIL; - } - rec_ele->valueT.counter_val = static_cast(counter_val); - - Debug("RecOp", "[MgmtRecordGet] Get Counter Var %s = %" PRId64 "", rec_ele->rec_name, rec_ele->valueT.counter_val); - break; - - case RECD_INT: - rec_ele->rec_type = TS_REC_INT; - if (!varIntFromName(rec_name, &(int_val))) { - return TS_ERR_FAIL; - } - rec_ele->valueT.int_val = static_cast(int_val); - - Debug("RecOp", "[MgmtRecordGet] Get Int Var %s = %" PRId64 "", rec_ele->rec_name, rec_ele->valueT.int_val); - break; - - case RECD_FLOAT: - rec_ele->rec_type = TS_REC_FLOAT; - if (!varFloatFromName(rec_name, &(rec_ele->valueT.float_val))) { - return TS_ERR_FAIL; - } - - Debug("RecOp", "[MgmtRecordGet] Get Float Var %s = %f", rec_ele->rec_name, rec_ele->valueT.float_val); - break; - - case RECD_STRING: - if (!varStrFromName(rec_name, rec_val, MAX_BUF_SIZE)) { - return TS_ERR_FAIL; - } - - if (rec_val[0] != '\0') { // non-NULL string value - // allocate memory & duplicate string value - str_val = ats_strdup(rec_val); - } else { - str_val = ats_strdup("NULL"); - } - - rec_ele->rec_type = TS_REC_STRING; - rec_ele->valueT.string_val = str_val; - Debug("RecOp", "[MgmtRecordGet] Get String Var %s = %s", rec_ele->rec_name, rec_ele->valueT.string_val); - break; - - default: // UNKNOWN TYPE - Debug("RecOp", "[MgmtRecordGet] Get Failed : %d is Unknown Var type %s", rec_type, rec_name); - return TS_ERR_FAIL; - } - - return TS_ERR_OKAY; -} - -// This is not implemented in the Core side of the API because we don't want -// to buffer up all the matching records in memory. We stream the records -// directory onto the management socket in handle_record_match(). This stub -// is just here for link time dependencies. -TSMgmtError -MgmtRecordGetMatching(const char * /* regex */, TSList /* rec_vals */) -{ - return TS_ERR_FAIL; -} - -TSMgmtError -MgmtConfigRecordDescribe(const char * /* rec_name */, unsigned /* flags */, TSConfigRecordDescription * /* val */) -{ - return TS_ERR_NOT_SUPPORTED; -} - -TSMgmtError -MgmtConfigRecordDescribeMatching(const char *, unsigned, TSList) -{ - return TS_ERR_NOT_SUPPORTED; -} - -/*------------------------------------------------------------------------- - * reads the RecordsConfig info to determine which type of action is needed - * when the record rec_name is changed; if the rec_name is invalid, - * then returns TS_ACTION_UNDEFINED - */ -TSActionNeedT -determine_action_need(const char *rec_name) -{ - RecUpdateT update_t; - - if (REC_ERR_OKAY != RecGetRecordUpdateType(rec_name, &update_t)) { - return TS_ACTION_UNDEFINED; - } - - switch (update_t) { - case RECU_NULL: // default:don't know behaviour - return TS_ACTION_UNDEFINED; - - case RECU_DYNAMIC: // update dynamically by rereading config files - return TS_ACTION_RECONFIGURE; - - case RECU_RESTART_TS: // requires TS restart - return TS_ACTION_RESTART; - - case RECU_RESTART_TM: // requires TM/TS restart - return TS_ACTION_RESTART; - - default: // shouldn't get here actually - return TS_ACTION_UNDEFINED; - } - - return TS_ACTION_UNDEFINED; // ERROR -} - -/*------------------------------------------------------------------------- - * MgmtRecordSet - *------------------------------------------------------------------------- - * Uses bool WebMgmtUtils::varSetFromStr(const char*, const char* ) - * Sets the named local manager variable from the value string - * passed in. Does the appropriate type conversion on - * value string to get it to the type of the local manager - * variable - * - * returns true if the variable was successfully set - * and false otherwise - */ -TSMgmtError -MgmtRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need) -{ - Debug("RecOp", "[MgmtRecordSet] Start"); - - if (!rec_name || !val || !action_need) { - return TS_ERR_PARAMS; - } - - *action_need = determine_action_need(rec_name); - - if (recordValidityCheck(rec_name, val)) { - if (varSetFromStr(rec_name, val)) { - return TS_ERR_OKAY; - } - } - - return TS_ERR_FAIL; -} - -/*------------------------------------------------------------------------- - * MgmtRecordSetInt - *------------------------------------------------------------------------- - * Use the record's name to look up the record value and its type. - * Returns TS_ERR_FAIL if the type is not a valid integer. - * Converts the integer value to a string and call MgmtRecordSet - */ -TSMgmtError -MgmtRecordSetInt(const char *rec_name, MgmtInt int_val, TSActionNeedT *action_need) -{ - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - // convert int value to string for validity check - char str_val[MAX_RECORD_SIZE]; - - memset(str_val, 0, MAX_RECORD_SIZE); - snprintf(str_val, sizeof(str_val), "%" PRId64 "", int_val); - - return MgmtRecordSet(rec_name, str_val, action_need); -} - -/*------------------------------------------------------------------------- - * MgmtRecordSetCounter - *------------------------------------------------------------------------- - * converts the counter_val to a string and uses MgmtRecordSet - */ -TSMgmtError -MgmtRecordSetCounter(const char *rec_name, MgmtIntCounter counter_val, TSActionNeedT *action_need) -{ - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - // convert int value to string for validity check - char str_val[MAX_RECORD_SIZE]; - - memset(str_val, 0, MAX_RECORD_SIZE); - snprintf(str_val, sizeof(str_val), "%" PRId64 "", counter_val); - - return MgmtRecordSet(rec_name, str_val, action_need); -} - -/*------------------------------------------------------------------------- - * MgmtRecordSetFloat - *------------------------------------------------------------------------- - * converts the float value to string (to do record validity check) - * and calls MgmtRecordSet - */ -TSMgmtError -MgmtRecordSetFloat(const char *rec_name, MgmtFloat float_val, TSActionNeedT *action_need) -{ - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - // convert float value to string for validity check - char str_val[MAX_RECORD_SIZE]; - - memset(str_val, 0, MAX_RECORD_SIZE); - snprintf(str_val, sizeof(str_val), "%f", float_val); - - return MgmtRecordSet(rec_name, str_val, action_need); -} - -/*------------------------------------------------------------------------- - * MgmtRecordSetString - *------------------------------------------------------------------------- - * The string value is copied so it's okay to free the string later - */ -TSMgmtError -MgmtRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT *action_need) -{ - return MgmtRecordSet(rec_name, string_val, action_need); -} - -/************************************************************************** - * EVENTS - *************************************************************************/ -/*------------------------------------------------------------------------- - * EventSignal - *------------------------------------------------------------------------- - * LAN: THIS FUNCTION IS HACKED AND INCOMPLETE!!!!! - * with the current alarm processor system, the argument list is NOT - * used; a set description is associated with each alarm already; - * be careful because this alarm description is used to keep track - * of alarms in the current alarm processor - */ -TSMgmtError -EventSignal(const char * /* event_name ATS_UNUSED */, va_list /* ap ATS_UNUSED */) -{ - // char *text; - // int id; - - // id = get_event_id(event_name); - // text = get_event_text(event_name); - // lmgmt->alarm_keeper->signalAlarm(id, text, NULL); - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * EventResolve - *------------------------------------------------------------------------- - * Resolves the event of the given event_name. If the event is already - * unresolved, just return TS_ERR_OKAY. - - */ -TSMgmtError -EventResolve(const char *event_name) -{ - alarm_t a; - - if (!event_name) { - return TS_ERR_PARAMS; - } - - a = get_event_id(event_name); - lmgmt->alarm_keeper->resolveAlarm(a); - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * ActiveEventGetMlt - *------------------------------------------------------------------------- - * returns failure, and an incomplete active_alarms list if any of - * functions fail for a single event - * note: returns list of local alarms at that instant of fn call (snapshot) - */ -TSMgmtError -ActiveEventGetMlt(LLQ *active_events) -{ - if (!active_events) { - return TS_ERR_PARAMS; - } - - // Alarms stores a hashtable of all active alarms where: - // key = alarm_t, - // value = alarm_description defined in Alarms.cc alarmText[] array - std::unordered_map const &event_ht = lmgmt->alarm_keeper->getLocalAlarms(); - - // iterate through hash-table and insert event_name's into active_events list - for (auto &&it : event_ht) { - // convert key to int; insert into llQ - int event_id = ink_atoi(it.first.c_str()); - char *event_name = get_event_name(event_id); - if (event_name) { - if (!enqueue(active_events, event_name)) { // returns true if successful - return TS_ERR_FAIL; - } - } - } - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * EventIsActive - *------------------------------------------------------------------------- - * Sets *is_current to true if the event named event_name is currently - * unresolved; otherwise sets *is_current to false. - */ -TSMgmtError -EventIsActive(const char *event_name, bool *is_current) -{ - alarm_t a; - - if (!event_name || !is_current) { - return TS_ERR_PARAMS; - } - - a = get_event_id(event_name); - // consider an invalid event_name an error - if (a < 0) { - return TS_ERR_PARAMS; - } - if (lmgmt->alarm_keeper->isCurrentAlarm(a)) { - *is_current = true; // currently an event - } else { - *is_current = false; - } - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * EventSignalCbRegister - *------------------------------------------------------------------------- - * This differs from the remote side callback registered. Technically, I think - * we need to redesign the alarm processor before we can handle the callback - * functionality we want to accomplish. Because currently the alarm processor - * only allow registering callbacks for general alarms. - * Mimic remote side and have a separate structure (eg. hashtable) of - * event callback functions for each type of event. The functions are also - * stored in the hashtable, not in the TM alarm processor model - */ -TSMgmtError -EventSignalCbRegister(const char *event_name, TSEventSignalFunc func, void *data) -{ - return cb_table_register(local_event_callbacks, event_name, func, data, nullptr); -} - -/*------------------------------------------------------------------------- - * EventSignalCbUnregister - *------------------------------------------------------------------------- - * Removes the callback function from the local side CallbackTable - */ -TSMgmtError -EventSignalCbUnregister(const char *event_name, TSEventSignalFunc func) -{ - return cb_table_unregister(local_event_callbacks, event_name, func); -} - -/*------------------------------------------------------------------------- - * HostStatusSetDown - *------------------------------------------------------------------------- - * Sets the HOST status to Down - * - * 'marshalled_req' is marshalled here, (host_name and down_time, na). - * 'len' is the length of the 'req' marshaled data. - * 'na' unused. - */ -TSMgmtError -HostStatusSetDown(const char *marshalled_req, int len, const char *na) -{ - lmgmt->hostStatusSetDown(marshalled_req, len); - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * HostStatusSetUp - *------------------------------------------------------------------------- - * Sets the HOST status to Up - * - * 'marshalled_req' is marshalled here, host_name. - * 'len' is the length of 'req' - * 'na' unused. - */ -TSMgmtError -HostStatusSetUp(const char *marshalled_req, int len, const char *na) -{ - lmgmt->hostStatusSetUp(marshalled_req, len); - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * StatsReset - *------------------------------------------------------------------------- - * Iterates through the RecordsConfig table, and for all stats - * (type PROCESS, NODE, CLUSTER), sets them back to their default value - * If one stat fails to be set correctly, then continues onto next one, - * but will return TS_ERR_FAIL. Only returns TS_ERR_OKAY if all - * stats are set back to defaults successfully. - */ -TSMgmtError -StatsReset(const char *name) -{ - lmgmt->clearStats(name); - return TS_ERR_OKAY; -} diff --git a/mgmt/api/CoreAPI.h b/mgmt/api/CoreAPI.h deleted file mode 100644 index aa4a44485c0..00000000000 --- a/mgmt/api/CoreAPI.h +++ /dev/null @@ -1,87 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include // for va_list - -#include "tscore/ink_llqueue.h" -#include "MgmtDefs.h" // MgmtInt, MgmtFloat, etc - -#include "mgmtapi.h" -#include "tscore/Tokenizer.h" - -// for buffer used temporarily to parse incoming commands. -#ifndef MAX_BUF_SIZE -#define MAX_BUF_SIZE 4098 -#endif - -TSMgmtError Init(const char *socket_path = nullptr, TSInitOptionT options = TS_MGMT_OPT_DEFAULTS); -TSMgmtError Terminate(); - -/*************************************************************************** - * Control Operations - ***************************************************************************/ -TSProxyStateT ProxyStateGet(); -TSMgmtError ProxyStateSet(TSProxyStateT state, TSCacheClearT clear); -TSMgmtError ServerBacktrace(unsigned options, char **trace); - -TSMgmtError Reconfigure(); // TS reread config files -TSMgmtError Restart(unsigned options); // restart TM -TSMgmtError Bounce(unsigned options); // restart traffic_server -TSMgmtError Stop(unsigned options); // stop traffic_server -TSMgmtError Drain(unsigned options); // drain requests of traffic_server -TSMgmtError StorageDeviceCmdOffline(const char *dev); // Storage device operation. -TSMgmtError LifecycleMessage(const char *tag, void const *data, size_t data_size); // Lifecycle alert to plugins. - -/*************************************************************************** - * Record Operations - ***************************************************************************/ -/* For remote implementation of this interface, these functions will have - to marshal/unmarshal and send request across the network */ -TSMgmtError MgmtRecordGet(const char *rec_name, TSRecordEle *rec_ele); - -TSMgmtError MgmtRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need); -TSMgmtError MgmtRecordSetInt(const char *rec_name, MgmtInt int_val, TSActionNeedT *action_need); -TSMgmtError MgmtRecordSetCounter(const char *rec_name, MgmtIntCounter counter_val, TSActionNeedT *action_need); -TSMgmtError MgmtRecordSetFloat(const char *rec_name, MgmtFloat float_val, TSActionNeedT *action_need); -TSMgmtError MgmtRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT *action_need); -TSMgmtError MgmtRecordGetMatching(const char *regex, TSList rec_vals); - -TSMgmtError MgmtConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val); -TSMgmtError MgmtConfigRecordDescribeMatching(const char *regex, unsigned flags, TSList rec_vals); - -/*************************************************************************** - * Events - ***************************************************************************/ - -TSMgmtError EventSignal(const char *event_name, va_list ap); -TSMgmtError EventResolve(const char *event_name); -TSMgmtError ActiveEventGetMlt(LLQ *active_events); -TSMgmtError EventIsActive(const char *event_name, bool *is_current); -TSMgmtError EventSignalCbRegister(const char *event_name, TSEventSignalFunc func, void *data); -TSMgmtError EventSignalCbUnregister(const char *event_name, TSEventSignalFunc func); - -TSMgmtError HostStatusSetDown(const char *host_name, int down_time, const char *reason); -TSMgmtError HostStatusSetUp(const char *host_name, int down_time, const char *reason); -TSMgmtError StatsReset(const char *name = nullptr); diff --git a/mgmt/api/CoreAPIRemote.cc b/mgmt/api/CoreAPIRemote.cc deleted file mode 100644 index 28a905046f9..00000000000 --- a/mgmt/api/CoreAPIRemote.cc +++ /dev/null @@ -1,1071 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: CoreAPIRemote.cc - * Purpose: Implementation of CoreAPI.h interface but from remote client - * perspective, so must also add networking calls. Basically, any - * TSMgmtAPI calls which are "special" for remote clients - * need to be implemented here. - * Note: For remote implementation of this interface, most functions will: - * 1) marshal: create the message to send across network - * 2) connect and send request - * 3) unmarshal: parse the reply (checking for TSMgmtError) - * - * Created: lant - * - ***************************************************************************/ - -#include "tscore/ink_config.h" -#include "tscore/ink_defs.h" -#include -#include "tscore/ink_string.h" -#include "tscore/I_Layout.h" -#include "tscore/ParseRules.h" -#include "tscore/ink_memory.h" -#include "CoreAPI.h" -#include "CoreAPIShared.h" -#include "NetworkUtilsRemote.h" - -#include "EventCallback.h" -#include "MgmtMarshall.h" - -// forward declarations -static TSMgmtError send_and_parse_list(OpType op, LLQ *list); -static TSMgmtError mgmt_record_set(const char *rec_name, const char *rec_val, TSActionNeedT *action_need); - -// global variables -// need to store the thread id associated with socket_test_thread -// in case we want to explicitly stop/cancel the testing thread -ink_thread ts_test_thread; -ink_thread ts_event_thread; -TSInitOptionT ts_init_options; - -/*************************************************************************** - * Helper Functions - ***************************************************************************/ - -/*------------------------------------------------------------------------- - * send_and_parse_list (helper function) - *------------------------------------------------------------------------- - * helper function used by operations which only require sending a simple - * operation type and parsing a string delimited list - * (delimited with REMOTE_DELIM_STR) and storing the tokens in the list - * parameter - */ -static TSMgmtError -send_and_parse_list(OpType op, LLQ *list) -{ - TSMgmtError ret; - const char *tok; - Tokenizer tokens(REMOTE_DELIM_STR); - tok_iter_state i_state; - - OpType optype = op; - MgmtMarshallInt err; - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallString strval = nullptr; - - if (!list) { - return TS_ERR_PARAMS; - } - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &optype); - if (ret != TS_ERR_OKAY) { - goto done; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - goto done; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, op, &err, &strval); - if (ret != TS_ERR_OKAY) { - goto done; - } - - if (err != TS_ERR_OKAY) { - ret = static_cast(err); - goto done; - } - - // tokenize the strval and put into LLQ; use Tokenizer - tokens.Initialize(strval, COPY_TOKS); - tok = tokens.iterFirst(&i_state); - while (tok != nullptr) { - enqueue(list, ats_strdup(tok)); // add token to LLQ - tok = tokens.iterNext(&i_state); - } - - ret = TS_ERR_OKAY; - -done: - ats_free(reply.ptr); - ats_free(strval); - return ret; -} - -/*------------------------------------------------------------------------- - * mgmt_record_set (helper function) - *------------------------------------------------------------------------- - * Helper function for all Set functions: - * NOTE: regardless of the type of the record being set, - * it is converted to a string. Then on the local side, the - * CoreAPI::MgmtRecordSet function will do the appropriate type - * conversion from the string to the record's type (eg. MgmtInt, MgmtString..) - * Hence, on the local side, don't have to worry about typecasting a - * void*. Just read out the string from socket and pass it MgmtRecordSet. - */ -static TSMgmtError -mgmt_record_set(const char *rec_name, const char *rec_val, TSActionNeedT *action_need) -{ - TSMgmtError ret; - - OpType optype = OpType::RECORD_SET; - MgmtMarshallString name = const_cast(rec_name); - MgmtMarshallString value = const_cast(rec_val); - - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallInt err; - MgmtMarshallInt action = TS_ACTION_UNDEFINED; - - if (!rec_name || !rec_val || !action_need) { - return TS_ERR_PARAMS; - } - - *action_need = TS_ACTION_UNDEFINED; - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECORD_SET, &optype, &name, &value); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, OpType::RECORD_SET, &err, &action); - ats_free(reply.ptr); - - if (ret != TS_ERR_OKAY) { - return ret; - } - - if (err != TS_ERR_OKAY) { - return static_cast(err); - } - - *action_need = static_cast(action); - return TS_ERR_OKAY; -} - -/*************************************************************************** - * SetUp Operations - ***************************************************************************/ -TSMgmtError -Init(const char *socket_path, TSInitOptionT options) -{ - TSMgmtError err = TS_ERR_OKAY; - - ts_init_options = options; - - // XXX This should use RecConfigReadRuntimeDir(), but that's not linked into the management - // libraries. The caller has to pass down the right socket path :( - if (!socket_path) { - Layout::create(); - socket_path = Layout::get()->runtimedir.c_str(); - } - - // store socket_path - set_socket_paths(socket_path); - - // need to ignore SIGPIPE signal; in the case that TM is restarted - signal(SIGPIPE, SIG_IGN); - - // EVENT setup - initialize callback queue - if (0 == (ts_init_options & TS_MGMT_OPT_NO_EVENTS)) { - remote_event_callbacks = create_callback_table("remote_callbacks"); - if (!remote_event_callbacks) { - return TS_ERR_SYS_CALL; - } - } else { - remote_event_callbacks = nullptr; - } - - // try to connect to traffic manager - // do this last so that everything else on client side is set up even if - // connection fails; this might happen if client is set up and running - // before TM - err = ts_connect(); - if (err != TS_ERR_OKAY) { - goto END; - } - - // if connected, create event thread that listens for events from TM - if (0 == (ts_init_options & TS_MGMT_OPT_NO_EVENTS)) { - ink_thread_create(&ts_event_thread, event_poll_thread_main, &event_socket_fd, 0, 0, nullptr); - } else { - ts_event_thread = ink_thread_null(); - } - -END: - - // create thread that periodically checks the socket connection - // with TM alive - reconnects if not alive - if (0 == (ts_init_options & TS_MGMT_OPT_NO_SOCK_TESTS)) { - ink_thread_create(&ts_test_thread, socket_test_thread, nullptr, 0, 0, nullptr); - } else { - ts_test_thread = ink_thread_null(); - } - - return err; -} - -// does clean up for remote API client; destroy structures and disconnects -TSMgmtError -Terminate() -{ - TSMgmtError err; - - if (remote_event_callbacks) { - delete_callback_table(remote_event_callbacks); - } - - // be sure to do this before reset socket_fd's - err = disconnect(); - if (err != TS_ERR_OKAY) { - return err; - } - - // cancel the listening socket thread - // it's important to call this before setting paths to NULL because the - // socket_test_thread actually will try to reconnect() and this function - // will seg fault if the socket paths are NULL while it is connecting; - // the thread will be cancelled at a cancellation point in the - // socket_test_thread, eg. sleep - if (ts_test_thread) { - ink_thread_cancel(ts_test_thread); - } - if (ts_event_thread) { - ink_thread_cancel(ts_event_thread); - } - - // Before clear, we should confirm these - // two threads have finished. Or the clear - // operation may lead them crash. - if (ts_test_thread) { - ink_thread_join(ts_test_thread); - } - if (ts_event_thread) { - ink_thread_join(ts_event_thread); - } - - // Clear operation - ts_test_thread = ink_thread_null(); - ts_event_thread = ink_thread_null(); - set_socket_paths(nullptr); // clear the socket_path - - return TS_ERR_OKAY; -} - -/*************************************************************************** - * Control Operations - ***************************************************************************/ -TSProxyStateT -ProxyStateGet() -{ - TSMgmtError ret; - OpType optype = OpType::PROXY_STATE_GET; - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallInt err; - MgmtMarshallInt state; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::PROXY_STATE_GET, &optype); - if (ret != TS_ERR_OKAY) { - return TS_PROXY_UNDEFINED; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return TS_PROXY_UNDEFINED; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, OpType::PROXY_STATE_GET, &err, &state); - ats_free(reply.ptr); - - if (ret != TS_ERR_OKAY || err != TS_ERR_OKAY) { - return TS_PROXY_UNDEFINED; - } - - return static_cast(state); -} - -TSMgmtError -ProxyStateSet(TSProxyStateT state, TSCacheClearT clear) -{ - TSMgmtError ret; - OpType optype = OpType::PROXY_STATE_SET; - MgmtMarshallInt pstate = state; - MgmtMarshallInt pclear = clear; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::PROXY_STATE_SET, &optype, &pstate, &pclear); - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::PROXY_STATE_SET, main_socket_fd) : ret; -} - -TSMgmtError -ServerBacktrace(unsigned options, char **trace) -{ - ink_release_assert(trace != nullptr); - TSMgmtError ret; - MgmtMarshallInt err; - OpType optype = OpType::SERVER_BACKTRACE; - MgmtMarshallInt flags = options; - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallString strval = nullptr; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::SERVER_BACKTRACE, &optype, &flags); - if (ret != TS_ERR_OKAY) { - goto fail; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - goto fail; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, OpType::SERVER_BACKTRACE, &err, &strval); - if (ret != TS_ERR_OKAY) { - goto fail; - } - - if (err != TS_ERR_OKAY) { - ret = static_cast(err); - goto fail; - } - - ats_free(reply.ptr); - *trace = strval; - return TS_ERR_OKAY; - -fail: - ats_free(reply.ptr); - ats_free(strval); - return ret; -} - -TSMgmtError -Reconfigure() -{ - TSMgmtError ret; - OpType optype = OpType::RECONFIGURE; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECONFIGURE, &optype); - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::RECONFIGURE, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * Restart - *------------------------------------------------------------------------- - * if restart of TM is successful, need to reconnect to TM; - * it's possible that the SUCCESS msg is received before the - * restarting of TM is totally complete(?) b/c the core Restart call - * only signals the event putting it in a msg queue; - * so keep trying to reconnect until successful or for MAX_CONN_TRIES - */ -TSMgmtError -Restart(unsigned options) -{ - TSMgmtError ret; - OpType optype = OpType::RESTART; - MgmtMarshallInt oval = options; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RESTART, &optype, &oval); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = parse_generic_response(OpType::RESTART, main_socket_fd); - if (ret == TS_ERR_OKAY) { - ret = reconnect_loop(MAX_CONN_TRIES); - } - - return ret; -} - -/*------------------------------------------------------------------------- - * Bounce - *------------------------------------------------------------------------- - * Restart the traffic_server process(es) only. - */ -TSMgmtError -Bounce(unsigned options) -{ - TSMgmtError ret; - OpType optype = OpType::BOUNCE; - MgmtMarshallInt oval = options; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::BOUNCE, &optype, &oval); - - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::BOUNCE, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * Stop - *------------------------------------------------------------------------- - * Restart the traffic_server process(es) only. - */ -TSMgmtError -Stop(unsigned options) -{ - TSMgmtError ret; - OpType optype = OpType::STOP; - MgmtMarshallInt oval = options; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::STOP, &optype, &oval); - - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::STOP, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * Drain - *------------------------------------------------------------------------- - * Drain requests of the traffic_server process(es) only. - */ -TSMgmtError -Drain(unsigned options) -{ - TSMgmtError ret; - OpType optype = OpType::DRAIN; - MgmtMarshallInt oval = options; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::DRAIN, &optype, &oval); - - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::DRAIN, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * StorageDeviceCmdOffline - *------------------------------------------------------------------------- - * Disable a storage device. - */ -TSMgmtError -StorageDeviceCmdOffline(const char *dev) -{ - TSMgmtError ret; - OpType optype = OpType::STORAGE_DEVICE_CMD_OFFLINE; - MgmtMarshallString name = const_cast(dev); - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::STORAGE_DEVICE_CMD_OFFLINE, &optype, &name); - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::STORAGE_DEVICE_CMD_OFFLINE, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * Lifecycle Alert - *------------------------------------------------------------------------- - * Send alert to plugins - */ -TSMgmtError -LifecycleMessage(const char *tag, void const *data, size_t data_size) -{ - TSMgmtError ret; - OpType optype = OpType::LIFECYCLE_MESSAGE; - MgmtMarshallString mtag = const_cast(tag); - MgmtMarshallData mdata = {const_cast(data), data_size}; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::LIFECYCLE_MESSAGE, &optype, &mtag, &mdata); - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::LIFECYCLE_MESSAGE, main_socket_fd) : ret; -} - -/*************************************************************************** - * Record Operations - ***************************************************************************/ - -static void -mgmt_record_convert_value(TSRecordT rec_type, const MgmtMarshallData &data, TSRecordValueT &value) -{ - // convert the record value to appropriate type - if (data.ptr) { - switch (rec_type) { - case TS_REC_INT: - ink_assert(data.len == sizeof(TSInt)); - value.int_val = *static_cast(data.ptr); - break; - case TS_REC_COUNTER: - ink_assert(data.len == sizeof(TSCounter)); - value.counter_val = *static_cast(data.ptr); - break; - case TS_REC_FLOAT: - ink_assert(data.len == sizeof(TSFloat)); - value.float_val = *static_cast(data.ptr); - break; - case TS_REC_STRING: - ink_assert(data.len == strlen((char *)data.ptr) + 1); - value.string_val = ats_strdup((char *)data.ptr); - break; - default:; // nothing ... shut up compiler! - } - } -} - -static TSMgmtError -mgmt_record_get_reply(OpType op, TSRecordEle *rec_ele) -{ - TSMgmtError ret; - - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallInt err; - MgmtMarshallInt rclass; - MgmtMarshallInt type; - MgmtMarshallString name = nullptr; - MgmtMarshallData value = {nullptr, 0}; - - ink_zero(*rec_ele); - rec_ele->rec_type = TS_REC_UNDEFINED; - - // Receive the next record reply. - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, op, &err, &rclass, &type, &name, &value); - ats_free(reply.ptr); - if (ret != TS_ERR_OKAY) { - goto done; - } - - if (err != TS_ERR_OKAY) { - ret = static_cast(err); - goto done; - } - - rec_ele->rec_class = static_cast(rclass); - rec_ele->rec_type = static_cast(type); - rec_ele->rec_name = ats_strdup(name); - mgmt_record_convert_value(rec_ele->rec_type, value, rec_ele->valueT); - -done: - ats_free(name); - ats_free(value.ptr); - return ret; -} - -static TSMgmtError -mgmt_record_describe_reply(TSConfigRecordDescription *val) -{ - TSMgmtError ret; - MgmtMarshallData reply = {nullptr, 0}; - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return ret; - } - - MgmtMarshallInt err; - MgmtMarshallString name = nullptr; - MgmtMarshallString expr = nullptr; - MgmtMarshallData value = {nullptr, 0}; - MgmtMarshallData deflt = {nullptr, 0}; - - MgmtMarshallInt rtype; - MgmtMarshallInt rclass; - MgmtMarshallInt version; - MgmtMarshallInt rsb; - MgmtMarshallInt order; - MgmtMarshallInt access; - MgmtMarshallInt update; - MgmtMarshallInt updatetype; - MgmtMarshallInt checktype; - MgmtMarshallInt source; - - ret = recv_mgmt_response(reply.ptr, reply.len, OpType::RECORD_DESCRIBE_CONFIG, &err, &name, &value, &deflt, &rtype, &rclass, - &version, &rsb, &order, &access, &update, &updatetype, &checktype, &source, &expr); - - ats_free(reply.ptr); - - if (ret != TS_ERR_OKAY) { - goto done; - } - - if (err != TS_ERR_OKAY) { - ret = static_cast(err); - goto done; - } - - // Everything is cool, populate the description ... - val->rec_name = ats_strdup(name); - val->rec_checkexpr = ats_strdup(expr); - val->rec_type = static_cast(rtype); - val->rec_class = rclass; - val->rec_version = version; - val->rec_rsb = rsb; - val->rec_order = order; - val->rec_access = access; - val->rec_updatetype = updatetype; - val->rec_checktype = checktype; - val->rec_source = source; - - mgmt_record_convert_value(val->rec_type, value, val->rec_value); - mgmt_record_convert_value(val->rec_type, deflt, val->rec_default); - -done: - ats_free(name); - ats_free(expr); - ats_free(value.ptr); - ats_free(deflt.ptr); - return ret; -} - -// note that the record value is being sent as chunk of memory, regardless of -// record type; it's not being converted to a string!! -TSMgmtError -MgmtRecordGet(const char *rec_name, TSRecordEle *rec_ele) -{ - TSMgmtError ret; - OpType optype = OpType::RECORD_GET; - MgmtMarshallString record = const_cast(rec_name); - - if (!rec_name || !rec_ele) { - return TS_ERR_PARAMS; - } - - // create and send request - if ((ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECORD_GET, &optype, &record)) != TS_ERR_OKAY) { - return ret; - } - - // drop the response if the record name doesn't match - // we need to do this because there might be left over data on the socket - // when restarting traffic_server, even though it can't be recreated in a - // test environment, it has been observed in production the names doesn't - // match and caused traffic_cop to crash due to type mismatch. - while ((ret = mgmt_record_get_reply(OpType::RECORD_GET, rec_ele)) == TS_ERR_OKAY && strcmp(rec_name, rec_ele->rec_name) != 0) { - } - return ret; -} - -TSMgmtError -MgmtConfigRecordDescribeMatching(const char *rec_name, unsigned options, TSList rec_vals) -{ - TSMgmtError ret; - OpType optype = OpType::RECORD_DESCRIBE_CONFIG; - MgmtMarshallInt flags = options | RECORD_DESCRIBE_FLAGS_MATCH; - MgmtMarshallString record = const_cast(rec_name); - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECORD_DESCRIBE_CONFIG, &optype, &record, &flags); - if (ret != TS_ERR_OKAY) { - return ret; - } - - for (;;) { - TSConfigRecordDescription *val; - - val = TSConfigRecordDescriptionCreate(); - - // parse the reply to get record value and type - ret = mgmt_record_describe_reply(val); - if (ret != TS_ERR_OKAY) { - TSConfigRecordDescriptionDestroy(val); - goto fail; - } - - // A NULL record ends the list. - if (val->rec_type == TS_REC_UNDEFINED) { - TSConfigRecordDescriptionDestroy(val); - break; - } - - enqueue(static_cast(rec_vals), val); - } - - return TS_ERR_OKAY; - -fail: - while (!queue_is_empty(static_cast(rec_vals))) { - TSConfigRecordDescription *val = static_cast(dequeue(static_cast(rec_vals))); - TSConfigRecordDescriptionDestroy(val); - } - - return ret; -} - -TSMgmtError -MgmtConfigRecordDescribe(const char *rec_name, unsigned options, TSConfigRecordDescription *val) -{ - TSMgmtError ret; - OpType optype = OpType::RECORD_DESCRIBE_CONFIG; - MgmtMarshallInt flags = options & ~RECORD_DESCRIBE_FLAGS_MATCH; - MgmtMarshallString record = const_cast(rec_name); - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECORD_DESCRIBE_CONFIG, &optype, &record, &flags); - if (ret != TS_ERR_OKAY) { - return ret; - } - - return mgmt_record_describe_reply(val); -} - -TSMgmtError -MgmtRecordGetMatching(const char *regex, TSList rec_vals) -{ - TSMgmtError ret; - TSRecordEle *rec_ele; - - OpType optype = OpType::RECORD_MATCH_GET; - MgmtMarshallString record = const_cast(regex); - - if (!regex || !rec_vals) { - return TS_ERR_PARAMS; - } - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::RECORD_MATCH_GET, &optype, &record); - if (ret != TS_ERR_OKAY) { - return ret; - } - - for (;;) { - rec_ele = TSRecordEleCreate(); - - // parse the reply to get record value and type - ret = mgmt_record_get_reply(OpType::RECORD_MATCH_GET, rec_ele); - if (ret != TS_ERR_OKAY) { - TSRecordEleDestroy(rec_ele); - goto fail; - } - - // A NULL record ends the list. - if (rec_ele->rec_type == TS_REC_UNDEFINED) { - TSRecordEleDestroy(rec_ele); - break; - } - - enqueue(static_cast(rec_vals), rec_ele); - } - - return TS_ERR_OKAY; - -fail: - while (!queue_is_empty(static_cast(rec_vals))) { - rec_ele = static_cast(dequeue(static_cast(rec_vals))); - TSRecordEleDestroy(rec_ele); - } - - return ret; -} - -TSMgmtError -MgmtRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need) -{ - TSMgmtError ret; - - if (!rec_name || !val || !action_need) { - return TS_ERR_PARAMS; - } - - ret = mgmt_record_set(rec_name, val, action_need); - return ret; -} - -// first convert the MgmtInt into a string -// NOTE: use long long, not just long, MgmtInt = int64_t -TSMgmtError -MgmtRecordSetInt(const char *rec_name, MgmtInt int_val, TSActionNeedT *action_need) -{ - char str_val[MAX_RECORD_SIZE]; - TSMgmtError ret; - - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - bzero(str_val, MAX_RECORD_SIZE); - snprintf(str_val, sizeof(str_val), "%" PRId64 "", int_val); - ret = mgmt_record_set(rec_name, str_val, action_need); - - return ret; -} - -// first convert the MgmtIntCounter into a string -TSMgmtError -MgmtRecordSetCounter(const char *rec_name, MgmtIntCounter counter_val, TSActionNeedT *action_need) -{ - char str_val[MAX_RECORD_SIZE]; - TSMgmtError ret; - - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - bzero(str_val, MAX_RECORD_SIZE); - snprintf(str_val, sizeof(str_val), "%" PRId64 "", counter_val); - ret = mgmt_record_set(rec_name, str_val, action_need); - - return ret; -} - -// first convert the MgmtFloat into string -TSMgmtError -MgmtRecordSetFloat(const char *rec_name, MgmtFloat float_val, TSActionNeedT *action_need) -{ - char str_val[MAX_RECORD_SIZE]; - TSMgmtError ret; - - bzero(str_val, MAX_RECORD_SIZE); - if (snprintf(str_val, sizeof(str_val), "%f", float_val) < 0) { - return TS_ERR_SYS_CALL; - } - ret = mgmt_record_set(rec_name, str_val, action_need); - - return ret; -} - -TSMgmtError -MgmtRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT *action_need) -{ - TSMgmtError ret; - - if (!rec_name || !action_need) { - return TS_ERR_PARAMS; - } - - ret = mgmt_record_set(rec_name, string_val, action_need); - return ret; -} - -/*************************************************************************** - * Events - ***************************************************************************/ -/*------------------------------------------------------------------------- - * EventSignal - *------------------------------------------------------------------------- - * LAN - need to implement - */ -TSMgmtError -EventSignal(const char * /* event_name ATS_UNUSED */, va_list /* ap ATS_UNUSED */) -{ - return TS_ERR_FAIL; -} - -/*------------------------------------------------------------------------- - * EventResolve - *------------------------------------------------------------------------- - * purpose: Resolves the event of the specified name - * note: when sending the message request, actually sends the event name, - * not the event id - */ -TSMgmtError -EventResolve(const char *event_name) -{ - TSMgmtError ret; - OpType optype = OpType::EVENT_RESOLVE; - MgmtMarshallString name = const_cast(event_name); - - if (!event_name) { - return TS_ERR_PARAMS; - } - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::EVENT_RESOLVE, &optype, &name); - return (ret == TS_ERR_OKAY) ? parse_generic_response(OpType::EVENT_RESOLVE, main_socket_fd) : ret; -} - -/*------------------------------------------------------------------------- - * ActiveEventGetMlt - *------------------------------------------------------------------------- - * purpose: Retrieves a list of active(unresolved) events - * note: list of event names returned in network msg which must be tokenized - */ -TSMgmtError -ActiveEventGetMlt(LLQ *active_events) -{ - if (!active_events) { - return TS_ERR_PARAMS; - } - - return (send_and_parse_list(OpType::EVENT_GET_MLT, active_events)); -} - -/*------------------------------------------------------------------------- - * EventIsActive - *------------------------------------------------------------------------- - * determines if the event_name is active; sets result in is_current - */ -TSMgmtError -EventIsActive(const char *event_name, bool *is_current) -{ - TSMgmtError ret; - OpType optype = OpType::EVENT_ACTIVE; - MgmtMarshallString name = const_cast(event_name); - - MgmtMarshallData reply = {nullptr, 0}; - MgmtMarshallInt err; - MgmtMarshallInt bval; - - if (!event_name || !is_current) { - return TS_ERR_PARAMS; - } - - // create and send request - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::EVENT_ACTIVE, &optype, &name); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return ret; - } - - ret = recv_mgmt_response(reply.ptr, reply.len, OpType::EVENT_ACTIVE, &err, &bval); - ats_free(reply.ptr); - - if (ret != TS_ERR_OKAY) { - return ret; - } - - *is_current = (bval != 0); - return static_cast(err); -} - -/*------------------------------------------------------------------------- - * EventSignalCbRegister - *------------------------------------------------------------------------- - * Adds the callback function in appropriate places in the remote side - * callback table. - * If this is the first callback to be registered for a certain event type, - * then sends a callback registration notification to TM so that TM will know - * which events have remote callbacks registered on it. - */ -TSMgmtError -EventSignalCbRegister(const char *event_name, TSEventSignalFunc func, void *data) -{ - bool first_time = false; - TSMgmtError ret; - - if (func == nullptr) { - return TS_ERR_PARAMS; - } - if (!remote_event_callbacks) { - return TS_ERR_FAIL; - } - - ret = cb_table_register(remote_event_callbacks, event_name, func, data, &first_time); - if (ret != TS_ERR_OKAY) { - return ret; - } - - // if we need to notify traffic manager of the event then send msg - if (first_time) { - OpType optype = OpType::EVENT_REG_CALLBACK; - MgmtMarshallString name = const_cast(event_name); - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, OpType::EVENT_REG_CALLBACK, &optype, &name); - if (ret != TS_ERR_OKAY) { - return ret; - } - } - - return TS_ERR_OKAY; -} - -/*------------------------------------------------------------------------- - * EventSignalCbUnregister - *------------------------------------------------------------------------- - * Removes the callback function from the remote side callback table. - * After removing the callback function, needs to check which events now - * no longer have any callbacks registered at all; sends an unregister callback - * notification to TM so that TM knows that event doesn't have any - * remote callbacks registered for it - * Input: event_name - the event to unregister the callback from; if NULL, - * unregisters the specified func from all events - * func - the callback function to unregister; if NULL, then - * unregisters all callback functions for the event_name - * specified - */ -TSMgmtError -EventSignalCbUnregister(const char *event_name, TSEventSignalFunc func) -{ - TSMgmtError err; - - if (!remote_event_callbacks) { - return TS_ERR_FAIL; - } - - // remove the callback function from the table - err = cb_table_unregister(remote_event_callbacks, event_name, func); - if (err != TS_ERR_OKAY) { - return err; - } - - // check if we need to notify traffic manager of the event (notify TM - // only if the event has no callbacks) - err = send_unregister_all_callbacks(event_socket_fd, remote_event_callbacks); - if (err != TS_ERR_OKAY) { - return err; - } - - return TS_ERR_OKAY; -} - -TSMgmtError -HostStatusSetDown(const char *host_name, int down_time, const char *reason) -{ - TSMgmtError ret = TS_ERR_PARAMS; - OpType op = OpType::HOST_STATUS_DOWN; - MgmtMarshallString name = const_cast(host_name); - MgmtMarshallString re = const_cast(reason); - MgmtMarshallInt dtime = down_time; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &op, &name, &re, &dtime); - return (ret == TS_ERR_OKAY) ? parse_generic_response(op, main_socket_fd) : ret; -} - -TSMgmtError -HostStatusSetUp(const char *host_name, int down_time, const char *reason) -{ - TSMgmtError ret = TS_ERR_PARAMS; - OpType op = OpType::HOST_STATUS_UP; - MgmtMarshallString name = const_cast(host_name); - MgmtMarshallString re = const_cast(reason); - MgmtMarshallInt dtime = down_time; - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &op, &name, &re, &dtime); - return (ret == TS_ERR_OKAY) ? parse_generic_response(op, main_socket_fd) : ret; -} - -TSMgmtError -StatsReset(const char *stat_name) -{ - TSMgmtError ret; - OpType op = OpType::STATS_RESET_NODE; - OpType optype = op; - MgmtMarshallString name = const_cast(stat_name); - - ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &optype, &name); - return (ret == TS_ERR_OKAY) ? parse_generic_response(op, main_socket_fd) : ret; -} diff --git a/mgmt/api/CoreAPIShared.cc b/mgmt/api/CoreAPIShared.cc index dc580ac5904..5514afe14b7 100644 --- a/mgmt/api/CoreAPIShared.cc +++ b/mgmt/api/CoreAPIShared.cc @@ -27,7 +27,6 @@ #include "tscore/ink_memory.h" #include "CoreAPIShared.h" -#include "MgmtSocket.h" // Forward declarations, used to be in the CoreAPIShared.h include file but // that doesn't make any sense since these are both statically declared. /leif @@ -278,87 +277,3 @@ poll_write(int fd, int timeout) return err; } - -/********************************************************************** - * Events - **********************************************************************/ -/********************************************************************** - * get_event_id - * - * Purpose: Given the event_name, returns the event's corresponding - * event id - * Note: this conversion is based on list defined in Alarms.h and - * the identical list defined in CoreAPIShared.cc - *********************************************************************/ -int -get_event_id(const char *event_name) -{ - if (strcmp("MGMT_ALARM_PROXY_PROCESS_DIED", event_name) == 0) { - return MGMT_ALARM_PROXY_PROCESS_DIED; - } else if (strcmp("MGMT_ALARM_PROXY_PROCESS_BORN", event_name) == 0) { - return MGMT_ALARM_PROXY_PROCESS_BORN; - } else if (strcmp("MGMT_ALARM_PROXY_CONFIG_ERROR", event_name) == 0) { - return MGMT_ALARM_PROXY_CONFIG_ERROR; - } else if (strcmp("MGMT_ALARM_PROXY_SYSTEM_ERROR", event_name) == 0) { - return MGMT_ALARM_PROXY_SYSTEM_ERROR; - } else if (strcmp("MGMT_ALARM_PROXY_CACHE_ERROR", event_name) == 0) { - return MGMT_ALARM_PROXY_CACHE_ERROR; - } else if (strcmp("MGMT_ALARM_PROXY_CACHE_WARNING", event_name) == 0) { - return MGMT_ALARM_PROXY_CACHE_WARNING; - } else if (strcmp("MGMT_ALARM_PROXY_LOGGING_ERROR", event_name) == 0) { - return MGMT_ALARM_PROXY_LOGGING_ERROR; - } else if (strcmp("MGMT_ALARM_PROXY_LOGGING_WARNING", event_name) == 0) { - return MGMT_ALARM_PROXY_LOGGING_WARNING; - } else if (strcmp("MGMT_ALARM_CONFIG_UPDATE_FAILED", event_name) == 0) { - return MGMT_ALARM_CONFIG_UPDATE_FAILED; - } - - return -1; -} - -/********************************************************************** - * get_event_id - * - * Purpose: based on alarm_id, determine the corresponding alarm name - * Note: allocates memory for the name returned - *********************************************************************/ -char * -get_event_name(int id) -{ - char name[MAX_EVENT_NAME_SIZE]; - - memset(name, 0, MAX_EVENT_NAME_SIZE); - switch (id) { - case MGMT_ALARM_PROXY_PROCESS_DIED: - ink_strlcpy(name, "MGMT_ALARM_PROXY_PROCESS_DIED", sizeof(name)); - break; - case MGMT_ALARM_PROXY_PROCESS_BORN: - ink_strlcpy(name, "MGMT_ALARM_PROXY_PROCESS_BORN", sizeof(name)); - break; - case MGMT_ALARM_PROXY_CONFIG_ERROR: - ink_strlcpy(name, "MGMT_ALARM_PROXY_CONFIG_ERROR", sizeof(name)); - break; - case MGMT_ALARM_PROXY_SYSTEM_ERROR: - ink_strlcpy(name, "MGMT_ALARM_PROXY_SYSTEM_ERROR", sizeof(name)); - break; - case MGMT_ALARM_PROXY_CACHE_ERROR: - ink_strlcpy(name, "MGMT_ALARM_PROXY_CACHE_ERROR", sizeof(name)); - break; - case MGMT_ALARM_PROXY_CACHE_WARNING: - ink_strlcpy(name, "MGMT_ALARM_PROXY_CACHE_WARNING", sizeof(name)); - break; - case MGMT_ALARM_PROXY_LOGGING_ERROR: - ink_strlcpy(name, "MGMT_ALARM_PROXY_LOGGING_ERROR", sizeof(name)); - break; - case MGMT_ALARM_PROXY_LOGGING_WARNING: - ink_strlcpy(name, "MGMT_ALARM_PROXY_LOGGING_WARNING", sizeof(name)); - break; - case MGMT_ALARM_CONFIG_UPDATE_FAILED: - ink_strlcpy(name, "MGMT_ALARM_CONFIG_UPDATE_FAILED", sizeof(name)); - break; - default: - return nullptr; - } - - return ats_strdup(name); -} diff --git a/mgmt/api/CoreAPIShared.h b/mgmt/api/CoreAPIShared.h index 6718f8ac863..6e1e8d77b9f 100644 --- a/mgmt/api/CoreAPIShared.h +++ b/mgmt/api/CoreAPIShared.h @@ -34,27 +34,6 @@ #include "mgmtapi.h" -#define NUM_EVENTS 19 // number of predefined TM events -#define MAX_EVENT_NAME_SIZE 100 // max length for an event name -#define MAX_RECORD_SIZE 20 // max length of buffer to hold record values - -// LAN - BAD BHACK; copied from Alarms.h !!!!! -/* Must be same as defined in Alarms.h; the reason we had to - * redefine them here is because the remote client also needs - * access to these values for its event handling - */ -#define MGMT_ALARM_UNDEFINED 0 - -#define MGMT_ALARM_PROXY_PROCESS_DIED 1 -#define MGMT_ALARM_PROXY_PROCESS_BORN 2 -#define MGMT_ALARM_PROXY_CONFIG_ERROR 3 -#define MGMT_ALARM_PROXY_SYSTEM_ERROR 4 -#define MGMT_ALARM_PROXY_CACHE_ERROR 5 -#define MGMT_ALARM_PROXY_CACHE_WARNING 6 -#define MGMT_ALARM_PROXY_LOGGING_ERROR 7 -#define MGMT_ALARM_PROXY_LOGGING_WARNING 8 -#define MGMT_ALARM_CONFIG_UPDATE_FAILED 9 - // used by TSReadFromUrl #define HTTP_DIVIDER "\r\n\r\n" #define URL_BUFSIZE 65536 // the max. length of URL obtainable (in bytes) @@ -62,15 +41,8 @@ #define HTTP_PORT 80 #define BUFSIZE 1024 -// Flags for management API behaviour. -#define MGMT_API_PRIVILEGED 0x0001u - // used by TSReadFromUrl TSMgmtError parseHTTPResponse(char *buffer, char **header, int *hdr_size, char **body, int *bdy_size); TSMgmtError readHTTPResponse(int sock, char *buffer, int bufsize, uint64_t timeout); TSMgmtError sendHTTPRequest(int sock, char *request, uint64_t timeout); int connectDirect(const char *host, int port, uint64_t timeout); - -// used for Events -int get_event_id(const char *event_name); -char *get_event_name(int id); diff --git a/mgmt/api/EventCallback.cc b/mgmt/api/EventCallback.cc deleted file mode 100644 index a0a70767fa4..00000000000 --- a/mgmt/api/EventCallback.cc +++ /dev/null @@ -1,348 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: EventCallback.cc - * Purpose: Generic module that deals with callbacks and a callback table - * Created: 01/08/01 - * Created by: lant - * - ***************************************************************************/ - -#include "tscore/ink_config.h" -#include "tscore/ink_memory.h" - -#include "EventCallback.h" -#include "CoreAPIShared.h" - -/********************************************************************** - * create_event_callback - * - * purpose: allocates and initializes members of EventCallbackT - * input: None - * output: EventCallbackT - * notes: None - **********************************************************************/ -EventCallbackT * -create_event_callback(TSEventSignalFunc func, void *data) -{ - EventCallbackT *event_cb = static_cast(ats_malloc(sizeof(EventCallbackT))); - - event_cb->func = func; - event_cb->data = data; - - return event_cb; -} - -/********************************************************************** - * delete_event_callback - * - * purpose:frees EventCallbackT - * input: None - * output: EventCallbackT - * notes: also frees memory for the data passed in; ASSUMES data was - * dynamically allocated - **********************************************************************/ -void -delete_event_callback(EventCallbackT *event_cb) -{ - ats_free(event_cb); - return; -} - -/********************************************************************** - * create_callback_table - * - * purpose: initializes the structures used to deal with events - * input: None - * output: TS_ERR_xx - * notes: None - **********************************************************************/ -CallbackTable * -create_callback_table(const char *) -{ - CallbackTable *cb_table = static_cast(ats_malloc(sizeof(CallbackTable))); - - for (auto &i : cb_table->event_callback_l) { - i = nullptr; - } - - // initialize the mutex - ink_mutex_init(&cb_table->event_callback_lock); - return cb_table; -} - -/********************************************************************** - * delete_callback_table - * - * purpose: frees the memory allocated for a CallbackTable; also - * destroys the lock - * input: None - * output: None - * notes: doesn't free pointers to functions - **********************************************************************/ -void -delete_callback_table(CallbackTable *cb_table) -{ - EventCallbackT *event_cb; - - // get lock - ink_mutex_acquire(&cb_table->event_callback_lock); - - // for each event - for (auto &i : cb_table->event_callback_l) { - if (i) { - // remove and delete each EventCallbackT for that event - while (!queue_is_empty(i)) { - event_cb = static_cast(dequeue(i)); - delete_event_callback(event_cb); - } - - delete_queue(i); - } - } - - // release lock - ink_mutex_release(&cb_table->event_callback_lock); - - // destroy lock - ink_mutex_destroy(&cb_table->event_callback_lock); - - ats_free(cb_table); - - return; -} - -/********************************************************************** - * get_events_with_callbacks - * - * purpose: returns a list of the event_id's that have at least - * one callback registered for that event - * input: cb_list - the table of callbacks to check - * output: returns a list of event_ids with at least one callback fun; - * returns NULL if all the events have a registered callback - * notes: - **********************************************************************/ -LLQ * -get_events_with_callbacks(CallbackTable *cb_table) -{ - LLQ *cb_ev_list; - bool all_events = true; // set to false if at least one event doesn't have registered callback - - cb_ev_list = create_queue(); - for (int i = 0; i < NUM_EVENTS; i++) { - if (!cb_table->event_callback_l[i]) { - all_events = false; - continue; // no callbacks registered - } - - enqueue(cb_ev_list, &i); - } - - if (all_events) { - delete_queue(cb_ev_list); - return nullptr; - } - - return cb_ev_list; -} - -/********************************************************************** - * cb_table_register - * - * purpose: Registers the specified function for the specified event in - * the specified callback list - * input: cb_list - the table of callbacks to store the callback fn - * event_name - the event to store the callback for (if NULL, register for all events) - * func - the callback function - * first_cb - true only if this is the event's first callback - * output: TS_ERR_xx - * notes: - **********************************************************************/ -TSMgmtError -cb_table_register(CallbackTable *cb_table, const char *event_name, TSEventSignalFunc func, void *data, bool *first_cb) -{ - bool first_time = false; - EventCallbackT *event_cb; // create new EventCallbackT EACH TIME enqueue - - // the data and event_name can be NULL - if (func == nullptr || !cb_table) { - return TS_ERR_PARAMS; - } - - ink_mutex_acquire(&(cb_table->event_callback_lock)); - - // got lock, add it - if (event_name == nullptr) { // register for all alarms - // printf("[EventSignalCbRegister] Register callback for all alarms\n"); - for (auto &i : cb_table->event_callback_l) { - if (!i) { - i = create_queue(); - first_time = true; - } - - if (!i) { - ink_mutex_release(&cb_table->event_callback_lock); - return TS_ERR_SYS_CALL; - } - - event_cb = create_event_callback(func, data); - enqueue(i, event_cb); - } - } else { // register callback for specific alarm - int id = get_event_id(event_name); - if (id != -1) { - if (!cb_table->event_callback_l[id]) { - cb_table->event_callback_l[id] = create_queue(); - first_time = true; - } - - if (!cb_table->event_callback_l[id]) { - ink_mutex_release(&cb_table->event_callback_lock); - return TS_ERR_SYS_CALL; - } - // now add to list - event_cb = create_event_callback(func, data); - enqueue(cb_table->event_callback_l[id], event_cb); - } - } - - // release lock on callback table - ink_mutex_release(&cb_table->event_callback_lock); - - if (first_cb) { - *first_cb = first_time; - } - - return TS_ERR_OKAY; -} - -/********************************************************************** - * cb_table_unregister - * - * purpose: Unregisters the specified function for the specified event in - * the specified callback list - * input: cb_table - the table of callbacks to store the callback fn - * event_name - the event to store the callback for (if NULL, register for all events) - * func - the callback function - * first_cb - true only if this is the event's first callback - * output: TS_ERR_xx - * notes: - **********************************************************************/ -TSMgmtError -cb_table_unregister(CallbackTable *cb_table, const char *event_name, TSEventSignalFunc func) -{ - TSEventSignalFunc cb_fun; - EventCallbackT *event_cb; - - ink_mutex_acquire(&cb_table->event_callback_lock); - - // got lock, add it - if (event_name == nullptr) { // unregister the callback for ALL EVENTS - // for each event - for (auto &i : cb_table->event_callback_l) { - if (!i) { // this event has no callbacks - continue; - } - - // func == NULL means unregister all functions associated with alarm - if (func == nullptr) { - while (!queue_is_empty(i)) { - event_cb = static_cast(dequeue(i)); - delete_event_callback(event_cb); - } - // clean up queue and set to NULL - delete_queue(i); - i = nullptr; - } else { // only remove the func passed in - int queue_depth; - - queue_depth = queue_len(i); - // remove this function - for (int j = 0; j < queue_depth; j++) { - event_cb = static_cast(dequeue(i)); - cb_fun = event_cb->func; - - // the pointers are the same so don't enqueue the fn back on - if (*cb_fun == *func) { - delete_event_callback(event_cb); - continue; - } - - enqueue(i, event_cb); - } - - // is queue empty now? then clean up - if (queue_is_empty(i)) { - delete_queue(i); - i = nullptr; - } - } - } // end for (int i = 0; i < NUM_EVENTS; i++) - } else { - // unregister for specific event - int id = get_event_id(event_name); - if (id != -1) { - if (cb_table->event_callback_l[id]) { - int queue_depth; - - queue_depth = queue_len(cb_table->event_callback_l[id]); - // func == NULL means unregister all functions associated with alarm - if (func == nullptr) { - while (!queue_is_empty(cb_table->event_callback_l[id])) { - event_cb = static_cast(dequeue(cb_table->event_callback_l[id])); - delete_event_callback(event_cb); - } - - // clean up queue and set to NULL - delete_queue(cb_table->event_callback_l[id]); - cb_table->event_callback_l[id] = nullptr; - } else { - // remove this function - for (int j = 0; j < queue_depth; j++) { - event_cb = static_cast(dequeue(cb_table->event_callback_l[id])); - cb_fun = event_cb->func; - - // the pointers are the same - if (*cb_fun == *func) { - delete_event_callback(event_cb); - continue; - } - - enqueue(cb_table->event_callback_l[id], event_cb); - } - - // is queue empty now? - if (queue_is_empty(cb_table->event_callback_l[id])) { - delete_queue(cb_table->event_callback_l[id]); - cb_table->event_callback_l[id] = nullptr; - } - } // end if NULL else - } - } - } - - ink_mutex_release(&cb_table->event_callback_lock); - - return TS_ERR_OKAY; -} diff --git a/mgmt/api/EventCallback.h b/mgmt/api/EventCallback.h deleted file mode 100644 index 34743f0be11..00000000000 --- a/mgmt/api/EventCallback.h +++ /dev/null @@ -1,78 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/*************************************************************************** - * EventCallback.h - * Purpose: defines the CallbackTable which stores callback functions for - * specific events - * - * - ***************************************************************************/ -/* - * EventCallback.h - * - * defines the CallbackTable which stores callback functions for - * specific events. Used by both local api and remote api. - */ - -#pragma once - -#include "tscore/ink_llqueue.h" - -#include "mgmtapi.h" -#include "CoreAPIShared.h" - -// when registering the callback function, can pass in void* data which -// will then be passed to the callback function; need to store this data with -// the callback in a struct -typedef struct { - TSEventSignalFunc func; - void *data; -} EventCallbackT; - -// event_call_back_l is a queue of EventCallbackT -typedef struct { - LLQ *event_callback_l[NUM_EVENTS]; - ink_mutex event_callback_lock; -} CallbackTable; - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -EventCallbackT *create_event_callback(TSEventSignalFunc func, void *data); -void delete_event_callback(EventCallbackT *event_cb); - -CallbackTable *create_callback_table(const char *lock_name); - -void delete_callback_table(CallbackTable *cb_table); - -// returns list of event_id that have at least one callback registered for it -LLQ *get_events_with_callbacks(CallbackTable *cb_table); - -TSMgmtError cb_table_register(CallbackTable *cb_table, const char *event_name, TSEventSignalFunc func, void *data, bool *first_cb); -TSMgmtError cb_table_unregister(CallbackTable *cb_table, const char *event_name, TSEventSignalFunc func); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ diff --git a/mgmt/api/EventControlMain.cc b/mgmt/api/EventControlMain.cc deleted file mode 100644 index ff154cb687c..00000000000 --- a/mgmt/api/EventControlMain.cc +++ /dev/null @@ -1,549 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: EventControlMain.cc - * Purpose: Handles all event requests from the user. - * Created: 01/08/01 - * Created by: lant - * - ***************************************************************************/ - -#include "tscore/ink_platform.h" -#include "tscore/ink_sock.h" -#include "LocalManager.h" -#include "MgmtSocket.h" -#include "MgmtMarshall.h" -#include "MgmtUtils.h" -#include "EventControlMain.h" -#include "CoreAPI.h" -#include "NetworkUtilsLocal.h" -#include "NetworkMessage.h" - -// variables that are very important -ink_mutex mgmt_events_lock; -LLQ *mgmt_events; -std::unordered_map accepted_clients; // list of all accepted client connections - -static TSMgmtError handle_event_message(EventClientT *client, void *req, size_t reqlen); - -/********************************************************************* - * new_event_client - * - * purpose: creates a new EventClientT and return pointer to it - * input: None - * output: EventClientT - * note: None - *********************************************************************/ -EventClientT * -new_event_client() -{ - EventClientT *ele = static_cast(ats_malloc(sizeof(EventClientT))); - - // now set the alarms registered section - for (bool &i : ele->events_registered) { - i = false; - } - - ele->adr = static_cast(ats_malloc(sizeof(struct sockaddr))); - return ele; -} - -/********************************************************************* - * delete_event_client - * - * purpose: frees memory allocated for an EventClientT - * input: EventClientT - * output: None - * note: None - *********************************************************************/ -void -delete_event_client(EventClientT *client) -{ - if (client) { - ats_free(client->adr); - ats_free(client); - } - return; -} - -/********************************************************************* - * remove_event_client - * - * purpose: removes the EventClientT from the specified hashtable; includes - * removing the binding and freeing the ClientT - * input: client - the ClientT to remove - * output: - *********************************************************************/ -void -remove_event_client(EventClientT *client, std::unordered_map &table) -{ - // close client socket - close_socket(client->fd); - - // remove client binding from hash table - table.erase(client->fd); - - // free ClientT - delete_event_client(client); - - return; -} - -/********************************************************************* - * init_mgmt_events - * - * purpose: initializes the mgmt_events queue which is intended to hold - * TM events. - * input: - * output: TS_ERR_xx - * note: None - *********************************************************************/ -TSMgmtError -init_mgmt_events() -{ - ink_mutex_init(&mgmt_events_lock); - - // initialize queue - mgmt_events = create_queue(); - if (!mgmt_events) { - ink_mutex_destroy(&mgmt_events_lock); - return TS_ERR_SYS_CALL; - } - - return TS_ERR_OKAY; -} - -/********************************************************************* - * delete_mgmt_events - * - * purpose: frees the mgmt_events queue. - * input: - * output: None - * note: None - *********************************************************************/ -void -delete_mgmt_events() -{ - // obtain lock - ink_mutex_acquire(&mgmt_events_lock); - - // delete the queue associated with the queue of events - delete_event_queue(mgmt_events); - - // release it - ink_mutex_release(&mgmt_events_lock); - - // kill lock - ink_mutex_destroy(&mgmt_events_lock); - - delete_queue(mgmt_events); - - return; -} - -/********************************************************************* - * delete_event_queue - * - * purpose: frees queue where the elements are of type TSMgmtEvent* 's - * input: LLQ * q - a queue with entries of TSMgmtEvent*'s - * output: None - * note: None - *********************************************************************/ -void -delete_event_queue(LLQ *q) -{ - if (!q) { - return; - } - - while (!queue_is_empty(q)) { - TSMgmtEvent *ele = static_cast(dequeue(q)); - ats_free(ele); - } - - delete_queue(q); - return; -} - -/********************************************************************* - * apiEventCallback - * - * purpose: callback function registered with alarm processor so that - * each time alarm is signalled, can enqueue it in the mgmt_events - * queue - * input: - * output: None - * note: None - *********************************************************************/ -void -apiEventCallback(alarm_t newAlarm, const char * /* ip ATS_UNUSED */, const char *desc) -{ - // create an TSMgmtEvent - // addEvent(new_alarm, ip, desc) // adds event to mgmt_events - TSMgmtEvent *newEvent; - - newEvent = TSEventCreate(); - newEvent->id = newAlarm; - newEvent->name = get_event_name(newEvent->id); - // newEvent->ip = ats_strdup(ip); - if (desc) { - newEvent->description = ats_strdup(desc); - } else { - newEvent->description = ats_strdup("None"); - } - - // add it to the mgmt_events list - ink_mutex_acquire(&mgmt_events_lock); - enqueue(mgmt_events, newEvent); - ink_mutex_release(&mgmt_events_lock); - - return; -} - -/********************************************************************* - * event_callback_main - * - * This function is run as a thread in WebIntrMain.cc that listens on a - * specified socket. It loops until Traffic Manager dies. - * In the loop, it just listens on a socket, ready to accept any connections, - * until receives a request from the remote API client. Parse the request - * to determine which CoreAPI call to make. - *********************************************************************/ -void * -event_callback_main(void *arg) -{ - int ret; - int *socket_fd; - int con_socket_fd; // main socket for listening to new connections - - socket_fd = static_cast(arg); - con_socket_fd = *socket_fd; // the socket for event callbacks - - Debug("event", "[event_callback_main] listen on socket = %d", con_socket_fd); - - // initialize queue for holding mgmt events - if (init_mgmt_events() != TS_ERR_OKAY) { - return nullptr; - } - // register callback with alarms processor - lmgmt->alarm_keeper->registerCallback(apiEventCallback); - - // now we can start listening, accepting connections and servicing requests - int new_con_fd; // new connection fd when socket accepts connection - - fd_set selectFDs; // for select call - EventClientT *client_entry; // an entry of fd to alarms mapping - struct timeval timeout; - - while (true) { - // LINUX fix: to prevent hard-spin reset timeout on each loop - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - FD_ZERO(&selectFDs); - - if (con_socket_fd >= 0) { - FD_SET(con_socket_fd, &selectFDs); - Debug("event", "[event_callback_main] add fd %d to select set", con_socket_fd); - } - // see if there are more fd to set - for (auto &&it : accepted_clients) { - client_entry = it.second; - if (client_entry->fd >= 0) { // add fd to select set - FD_SET(client_entry->fd, &selectFDs); - } - } - - // select call - timeout is set so we can check events at regular intervals - int fds_ready = mgmt_select(FD_SETSIZE, &selectFDs, (fd_set *)nullptr, (fd_set *)nullptr, &timeout); - - // check return - if (fds_ready > 0) { - // we got connections or requests! - - // first check for connections! - if (con_socket_fd >= 0 && FD_ISSET(con_socket_fd, &selectFDs)) { - fds_ready--; - - // create a new instance of the fd to alarms registered mapping - EventClientT *new_client_con = new_event_client(); - - if (!new_client_con) { - // Debug ("TS_Control_Main", "can't create new EventClientT for new connection"); - } else { - // accept connection - socklen_t addr_len = (sizeof(struct sockaddr)); - new_con_fd = mgmt_accept(con_socket_fd, new_client_con->adr, &addr_len); - new_client_con->fd = new_con_fd; - accepted_clients.emplace(new_client_con->fd, new_client_con); - Debug("event", "[event_callback_main] Accept new connection: fd=%d", new_con_fd); - } - } // end if (new_con_fd >= 0 && FD_ISSET(new_con_fd, &selectFDs)) - - // some other file descriptor; for each one, service request - if (fds_ready > 0) { // RECEIVED A REQUEST from remote API client - // see if there are more fd to set - iterate through all entries in hash table - for (auto it = accepted_clients.begin(); it != accepted_clients.end();) { - client_entry = it->second; - ++it; // prevent the breaking of remove_event_client - // got information check - if (client_entry->fd && FD_ISSET(client_entry->fd, &selectFDs)) { - // SERVICE REQUEST - read the op and message into a buffer - // clear the fields first - void *req; - size_t reqlen; - - ret = preprocess_msg(client_entry->fd, &req, &reqlen); - if (ret == TS_ERR_NET_READ || ret == TS_ERR_NET_EOF) { // preprocess_msg FAILED! - Debug("event", "[event_callback_main] preprocess_msg FAILED; skip!"); - remove_event_client(client_entry, accepted_clients); - continue; - } - - ret = handle_event_message(client_entry, req, reqlen); - ats_free(req); - - if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) { - Debug("event", "[event_callback_main] ERROR: handle_control_message"); - remove_event_client(client_entry, accepted_clients); - continue; - } - - } // end if(client_entry->fd && FD_ISSET(client_entry->fd, &selectFDs)) - } // end for (auto it = accepted_clients.begin(); it != accepted_clients.end();) - } // end if (fds_ready > 0) - - } // end if (fds_ready > 0) - - // ------------ service loop is done, check for events now ------------- - // for each event in the mgmt_events list, uses the event id to check the - // events_registered queue for each client connection to see if that client - // has a callback registered for that event_id - - TSMgmtEvent *event; - - if (!mgmt_events || queue_is_empty(mgmt_events)) { // no events to process - // fprintf(stderr, "[event_callback_main] NO EVENTS TO PROCESS\n"); - Debug("event", "[event_callback_main] NO EVENTS TO PROCESS"); - continue; - } - // iterate through each event in mgmt_events - while (!queue_is_empty(mgmt_events)) { - ink_mutex_acquire(&mgmt_events_lock); // acquire lock - event = static_cast(dequeue(mgmt_events)); // get what we want - ink_mutex_release(&mgmt_events_lock); // release lock - - if (!event) { - continue; - } - - // fprintf(stderr, "[event_callback_main] have an EVENT TO PROCESS\n"); - - // iterate through all entries in hash table, if any - for (auto &&it : accepted_clients) { - client_entry = it.second; - if (client_entry->events_registered[event->id]) { - OpType optype = OpType::EVENT_NOTIFY; - MgmtMarshallString name = event->name; - MgmtMarshallString desc = event->description; - - ret = send_mgmt_request(client_entry->fd, OpType::EVENT_NOTIFY, &optype, &name, &desc); - if (ret != TS_ERR_OKAY) { - Debug("event", "sending even notification to fd [%d] failed.", client_entry->fd); - } - } - // get next client connection, if any - } // end while(con_entry) - - // now we can delete the event - // fprintf(stderr, "[event_callback_main] DELETE EVENT\n"); - TSEventDestroy(event); - } // end while (!queue_is_empty) - - } // end while (1) - - // delete tables - delete_mgmt_events(); - - // iterate through hash table; close client socket connections and remove entry - for (auto &&it : accepted_clients) { - client_entry = it.second; - if (client_entry->fd >= 0) { - close_socket(client_entry->fd); - } - accepted_clients.erase(client_entry->fd); // remove binding - delete_event_client(client_entry); // free ClientT - } - // all entries should be removed and freed already - accepted_clients.clear(); - - ink_thread_exit(nullptr); - return nullptr; -} - -/*------------------------------------------------------------------------- - HANDLER FUNCTIONS - --------------------------------------------------------------------------*/ - -/************************************************************************** - * handle_event_reg_callback - * - * purpose: handles request to register a callback for a specific event (or all events) - * input: client - the client currently reading the msg from - * req - the event_name - * output: TS_ERR_xx - * note: the req should be the event name; does not send a reply to client - *************************************************************************/ -static TSMgmtError -handle_event_reg_callback(EventClientT *client, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - TSMgmtError ret; - - ret = recv_mgmt_request(req, reqlen, OpType::EVENT_REG_CALLBACK, &optype, &name); - if (ret != TS_ERR_OKAY) { - goto done; - } - - // mark the specified alarm as "wanting to be notified" in the client's alarm_registered list - if (strlen(name) == 0) { // mark all alarms - for (bool &i : client->events_registered) { - i = true; - } - } else { - int id = get_event_id(name); - if (id < 0) { - ret = TS_ERR_FAIL; - goto done; - } - - client->events_registered[id] = true; - } - - ret = TS_ERR_OKAY; - -done: - ats_free(name); - return ret; -} - -/************************************************************************** - * handle_event_unreg_callback - * - * purpose: handles request to unregister a callback for a specific event (or all events) - * input: client - the client currently reading the msg from - * req - the event_name - * output: TS_ERR_xx - * note: the req should be the event name; does not send reply to client - *************************************************************************/ -static TSMgmtError -handle_event_unreg_callback(EventClientT *client, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - TSMgmtError ret; - - ret = recv_mgmt_request(req, reqlen, OpType::EVENT_UNREG_CALLBACK, &optype, &name); - if (ret != TS_ERR_OKAY) { - goto done; - } - - // mark the specified alarm as "wanting to be notified" in the client's alarm_registered list - if (strlen(name) == 0) { // mark all alarms - for (bool &i : client->events_registered) { - i = false; - } - } else { - int id = get_event_id(name); - if (id < 0) { - ret = TS_ERR_FAIL; - goto done; - } - - client->events_registered[id] = false; - } - - ret = TS_ERR_OKAY; - -done: - ats_free(name); - return ret; -} - -using event_message_handler = TSMgmtError (*)(EventClientT *, void *, size_t); - -static const event_message_handler handlers[] = { - nullptr, // RECORD_SET - nullptr, // RECORD_GET - nullptr, // PROXY_STATE_GET - nullptr, // PROXY_STATE_SET - nullptr, // RECONFIGURE - nullptr, // RESTART - nullptr, // BOUNCE - nullptr, // EVENT_RESOLVE - nullptr, // EVENT_GET_MLT - nullptr, // EVENT_ACTIVE - handle_event_reg_callback, // EVENT_REG_CALLBACK - handle_event_unreg_callback, // EVENT_UNREG_CALLBACK - nullptr, // EVENT_NOTIFY - nullptr, // DIAGS - nullptr, // STATS_RESET_NODE - nullptr, // STORAGE_DEVICE_CMD_OFFLINE - nullptr, // RECORD_MATCH_GET - nullptr, // LIFECYCLE_MESSAGE - nullptr, // HOST_STATUS_UP - nullptr, // HOST_STATUS_DOWN -}; - -static TSMgmtError -handle_event_message(EventClientT *client, void *req, size_t reqlen) -{ - OpType optype = extract_mgmt_request_optype(req, reqlen); - - if (static_cast(optype) >= countof(handlers)) { - goto fail; - } - - if (handlers[static_cast(optype)] == nullptr) { - goto fail; - } - - if (mgmt_has_peereid()) { - uid_t euid = -1; - gid_t egid = -1; - - // For now, all event messages require privilege. This is compatible with earlier - // versions of Traffic Server that always required privilege. - if (mgmt_get_peereid(client->fd, &euid, &egid) == -1 || (euid != 0 && euid != geteuid())) { - return TS_ERR_PERMISSION_DENIED; - } - } - - return handlers[static_cast(optype)](client, req, reqlen); - -fail: - mgmt_elog(0, "%s: missing handler for type %d event message\n", __func__, static_cast(optype)); - return TS_ERR_PARAMS; -} diff --git a/mgmt/api/EventControlMain.h b/mgmt/api/EventControlMain.h deleted file mode 100644 index df2097c3438..00000000000 --- a/mgmt/api/EventControlMain.h +++ /dev/null @@ -1,57 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: EventControlMain.h - * Purpose: Handles event callbacks only - * Created: 6/26/00 - * Created by: lant - * - ***************************************************************************/ - -#pragma once - -#include "mgmtapi.h" //add the include path b/c included in web dir -#include "CoreAPIShared.h" // for NUM_EVENTS -#include "Alarms.h" -#include "tscore/ink_llqueue.h" - -#include - -// use events_registered[event_id] as index to check if alarm is registered -typedef struct { - int fd; // client socket - struct sockaddr *adr; - bool events_registered[NUM_EVENTS]; -} EventClientT; - -EventClientT *new_event_client(); -void delete_event_client(EventClientT *client); -void remove_event_client(EventClientT *client, std::unordered_map &table); - -TSMgmtError init_mgmt_events(); -void delete_mgmt_events(); -void delete_event_queue(LLQ *q); - -void apiAlarmCallback(alarm_t newAlarm, char *ip, char *desc); -void *event_callback_main(void *arg); diff --git a/mgmt/api/INKMgmtAPI.cc b/mgmt/api/INKMgmtAPI.cc index 3f4b9dde369..38e38928c6d 100644 --- a/mgmt/api/INKMgmtAPI.cc +++ b/mgmt/api/INKMgmtAPI.cc @@ -36,8 +36,8 @@ #include "tscore/I_Layout.h" #include "mgmtapi.h" -#include "CoreAPI.h" #include "CoreAPIShared.h" +#include "tscore/ink_llqueue.h" #include "tscore/TextBuffer.h" @@ -354,491 +354,6 @@ TSIntListIsValid(TSIntList intl, int min, int max) return true; } -/*--- allocate/deallocate operations --------------------------------------*/ -tsapi TSMgmtEvent * -TSEventCreate(void) -{ - TSMgmtEvent *event = static_cast(ats_malloc(sizeof(TSMgmtEvent))); - - event->id = -1; - event->name = nullptr; - event->description = nullptr; - event->priority = TS_EVENT_PRIORITY_UNDEFINED; - - return event; -} - -tsapi void -TSEventDestroy(TSMgmtEvent *event) -{ - if (event) { - ats_free(event->name); - ats_free(event->description); - ats_free(event); - } - return; -} - -tsapi TSRecordEle * -TSRecordEleCreate(void) -{ - TSRecordEle *ele = static_cast(ats_malloc(sizeof(TSRecordEle))); - - ele->rec_name = nullptr; - ele->rec_type = TS_REC_UNDEFINED; - - return ele; -} - -tsapi void -TSRecordEleDestroy(TSRecordEle *ele) -{ - if (ele) { - ats_free(ele->rec_name); - if (ele->rec_type == TS_REC_STRING && ele->valueT.string_val) { - ats_free(ele->valueT.string_val); - } - ats_free(ele); - } - return; -} - -/*************************************************************************** - * API Core - ***************************************************************************/ - -/*--- host status operations ----------------------------------------------- */ -tsapi TSMgmtError -TSHostStatusSetUp(const char *host_name, int down_time, const char *reason) -{ - return HostStatusSetUp(host_name, down_time, reason); -} - -tsapi TSMgmtError -TSHostStatusSetDown(const char *host_name, int down_time, const char *reason) -{ - return HostStatusSetDown(host_name, down_time, reason); -} - -/*--- statistics operations ----------------------------------------------- */ -tsapi TSMgmtError -TSStatsReset(const char *name) -{ - return StatsReset(name); -} - -/*--- variable operations ------------------------------------------------- */ -/* Call the CfgFileIO variable operations */ - -tsapi TSMgmtError -TSRecordGet(const char *rec_name, TSRecordEle *rec_val) -{ - return MgmtRecordGet(rec_name, rec_val); -} - -TSMgmtError -TSRecordGetInt(const char *rec_name, TSInt *int_val) -{ - TSMgmtError ret = TS_ERR_OKAY; - - TSRecordEle *ele = TSRecordEleCreate(); - ret = MgmtRecordGet(rec_name, ele); - if (ret != TS_ERR_OKAY) { - goto END; - } - - *int_val = ele->valueT.int_val; - -END: - TSRecordEleDestroy(ele); - return ret; -} - -TSMgmtError -TSRecordGetCounter(const char *rec_name, TSCounter *counter_val) -{ - TSMgmtError ret; - - TSRecordEle *ele = TSRecordEleCreate(); - ret = MgmtRecordGet(rec_name, ele); - if (ret != TS_ERR_OKAY) { - goto END; - } - *counter_val = ele->valueT.counter_val; - -END: - TSRecordEleDestroy(ele); - return ret; -} - -TSMgmtError -TSRecordGetFloat(const char *rec_name, TSFloat *float_val) -{ - TSMgmtError ret; - - TSRecordEle *ele = TSRecordEleCreate(); - ret = MgmtRecordGet(rec_name, ele); - if (ret != TS_ERR_OKAY) { - goto END; - } - *float_val = ele->valueT.float_val; - -END: - TSRecordEleDestroy(ele); - return ret; -} - -TSMgmtError -TSRecordGetString(const char *rec_name, TSString *string_val) -{ - TSMgmtError ret; - - TSRecordEle *ele = TSRecordEleCreate(); - ret = MgmtRecordGet(rec_name, ele); - if (ret != TS_ERR_OKAY) { - goto END; - } - - *string_val = ats_strdup(ele->valueT.string_val); - -END: - TSRecordEleDestroy(ele); - return ret; -} - -/*------------------------------------------------------------------------- - * TSRecordGetMlt - *------------------------------------------------------------------------- - * Purpose: Retrieves list of record values specified in the rec_names list - * Input: rec_names - list of record names to retrieve - * rec_vals - queue of TSRecordEle* that corresponds to rec_names - * Output: If at any point, while retrieving one of the records there's a - * a failure then the entire process is aborted, all the allocated - * TSRecordEle's are deallocated and TS_ERR_FAIL is returned. - * Note: rec_names is not freed; if function is successful, the rec_names - * list is unchanged! - * - * IS THIS FUNCTION AN ATOMIC TRANSACTION? Technically, all the variables - * requested should refer to the same config file. But a lock is only - * put on each variable it is looked up. Need to be able to lock - * a file while retrieving all the requested records! - */ - -tsapi TSMgmtError -TSRecordGetMlt(TSStringList rec_names, TSList rec_vals) -{ - int num_recs, i, j; - TSMgmtError ret; - - if (!rec_names || !rec_vals) { - return TS_ERR_PARAMS; - } - - num_recs = queue_len(static_cast(rec_names)); - for (i = 0; i < num_recs; i++) { - char *rec_name = static_cast(dequeue(static_cast(rec_names))); // remove name from list - if (!rec_name) { - return TS_ERR_PARAMS; // NULL is invalid record name - } - - TSRecordEle *ele = TSRecordEleCreate(); - - ret = MgmtRecordGet(rec_name, ele); - enqueue(static_cast(rec_names), rec_name); // return name to list - - if (ret != TS_ERR_OKAY) { // RecordGet failed - // need to free all the ele's allocated by MgmtRecordGet so far - TSRecordEleDestroy(ele); - for (j = 0; j < i; j++) { - ele = static_cast(dequeue(static_cast(rec_vals))); - if (ele) { - TSRecordEleDestroy(ele); - } - } - return ret; - } - enqueue(static_cast(rec_vals), ele); // all is good; add ele to end of list - } - - return TS_ERR_OKAY; -} - -tsapi TSMgmtError -TSRecordGetMatchMlt(const char *regex, TSList rec_vals) -{ - if (!regex || !rec_vals) { - return TS_ERR_PARAMS; - } - - return MgmtRecordGetMatching(regex, rec_vals); -} - -tsapi TSMgmtError -TSRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need) -{ - return MgmtRecordSet(rec_name, val, action_need); -} - -tsapi TSMgmtError -TSRecordSetInt(const char *rec_name, TSInt int_val, TSActionNeedT *action_need) -{ - return MgmtRecordSetInt(rec_name, int_val, action_need); -} - -tsapi TSMgmtError -TSRecordSetCounter(const char *rec_name, TSCounter counter_val, TSActionNeedT *action_need) -{ - return MgmtRecordSetCounter(rec_name, counter_val, action_need); -} - -tsapi TSMgmtError -TSRecordSetFloat(const char *rec_name, TSFloat float_val, TSActionNeedT *action_need) -{ - return MgmtRecordSetFloat(rec_name, float_val, action_need); -} - -tsapi TSMgmtError -TSRecordSetString(const char *rec_name, const char *str_val, TSActionNeedT *action_need) -{ - return MgmtRecordSetString(rec_name, str_val, action_need); -} - -/*------------------------------------------------------------------------- - * TSRecordSetMlt - *------------------------------------------------------------------------- - * Basically iterates through each RecordEle in rec_list and calls the - * appropriate "MgmtRecordSetxx" function for that record - * Input: rec_list - queue of TSRecordEle*; each TSRecordEle* must have - * a valid record name (remains unchanged on return) - * Output: if there is an error during the setting of one of the variables then - * will continue to try to set the other variables. Error response will - * indicate though that not all set operations were successful. - * TS_ERR_OKAY is returned if all the records are set successfully - * Note: Determining the action needed is more complex b/c need to keep - * track of which record change is the most drastic out of the group of - * records; action_need will be set to the most severe action needed of - * all the "Set" calls - */ -tsapi TSMgmtError -TSRecordSetMlt(TSList rec_list, TSActionNeedT *action_need) -{ - int num_recs, ret, i; - TSMgmtError status = TS_ERR_OKAY; - TSActionNeedT top_action_req = TS_ACTION_UNDEFINED; - - if (!rec_list || !action_need) { - return TS_ERR_PARAMS; - } - - num_recs = queue_len(static_cast(rec_list)); - - for (i = 0; i < num_recs; i++) { - TSRecordEle *ele = static_cast(dequeue(static_cast(rec_list))); - if (ele) { - switch (ele->rec_type) { - case TS_REC_INT: - ret = MgmtRecordSetInt(ele->rec_name, ele->valueT.int_val, action_need); - break; - case TS_REC_COUNTER: - ret = MgmtRecordSetCounter(ele->rec_name, ele->valueT.counter_val, action_need); - break; - case TS_REC_FLOAT: - ret = MgmtRecordSetFloat(ele->rec_name, ele->valueT.float_val, action_need); - break; - case TS_REC_STRING: - ret = MgmtRecordSetString(ele->rec_name, ele->valueT.string_val, action_need); - break; - default: - ret = TS_ERR_FAIL; - break; - }; /* end of switch (ele->rec_type) */ - if (ret != TS_ERR_OKAY) { - status = TS_ERR_FAIL; - } - - // keep track of most severe action; reset if needed - // the TSActionNeedT should be listed such that most severe actions have - // a lower number (so most severe action == 0) - if (*action_need < top_action_req) { // a more severe action - top_action_req = *action_need; - } - } - enqueue(static_cast(rec_list), ele); - } - - // set the action_need to be the most sever action needed of all the "set" calls - *action_need = top_action_req; - - return status; -} - -/*--- api initialization and shutdown -------------------------------------*/ -tsapi TSMgmtError -TSInit(const char *socket_path, TSInitOptionT options) -{ - return Init(socket_path, options); -} - -tsapi TSMgmtError -TSTerminate() -{ - return Terminate(); -} - -/*--- plugin initialization -----------------------------------------------*/ -inkexp extern void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) -{ -} - -/*--- network operations --------------------------------------------------*/ -tsapi TSMgmtError -TSConnect(TSIpAddr /* ip_addr ATS_UNUSED */, int /* port ATS_UNUSED */) -{ - return TS_ERR_OKAY; -} -tsapi TSMgmtError -TSDisconnectCbRegister(TSDisconnectFunc * /* func ATS_UNUSED */, void * /* data ATS_UNUSED */) -{ - return TS_ERR_OKAY; -} -tsapi TSMgmtError -TSDisconnectRetrySet(int /* retries ATS_UNUSED */, int /* retry_sleep_msec ATS_UNUSED */) -{ - return TS_ERR_OKAY; -} -tsapi TSMgmtError -TSDisconnect() -{ - return TS_ERR_OKAY; -} - -/*--- control operations --------------------------------------------------*/ -/* NOTE: these operations are wrappers that make direct calls to the CoreAPI */ - -/* TSProxyStateGet: get the proxy state (on/off) - * Input: - * Output: proxy state (on/off) - */ -tsapi TSProxyStateT -TSProxyStateGet() -{ - return ProxyStateGet(); -} - -/* TSProxyStateSet: set the proxy state (on/off) - * Input: proxy_state - set to on/off - * clear - start TS with cache clearing option, - * when stopping TS should always be TS_CACHE_CLEAR_NONE - * Output: TSMgmtError - */ -tsapi TSMgmtError -TSProxyStateSet(TSProxyStateT proxy_state, unsigned clear) -{ - unsigned mask = TS_CACHE_CLEAR_NONE | TS_CACHE_CLEAR_CACHE | TS_CACHE_CLEAR_HOSTDB; - - if (clear & ~mask) { - return TS_ERR_PARAMS; - } - - return ProxyStateSet(proxy_state, static_cast(clear)); -} - -tsapi TSMgmtError -TSProxyBacktraceGet(unsigned options, TSString *trace) -{ - if (options != 0) { - return TS_ERR_PARAMS; - } - - if (trace == nullptr) { - return TS_ERR_PARAMS; - } - - return ServerBacktrace(options, trace); -} - -/* TSReconfigure: tell traffic_server to re-read its configuration files - * Input: - * Output: TSMgmtError - */ -tsapi TSMgmtError -TSReconfigure() -{ - return Reconfigure(); -} - -/* TSRestart: restarts Traffic Server - * Input: options - bitmask of TSRestartOptionT - * Output: TSMgmtError - */ -tsapi TSMgmtError -TSRestart(unsigned options) -{ - return Restart(options); -} - -/* TSActionDo: based on TSActionNeedT, will take appropriate action - * Input: action - action that needs to be taken - * Output: TSMgmtError - */ -tsapi TSMgmtError -TSActionDo(TSActionNeedT action) -{ - TSMgmtError ret; - - switch (action) { - case TS_ACTION_RESTART: - ret = Restart(true); // cluster wide by default? - break; - case TS_ACTION_RECONFIGURE: - ret = Reconfigure(); - break; - case TS_ACTION_DYNAMIC: - /* do nothing - change takes effect immediately */ - return TS_ERR_OKAY; - case TS_ACTION_SHUTDOWN: - default: - return TS_ERR_FAIL; - } - - return ret; -} - -/* TSBouncer: restarts the traffic_server process(es) - * Input: options - bitmask of TSRestartOptionT - * Output: TSMgmtError - */ -tsapi TSMgmtError -TSBounce(unsigned options) -{ - return Bounce(options); -} - -tsapi TSMgmtError -TSStop(unsigned options) -{ - return Stop(options); -} - -tsapi TSMgmtError -TSDrain(unsigned options) -{ - return Drain(options); -} - -tsapi TSMgmtError -TSStorageDeviceCmdOffline(const char *dev) -{ - return StorageDeviceCmdOffline(dev); -} - -tsapi TSMgmtError -TSLifecycleMessage(const char *tag, void const *data, size_t data_size) -{ - return LifecycleMessage(tag, data, data_size); -} - /* NOTE: user must deallocate the memory for the string returned */ char * TSGetErrorMessage(TSMgmtError err_id) @@ -1010,310 +525,3 @@ TSReadFromUrlEx(const char *url, char **header, int *headerSize, char **body, in return status; } - -/*--- cache inspector operations -------------------------------------------*/ - -tsapi TSMgmtError -TSLookupFromCacheUrl(TSString url, TSString *info) -{ - TSMgmtError err = TS_ERR_OKAY; - int fd; - char request[BUFSIZE]; - char response[URL_BUFSIZE]; - char *header; - char *body; - int hdr_size; - int bdy_size; - int timeout = URL_TIMEOUT; - TSInt ts_port = 8080; - - if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) { - goto END; - } - - if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { - err = TS_ERR_FAIL; - goto END; - } - snprintf(request, BUFSIZE, "http://{cache}/lookup_url?url=%s", url); - if ((err = sendHTTPRequest(fd, request, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - memset(response, 0, URL_BUFSIZE); - if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) { - goto END; - } - - *info = ats_strndup(body, bdy_size); - -END: - return err; -} - -tsapi TSMgmtError -TSLookupFromCacheUrlRegex(TSString url_regex, TSString *list) -{ - TSMgmtError err = TS_ERR_OKAY; - int fd = -1; - char request[BUFSIZE]; - char response[URL_BUFSIZE]; - char *header; - char *body; - int hdr_size; - int bdy_size; - int timeout = -1; - TSInt ts_port = 8080; - - if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) { - goto END; - } - - if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { - err = TS_ERR_FAIL; - goto END; - } - snprintf(request, BUFSIZE, "http://{cache}/lookup_regex?url=%s", url_regex); - if ((err = sendHTTPRequest(fd, request, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - memset(response, 0, URL_BUFSIZE); - if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) { - goto END; - } - - *list = ats_strndup(body, bdy_size); -END: - return err; -} - -tsapi TSMgmtError -TSDeleteFromCacheUrl(TSString url, TSString *info) -{ - TSMgmtError err = TS_ERR_OKAY; - int fd = -1; - char request[BUFSIZE]; - char response[URL_BUFSIZE]; - char *header; - char *body; - int hdr_size; - int bdy_size; - int timeout = URL_TIMEOUT; - TSInt ts_port = 8080; - - if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) { - goto END; - } - - if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { - err = TS_ERR_FAIL; - goto END; - } - snprintf(request, BUFSIZE, "http://{cache}/delete_url?url=%s", url); - if ((err = sendHTTPRequest(fd, request, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - memset(response, 0, URL_BUFSIZE); - if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) { - goto END; - } - - *info = ats_strndup(body, bdy_size); - -END: - return err; -} - -tsapi TSMgmtError -TSDeleteFromCacheUrlRegex(TSString url_regex, TSString *list) -{ - TSMgmtError err = TS_ERR_OKAY; - int fd = -1; - char request[BUFSIZE]; - char response[URL_BUFSIZE]; - char *header; - char *body; - int hdr_size; - int bdy_size; - int timeout = -1; - TSInt ts_port = 8080; - - if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) { - goto END; - } - - if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { - err = TS_ERR_FAIL; - goto END; - } - snprintf(request, BUFSIZE, "http://{cache}/delete_regex?url=%s", url_regex); - if ((err = sendHTTPRequest(fd, request, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - memset(response, 0, URL_BUFSIZE); - if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) { - goto END; - } - - *list = ats_strndup(body, bdy_size); -END: - return err; -} - -tsapi TSMgmtError -TSInvalidateFromCacheUrlRegex(TSString url_regex, TSString *list) -{ - TSMgmtError err = TS_ERR_OKAY; - int fd = -1; - char request[BUFSIZE]; - char response[URL_BUFSIZE]; - char *header; - char *body; - int hdr_size; - int bdy_size; - int timeout = -1; - TSInt ts_port = 8080; - - if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) { - goto END; - } - - if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { - err = TS_ERR_FAIL; - goto END; - } - snprintf(request, BUFSIZE, "http://{cache}/invalidate_regex?url=%s", url_regex); - if ((err = sendHTTPRequest(fd, request, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - memset(response, 0, URL_BUFSIZE); - if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast(timeout))) != TS_ERR_OKAY) { - goto END; - } - - if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) { - goto END; - } - - *list = ats_strndup(body, bdy_size); -END: - return err; -} - -/*--- events --------------------------------------------------------------*/ -tsapi TSMgmtError -TSEventSignal(char *event_name, ...) -{ - va_list ap; - TSMgmtError ret; - - va_start(ap, event_name); // initialize the argument pointer ap - ret = EventSignal(event_name, ap); - va_end(ap); - return ret; -} - -tsapi TSMgmtError -TSEventResolve(const char *event_name) -{ - return EventResolve(event_name); -} - -tsapi TSMgmtError -TSActiveEventGetMlt(TSList active_events) -{ - return ActiveEventGetMlt(static_cast(active_events)); -} - -tsapi TSMgmtError -TSEventIsActive(char *event_name, bool *is_current) -{ - return EventIsActive(event_name, is_current); -} - -tsapi TSMgmtError -TSEventSignalCbRegister(char *event_name, TSEventSignalFunc func, void *data) -{ - return EventSignalCbRegister(event_name, func, data); -} - -tsapi TSMgmtError -TSEventSignalCbUnregister(char *event_name, TSEventSignalFunc func) -{ - return EventSignalCbUnregister(event_name, func); -} - -TSConfigRecordDescription * -TSConfigRecordDescriptionCreate(void) -{ - TSConfigRecordDescription *val = static_cast(ats_malloc(sizeof(TSConfigRecordDescription))); - - ink_zero(*val); - val->rec_type = TS_REC_UNDEFINED; - - return val; -} - -void -TSConfigRecordDescriptionDestroy(TSConfigRecordDescription *val) -{ - TSConfigRecordDescriptionFree(val); - ats_free(val); -} - -void -TSConfigRecordDescriptionFree(TSConfigRecordDescription *val) -{ - if (val) { - ats_free(val->rec_name); - ats_free(val->rec_checkexpr); - - if (val->rec_type == TS_REC_STRING) { - ats_free(val->rec_value.string_val); - } - - ink_zero(*val); - val->rec_type = TS_REC_UNDEFINED; - } -} - -TSMgmtError -TSConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val) -{ - if (!rec_name || !val) { - return TS_ERR_PARAMS; - } - - TSConfigRecordDescriptionFree(val); - return MgmtConfigRecordDescribe(rec_name, flags, val); -} - -TSMgmtError -TSConfigRecordDescribeMatchMlt(const char *rec_regex, unsigned flags, TSList rec_vals) -{ - if (!rec_regex || !rec_vals) { - return TS_ERR_PARAMS; - } - - return MgmtConfigRecordDescribeMatching(rec_regex, flags, rec_vals); -} diff --git a/mgmt/api/Makefile.am b/mgmt/api/Makefile.am index 40890dc861a..b87af924d72 100644 --- a/mgmt/api/Makefile.am +++ b/mgmt/api/Makefile.am @@ -31,59 +31,13 @@ AM_CPPFLAGS += \ $(TS_INCLUDES) \ $(LIBUNWIND_CFLAGS) -noinst_LTLIBRARIES = libmgmtapilocal.la libmgmtapi.la -lib_LTLIBRARIES = libtsmgmt.la +noinst_LTLIBRARIES = libmgmtapi.la libmgmtapi_la_SOURCES = \ - CoreAPI.h \ CoreAPIShared.cc \ CoreAPIShared.h \ - EventCallback.cc \ - EventCallback.h \ INKMgmtAPI.cc \ - NetworkMessage.cc \ - NetworkMessage.h \ include/mgmtapi.h -if BUILD_TESTS -noinst_PROGRAMS = traffic_api_cli_remote -endif - -libmgmtapilocal_la_SOURCES = \ - CoreAPI.cc \ - EventControlMain.cc \ - EventControlMain.h \ - NetworkUtilsLocal.cc \ - NetworkUtilsLocal.h \ - TSControlMain.cc \ - TSControlMain.h - -libtsmgmt_la_SOURCES = \ - CoreAPIRemote.cc \ - NetworkUtilsRemote.cc \ - NetworkUtilsRemote.h - -libmgmtapilocal_la_LIBADD = \ - libmgmtapi.la \ - $(top_builddir)/src/tscore/libtscore.la - -libtsmgmt_la_LDFLAGS = @AM_LDFLAGS@ -no-undefined -version-info @TS_LIBTOOL_VERSION@ -libtsmgmt_la_LIBADD = @LIBOBJS@ \ - libmgmtapi.la \ - $(top_builddir)/src/tscore/libtscore.la \ - $(top_builddir)/mgmt/utils/libutils_p.la - -if BUILD_TESTS -traffic_api_cli_remote_SOURCES = APITestCliRemote.cc -endif - -traffic_api_cli_remote_LDADD = \ - $(top_builddir)/src/tscpp/util/libtscpputil.la \ - libtsmgmt.la \ - $(top_builddir)/src/tscpp/util/libtscpputil.la \ - $(top_builddir)/src/tscore/libtscore.la \ - $(top_builddir)/src/tscpp/util/libtscpputil.la \ - @OPENSSL_LIBS@ - clang-tidy-local: $(DIST_SOURCES) $(CXX_Clang_Tidy) diff --git a/mgmt/api/NetworkMessage.cc b/mgmt/api/NetworkMessage.cc deleted file mode 100644 index 99489086d32..00000000000 --- a/mgmt/api/NetworkMessage.cc +++ /dev/null @@ -1,372 +0,0 @@ -/** @file - - Network message marshalling. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_config.h" -#include "tscore/ink_defs.h" -#include "tscore/ink_error.h" -#include "tscore/ink_assert.h" -#include "tscore/ink_memory.h" -#include "mgmtapi.h" -#include "NetworkMessage.h" - -#define MAX_OPERATION_FIELDS 16 - -struct NetCmdOperation { - unsigned nfields; - const MgmtMarshallType fields[MAX_OPERATION_FIELDS]; -}; - -// Requests always begin with a OpType, followed by additional fields. -static const struct NetCmdOperation requests[] = { - /* RECORD_SET */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING}}, - /* RECORD_GET */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* PROXY_STATE_GET */ {1, {MGMT_MARSHALL_INT}}, - /* PROXY_STATE_SET */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* RECONFIGURE */ {1, {MGMT_MARSHALL_INT}}, - /* RESTART */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* BOUNCE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* STOP */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* DRAIN */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* EVENT_RESOLVE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* EVENT_GET_MLT */ {1, {MGMT_MARSHALL_INT}}, - /* EVENT_ACTIVE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* EVENT_REG_CALLBACK */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* EVENT_UNREG_CALLBACK */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* EVENT_NOTIFY */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING}}, // only msg sent from TM to - // client - /* STATS_RESET_NODE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* STORAGE_DEVICE_CMD_OFFLINE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* RECORD_MATCH_GET */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* API_PING */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* SERVER_BACKTRACE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* RECORD_DESCRIBE_CONFIG */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}}, - /* LIFECYCLE_MESSAGE */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA}}, - /* HOST_STATUS_HOST_UP */ {4, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}}, - /* HOST_STATUS_HOST_DOWN */ {4, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}}, -}; - -// Responses always begin with a TSMgmtError code, followed by additional fields. -static const struct NetCmdOperation responses[] = { - /* RECORD_SET */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* RECORD_GET */ - {5, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA}}, - /* PROXY_STATE_GET */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* PROXY_STATE_SET */ {1, {MGMT_MARSHALL_INT}}, - /* RECONFIGURE */ {1, {MGMT_MARSHALL_INT}}, - /* RESTART */ {1, {MGMT_MARSHALL_INT}}, - /* BOUNCE */ {1, {MGMT_MARSHALL_INT}}, - /* STOP */ {1, {MGMT_MARSHALL_INT}}, - /* DRAIN */ {1, {MGMT_MARSHALL_INT}}, - /* EVENT_RESOLVE */ {1, {MGMT_MARSHALL_INT}}, - /* EVENT_GET_MLT */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* EVENT_ACTIVE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}}, - /* EVENT_REG_CALLBACK */ {0, {}}, // no reply - /* EVENT_UNREG_CALLBACK */ {0, {}}, // no reply - /* EVENT_NOTIFY */ {0, {}}, // no reply - /* STATS_RESET_NODE */ {1, {MGMT_MARSHALL_INT}}, - /* STORAGE_DEVICE_CMD_OFFLINE */ {1, {MGMT_MARSHALL_INT}}, - /* RECORD_MATCH_GET */ - {5, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA}}, - /* API_PING */ {0, {}}, // no reply - /* SERVER_BACKTRACE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING}}, - /* RECORD_DESCRIBE_CONFIG */ - {15, - {MGMT_MARSHALL_INT /* status */, MGMT_MARSHALL_STRING /* name */, MGMT_MARSHALL_DATA /* value */, - MGMT_MARSHALL_DATA /* default */, MGMT_MARSHALL_INT /* type */, MGMT_MARSHALL_INT /* class */, MGMT_MARSHALL_INT /* version */, - MGMT_MARSHALL_INT /* rsb */, MGMT_MARSHALL_INT /* order */, MGMT_MARSHALL_INT /* access */, MGMT_MARSHALL_INT /* update */, - MGMT_MARSHALL_INT /* updatetype */, MGMT_MARSHALL_INT /* checktype */, MGMT_MARSHALL_INT /* source */, - MGMT_MARSHALL_STRING /* checkexpr */}}, - /* LIFECYCLE_MESSAGE */ {1, {MGMT_MARSHALL_INT}}, - /* HOST_STATUS_UP */ {1, {MGMT_MARSHALL_INT}}, - /* HOST_STATUS_DOWN */ {1, {MGMT_MARSHALL_INT}}, -}; - -#define GETCMD(ops, optype, cmd) \ - do { \ - if (static_cast(optype) >= countof(ops)) { \ - return TS_ERR_PARAMS; \ - } \ - if (ops[static_cast(optype)].nfields == 0) { \ - return TS_ERR_PARAMS; \ - } \ - cmd = &ops[static_cast(optype)]; \ - } while (0); - -TSMgmtError -send_mgmt_request(const mgmt_message_sender &snd, OpType optype, ...) -{ - va_list ap; - ats_scoped_mem msgbuf; - MgmtMarshallInt msglen; - const MgmtMarshallType lenfield[] = {MGMT_MARSHALL_INT}; - const NetCmdOperation *cmd; - - if (!snd.is_connected()) { - return TS_ERR_NET_ESTABLISH; // no connection. - } - - GETCMD(requests, optype, cmd); - - va_start(ap, optype); - msglen = mgmt_message_length_v(cmd->fields, cmd->nfields, ap); - va_end(ap); - - msgbuf = static_cast(ats_malloc(msglen + 4)); - - // First marshall the total message length. - mgmt_message_marshall((char *)msgbuf, msglen, lenfield, countof(lenfield), &msglen); - - // Now marshall the message itself. - va_start(ap, optype); - if (mgmt_message_marshall_v((char *)msgbuf + 4, msglen, cmd->fields, cmd->nfields, ap) == -1) { - va_end(ap); - return TS_ERR_PARAMS; - } - - va_end(ap); - return snd.send(msgbuf, msglen + 4); -} - -TSMgmtError -send_mgmt_request(int fd, OpType optype, ...) -{ - va_list ap; - MgmtMarshallInt msglen; - MgmtMarshallData req = {nullptr, 0}; - const MgmtMarshallType fields[] = {MGMT_MARSHALL_DATA}; - const NetCmdOperation *cmd; - - GETCMD(requests, optype, cmd); - - // Figure out the payload length. - va_start(ap, optype); - msglen = mgmt_message_length_v(cmd->fields, cmd->nfields, ap); - va_end(ap); - - ink_assert(msglen >= 0); - - req.ptr = static_cast(ats_malloc(msglen)); - req.len = msglen; - - // Marshall the message itself. - va_start(ap, optype); - if (mgmt_message_marshall_v(req.ptr, req.len, cmd->fields, cmd->nfields, ap) == -1) { - ats_free(req.ptr); - va_end(ap); - return TS_ERR_PARAMS; - } - - va_end(ap); - - MgmtMarshallInt op; - MgmtMarshallString name; - int down_time; - static const MgmtMarshallType fieldso[] = {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}; - - if (mgmt_message_parse(static_cast(req.ptr), msglen, fieldso, countof(fieldso), &op, &name, &down_time) == -1) { - printf("Plugin message - RPC parsing error - message discarded.\n"); - } - - // Send the response as the payload of a data object. - if (mgmt_message_write(fd, fields, countof(fields), &req) == -1) { - ats_free(req.ptr); - return TS_ERR_NET_WRITE; - } - - ats_free(req.ptr); - return TS_ERR_OKAY; -} - -TSMgmtError -send_mgmt_error(int fd, OpType optype, TSMgmtError error) -{ - MgmtMarshallInt ecode = error; - MgmtMarshallInt intval = 0; - MgmtMarshallData dataval = {nullptr, 0}; - MgmtMarshallString strval = nullptr; - - // Switch on operations, grouped by response format. - switch (optype) { - case OpType::BOUNCE: - case OpType::STOP: - case OpType::DRAIN: - case OpType::EVENT_RESOLVE: - case OpType::LIFECYCLE_MESSAGE: - case OpType::PROXY_STATE_SET: - case OpType::RECONFIGURE: - case OpType::RESTART: - case OpType::STATS_RESET_NODE: - case OpType::HOST_STATUS_UP: - case OpType::HOST_STATUS_DOWN: - case OpType::STORAGE_DEVICE_CMD_OFFLINE: - ink_release_assert(responses[static_cast(optype)].nfields == 1); - return send_mgmt_response(fd, optype, &ecode); - - case OpType::RECORD_SET: - case OpType::PROXY_STATE_GET: - case OpType::EVENT_ACTIVE: - ink_release_assert(responses[static_cast(optype)].nfields == 2); - return send_mgmt_response(fd, optype, &ecode, &intval); - - case OpType::EVENT_GET_MLT: - case OpType::SERVER_BACKTRACE: - ink_release_assert(responses[static_cast(optype)].nfields == 2); - return send_mgmt_response(fd, optype, &ecode, &strval); - - case OpType::RECORD_GET: - case OpType::RECORD_MATCH_GET: - ink_release_assert(responses[static_cast(optype)].nfields == 5); - return send_mgmt_response(fd, optype, &ecode, &intval, &intval, &strval, &dataval); - - case OpType::RECORD_DESCRIBE_CONFIG: - ink_release_assert(responses[static_cast(optype)].nfields == 15); - return send_mgmt_response(fd, optype, &ecode, &strval /* name */, &dataval /* value */, &dataval /* default */, - &intval /* type */, &intval /* class */, &intval /* version */, &intval /* rsb */, - &intval /* order */, &intval /* access */, &intval /* update */, &intval /* updatetype */, - &intval /* checktype */, &intval /* source */, &strval /* checkexpr */); - - case OpType::EVENT_REG_CALLBACK: - case OpType::EVENT_UNREG_CALLBACK: - case OpType::EVENT_NOTIFY: - case OpType::API_PING: - /* no response for these */ - ink_release_assert(responses[static_cast(optype)].nfields == 0); - return TS_ERR_OKAY; - - case OpType::UNDEFINED_OP: - return TS_ERR_OKAY; - } - - // We should never get here unless OpTypes are added without - // updating the switch statement above. Don't do that; this - // code must be able to handle every OpType. - - ink_fatal("missing generic error support for type %d management message", static_cast(optype)); - return TS_ERR_FAIL; -} - -// Send a management message response. We don't need to worry about retransmitting the message if we get -// disconnected, so this is much simpler. We can directly marshall the response as a data object. -TSMgmtError -send_mgmt_response(int fd, OpType optype, ...) -{ - va_list ap; - MgmtMarshallInt msglen; - MgmtMarshallData reply = {nullptr, 0}; - const MgmtMarshallType fields[] = {MGMT_MARSHALL_DATA}; - const NetCmdOperation *cmd; - - GETCMD(responses, optype, cmd); - - va_start(ap, optype); - msglen = mgmt_message_length_v(cmd->fields, cmd->nfields, ap); - va_end(ap); - - ink_assert(msglen >= 0); - - reply.ptr = static_cast(ats_malloc(msglen)); - reply.len = msglen; - - // Marshall the message itself. - va_start(ap, optype); - if (mgmt_message_marshall_v(reply.ptr, reply.len, cmd->fields, cmd->nfields, ap) == -1) { - ats_free(reply.ptr); - va_end(ap); - return TS_ERR_PARAMS; - } - - va_end(ap); - - // Send the response as the payload of a data object. - if (mgmt_message_write(fd, fields, countof(fields), &reply) == -1) { - ats_free(reply.ptr); - return TS_ERR_NET_WRITE; - } - - ats_free(reply.ptr); - return TS_ERR_OKAY; -} - -template -static TSMgmtError -recv_x(const struct NetCmdOperation (&ops)[N], void *buf, size_t buflen, OpType optype, va_list ap) -{ - ssize_t msglen; - const NetCmdOperation *cmd; - - GETCMD(ops, optype, cmd); - - msglen = mgmt_message_parse_v(buf, buflen, cmd->fields, cmd->nfields, ap); - return (msglen == -1) ? TS_ERR_PARAMS : TS_ERR_OKAY; -} - -TSMgmtError -recv_mgmt_request(void *buf, size_t buflen, OpType optype, ...) -{ - TSMgmtError err; - va_list ap; - - va_start(ap, optype); - err = recv_x(requests, buf, buflen, optype, ap); - va_end(ap); - - return err; -} - -TSMgmtError -recv_mgmt_response(void *buf, size_t buflen, OpType optype, ...) -{ - TSMgmtError err; - va_list ap; - - va_start(ap, optype); - err = recv_x(responses, buf, buflen, optype, ap); - va_end(ap); - - return err; -} - -TSMgmtError -recv_mgmt_message(int fd, MgmtMarshallData &msg) -{ - const MgmtMarshallType fields[] = {MGMT_MARSHALL_DATA}; - - if (mgmt_message_read(fd, fields, countof(fields), &msg) == -1) { - return TS_ERR_NET_READ; - } - - return TS_ERR_OKAY; -} - -OpType -extract_mgmt_request_optype(void *msg, size_t msglen) -{ - const MgmtMarshallType fields[] = {MGMT_MARSHALL_INT}; - MgmtMarshallInt optype; - - if (mgmt_message_parse(msg, msglen, fields, countof(fields), &optype) == -1) { - return OpType::UNDEFINED_OP; - } - - return static_cast(optype); -} diff --git a/mgmt/api/NetworkMessage.h b/mgmt/api/NetworkMessage.h deleted file mode 100644 index 70f15e72a11..00000000000 --- a/mgmt/api/NetworkMessage.h +++ /dev/null @@ -1,94 +0,0 @@ -/** @file - - Network message marshalling. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "MgmtMarshall.h" - -#define REMOTE_DELIM ':' -#define REMOTE_DELIM_STR ":" - -#define MAX_CONN_TRIES 10 // maximum number of attempts to reconnect to TM - -// the possible operations or msg types sent from remote client to TM -enum class OpType : MgmtMarshallInt { - RECORD_SET, - RECORD_GET, - PROXY_STATE_GET, - PROXY_STATE_SET, - RECONFIGURE, - RESTART, - BOUNCE, - STOP, - DRAIN, - EVENT_RESOLVE, - EVENT_GET_MLT, - EVENT_ACTIVE, - EVENT_REG_CALLBACK, - EVENT_UNREG_CALLBACK, - EVENT_NOTIFY, /* only msg sent from TM to client */ - STATS_RESET_NODE, - STORAGE_DEVICE_CMD_OFFLINE, - RECORD_MATCH_GET, - API_PING, - SERVER_BACKTRACE, - RECORD_DESCRIBE_CONFIG, - LIFECYCLE_MESSAGE, - HOST_STATUS_UP, - HOST_STATUS_DOWN, - UNDEFINED_OP /* This must be last */ -}; - -enum { - RECORD_DESCRIBE_FLAGS_MATCH = 0x0001, -}; - -struct mgmt_message_sender { - virtual TSMgmtError send(void *msg, size_t msglen) const = 0; - virtual ~mgmt_message_sender(){}; - - // Check if the sender is connected. - virtual bool is_connected() const = 0; -}; - -// Marshall and send a request, prefixing the message length as a MGMT_MARSHALL_INT. -TSMgmtError send_mgmt_request(const mgmt_message_sender &snd, OpType optype, ...); -TSMgmtError send_mgmt_request(int fd, OpType optype, ...); - -// Marshall and send an error response for this operation type. -TSMgmtError send_mgmt_error(int fd, OpType op, TSMgmtError error); - -// Parse a request message from a buffer. -TSMgmtError recv_mgmt_request(void *buf, size_t buflen, OpType optype, ...); - -// Marshall and send a response, prefixing the message length as a MGMT_MARSHALL_INT. -TSMgmtError send_mgmt_response(int fd, OpType optype, ...); - -// Parse a response message from a buffer. -TSMgmtError recv_mgmt_response(void *buf, size_t buflen, OpType optype, ...); - -// Pull a management message (either request or response) off the wire. -TSMgmtError recv_mgmt_message(int fd, MgmtMarshallData &msg); - -// Extract the first MGMT_MARSHALL_INT from the buffered message. This is the OpType. -OpType extract_mgmt_request_optype(void *msg, size_t msglen); diff --git a/mgmt/api/NetworkUtilsLocal.cc b/mgmt/api/NetworkUtilsLocal.cc deleted file mode 100644 index 50fb8028d14..00000000000 --- a/mgmt/api/NetworkUtilsLocal.cc +++ /dev/null @@ -1,77 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/*************************************************************************** - * NetworkUtilsLocal.cc - * - * contains implementation of local networking utility functions, such as - * unmarshalling requests from a remote client and marshalling replies - * - * - ***************************************************************************/ - -#include "tscore/ink_platform.h" -#include "tscore/ink_sock.h" -#include "tscore/Diags.h" -#include "MgmtUtils.h" -#include "MgmtSocket.h" -#include "MgmtMarshall.h" -#include "CoreAPIShared.h" -#include "NetworkUtilsLocal.h" -#include "NetworkMessage.h" - -/********************************************************************** - * preprocess_msg - * - * purpose: reads in all the message; parses the message into header info - * (OpType + msg_len) and the request portion (used by the handle_xx fns) - * input: sock_info - socket msg is read from - * msg - the data from the network message (no OpType or msg_len) - * output: TS_ERR_xx ( if TS_ERR_OKAY, then parameters set successfully) - * notes: Since preprocess_msg already removes the OpType and msg_len, this part o - * the message is not dealt with by the other parsing functions - **********************************************************************/ -TSMgmtError -preprocess_msg(int fd, void **req, size_t *reqlen) -{ - TSMgmtError ret; - MgmtMarshallData msg; - - *req = nullptr; - *reqlen = 0; - - ret = recv_mgmt_message(fd, msg); - if (ret != TS_ERR_OKAY) { - return ret; - } - - // We should never receive an empty payload. - if (msg.ptr == nullptr) { - return TS_ERR_NET_READ; - } - - *req = msg.ptr; - *reqlen = msg.len; - Debug("ts_main", "[preprocess_msg] read message length = %zd", msg.len); - return TS_ERR_OKAY; -} diff --git a/mgmt/api/NetworkUtilsLocal.h b/mgmt/api/NetworkUtilsLocal.h deleted file mode 100644 index d60006658c0..00000000000 --- a/mgmt/api/NetworkUtilsLocal.h +++ /dev/null @@ -1,32 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "tscore/ink_defs.h" -#include "mgmtapi.h" - -/***************************************************************************** - * Unmarshalling/marshalling - *****************************************************************************/ -TSMgmtError preprocess_msg(int fd, void **req, size_t *reqlen); diff --git a/mgmt/api/NetworkUtilsRemote.cc b/mgmt/api/NetworkUtilsRemote.cc deleted file mode 100644 index 780f4975c62..00000000000 --- a/mgmt/api/NetworkUtilsRemote.cc +++ /dev/null @@ -1,719 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_config.h" -#include "tscore/ink_defs.h" -#include "tscore/ink_sock.h" -#include "tscore/ink_string.h" -#include "tscore/ink_memory.h" -#include "tscore/I_Layout.h" -#include "NetworkUtilsRemote.h" -#include "CoreAPI.h" -#include "CoreAPIShared.h" -#include "MgmtSocket.h" -#include "MgmtMarshall.h" - -CallbackTable *remote_event_callbacks; - -int main_socket_fd = -1; -int event_socket_fd = -1; - -// need to store for reconnecting scenario -char *main_socket_path = nullptr; // "/mgmtapi.sock" -char *event_socket_path = nullptr; // "/eventapi.sock" - -static void *event_callback_thread(void *arg); - -/********************************************************************** - * Socket Helper Functions - **********************************************************************/ -void -set_socket_paths(const char *path) -{ - // free previously set paths if needed - ats_free(main_socket_path); - ats_free(event_socket_path); - - // construct paths based on user input - // form by replacing "mgmtapi.sock" with "eventapi.sock" - if (path) { - main_socket_path = ats_stringdup(Layout::relative_to(path, MGMTAPI_MGMT_SOCKET_NAME)); - event_socket_path = ats_stringdup(Layout::relative_to(path, MGMTAPI_EVENT_SOCKET_NAME)); - } else { - main_socket_path = nullptr; - event_socket_path = nullptr; - } - - return; -} - -/********************************************************************** - * socket_test - * - * purpose: performs socket write to check status of other end of connection - * input: None - * output: return false if socket write failed due to some other error - * return true if socket write successful - * notes: send the API_PING test msg - **********************************************************************/ -static bool -socket_test(int fd) -{ - OpType optype = OpType::API_PING; - MgmtMarshallInt now = time(nullptr); - - if (MGMTAPI_SEND_MESSAGE(fd, OpType::API_PING, &optype, &now) == TS_ERR_OKAY) { - return true; // write was successful; connection still open - } - - return false; -} - -/*************************************************************************** - * connect - * - * purpose: connects to the port on traffic server that listens to mgmt - * requests & issues out responses and alerts - * 1) create and set the client socket_fd; connect to TM - * 2) create and set the client's event_socket_fd; connect to TM - * output: TS_ERR_OKAY - if both sockets successfully connect to TM - * TS_ERR_NET_ESTABLISH - at least one unsuccessful connection - * notes: If connection breaks it is responsibility of client to reconnect - * otherwise traffic server will assume mgmt stopped request and - * goes back to just sitting and listening for connection. - ***************************************************************************/ -TSMgmtError -ts_connect() -{ - struct sockaddr_un client_sock; - struct sockaddr_un client_event_sock; - - int sockaddr_len; - - // make sure a socket path is set up - if (!main_socket_path || !event_socket_path) { - goto ERROR; - } - // make sure the length of main_socket_path do not exceed the sizeof(sun_path) - if (strlen(main_socket_path) > sizeof(client_sock.sun_path) - 1) { - goto ERROR; - } - // make sure the length of event_socket_path do not exceed the sizeof(sun_path) - if (strlen(event_socket_path) > sizeof(client_event_sock.sun_path) - 1) { - goto ERROR; - } - // create a socket - main_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (main_socket_fd < 0) { - goto ERROR; // ERROR - can't open socket - } - // setup Unix domain socket - memset(&client_sock, 0, sizeof(sockaddr_un)); - client_sock.sun_family = AF_UNIX; - ink_strlcpy(client_sock.sun_path, main_socket_path, sizeof(client_sock.sun_path)); -#if defined(darwin) || defined(freebsd) - sockaddr_len = sizeof(sockaddr_un); -#else - sockaddr_len = sizeof(client_sock.sun_family) + strlen(client_sock.sun_path); -#endif - // connect call - if (connect(main_socket_fd, reinterpret_cast(&client_sock), sockaddr_len) < 0) { - close(main_socket_fd); - main_socket_fd = -1; - goto ERROR; // connection is down - } - // -------- set up the event socket ------------------ - // create a socket - event_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (event_socket_fd < 0) { - close(main_socket_fd); // close the other socket too! - main_socket_fd = -1; - goto ERROR; // ERROR - can't open socket - } - // setup Unix domain socket - memset(&client_event_sock, 0, sizeof(sockaddr_un)); - client_event_sock.sun_family = AF_UNIX; - ink_strlcpy(client_event_sock.sun_path, event_socket_path, sizeof(client_event_sock.sun_path)); -#if defined(darwin) || defined(freebsd) - sockaddr_len = sizeof(sockaddr_un); -#else - sockaddr_len = sizeof(client_event_sock.sun_family) + strlen(client_event_sock.sun_path); -#endif - // connect call - if (connect(event_socket_fd, reinterpret_cast(&client_event_sock), sockaddr_len) < 0) { - close(event_socket_fd); - close(main_socket_fd); - event_socket_fd = -1; - main_socket_fd = -1; - goto ERROR; // connection is down - } - - return TS_ERR_OKAY; - -ERROR: - return TS_ERR_NET_ESTABLISH; -} - -/*************************************************************************** - * disconnect - * - * purpose: disconnect from traffic server; closes sockets and resets their values - * input: None - * output: TS_ERR_FAIL, TS_ERR_OKAY - * notes: doesn't do clean up - all cleanup should be done before here - ***************************************************************************/ -TSMgmtError -disconnect() -{ - int ret; - - if (main_socket_fd > 0) { - ret = close(main_socket_fd); - main_socket_fd = -1; - if (ret < 0) { - return TS_ERR_FAIL; - } - } - - if (event_socket_fd > 0) { - ret = close(event_socket_fd); - event_socket_fd = -1; - if (ret < 0) { - return TS_ERR_FAIL; - } - } - - return TS_ERR_OKAY; -} - -/*************************************************************************** - * reconnect - * - * purpose: reconnects to TM (eg. when TM restarts); does all the necessary - * set up for reconnection - * input: None - * output: TS_ERR_FAIL, TS_ERR_OKAY - * notes: necessary events for a new client-TM connection: - * 1) get new socket_fd using old socket_path by calling connect() - * 2) relaunch event_poll_thread_main with new socket_fd - * 3) re-notify TM of all the client's registered callbacks by send msg - ***************************************************************************/ -TSMgmtError -reconnect() -{ - TSMgmtError err; - - err = disconnect(); - if (err != TS_ERR_OKAY) { // problem disconnecting - return err; - } - - // use the socket_path that was called by remote client on first init - // use connect instead of TSInit() b/c if TM restarted, client-side tables - // would be recreated; just want to reconnect to same socket_path - err = ts_connect(); - if (err != TS_ERR_OKAY) { // problem establishing connection - return err; - } - - // relaunch a new event thread since socket_fd changed - if (0 == (ts_init_options & TS_MGMT_OPT_NO_EVENTS)) { - ink_thread_create(&ts_event_thread, event_poll_thread_main, &event_socket_fd, 0, 0, nullptr); - // re-register the callbacks on the TM side for this new client connection - if (remote_event_callbacks) { - err = send_register_all_callbacks(event_socket_fd, remote_event_callbacks); - if (err != TS_ERR_OKAY) { // problem establishing connection - return err; - } - } - } else { - ts_event_thread = ink_thread_null(); - } - - return TS_ERR_OKAY; -} - -/*************************************************************************** - * reconnect_loop - * - * purpose: attempts to reconnect to TM (eg. when TM restarts) for the - * specified number of times - * input: num_attempts - number of reconnection attempts to try before quit - * output: TS_ERR_OKAY - if successfully reconnected within num_attempts - * TS_ERR_xx - the reason the reconnection failed - * notes: - ***************************************************************************/ -TSMgmtError -reconnect_loop(int num_attempts) -{ - int numTries = 0; - TSMgmtError err = TS_ERR_FAIL; - - while (numTries < num_attempts) { - numTries++; - err = reconnect(); - if (err == TS_ERR_OKAY) { - return TS_ERR_OKAY; // successful connection - } - sleep(1); // to make it slower - } - - return err; // unsuccessful connection after num_attempts -} - -/************************************************************************* - * connect_and_send - * - * purpose: - * When sending a request, it's possible that the user had restarted - * Traffic Manager. This means that the connection between TM and - * the remote client has been broken, so the client needs to re-"connect" - * to Traffic Manager. So, after "writing" to the socket in each - * "send_xx_request" function, need to check if the TM socket has - * been closed or not; the "write" function's errno will indicate if - * the other end of the socket has been closed or not. If it is closed, - * then need to try to re"connect", then resend the message request if - * the "connect" was successful. - * 1) try connect() - * 2) if connect() success, then resend the request. - * output: TS_ERR_NET_xx - connection problem or TS_ERR_OKAY - * notes: - * This function is basically called by the special "socket_write_conn" fn - * which will call this fn if it tries to write to the socket and discovers - * the local end of the socket is closed - * Warning: system also sends a SIGPIPE error when try to write to socket - * which is not open; which will by default terminate the process; - * client needs to "ignore" the SIGPIPE signal - **************************************************************************/ -static TSMgmtError -main_socket_reconnect() -{ - TSMgmtError err; - - // connects to TM and does all necessary event updates required - err = reconnect(); - if (err != TS_ERR_OKAY) { - return err; - } - - // makes sure the descriptor is writable - if (mgmt_write_timeout(main_socket_fd, MAX_TIME_WAIT, 0) <= 0) { - return TS_ERR_NET_TIMEOUT; - } - - return TS_ERR_OKAY; -} - -static TSMgmtError -socket_write_conn(int fd, const void *msg_buf, size_t bytes) -{ - size_t byte_wrote = 0; - - // makes sure the descriptor is writable - if (mgmt_write_timeout(fd, MAX_TIME_WAIT, 0) <= 0) { - return TS_ERR_NET_TIMEOUT; - } - - // write until we fulfill the number - while (byte_wrote < bytes) { - ssize_t ret = write(fd, static_cast(msg_buf) + byte_wrote, bytes - byte_wrote); - - if (ret == 0) { - return TS_ERR_NET_EOF; - } - - if (ret < 0) { - if (mgmt_transient_error()) { - continue; - } else { - return TS_ERR_NET_WRITE; - } - } - - // we are all good here - byte_wrote += ret; - } - - return TS_ERR_OKAY; -} - -TSMgmtError -mgmtapi_sender::send(void *msg, size_t msglen) const -{ - const unsigned tries = 5; - TSMgmtError err; - - for (unsigned i = 0; i < tries; ++i) { - err = socket_write_conn(this->fd, msg, msglen); - if (err == TS_ERR_OKAY) { - return err; - } - - // clean-up sockets - close(main_socket_fd); - close(event_socket_fd); - main_socket_fd = -1; - event_socket_fd = -1; - - err = main_socket_reconnect(); - if (err != TS_ERR_OKAY) { - return err; - } - } - - return TS_ERR_NET_ESTABLISH; // can't establish connection -} - -/********************************************************************** - * socket_test_thread - * - * purpose: continually polls to check if local end of socket connection - * is still open; this thread is created when the client calls - * Init() to initialize the API; and will not - * die until the client process dies - * input: none - * output: if other end is closed, it reconnects to TM - * notes: uses the current main_socket_fd because the main_socket_fd could be - * in flux; basically it is possible that the client will reconnect - * from some other call, thus making the main_socket_fd actually - * valid when socket_test is called - * reason: decided to create this "watcher" thread for the socket - * connection because if TM is restarted or the client process - * is started before the TM process, then the client will not - * be able to receive any event notifications until a "request" - * is issued. In order to prevent losing an event notifications - * that are called in between the time TM is restarted and - * client issues a first request, we just run this thread which - * will try to reconnect to TM if it is not already connected - **********************************************************************/ -void * -socket_test_thread(void *) -{ - // loop until client process dies - while (true) { - if (main_socket_fd == -1 || !socket_test(main_socket_fd)) { - // ASSUMES that in between the time the socket_test is made - // and this reconnect call is made, the main_socket_fd remains - // the same (eg. no one else called reconnect to TM successfully!! - // WHAT IF in between this time, the client had issued a request - // calling socket_write_conn which then calls reconnect(); then - // reconnect will return an "ALREADY CONNECTED" error when it - // tries to connect, and on the next loop iteration, the socket_test - // will actually pass because main_socket_fd is valid!! - reconnect(); - } - - sleep(5); - } - - ink_thread_exit(nullptr); - return nullptr; -} - -/********************************************************************** - * MARSHALL REQUESTS - **********************************************************************/ - -/*------ events -------------------------------------------------------*/ - -/********************************************************************** - * send_register_all_callbacks - * - * purpose: determines all events which have at least one callback registered - * and sends message to notify TM that this client has a callback - * registered for each event - * input: None - * output: return TS_ERR_OKAY only if ALL events sent okay - * 1) get list of all events with callbacks - * 2) for each event, send a EVENT_REG_CALLBACK message - **********************************************************************/ -TSMgmtError -send_register_all_callbacks(int fd, CallbackTable *cb_table) -{ - LLQ *events_with_cb; - TSMgmtError err, send_err = TS_ERR_FAIL; - bool no_errors = true; // set to false if one send is not okay - - events_with_cb = get_events_with_callbacks(cb_table); - // need to check that the list has all the events registered - if (!events_with_cb) { // all events have registered callback - OpType optype = OpType::EVENT_REG_CALLBACK; - MgmtMarshallString event_name = nullptr; - - err = MGMTAPI_SEND_MESSAGE(fd, OpType::EVENT_REG_CALLBACK, &optype, &event_name); - if (err != TS_ERR_OKAY) { - return err; - } - } else { - int num_events = queue_len(events_with_cb); - // iterate through the LLQ and send request for each event - for (int i = 0; i < num_events; i++) { - OpType optype = OpType::EVENT_REG_CALLBACK; - MgmtMarshallInt event_id = *static_cast(dequeue(events_with_cb)); - MgmtMarshallString event_name = get_event_name(event_id); - - if (event_name) { - err = MGMTAPI_SEND_MESSAGE(fd, OpType::EVENT_REG_CALLBACK, &optype, &event_name); - ats_free(event_name); // free memory - if (err != TS_ERR_OKAY) { - send_err = err; // save the type of send error - no_errors = false; - } - } - // REMEMBER: WON"T GET A REPLY from TM side! - } - } - - if (events_with_cb) { - delete_queue(events_with_cb); - } - - if (no_errors) { - return TS_ERR_OKAY; - } else { - return send_err; - } -} - -/********************************************************************** - * send_unregister_all_callbacks - * - * purpose: determines all events which have no callback registered - * and sends message to notify TM that this client has no - * callbacks registered for that event - * input: None - * output: TS_ERR_OKAY only if all send requests are okay - **********************************************************************/ -TSMgmtError -send_unregister_all_callbacks(int fd, CallbackTable *cb_table) -{ - LLQ *events_with_cb; // list of events with at least one callback - int reg_callback[NUM_EVENTS]; - TSMgmtError err, send_err = TS_ERR_FAIL; - bool no_errors = true; // set to false if at least one send fails - - // init array so that all events don't have any callbacks - for (int &i : reg_callback) { - i = 0; - } - - events_with_cb = get_events_with_callbacks(cb_table); - if (!events_with_cb) { // all events have a registered callback - return TS_ERR_OKAY; - } else { - int num_events = queue_len(events_with_cb); - // iterate through the LLQ and mark events that have a callback - for (int i = 0; i < num_events; i++) { - int event_id = *static_cast(dequeue(events_with_cb)); - reg_callback[event_id] = 1; // mark the event as having a callback - } - delete_queue(events_with_cb); - } - - // send message to TM to mark unregister - for (int k = 0; k < NUM_EVENTS; k++) { - if (reg_callback[k] == 0) { // event has no registered callbacks - OpType optype = OpType::EVENT_UNREG_CALLBACK; - MgmtMarshallString event_name = get_event_name(k); - - err = MGMTAPI_SEND_MESSAGE(fd, OpType::EVENT_UNREG_CALLBACK, &optype, &event_name); - ats_free(event_name); - if (err != TS_ERR_OKAY) { - send_err = err; // save the type of the sending error - no_errors = false; - } - // REMEMBER: WON"T GET A REPLY! - // only the event_poll_thread_main does any reading of the event_socket; - // so DO NOT parse reply b/c a reply won't be sent - } - } - - if (no_errors) { - return TS_ERR_OKAY; - } else { - return send_err; - } -} - -/********************************************************************** - * UNMARSHAL REPLIES - **********************************************************************/ - -TSMgmtError -parse_generic_response(OpType optype, int fd) -{ - TSMgmtError err; - MgmtMarshallInt ival; - MgmtMarshallData data = {nullptr, 0}; - - err = recv_mgmt_message(fd, data); - if (err != TS_ERR_OKAY) { - return err; - } - - err = recv_mgmt_response(data.ptr, data.len, optype, &ival); - ats_free(data.ptr); - - if (err != TS_ERR_OKAY) { - return err; - } - - return static_cast(ival); -} - -/********************************************************************** - * event_poll_thread_main - * - * purpose: thread listens on the client's event socket connection; - * only reads from the event_socket connection and - * processes EVENT_NOTIFY messages; each time client - * makes new event-socket connection to TM, must launch - * a new event_poll_thread_main thread - * input: arg - contains the socket_fd to listen on - * output: NULL - if error - * notes: each time the client's socket connection to TM is reset - * a new thread will be launched as old one dies; there are - * only two places where a new thread is created: - * 1) when client first connects (TSInit call) - * 2) client reconnects() due to a TM restart - * Uses blocking socket; so blocks until receives an event notification. - * Shouldn't need to use select since only waiting for a notification - * message from event_callback_main thread! - **********************************************************************/ -void * -event_poll_thread_main(void *arg) -{ - int sock_fd; - - sock_fd = *(static_cast(arg)); // should be same as event_socket_fd - - // the sock_fd is going to be the one we listen for events on - while (true) { - TSMgmtError ret; - TSMgmtEvent *event = nullptr; - - MgmtMarshallData reply = {nullptr, 0}; - OpType optype; - MgmtMarshallString name = nullptr; - MgmtMarshallString desc = nullptr; - - // possible sock_fd is invalid if TM restarts and client reconnects - if (sock_fd < 0) { - break; - } - - // Just wait until we get an event or error. The 0 return from select(2) - // means we timed out ... - if (mgmt_read_timeout(main_socket_fd, MAX_TIME_WAIT, 0) == 0) { - continue; - } - - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - break; - } - - ret = recv_mgmt_request(reply.ptr, reply.len, OpType::EVENT_NOTIFY, &optype, &name, &desc); - ats_free(reply.ptr); - - if (ret != TS_ERR_OKAY) { - ats_free(name); - ats_free(desc); - break; - } - - ink_assert(optype == OpType::EVENT_NOTIFY); - - // The new event takes ownership of the message strings. - event = TSEventCreate(); - event->name = name; - event->id = get_event_id(name); - event->description = desc; - - // got event notice; spawn new thread to handle the event's callback functions - ink_thread_create(nullptr, event_callback_thread, (void *)event, 0, 0, nullptr); - } - - ink_thread_exit(nullptr); - return nullptr; -} - -/********************************************************************** - * event_callback_thread - * - * purpose: Given an event, determines and calls the registered cb functions - * in the CallbackTable for remote events - * input: arg - should be an TSMgmtEvent with the event info sent from TM msg - * output: returns when done calling all the callbacks - * notes: None - **********************************************************************/ -static void * -event_callback_thread(void *arg) -{ - TSMgmtEvent *event_notice; - EventCallbackT *event_cb; - int index; - - event_notice = static_cast(arg); - index = event_notice->id; - LLQ *func_q; // list of callback functions need to call - - func_q = create_queue(); - if (!func_q) { - TSEventDestroy(event_notice); - return nullptr; - } - - // obtain lock - ink_mutex_acquire(&remote_event_callbacks->event_callback_lock); - - TSEventSignalFunc cb; - - // check if we have functions to call - if (remote_event_callbacks->event_callback_l[index] && (!queue_is_empty(remote_event_callbacks->event_callback_l[index]))) { - int queue_depth = queue_len(remote_event_callbacks->event_callback_l[index]); - - for (int i = 0; i < queue_depth; i++) { - event_cb = static_cast(dequeue(remote_event_callbacks->event_callback_l[index])); - cb = event_cb->func; - enqueue(remote_event_callbacks->event_callback_l[index], event_cb); - enqueue(func_q, reinterpret_cast(cb)); // add callback function only to list - } - } - // release lock - ink_mutex_release(&remote_event_callbacks->event_callback_lock); - - // execute the callback function - while (!queue_is_empty(func_q)) { - cb = reinterpret_cast(dequeue(func_q)); - (*cb)(event_notice->name, event_notice->description, event_notice->priority, nullptr); - } - - // clean up event notice - TSEventDestroy(event_notice); - delete_queue(func_q); - - // all done! - ink_thread_exit(nullptr); - return nullptr; -} diff --git a/mgmt/api/NetworkUtilsRemote.h b/mgmt/api/NetworkUtilsRemote.h deleted file mode 100644 index f8413dd7c21..00000000000 --- a/mgmt/api/NetworkUtilsRemote.h +++ /dev/null @@ -1,95 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: NetworkUtilsRemote.h - * Purpose: This file contains functions used by remote api client to - * marshal requests to TM and unmarshal replies from TM. - * Also contains functions used to store information specific - * to a remote client connection. - * Created: 8/9/00 - * Created by: lant - * - ***************************************************************************/ - -#pragma once - -#include "mgmtapi.h" -#include "ts/apidefs.h" -#include "NetworkMessage.h" -#include "EventCallback.h" - -extern int main_socket_fd; -extern int event_socket_fd; -extern CallbackTable *remote_event_callbacks; - -// From CoreAPIRemote.cc -extern ink_thread ts_event_thread; -extern TSInitOptionT ts_init_options; - -/********************************************************************** - * Socket Helper Functions - **********************************************************************/ -void set_socket_paths(const char *path); - -/* The following functions are specific for a client connection; uses - * the client connection information stored in the variables in - * NetworkUtilsRemote.cc - */ -TSMgmtError -ts_connect(); /* TODO: update documentation, Renamed due to conflict with connect() in on some platforms*/ -TSMgmtError disconnect(); -TSMgmtError reconnect(); -TSMgmtError reconnect_loop(int num_attempts); - -void *socket_test_thread(void *arg); -void *event_poll_thread_main(void *arg); - -struct mgmtapi_sender : public mgmt_message_sender { - explicit mgmtapi_sender(int _fd) : fd(_fd) {} - TSMgmtError send(void *msg, size_t msglen) const override; - bool - is_connected() const override - { - return fd != ts::NO_FD; - } - - int fd; -}; - -#define MGMTAPI_SEND_MESSAGE(fd, optype, ...) send_mgmt_request(mgmtapi_sender(fd), (optype), __VA_ARGS__) - -#define MGMTAPI_MGMT_SOCKET_NAME "mgmtapi.sock" -#define MGMTAPI_EVENT_SOCKET_NAME "eventapi.sock" - -/***************************************************************************** - * Marshalling (create requests) - *****************************************************************************/ - -TSMgmtError send_register_all_callbacks(int fd, CallbackTable *cb_table); -TSMgmtError send_unregister_all_callbacks(int fd, CallbackTable *cb_table); - -/***************************************************************************** - * Un-marshalling (parse responses) - *****************************************************************************/ -TSMgmtError parse_generic_response(OpType optype, int fd); diff --git a/mgmt/api/TSControlMain.cc b/mgmt/api/TSControlMain.cc deleted file mode 100644 index 74cc778e398..00000000000 --- a/mgmt/api/TSControlMain.cc +++ /dev/null @@ -1,1091 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: TSControlMain.cc - * Purpose: The main section for traffic server that handles all the requests - * from the user. - * Created: 01/08/01 - * Created by: Stephanie Song - * - ***************************************************************************/ - -#include "mgmtapi.h" -#include "tscore/ink_platform.h" -#include "tscore/ink_sock.h" -#include "LocalManager.h" -#include "MgmtUtils.h" -#include "MgmtSocket.h" -#include "NetworkMessage.h" -#include "TSControlMain.h" -#include "CoreAPI.h" -#include "CoreAPIShared.h" -#include "NetworkUtilsLocal.h" - -#include - -#define TIMEOUT_SECS 1 // the num secs for select timeout - -static std::unordered_map accepted_con; // a list of all accepted client connections - -static TSMgmtError handle_control_message(int fd, void *msg, size_t msglen); - -/********************************************************************* - * create_client - * - * purpose: creates a new ClientT and return pointer to it - * input: None - * output: ClientT - * note: created for each accepted client connection - *********************************************************************/ -static ClientT * -create_client() -{ - ClientT *ele = static_cast(ats_malloc(sizeof(ClientT))); - - ele->adr = static_cast(ats_malloc(sizeof(struct sockaddr))); - return ele; -} - -/********************************************************************* - * delete_client - * - * purpose: frees dynamic memory allocated for a ClientT - * input: client - the ClientT to free - * output: - *********************************************************************/ -static void -delete_client(ClientT *client) -{ - if (client) { - ats_free(client->adr); - ats_free(client); - } - return; -} - -/********************************************************************* - * remove_client - * - * purpose: removes the ClientT from the specified hashtable; includes - * removing the binding and freeing the ClientT - * input: client - the ClientT to remove - * output: - *********************************************************************/ -static void -remove_client(ClientT *client, std::unordered_map &table) -{ - // close client socket - close_socket(client->fd); - - // remove client binding from hash table - table.erase(client->fd); - - // free ClientT - delete_client(client); - - return; -} - -/********************************************************************* - * ts_ctrl_main - * - * This function is run as a thread in WebIntrMain.cc that listens on a - * specified socket. It loops until Traffic Manager dies. - * In the loop, it just listens on a socket, ready to accept any connections, - * until receives a request from the remote API client. Parse the request - * to determine which CoreAPI call to make. - *********************************************************************/ -void * -ts_ctrl_main(void *arg) -{ - int ret; - int *socket_fd; - int con_socket_fd; // main socket for listening to new connections - - socket_fd = static_cast(arg); - con_socket_fd = *socket_fd; - - // now we can start listening, accepting connections and servicing requests - int new_con_fd; // new socket fd when accept connection - - fd_set selectFDs; // for select call - ClientT *client_entry; // an entry of fd to alarms mapping - struct timeval timeout; - - // loops until TM dies; waits for and processes requests from clients - while (true) { - // LINUX: to prevent hard-spin of CPU, reset timeout on each loop - timeout.tv_sec = TIMEOUT_SECS; - timeout.tv_usec = 0; - - FD_ZERO(&selectFDs); - - if (con_socket_fd >= 0) { - FD_SET(con_socket_fd, &selectFDs); - // Debug("ts_main", "[ts_ctrl_main] add fd %d to select set", con_socket_fd); - } - - for (auto &&it : accepted_con) { - client_entry = it.second; - if (client_entry->fd >= 0) { // add fd to select set - FD_SET(client_entry->fd, &selectFDs); - Debug("ts_main", "[ts_ctrl_main] add fd %d to select set", client_entry->fd); - } - } - - // select call - timeout is set so we can check events at regular intervals - int fds_ready = mgmt_select(FD_SETSIZE, &selectFDs, (fd_set *)nullptr, (fd_set *)nullptr, &timeout); - - // check if have any connections or requests - if (fds_ready > 0) { - // first check for connections! - if (con_socket_fd >= 0 && FD_ISSET(con_socket_fd, &selectFDs)) { - fds_ready--; - - // create a new instance to store client connection info - ClientT *new_client_con = create_client(); - if (!new_client_con) { - // return TS_ERR_SYS_CALL; WHAT TO DO? just keep going - Debug("ts_main", "[ts_ctrl_main] can't allocate new ClientT"); - } else { // accept connection - socklen_t addr_len = (sizeof(struct sockaddr)); - new_con_fd = mgmt_accept(con_socket_fd, new_client_con->adr, &addr_len); - new_client_con->fd = new_con_fd; - accepted_con.emplace(new_client_con->fd, new_client_con); - Debug("ts_main", "[ts_ctrl_main] Add new client connection"); - } - } // end if(new_con_fd >= 0 && FD_ISSET(new_con_fd, &selectFDs)) - - // some other file descriptor; for each one, service request - if (fds_ready > 0) { // RECEIVED A REQUEST from remote API client - // see if there are more fd to set - iterate through all entries in hash table - - for (auto it = accepted_con.begin(); it != accepted_con.end();) { - Debug("ts_main", "[ts_ctrl_main] We have a remote client request!"); - client_entry = it->second; - ++it; // prevent the breaking of remove_client - // got information; check - if (client_entry->fd && FD_ISSET(client_entry->fd, &selectFDs)) { - void *req = nullptr; - size_t reqlen; - - ret = preprocess_msg(client_entry->fd, &req, &reqlen); - if (ret == TS_ERR_NET_READ || ret == TS_ERR_NET_EOF) { - // occurs when remote API client terminates connection - Debug("ts_main", "[ts_ctrl_main] ERROR: preprocess_msg - remove client %d ", client_entry->fd); - remove_client(client_entry, accepted_con); - continue; - } - - ret = handle_control_message(client_entry->fd, req, reqlen); - ats_free(req); - - if (ret != TS_ERR_OKAY) { - Debug("ts_main", "[ts_ctrl_main] ERROR: sending response for message (%d)", ret); - // XXX this doesn't actually send a error response ... - remove_client(client_entry, accepted_con); - continue; - } - - } // end if(client_entry->fd && FD_ISSET(client_entry->fd, &selectFDs)) - } // end for (auto it = accepted_con.begin(); it != accepted_con.end();) - } // end if (fds_ready > 0) - - } // end if (fds_ready > 0) - - } // end while (1) - - // if we get here something's wrong, just clean up - Debug("ts_main", "[ts_ctrl_main] CLOSING AND SHUTTING DOWN OPERATIONS"); - close_socket(con_socket_fd); - - for (auto &&it : accepted_con) { - client_entry = it.second; - if (client_entry->fd >= 0) { - close_socket(client_entry->fd); // close socket - } - accepted_con.erase(client_entry->fd); - delete_client(client_entry); // free ClientT - } - // all entries should be removed and freed already - accepted_con.clear(); - - ink_thread_exit(nullptr); - return nullptr; -} - -/*------------------------------------------------------------------------- - HANDLER FUNCTIONS - --------------------------------------------------------------------------*/ -/* NOTE: all the handle_xx functions basically, take the request, parse it, - * and send a reply back to the remote client. So even if error occurs, - * each handler functions MUST SEND A REPLY BACK!! - */ - -static TSMgmtError -marshall_rec_data(RecDataT rec_type, const RecData &rec_data, MgmtMarshallData &data) -{ - switch (rec_type) { - case RECD_INT: - data.ptr = const_cast(&rec_data.rec_int); - data.len = sizeof(TSInt); - break; - case RECD_COUNTER: - data.ptr = const_cast(&rec_data.rec_counter); - data.len = sizeof(TSCounter); - break; - case RECD_FLOAT: - data.ptr = const_cast(&rec_data.rec_float); - data.len = sizeof(TSFloat); - break; - case RECD_STRING: - // Make sure to send the NULL in the string value response. - if (rec_data.rec_string) { - data.ptr = rec_data.rec_string; - data.len = strlen(rec_data.rec_string) + 1; - } else { - data.ptr = (void *)"NULL"; - data.len = countof("NULL"); - } - break; - default: // invalid record type - return TS_ERR_FAIL; - } - - return TS_ERR_OKAY; -} - -static TSMgmtError -send_record_get_response(int fd, const RecRecord *rec) -{ - MgmtMarshallInt err = TS_ERR_OKAY; - MgmtMarshallInt type; - MgmtMarshallInt rclass; - MgmtMarshallString name; - MgmtMarshallData value = {nullptr, 0}; - - if (rec) { - type = rec->data_type; - rclass = rec->rec_type; - name = const_cast(rec->name); - } else { - type = RECD_NULL; - rclass = RECT_NULL; - name = nullptr; - } - - switch (type) { - case RECD_INT: - type = TS_REC_INT; - value.ptr = (void *)&rec->data.rec_int; - value.len = sizeof(RecInt); - break; - case RECD_COUNTER: - type = TS_REC_COUNTER; - value.ptr = (void *)&rec->data.rec_counter; - value.len = sizeof(RecCounter); - break; - case RECD_FLOAT: - type = TS_REC_FLOAT; - value.ptr = (void *)&rec->data.rec_float; - value.len = sizeof(RecFloat); - break; - case RECD_STRING: - // For NULL string parameters, send the literal "NULL" to match the behavior of MgmtRecordGet(). Make sure to send - // the trailing NULL. - type = TS_REC_STRING; - if (rec->data.rec_string) { - value.ptr = rec->data.rec_string; - value.len = strlen(rec->data.rec_string) + 1; - } else { - value.ptr = const_cast("NULL"); - value.len = countof("NULL"); - } - break; - default: - type = TS_REC_UNDEFINED; - break; // skip it - } - - return send_mgmt_response(fd, OpType::RECORD_GET, &err, &rclass, &type, &name, &value); -} - -/************************************************************************** - * handle_record_get - * - * purpose: handles requests to retrieve values of certain variables - * in TM. (see local/TSCtrlFunc.cc) - * input: socket information - * req - the msg sent (should = record name to get) - * output: SUCC or ERR - * note: - *************************************************************************/ -static void -send_record_get(const RecRecord *rec, void *edata) -{ - int *fd = static_cast(edata); - *fd = send_record_get_response(*fd, rec); -} - -static TSMgmtError -handle_record_get(int fd, void *req, size_t reqlen) -{ - TSMgmtError ret; - MgmtMarshallInt optype; - MgmtMarshallString name; - - int fderr = fd; // [in,out] variable for the fd and error - - ret = recv_mgmt_request(req, reqlen, OpType::RECORD_GET, &optype, &name); - if (ret != TS_ERR_OKAY) { - return ret; - } - - if (strlen(name) == 0) { - ret = TS_ERR_PARAMS; - goto done; - } - - fderr = fd; - if (RecLookupRecord(name, send_record_get, &fderr) != REC_ERR_OKAY) { - ret = TS_ERR_PARAMS; - goto done; - } - - // If the lookup succeeded, the final error is in "fderr". - if (ret == TS_ERR_OKAY) { - ret = static_cast(fderr); - } - -done: - ats_free(name); - return ret; -} - -struct record_match_state { - TSMgmtError err; - int fd; -}; - -static void -send_record_match(const RecRecord *rec, void *edata) -{ - record_match_state *match = static_cast(edata); - - if (match->err != TS_ERR_OKAY) { - return; - } - - match->err = send_record_get_response(match->fd, rec); -} - -static TSMgmtError -handle_record_match(int fd, void *req, size_t reqlen) -{ - TSMgmtError ret; - record_match_state match; - MgmtMarshallInt optype; - MgmtMarshallString name; - - ret = recv_mgmt_request(req, reqlen, OpType::RECORD_MATCH_GET, &optype, &name); - if (ret != TS_ERR_OKAY) { - return ret; - } - - if (strlen(name) == 0) { - ats_free(name); - return TS_ERR_FAIL; - } - - match.err = TS_ERR_OKAY; - match.fd = fd; - - if (RecLookupMatchingRecords(RECT_ALL, name, send_record_match, &match) != REC_ERR_OKAY) { - ats_free(name); - return TS_ERR_FAIL; - } - - ats_free(name); - - // If successful, send a list terminator. - if (match.err == TS_ERR_OKAY) { - return send_record_get_response(fd, nullptr); - } - - return match.err; -} - -/************************************************************************** - * handle_record_set - * - * purpose: handles a set request sent by the client - * output: SUCC or ERR - * note: request format = DELIMITER - *************************************************************************/ -static TSMgmtError -handle_record_set(int fd, void *req, size_t reqlen) -{ - TSMgmtError ret; - TSActionNeedT action = TS_ACTION_UNDEFINED; - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - MgmtMarshallString value = nullptr; - - ret = recv_mgmt_request(req, reqlen, OpType::RECORD_SET, &optype, &name, &value); - if (ret != TS_ERR_OKAY) { - ret = TS_ERR_FAIL; - goto fail; - } - - if (strlen(name) == 0) { - ret = TS_ERR_PARAMS; - goto fail; - } - - // call CoreAPI call on Traffic Manager side - ret = MgmtRecordSet(name, value, &action); - -fail: - ats_free(name); - ats_free(value); - - MgmtMarshallInt err = ret; - MgmtMarshallInt act = action; - return send_mgmt_response(fd, OpType::RECORD_SET, &err, &act); -} - -/************************************************************************** - * handle_proxy_state_get - * - * purpose: handles request to get the state of the proxy (TS) - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_proxy_state_get(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallInt err; - MgmtMarshallInt state = TS_PROXY_UNDEFINED; - - err = recv_mgmt_request(req, reqlen, OpType::PROXY_STATE_GET, &optype); - if (err == TS_ERR_OKAY) { - state = ProxyStateGet(); - } - - return send_mgmt_response(fd, OpType::PROXY_STATE_GET, &err, &state); -} - -/************************************************************************** - * handle_proxy_state_set - * - * purpose: handles the request to set the state of the proxy (TS) - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_proxy_state_set(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallInt state; - MgmtMarshallInt clear; - - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::PROXY_STATE_SET, &optype, &state, &clear); - if (err != TS_ERR_OKAY) { - return send_mgmt_response(fd, OpType::PROXY_STATE_SET, &err); - } - - err = ProxyStateSet(static_cast(state), static_cast(clear)); - return send_mgmt_response(fd, OpType::PROXY_STATE_SET, &err); -} - -/************************************************************************** - * handle_reconfigure - * - * purpose: handles request to reread the config files - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_reconfigure(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt err; - MgmtMarshallInt optype; - - err = recv_mgmt_request(req, reqlen, OpType::RECONFIGURE, &optype); - if (err == TS_ERR_OKAY) { - err = Reconfigure(); - } - - return send_mgmt_response(fd, OpType::RECONFIGURE, &err); -} - -/************************************************************************** - * handle_restart - * - * purpose: handles request to restart TM and TS - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_restart(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallInt options; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::RESTART, &optype, &options); - if (err == TS_ERR_OKAY) { - switch (optype) { - case OpType::BOUNCE: - err = Bounce(options); - break; - case OpType::RESTART: - err = Restart(options); - break; - default: - err = TS_ERR_PARAMS; - break; - } - } - - return send_mgmt_response(fd, OpType::RESTART, &err); -} - -/************************************************************************** - * handle_stop - * - * purpose: handles request to stop TS - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_stop(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallInt options; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::STOP, &optype, &options); - if (err == TS_ERR_OKAY) { - err = Stop(options); - } - - return send_mgmt_response(fd, OpType::STOP, &err); -} - -/************************************************************************** - * handle_drain - * - * purpose: handles request to drain TS - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_drain(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallInt options; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::DRAIN, &optype, &options); - if (err == TS_ERR_OKAY) { - err = Drain(options); - } - - return send_mgmt_response(fd, OpType::DRAIN, &err); -} - -/************************************************************************** - * handle_storage_device_cmd_offline - * - * purpose: handle storage offline command. - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_storage_device_cmd_offline(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::STORAGE_DEVICE_CMD_OFFLINE, &optype, &name); - if (err == TS_ERR_OKAY) { - // forward to server - lmgmt->signalEvent(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, name); - } - - return send_mgmt_response(fd, OpType::STORAGE_DEVICE_CMD_OFFLINE, &err); -} - -/************************************************************************** - * handle_event_resolve - * - * purpose: handles request to resolve an event - * output: TS_ERR_xx - * note: the req should be the event name - *************************************************************************/ -static TSMgmtError -handle_event_resolve(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::EVENT_RESOLVE, &optype, &name); - if (err == TS_ERR_OKAY) { - err = EventResolve(name); - } - - ats_free(name); - return send_mgmt_response(fd, OpType::EVENT_RESOLVE, &err); -} - -/************************************************************************** - * handle_event_get_mlt - * - * purpose: handles request to get list of active events - * output: TS_ERR_xx - * note: the req should be the event name - *************************************************************************/ -static TSMgmtError -handle_event_get_mlt(int fd, void *req, size_t reqlen) -{ - LLQ *event_list = create_queue(); - char buf[MAX_BUF_SIZE]; - char *event_name; - int buf_pos = 0; - - MgmtMarshallInt optype; - MgmtMarshallInt err; - MgmtMarshallString list = nullptr; - - err = recv_mgmt_request(req, reqlen, OpType::EVENT_GET_MLT, &optype); - if (err != TS_ERR_OKAY) { - goto done; - } - - // call CoreAPI call on Traffic Manager side; req == event_name - err = ActiveEventGetMlt(event_list); - if (err != TS_ERR_OKAY) { - goto done; - } - - // iterate through list and put into a delimited string list - memset(buf, 0, MAX_BUF_SIZE); - while (!queue_is_empty(event_list)) { - event_name = static_cast(dequeue(event_list)); - if (event_name) { - snprintf(buf + buf_pos, (MAX_BUF_SIZE - buf_pos), "%s%c", event_name, REMOTE_DELIM); - buf_pos += (strlen(event_name) + 1); - ats_free(event_name); // free the llq entry - } - } - buf[buf_pos] = '\0'; // end the string - - // Point the send list to the filled buffer. - list = buf; - -done: - delete_queue(event_list); - return send_mgmt_response(fd, OpType::EVENT_GET_MLT, &err, &list); -} - -/************************************************************************** - * handle_event_active - * - * purpose: handles request to resolve an event - * output: TS_ERR_xx - * note: the req should be the event name - *************************************************************************/ -static TSMgmtError -handle_event_active(int fd, void *req, size_t reqlen) -{ - bool active; - MgmtMarshallInt optype; - MgmtMarshallString name = nullptr; - - MgmtMarshallInt err; - MgmtMarshallInt bval = 0; - - err = recv_mgmt_request(req, reqlen, OpType::EVENT_ACTIVE, &optype, &name); - if (err != TS_ERR_OKAY) { - goto done; - } - - if (strlen(name) == 0) { - err = TS_ERR_PARAMS; - goto done; - } - - err = EventIsActive(name, &active); - if (err == TS_ERR_OKAY) { - bval = active ? 1 : 0; - } - -done: - ats_free(name); - return send_mgmt_response(fd, OpType::EVENT_ACTIVE, &err, &bval); -} - -/************************************************************************** - * handle_stats_reset - * - * purpose: handles request to reset statistics to default values - * output: TS_ERR_xx - *************************************************************************/ -static TSMgmtError -handle_stats_reset(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallString name = nullptr; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::STATS_RESET_NODE, &optype, &name); - if (err == TS_ERR_OKAY) { - err = StatsReset(name); - } - - ats_free(name); - return send_mgmt_response(fd, optype, &err); -} - -/************************************************************************** - * handle_host_status_up - * - * purpose: handles request to reset statistics to default values - * output: TS_ERR_xx - *************************************************************************/ -static TSMgmtError -handle_host_status_up(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallString name = nullptr; - MgmtMarshallString reason = nullptr; - MgmtMarshallInt err; - MgmtMarshallInt down_time; - - err = recv_mgmt_request(req, reqlen, OpType::HOST_STATUS_UP, &optype, &name, &reason, &down_time); - if (err == TS_ERR_OKAY) { - lmgmt->signalEvent(MGMT_EVENT_HOST_STATUS_UP, static_cast(req), reqlen); - } - - ats_free(name); - return send_mgmt_response(fd, optype, &err); -} - -/************************************************************************** - * handle_host_status_down - * - * purpose: handles request to reset statistics to default values - * output: TS_ERR_xx - *************************************************************************/ -static TSMgmtError -handle_host_status_down(int fd, void *req, size_t reqlen) -{ - OpType optype; - MgmtMarshallString name = nullptr; - MgmtMarshallString reason = nullptr; - MgmtMarshallInt err; - MgmtMarshallInt down_time; - - err = recv_mgmt_request(req, reqlen, OpType::HOST_STATUS_DOWN, &optype, &name, &reason, &down_time); - if (err == TS_ERR_OKAY) { - lmgmt->signalEvent(MGMT_EVENT_HOST_STATUS_DOWN, static_cast(req), reqlen); - } - - ats_free(name); - return send_mgmt_response(fd, optype, &err); -} -/************************************************************************** - * handle_api_ping - * - * purpose: handles the API_PING message that is sent by API clients to keep - * the management socket alive - * output: TS_ERR_xx. There is no response message. - *************************************************************************/ -static TSMgmtError -handle_api_ping(int /* fd */, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallInt stamp; - - return recv_mgmt_request(req, reqlen, OpType::API_PING, &optype, &stamp); -} - -static TSMgmtError -handle_server_backtrace(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallInt options; - MgmtMarshallString trace = nullptr; - MgmtMarshallInt err; - - err = recv_mgmt_request(req, reqlen, OpType::SERVER_BACKTRACE, &optype, &options); - if (err == TS_ERR_OKAY) { - err = ServerBacktrace(options, &trace); - } - - err = send_mgmt_response(fd, OpType::SERVER_BACKTRACE, &err, &trace); - ats_free(trace); - - return static_cast(err); -} - -static void -send_record_describe(const RecRecord *rec, void *edata) -{ - MgmtMarshallString rec_name = nullptr; - MgmtMarshallData rec_value = {nullptr, 0}; - MgmtMarshallData rec_default = {nullptr, 0}; - MgmtMarshallInt rec_type = TS_REC_UNDEFINED; - MgmtMarshallInt rec_class = RECT_NULL; - MgmtMarshallInt rec_version = 0; - MgmtMarshallInt rec_rsb = 0; - MgmtMarshallInt rec_order = 0; - MgmtMarshallInt rec_access = RECA_NULL; - MgmtMarshallInt rec_update = RECU_NULL; - MgmtMarshallInt rec_updatetype = 0; - MgmtMarshallInt rec_checktype = RECC_NULL; - MgmtMarshallInt rec_source = REC_SOURCE_NULL; - MgmtMarshallString rec_checkexpr = nullptr; - - TSMgmtError err = TS_ERR_OKAY; - - record_match_state *match = static_cast(edata); - - if (match->err != TS_ERR_OKAY) { - return; - } - - if (rec) { - // We only describe config variables (for now). - if (!REC_TYPE_IS_CONFIG(rec->rec_type)) { - match->err = TS_ERR_PARAMS; - return; - } - - rec_name = const_cast(rec->name); - rec_type = rec->data_type; - rec_class = rec->rec_type; - rec_version = rec->version; - rec_rsb = rec->rsb_id; - rec_order = rec->order; - rec_access = rec->config_meta.access_type; - rec_update = rec->config_meta.update_required; - rec_updatetype = rec->config_meta.update_type; - rec_checktype = rec->config_meta.check_type; - rec_source = rec->config_meta.source; - rec_checkexpr = rec->config_meta.check_expr; - - switch (rec_type) { - case RECD_INT: - rec_type = TS_REC_INT; - break; - case RECD_FLOAT: - rec_type = TS_REC_FLOAT; - break; - case RECD_STRING: - rec_type = TS_REC_STRING; - break; - case RECD_COUNTER: - rec_type = TS_REC_COUNTER; - break; - default: - rec_type = TS_REC_UNDEFINED; - } - - err = marshall_rec_data(rec->data_type, rec->data, rec_value); - if (err != TS_ERR_OKAY) { - goto done; - } - - err = marshall_rec_data(rec->data_type, rec->data_default, rec_default); - if (err != TS_ERR_OKAY) { - goto done; - } - } - - err = send_mgmt_response(match->fd, OpType::RECORD_DESCRIBE_CONFIG, &err, &rec_name, &rec_value, &rec_default, &rec_type, - &rec_class, &rec_version, &rec_rsb, &rec_order, &rec_access, &rec_update, &rec_updatetype, - &rec_checktype, &rec_source, &rec_checkexpr); - -done: - match->err = err; -} - -static TSMgmtError -handle_record_describe(int fd, void *req, size_t reqlen) -{ - TSMgmtError ret; - record_match_state match; - MgmtMarshallInt optype; - MgmtMarshallInt options; - MgmtMarshallString name; - - ret = recv_mgmt_request(req, reqlen, OpType::RECORD_DESCRIBE_CONFIG, &optype, &name, &options); - if (ret != TS_ERR_OKAY) { - return ret; - } - - if (strlen(name) == 0) { - ret = TS_ERR_PARAMS; - goto done; - } - - match.err = TS_ERR_OKAY; - match.fd = fd; - - if (options & RECORD_DESCRIBE_FLAGS_MATCH) { - if (RecLookupMatchingRecords(RECT_CONFIG | RECT_LOCAL, name, send_record_describe, &match) != REC_ERR_OKAY) { - ret = TS_ERR_PARAMS; - goto done; - } - - // If successful, send a list terminator. - if (match.err == TS_ERR_OKAY) { - send_record_describe(nullptr, &match); - } - - } else { - if (RecLookupRecord(name, send_record_describe, &match) != REC_ERR_OKAY) { - ret = TS_ERR_PARAMS; - goto done; - } - } - - if (ret == TS_ERR_OKAY) { - ret = match.err; - } - -done: - ats_free(name); - return ret; -} -/************************************************************************** - * handle_lifecycle_message - * - * purpose: handle lifecycle message to plugins - * output: TS_ERR_xx - * note: None - *************************************************************************/ -static TSMgmtError -handle_lifecycle_message(int fd, void *req, size_t reqlen) -{ - MgmtMarshallInt optype; - MgmtMarshallInt err; - MgmtMarshallString tag; - MgmtMarshallData data; - - err = recv_mgmt_request(req, reqlen, OpType::LIFECYCLE_MESSAGE, &optype, &tag, &data); - if (err == TS_ERR_OKAY) { - lmgmt->signalEvent(MGMT_EVENT_LIFECYCLE_MESSAGE, static_cast(req), reqlen); - } - - return send_mgmt_response(fd, OpType::LIFECYCLE_MESSAGE, &err); -} -/**************************************************************************/ - -struct control_message_handler { - unsigned flags; - TSMgmtError (*handler)(int, void *, size_t); -}; - -static const control_message_handler handlers[] = { - /* RECORD_SET */ {MGMT_API_PRIVILEGED, handle_record_set}, - /* RECORD_GET */ {0, handle_record_get}, - /* PROXY_STATE_GET */ {0, handle_proxy_state_get}, - /* PROXY_STATE_SET */ {MGMT_API_PRIVILEGED, handle_proxy_state_set}, - /* RECONFIGURE */ {MGMT_API_PRIVILEGED, handle_reconfigure}, - /* RESTART */ {MGMT_API_PRIVILEGED, handle_restart}, - /* BOUNCE */ {MGMT_API_PRIVILEGED, handle_restart}, - /* STOP */ {MGMT_API_PRIVILEGED, handle_stop}, - /* DRAIN */ {MGMT_API_PRIVILEGED, handle_drain}, - /* EVENT_RESOLVE */ {MGMT_API_PRIVILEGED, handle_event_resolve}, - /* EVENT_GET_MLT */ {0, handle_event_get_mlt}, - /* EVENT_ACTIVE */ {0, handle_event_active}, - /* EVENT_REG_CALLBACK */ {0, nullptr}, - /* EVENT_UNREG_CALLBACK */ {0, nullptr}, - /* EVENT_NOTIFY */ {0, nullptr}, - /* STATS_RESET_NODE */ {MGMT_API_PRIVILEGED, handle_stats_reset}, - /* STORAGE_DEVICE_CMD_OFFLINE */ {MGMT_API_PRIVILEGED, handle_storage_device_cmd_offline}, - /* RECORD_MATCH_GET */ {0, handle_record_match}, - /* API_PING */ {0, handle_api_ping}, - /* SERVER_BACKTRACE */ {MGMT_API_PRIVILEGED, handle_server_backtrace}, - /* RECORD_DESCRIBE_CONFIG */ {0, handle_record_describe}, - /* LIFECYCLE_MESSAGE */ {MGMT_API_PRIVILEGED, handle_lifecycle_message}, - /* HOST_STATUS_UP */ {MGMT_API_PRIVILEGED, handle_host_status_up}, - /* HOST_STATUS_DOWN */ {MGMT_API_PRIVILEGED, handle_host_status_down}, -}; - -// This should use countof(), but we need a constexpr :-/ -static_assert((sizeof(handlers) / sizeof(handlers[0])) == static_cast(OpType::UNDEFINED_OP), - "handlers array is not of correct size"); - -static TSMgmtError -handle_control_message(int fd, void *req, size_t reqlen) -{ - OpType optype = extract_mgmt_request_optype(req, reqlen); - TSMgmtError error; - - if (static_cast(optype) >= countof(handlers)) { - goto fail; - } - - if (handlers[static_cast(optype)].handler == nullptr) { - goto fail; - } - - if (mgmt_has_peereid()) { - uid_t euid = -1; - gid_t egid = -1; - - // For privileged calls, ensure we have caller credentials and that the caller is privileged. - if (handlers[static_cast(optype)].flags & MGMT_API_PRIVILEGED) { - if (mgmt_get_peereid(fd, &euid, &egid) == -1 || (euid != 0 && euid != geteuid())) { - Debug("ts_main", "denied privileged API access on fd=%d for uid=%d gid=%d", fd, euid, egid); - return send_mgmt_error(fd, optype, TS_ERR_PERMISSION_DENIED); - } - } - } - - Debug("ts_main", "handling message type=%d ptr=%p len=%zu on fd=%d", static_cast(optype), req, reqlen, fd); - - error = handlers[static_cast(optype)].handler(fd, req, reqlen); - if (error != TS_ERR_OKAY) { - // NOTE: if the error was produced by the handler sending a response, this could attempt to - // send a response again. However, this would only happen if sending the response failed, so - // it is safe to fail to send it again here ... - return send_mgmt_error(fd, optype, error); - } - - return TS_ERR_OKAY; - -fail: - mgmt_elog(0, "%s: missing handler for type %d control message\n", __func__, static_cast(optype)); - return TS_ERR_PARAMS; -} diff --git a/mgmt/api/TSControlMain.h b/mgmt/api/TSControlMain.h deleted file mode 100644 index d7b17b85a6f..00000000000 --- a/mgmt/api/TSControlMain.h +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/***************************************************************************** - * Filename: TSControlMain.h - * Purpose: The main section for traffic server that handles all the request - * from the user. - * Created: 6/26/00 - * Created by: Stephanie Song - * - ***************************************************************************/ - -#pragma once - -#include "mgmtapi.h" - -typedef struct { - int fd; - struct sockaddr *adr; -} ClientT; - -void *ts_ctrl_main(void *arg); diff --git a/mgmt/api/include/mgmtapi.h b/mgmt/api/include/mgmtapi.h index 38e85a6b084..d36181cbec7 100644 --- a/mgmt/api/include/mgmtapi.h +++ b/mgmt/api/include/mgmtapi.h @@ -279,25 +279,6 @@ tsapi void TSRecordEleDestroy(TSRecordEle *ele); * API Core ***************************************************************************/ -/*--- api initialization and shutdown -------------------------------------*/ -/* TSInit: initializations required for API clients - * Input: socket_path - not applicable for local clients - * for remote users, the path to the config directory. - * If == NULL, we use the Layout engine by default. - * options - Control some features of the APIs - * Output: TS_ERR_xx - * Note: If remote client successfully connects, returns TS_ERR_OKAY; but - * even if not successful connection (eg. client program is started - * before TM) then can still make API calls and will try connecting then - */ -tsapi TSMgmtError TSInit(const char *socket_path, TSInitOptionT options); - -/* TSTerminate: does clean up for API clients - * Input: - * Output: - */ -tsapi TSMgmtError TSTerminate(); - /*--- plugin initialization -----------------------------------------------*/ /* TSPluginInit: called by traffic_manager to initialize the plugin * Input: argc - argument count @@ -313,78 +294,6 @@ tsapi TSMgmtError TSDisconnectCbRegister(TSDisconnectFunc *func, void *data); tsapi TSMgmtError TSDisconnectRetrySet(int retries, int retry_sleep_msec); tsapi TSMgmtError TSDisconnect(); -/*--- control operations --------------------------------------------------*/ -/* TSProxyStateGet: get the proxy state (on/off) - * Input: - * Output: proxy state (on/off) - */ -tsapi TSProxyStateT TSProxyStateGet(); - -/* TSProxyStateSet: set the proxy state (on/off) - * Input: proxy_state - set to on/off - * clear - a TSCacheClearT bitmask, - * specifies if want to start TS with clear_cache or - * clear_cache_hostdb option, or just run TS with no options; - * only applies when turning proxy on - * Output: TSMgmtError - */ -tsapi TSMgmtError TSProxyStateSet(TSProxyStateT proxy_state, unsigned clear); - -/* TSProxyBacktraceGet: get a backtrace of the proxy - * Input: unsigned options - stack trace options - * Output: formatted backtrace of the proxy - * the caller must free this with TSfree - */ -tsapi TSMgmtError TSProxyBacktraceGet(unsigned, TSString *); - -/* TSReconfigure: tell traffic_server to re-read its configuration files - * Input: - * Output: TSMgmtError - */ -tsapi TSMgmtError TSReconfigure(); - -/* TSRestart: restarts Traffic Manager and Traffic Server - * Input: options - bitmask of TSRestartOptionT - * Output: TSMgmtError - */ -tsapi TSMgmtError TSRestart(unsigned options); - -/* TSActionDo: based on TSActionNeedT, will take appropriate action - * Input: action - action that needs to be taken - * Output: TSMgmtError - */ -tsapi TSMgmtError TSActionDo(TSActionNeedT action); - -/* TSBounce: restart the traffic_server process(es). - * Input: options - bitmask of TSRestartOptionT - * Output TSMgmtError - */ -tsapi TSMgmtError TSBounce(unsigned options); - -/* TSStop: stop the traffic_server process(es). - * Input: options - bitmask of TSRestartOptionT - * Output TSMgmtError - */ -tsapi TSMgmtError TSStop(unsigned options); - -/* TSDrain: drain requests of the traffic_server process. - * Input: options - TSDrainOptionT - * Output TSMgmtError - */ -tsapi TSMgmtError TSDrain(unsigned options); - -/* TSStorageDeviceCmdOffline: Request to make a cache storage device offline. - * @arg dev Target device, specified by path to device. - * @return Success. - */ -tsapi TSMgmtError TSStorageDeviceCmdOffline(const char *dev); - -/* TSLifecycleMessage: Send a lifecycle message to the plugins. - * @arg tag Alert tag string (null-terminated) - * @return Success - */ -tsapi TSMgmtError TSLifecycleMessage(const char *tag, void const *data, size_t data_size); - /* TSGetErrorMessage: convert error id to error message * Input: error id (defined in TSMgmtError) * Output: corresponding error message (allocated memory) @@ -428,164 +337,6 @@ tsapi TSMgmtError TSReadFromUrl(char *url, char **header, int *headerSize, char * NOTE: header and headerSize can be NULL */ tsapi TSMgmtError TSReadFromUrlEx(const char *url, char **header, int *headerSize, char **body, int *bodySize, int timeout); -tsapi TSMgmtError TSHostStatusSetUp(const char *host_name, int down_time, const char *reason); -tsapi TSMgmtError TSHostStatusSetDown(const char *host_name, int down_time, const char *reason); -/*--- statistics operations -----------------------------------------------*/ -/* TSStatsReset: sets all the statistics variables to their default values - * Output: TSMgmtError - */ -tsapi TSMgmtError TSStatsReset(const char *name); - -/*--- variable operations -------------------------------------------------*/ -/* TSRecordGet: gets a record - * Input: rec_name - the name of the record (proxy.config.record_name) - * rec_val - allocated TSRecordEle structure, value stored inside - * Output: TSMgmtError (if the rec_name does not exist, returns TS_ERR_FAIL) - */ -tsapi TSMgmtError TSRecordGet(const char *rec_name, TSRecordEle *rec_val); - -/* TSRecordGet*: gets a record w/ a known type - * Input: rec_name - the name of the record (proxy.config.record_name) - * *_val - allocated TSRecordEle structure, value stored inside - * Output: TSMgmtError - * Note: For TSRecordGetString, the function will allocate memory for the - * *string_val, so the caller must free (*string_val); - */ -tsapi TSMgmtError TSRecordGetInt(const char *rec_name, TSInt *int_val); -tsapi TSMgmtError TSRecordGetCounter(const char *rec_name, TSCounter *counter_val); -tsapi TSMgmtError TSRecordGetFloat(const char *rec_name, TSFloat *float_val); -tsapi TSMgmtError TSRecordGetString(const char *rec_name, TSString *string_val); - -/* TSRecordGetMlt: gets a set of records - * Input: rec_list - list of record names the user wants to retrieve; - * resulting gets will be stored in the same list; - * if one get fails, transaction will be aborted - * Output: TSMgmtError - */ -tsapi TSMgmtError TSRecordGetMlt(TSStringList rec_names, TSList rec_vals); - -/* TSRecordGetMatchMlt: gets a set of records - * Input: rec_regex - regular expression to match against record names - * Output: TSMgmtError, TSList of TSRecordEle - */ -tsapi TSMgmtError TSRecordGetMatchMlt(const char *rec_regex, TSList list); - -/* TSRecordSet*: sets a record w/ a known type - * Input: rec_name - the name of the record (proxy.config.record_name) - * *_val - the value to set the record to - * *action_need - indicates which operation required by user for changes to take effect - * Output: TSMgmtError - */ - -tsapi TSMgmtError TSRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need); -tsapi TSMgmtError TSRecordSetInt(const char *rec_name, TSInt int_val, TSActionNeedT *action_need); -tsapi TSMgmtError TSRecordSetCounter(const char *rec_name, TSCounter counter_val, TSActionNeedT *action_need); -tsapi TSMgmtError TSRecordSetFloat(const char *rec_name, TSFloat float_val, TSActionNeedT *action_need); -tsapi TSMgmtError TSRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT *action_need); - -/* TSConfigRecordDescribe: fetch a full description of a configuration record - * Input: rec_name - name of the record - * flags - (unused) fetch flags bitmask - * val - output value; - * Output: TSMgmtError - */ -tsapi TSMgmtError TSConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val); -tsapi TSMgmtError TSConfigRecordDescribeMatchMlt(const char *rec_regex, unsigned flags, TSList list); - -/* TSRecordSetMlt: sets a set of records - * Input: rec_list - list of record names the user wants to set; - * if one set fails, transaction will be aborted - * *action_need - indicates which operation required by user for changes to take effect - * Output: TSMgmtError - */ -tsapi TSMgmtError TSRecordSetMlt(TSList rec_list, TSActionNeedT *action_need); - -/*--- events --------------------------------------------------------------*/ -/* Only a set of statically defined events exist. An event is either - * active or inactive. An event is active when it is triggered, and - * becomes inactive when resolved. Events are triggered and resolved - * by specifying the event's name (which is predefined and immutable). - */ - -/* TSEventResolve: enables the user to resolve an event - * Input: event_name - event to resolve - * Output: TSMgmtError - */ -tsapi TSMgmtError TSEventResolve(const char *event_name); - -/* TSActiveEventGetMlt: query for a list of all the currently active events - * Input: active_events - an empty TSList; if function call is successful, - * active_events will contain names of the currently - * active events - * Output: TSMgmtError - */ -tsapi TSMgmtError TSActiveEventGetMlt(TSList active_events); - -/* TSEventIsActive: check if the specified event is active - * Input: event_name - name of event to check if active; must be one of - * the predefined names - * is_current - when function completes, if true, then the event is - * active - * Output: TSMgmtError - */ -tsapi TSMgmtError TSEventIsActive(char *event_name, bool *is_current); - -/* TSEventSignalCbRegister: register a callback for a specific event or - * for any event - * Input: event_name - the name of event to register callback for; - * if NULL, the callback is registered for all events - * func - callback function - * data - data to pass to callback - * Output: TSMgmtError - */ -tsapi TSMgmtError TSEventSignalCbRegister(char *event_name, TSEventSignalFunc func, void *data); - -/* TSEventSignalCbUnregister: unregister a callback for a specific event - * or for any event - * Input: event_name - the name of event to unregister callback for; - * if NULL, the callback is unregistered for all events - * func - callback function - * Output: TSMgmtError - */ -tsapi TSMgmtError TSEventSignalCbUnregister(char *event_name, TSEventSignalFunc func); - -/*--- TS Cache Inspector Operations --------------------------------------------*/ - -/* TSLookupFromCacheUrl - * Function takes an url and an 'info' buffer as input, - * lookups cache information of the url and saves the - * cache info to the info buffer - */ -tsapi TSMgmtError TSLookupFromCacheUrl(TSString url, TSString *info); - -/* TSLookupFromCacheUrlRegex - * Function takes a string in a regex form and returns - * a list of urls that match the regex - ********************************************************/ - -tsapi TSMgmtError TSLookupFromCacheUrlRegex(TSString url_regex, TSString *list); - -/* TSDeleteFromCacheUrl - * Function takes an url and an 'info' buffer as input, - * deletes the url from cache if it's in the cache and - * returns the status of deletion - ********************************************************/ - -tsapi TSMgmtError TSDeleteFromCacheUrl(TSString url, TSString *info); - -/* TSDeleteFromCacheUrlRegex - * Function takes a string in a regex form and returns - * a list of urls deleted from cache - ********************************************************/ - -tsapi TSMgmtError TSDeleteFromCacheUrlRegex(TSString url_regex, TSString *list); - -/* TSInvalidateFromCacheUrlRegex - * Function takes a string in a regex form and returns - * a list of urls invalidated from cache - ********************************************************/ - -tsapi TSMgmtError TSInvalidateFromCacheUrlRegex(TSString url_regex, TSString *list); #ifdef __cplusplus } diff --git a/mgmt2/config/AddConfigFilesHere.cc b/mgmt/config/AddConfigFilesHere.cc similarity index 100% rename from mgmt2/config/AddConfigFilesHere.cc rename to mgmt/config/AddConfigFilesHere.cc diff --git a/mgmt2/config/FileManager.cc b/mgmt/config/FileManager.cc similarity index 99% rename from mgmt2/config/FileManager.cc rename to mgmt/config/FileManager.cc index 4bb6aa9a378..a28d5dbf5e5 100644 --- a/mgmt2/config/FileManager.cc +++ b/mgmt/config/FileManager.cc @@ -29,7 +29,6 @@ #include "tscore/ink_platform.h" #include "tscore/ink_file.h" -#include "ConfigManager.h" #include "records/P_RecCore.h" #include "tscore/Diags.h" #include "tscore/Filenames.h" diff --git a/mgmt2/config/FileManager.h b/mgmt/config/FileManager.h similarity index 100% rename from mgmt2/config/FileManager.h rename to mgmt/config/FileManager.h diff --git a/mgmt2/config/Makefile.am b/mgmt/config/Makefile.am similarity index 98% rename from mgmt2/config/Makefile.am rename to mgmt/config/Makefile.am index 7e4ab952d26..17e642d0738 100644 --- a/mgmt2/config/Makefile.am +++ b/mgmt/config/Makefile.am @@ -26,7 +26,6 @@ AM_CPPFLAGS += \ -I$(abs_top_srcdir)/lib/ \ -I$(abs_top_srcdir)/mgmt/rpc \ -I$(abs_top_srcdir)/mgmt/ \ - -I$(abs_top_srcdir)/mgmt2/ \ -I$(abs_top_srcdir)/mgmt/utils \ -I$(abs_top_srcdir)/proxy/ \ -I$(abs_top_srcdir)/proxy/http \ diff --git a/mgmt2/rpc/Makefile.am b/mgmt/rpc/Makefile.am similarity index 99% rename from mgmt2/rpc/Makefile.am rename to mgmt/rpc/Makefile.am index d4de43b0e3d..e2fc31144d0 100644 --- a/mgmt2/rpc/Makefile.am +++ b/mgmt/rpc/Makefile.am @@ -22,7 +22,7 @@ AM_CPPFLAGS += \ -I$(abs_top_srcdir)/iocore/utils \ -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/lib/ \ - -I$(abs_top_srcdir)/mgmt2/ \ + -I$(abs_top_srcdir)/mgmt/ \ $(TS_INCLUDES) \ @YAMLCPP_INCLUDES@ diff --git a/mgmt2/rpc/config/JsonRPCConfig.cc b/mgmt/rpc/config/JsonRPCConfig.cc similarity index 100% rename from mgmt2/rpc/config/JsonRPCConfig.cc rename to mgmt/rpc/config/JsonRPCConfig.cc diff --git a/mgmt2/rpc/config/JsonRPCConfig.h b/mgmt/rpc/config/JsonRPCConfig.h similarity index 100% rename from mgmt2/rpc/config/JsonRPCConfig.h rename to mgmt/rpc/config/JsonRPCConfig.h diff --git a/mgmt2/rpc/handlers/common/ErrorUtils.h b/mgmt/rpc/handlers/common/ErrorUtils.h similarity index 100% rename from mgmt2/rpc/handlers/common/ErrorUtils.h rename to mgmt/rpc/handlers/common/ErrorUtils.h diff --git a/mgmt2/rpc/handlers/common/RecordsUtils.cc b/mgmt/rpc/handlers/common/RecordsUtils.cc similarity index 100% rename from mgmt2/rpc/handlers/common/RecordsUtils.cc rename to mgmt/rpc/handlers/common/RecordsUtils.cc diff --git a/mgmt2/rpc/handlers/common/RecordsUtils.h b/mgmt/rpc/handlers/common/RecordsUtils.h similarity index 100% rename from mgmt2/rpc/handlers/common/RecordsUtils.h rename to mgmt/rpc/handlers/common/RecordsUtils.h diff --git a/mgmt2/rpc/handlers/common/Utils.h b/mgmt/rpc/handlers/common/Utils.h similarity index 100% rename from mgmt2/rpc/handlers/common/Utils.h rename to mgmt/rpc/handlers/common/Utils.h diff --git a/mgmt2/rpc/handlers/common/convert.h b/mgmt/rpc/handlers/common/convert.h similarity index 100% rename from mgmt2/rpc/handlers/common/convert.h rename to mgmt/rpc/handlers/common/convert.h diff --git a/mgmt2/rpc/handlers/config/Configuration.cc b/mgmt/rpc/handlers/config/Configuration.cc similarity index 100% rename from mgmt2/rpc/handlers/config/Configuration.cc rename to mgmt/rpc/handlers/config/Configuration.cc diff --git a/mgmt2/rpc/handlers/config/Configuration.h b/mgmt/rpc/handlers/config/Configuration.h similarity index 100% rename from mgmt2/rpc/handlers/config/Configuration.h rename to mgmt/rpc/handlers/config/Configuration.h diff --git a/mgmt2/rpc/handlers/plugins/Plugins.cc b/mgmt/rpc/handlers/plugins/Plugins.cc similarity index 100% rename from mgmt2/rpc/handlers/plugins/Plugins.cc rename to mgmt/rpc/handlers/plugins/Plugins.cc diff --git a/mgmt2/rpc/handlers/plugins/Plugins.h b/mgmt/rpc/handlers/plugins/Plugins.h similarity index 100% rename from mgmt2/rpc/handlers/plugins/Plugins.h rename to mgmt/rpc/handlers/plugins/Plugins.h diff --git a/mgmt2/rpc/handlers/records/Records.cc b/mgmt/rpc/handlers/records/Records.cc similarity index 100% rename from mgmt2/rpc/handlers/records/Records.cc rename to mgmt/rpc/handlers/records/Records.cc diff --git a/mgmt2/rpc/handlers/records/Records.h b/mgmt/rpc/handlers/records/Records.h similarity index 100% rename from mgmt2/rpc/handlers/records/Records.h rename to mgmt/rpc/handlers/records/Records.h diff --git a/mgmt2/rpc/handlers/server/Server.cc b/mgmt/rpc/handlers/server/Server.cc similarity index 100% rename from mgmt2/rpc/handlers/server/Server.cc rename to mgmt/rpc/handlers/server/Server.cc diff --git a/mgmt2/rpc/handlers/server/Server.h b/mgmt/rpc/handlers/server/Server.h similarity index 100% rename from mgmt2/rpc/handlers/server/Server.h rename to mgmt/rpc/handlers/server/Server.h diff --git a/mgmt2/rpc/handlers/storage/Storage.cc b/mgmt/rpc/handlers/storage/Storage.cc similarity index 100% rename from mgmt2/rpc/handlers/storage/Storage.cc rename to mgmt/rpc/handlers/storage/Storage.cc diff --git a/mgmt2/rpc/handlers/storage/Storage.h b/mgmt/rpc/handlers/storage/Storage.h similarity index 100% rename from mgmt2/rpc/handlers/storage/Storage.h rename to mgmt/rpc/handlers/storage/Storage.h diff --git a/mgmt2/rpc/jsonrpc/Context.cc b/mgmt/rpc/jsonrpc/Context.cc similarity index 100% rename from mgmt2/rpc/jsonrpc/Context.cc rename to mgmt/rpc/jsonrpc/Context.cc diff --git a/mgmt2/rpc/jsonrpc/Context.h b/mgmt/rpc/jsonrpc/Context.h similarity index 100% rename from mgmt2/rpc/jsonrpc/Context.h rename to mgmt/rpc/jsonrpc/Context.h diff --git a/mgmt2/rpc/jsonrpc/Defs.h b/mgmt/rpc/jsonrpc/Defs.h similarity index 100% rename from mgmt2/rpc/jsonrpc/Defs.h rename to mgmt/rpc/jsonrpc/Defs.h diff --git a/mgmt2/rpc/jsonrpc/JsonRPC.h b/mgmt/rpc/jsonrpc/JsonRPC.h similarity index 100% rename from mgmt2/rpc/jsonrpc/JsonRPC.h rename to mgmt/rpc/jsonrpc/JsonRPC.h diff --git a/mgmt2/rpc/jsonrpc/JsonRPCManager.cc b/mgmt/rpc/jsonrpc/JsonRPCManager.cc similarity index 100% rename from mgmt2/rpc/jsonrpc/JsonRPCManager.cc rename to mgmt/rpc/jsonrpc/JsonRPCManager.cc diff --git a/mgmt2/rpc/jsonrpc/JsonRPCManager.h b/mgmt/rpc/jsonrpc/JsonRPCManager.h similarity index 100% rename from mgmt2/rpc/jsonrpc/JsonRPCManager.h rename to mgmt/rpc/jsonrpc/JsonRPCManager.h diff --git a/mgmt2/rpc/jsonrpc/error/RPCError.cc b/mgmt/rpc/jsonrpc/error/RPCError.cc similarity index 100% rename from mgmt2/rpc/jsonrpc/error/RPCError.cc rename to mgmt/rpc/jsonrpc/error/RPCError.cc diff --git a/mgmt2/rpc/jsonrpc/error/RPCError.h b/mgmt/rpc/jsonrpc/error/RPCError.h similarity index 100% rename from mgmt2/rpc/jsonrpc/error/RPCError.h rename to mgmt/rpc/jsonrpc/error/RPCError.h diff --git a/mgmt2/rpc/jsonrpc/json/YAMLCodec.h b/mgmt/rpc/jsonrpc/json/YAMLCodec.h similarity index 100% rename from mgmt2/rpc/jsonrpc/json/YAMLCodec.h rename to mgmt/rpc/jsonrpc/json/YAMLCodec.h diff --git a/mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc b/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc similarity index 100% rename from mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc rename to mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc diff --git a/mgmt2/rpc/jsonrpc/unit_tests/unit_test_main.cc b/mgmt/rpc/jsonrpc/unit_tests/unit_test_main.cc similarity index 100% rename from mgmt2/rpc/jsonrpc/unit_tests/unit_test_main.cc rename to mgmt/rpc/jsonrpc/unit_tests/unit_test_main.cc diff --git a/mgmt2/rpc/schema/admin_lookup_records_params_schema.json b/mgmt/rpc/schema/admin_lookup_records_params_schema.json similarity index 100% rename from mgmt2/rpc/schema/admin_lookup_records_params_schema.json rename to mgmt/rpc/schema/admin_lookup_records_params_schema.json diff --git a/mgmt2/rpc/schema/jsonrpc_request_schema.json b/mgmt/rpc/schema/jsonrpc_request_schema.json similarity index 100% rename from mgmt2/rpc/schema/jsonrpc_request_schema.json rename to mgmt/rpc/schema/jsonrpc_request_schema.json diff --git a/mgmt2/rpc/schema/jsonrpc_response_schema.json b/mgmt/rpc/schema/jsonrpc_response_schema.json similarity index 100% rename from mgmt2/rpc/schema/jsonrpc_response_schema.json rename to mgmt/rpc/schema/jsonrpc_response_schema.json diff --git a/mgmt2/rpc/schema/success_response_schema.json b/mgmt/rpc/schema/success_response_schema.json similarity index 100% rename from mgmt2/rpc/schema/success_response_schema.json rename to mgmt/rpc/schema/success_response_schema.json diff --git a/mgmt2/rpc/server/CommBase.cc b/mgmt/rpc/server/CommBase.cc similarity index 100% rename from mgmt2/rpc/server/CommBase.cc rename to mgmt/rpc/server/CommBase.cc diff --git a/mgmt2/rpc/server/CommBase.h b/mgmt/rpc/server/CommBase.h similarity index 100% rename from mgmt2/rpc/server/CommBase.h rename to mgmt/rpc/server/CommBase.h diff --git a/mgmt2/rpc/server/IPCSocketServer.cc b/mgmt/rpc/server/IPCSocketServer.cc similarity index 100% rename from mgmt2/rpc/server/IPCSocketServer.cc rename to mgmt/rpc/server/IPCSocketServer.cc diff --git a/mgmt2/rpc/server/IPCSocketServer.h b/mgmt/rpc/server/IPCSocketServer.h similarity index 100% rename from mgmt2/rpc/server/IPCSocketServer.h rename to mgmt/rpc/server/IPCSocketServer.h diff --git a/mgmt2/rpc/server/RPCServer.cc b/mgmt/rpc/server/RPCServer.cc similarity index 100% rename from mgmt2/rpc/server/RPCServer.cc rename to mgmt/rpc/server/RPCServer.cc diff --git a/mgmt2/rpc/server/RPCServer.h b/mgmt/rpc/server/RPCServer.h similarity index 100% rename from mgmt2/rpc/server/RPCServer.h rename to mgmt/rpc/server/RPCServer.h diff --git a/mgmt2/rpc/server/unit_tests/test_rpcserver.cc b/mgmt/rpc/server/unit_tests/test_rpcserver.cc similarity index 100% rename from mgmt2/rpc/server/unit_tests/test_rpcserver.cc rename to mgmt/rpc/server/unit_tests/test_rpcserver.cc diff --git a/mgmt2/rpc/server/unit_tests/unit_test_main.cc b/mgmt/rpc/server/unit_tests/unit_test_main.cc similarity index 100% rename from mgmt2/rpc/server/unit_tests/unit_test_main.cc rename to mgmt/rpc/server/unit_tests/unit_test_main.cc diff --git a/mgmt/utils/Makefile.am b/mgmt/utils/Makefile.am index 610d1fda3f6..30702ca7ca7 100644 --- a/mgmt/utils/Makefile.am +++ b/mgmt/utils/Makefile.am @@ -37,8 +37,6 @@ check_PROGRAMS = test_mgmt_utils TESTS = $(check_PROGRAMS) libutils_COMMON = \ - MgmtMarshall.cc \ - MgmtMarshall.h \ MgmtSocket.cc \ MgmtSocket.h \ MgmtUtils.cc \ @@ -47,12 +45,10 @@ libutils_COMMON = \ libutils_lm_la_SOURCES = \ $(libutils_COMMON) \ ExpandingArray.cc \ - ExpandingArray.h \ - MgmtLocalCleanup.cc + ExpandingArray.h libutils_p_la_SOURCES = \ - $(libutils_COMMON) \ - MgmtProcessCleanup.cc + $(libutils_COMMON) test_mgmt_utils_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include @@ -61,8 +57,7 @@ test_mgmt_utils_LDFLAGS = \ @OPENSSL_LDFLAGS@ test_mgmt_utils_SOURCES = \ - unit_tests/unit_test_main.cc \ - unit_tests/test_marshall.cc + unit_tests/unit_test_main.cc test_mgmt_utils_LDADD = \ libutils_p.la \ diff --git a/mgmt/utils/MgmtLocalCleanup.cc b/mgmt/utils/MgmtLocalCleanup.cc deleted file mode 100644 index c57e34347e3..00000000000 --- a/mgmt/utils/MgmtLocalCleanup.cc +++ /dev/null @@ -1,33 +0,0 @@ -/** @file - - Management cleanup for the local manager. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "MgmtUtils.h" -#include "LocalManager.h" - -void -mgmt_cleanup() -{ - if (lmgmt != nullptr) { - lmgmt->mgmtShutdown(); - } -} diff --git a/mgmt/utils/MgmtMarshall.cc b/mgmt/utils/MgmtMarshall.cc deleted file mode 100644 index 61d6f4e86dd..00000000000 --- a/mgmt/utils/MgmtMarshall.cc +++ /dev/null @@ -1,532 +0,0 @@ -/** @file - - Management packet marshalling. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/ink_memory.h" -#include "tscore/ink_assert.h" -#include "MgmtMarshall.h" -#include "MgmtSocket.h" - -union MgmtMarshallAnyPtr { - MgmtMarshallInt *m_int; - MgmtMarshallLong *m_long; - MgmtMarshallString *m_string; - MgmtMarshallData *m_data; - void *m_void; -}; - -static char *empty = const_cast(""); - -static bool -data_is_nul_terminated(const MgmtMarshallData *data) -{ - const char *str = static_cast(data->ptr); - - ink_assert(str); - if (str[data->len - 1] != '\0') { - return false; - } - - if (strlen(str) != (data->len - 1)) { - return false; - } - - return true; -} - -static ssize_t -socket_read_bytes(int fd, void *buf, size_t needed) -{ - size_t nread = 0; - - // makes sure the descriptor is readable - if (mgmt_read_timeout(fd, MAX_TIME_WAIT, 0) <= 0) { - return -1; - } - - while (needed > nread) { - ssize_t ret = read(fd, buf, needed - nread); - - if (ret < 0) { - if (mgmt_transient_error()) { - continue; - } else { - return -1; - } - } - - if (ret == 0) { - // End of file before reading the remaining bytes. - errno = ECONNRESET; - return -1; - } - - buf = static_cast(buf) + ret; - nread += ret; - } - - return nread; -} - -static ssize_t -socket_write_bytes(int fd, const void *buf, ssize_t bytes) -{ - ssize_t nwritten = 0; - - // makes sure the descriptor is writable - if (mgmt_write_timeout(fd, MAX_TIME_WAIT, 0) <= 0) { - return -1; - } - - // write until we fulfill the number - while (nwritten < bytes) { - ssize_t ret = write(fd, buf, bytes - nwritten); - if (ret < 0) { - if (mgmt_transient_error()) { - continue; - } - return -1; - } - - buf = (uint8_t *)buf + ret; - nwritten += ret; - } - - return nwritten; -} - -static ssize_t -socket_write_buffer(int fd, const MgmtMarshallData *data) -{ - ssize_t nwrite; - - nwrite = socket_write_bytes(fd, &(data->len), 4); - if (nwrite != 4) { - goto fail; - } - - if (data->len) { - nwrite = socket_write_bytes(fd, data->ptr, data->len); - if (nwrite != static_cast(data->len)) { - goto fail; - } - } - - return data->len + 4; - -fail: - return -1; -} - -static ssize_t -socket_read_buffer(int fd, MgmtMarshallData *data) -{ - ssize_t nread; - - ink_zero(*data); - - nread = socket_read_bytes(fd, &(data->len), 4); - if (nread != 4) { - goto fail; - } - - if (data->len) { - data->ptr = ats_malloc(data->len); - nread = socket_read_bytes(fd, data->ptr, data->len); - if (nread != static_cast(data->len)) { - goto fail; - } - } - - return data->len + 4; - -fail: - ats_free(data->ptr); - ink_zero(*data); - return -1; -} - -static ssize_t -buffer_read_buffer(const uint8_t *buf, size_t len, MgmtMarshallData *data) -{ - ink_zero(*data); - - if (len < 4) { - goto fail; - } - - memcpy(&(data->len), buf, 4); - buf += 4; - len -= 4; - - if (len < data->len) { - goto fail; - } - - if (data->len) { - data->ptr = ats_malloc(data->len); - memcpy(data->ptr, buf, data->len); - } - - return data->len + 4; - -fail: - ats_free(data->ptr); - ink_zero(*data); - return -1; -} - -MgmtMarshallInt -mgmt_message_length(const MgmtMarshallType *fields, unsigned count, ...) -{ - MgmtMarshallInt length; - va_list ap; - - va_start(ap, count); - length = mgmt_message_length_v(fields, count, ap); - va_end(ap); - - return length; -} - -MgmtMarshallInt -mgmt_message_length_v(const MgmtMarshallType *fields, unsigned count, va_list ap) -{ - MgmtMarshallAnyPtr ptr; - MgmtMarshallInt nbytes = 0; - - for (unsigned n = 0; n < count; ++n) { - switch (fields[n]) { - case MGMT_MARSHALL_INT: - ptr.m_int = va_arg(ap, MgmtMarshallInt *); - nbytes += 4; - break; - case MGMT_MARSHALL_LONG: - ptr.m_long = va_arg(ap, MgmtMarshallLong *); - nbytes += 8; - break; - case MGMT_MARSHALL_STRING: - nbytes += 4; - ptr.m_string = va_arg(ap, MgmtMarshallString *); - if (*ptr.m_string == nullptr) { - ptr.m_string = ∅ - } - nbytes += strlen(*ptr.m_string) + 1; - break; - case MGMT_MARSHALL_DATA: - nbytes += 4; - ptr.m_data = va_arg(ap, MgmtMarshallData *); - nbytes += ptr.m_data->len; - break; - default: - errno = EINVAL; - return -1; - } - } - - return nbytes; -} - -ssize_t -mgmt_message_write(int fd, const MgmtMarshallType *fields, unsigned count, ...) -{ - ssize_t nbytes; - va_list ap; - - va_start(ap, count); - nbytes = mgmt_message_write_v(fd, fields, count, ap); - va_end(ap); - - return nbytes; -} - -ssize_t -mgmt_message_write_v(int fd, const MgmtMarshallType *fields, unsigned count, va_list ap) -{ - MgmtMarshallAnyPtr ptr; - ssize_t nbytes = 0; - - for (unsigned n = 0; n < count; ++n) { - ssize_t nwritten = 0; - - switch (fields[n]) { - case MGMT_MARSHALL_INT: - ptr.m_int = va_arg(ap, MgmtMarshallInt *); - nwritten = socket_write_bytes(fd, ptr.m_void, 4); - break; - case MGMT_MARSHALL_LONG: - ptr.m_long = va_arg(ap, MgmtMarshallLong *); - nwritten = socket_write_bytes(fd, ptr.m_void, 8); - break; - case MGMT_MARSHALL_STRING: { - MgmtMarshallData data; - ptr.m_string = va_arg(ap, MgmtMarshallString *); - if (*ptr.m_string == nullptr) { - ptr.m_string = ∅ - } - data.ptr = *ptr.m_string; - data.len = strlen(*ptr.m_string) + 1; - nwritten = socket_write_buffer(fd, &data); - break; - } - case MGMT_MARSHALL_DATA: - ptr.m_data = va_arg(ap, MgmtMarshallData *); - nwritten = socket_write_buffer(fd, ptr.m_data); - break; - default: - errno = EINVAL; - return -1; - } - - if (nwritten == -1) { - return -1; - } - - nbytes += nwritten; - } - - return nbytes; -} - -ssize_t -mgmt_message_read(int fd, const MgmtMarshallType *fields, unsigned count, ...) -{ - ssize_t nbytes; - va_list ap; - - va_start(ap, count); - nbytes = mgmt_message_read_v(fd, fields, count, ap); - va_end(ap); - - return nbytes; -} - -ssize_t -mgmt_message_read_v(int fd, const MgmtMarshallType *fields, unsigned count, va_list ap) -{ - MgmtMarshallAnyPtr ptr; - ssize_t nbytes = 0; - - for (unsigned n = 0; n < count; ++n) { - ssize_t nread; - - switch (fields[n]) { - case MGMT_MARSHALL_INT: - ptr.m_int = va_arg(ap, MgmtMarshallInt *); - nread = socket_read_bytes(fd, ptr.m_void, 4); - break; - case MGMT_MARSHALL_LONG: - ptr.m_long = va_arg(ap, MgmtMarshallLong *); - nread = socket_read_bytes(fd, ptr.m_void, 8); - break; - case MGMT_MARSHALL_STRING: { - MgmtMarshallData data; - - nread = socket_read_buffer(fd, &data); - if (nread == -1) { - break; - } - - ink_assert(data_is_nul_terminated(&data)); - ptr.m_string = va_arg(ap, MgmtMarshallString *); - *ptr.m_string = static_cast(data.ptr); - break; - } - case MGMT_MARSHALL_DATA: - ptr.m_data = va_arg(ap, MgmtMarshallData *); - nread = socket_read_buffer(fd, ptr.m_data); - break; - default: - errno = EINVAL; - return -1; - } - - if (nread == -1) { - return -1; - } - - nbytes += nread; - } - - return nbytes; -} - -ssize_t -mgmt_message_marshall(void *buf, size_t remain, const MgmtMarshallType *fields, unsigned count, ...) -{ - ssize_t nbytes = 0; - va_list ap; - - va_start(ap, count); - nbytes = mgmt_message_marshall_v(buf, remain, fields, count, ap); - va_end(ap); - - return nbytes; -} - -ssize_t -mgmt_message_marshall_v(void *buf, size_t remain, const MgmtMarshallType *fields, unsigned count, va_list ap) -{ - MgmtMarshallAnyPtr ptr; - ssize_t nbytes = 0; - - for (unsigned n = 0; n < count; ++n) { - ssize_t nwritten = 0; - - switch (fields[n]) { - case MGMT_MARSHALL_INT: - if (remain < 4) { - goto nospace; - } - ptr.m_int = va_arg(ap, MgmtMarshallInt *); - memcpy(buf, ptr.m_int, 4); - nwritten = 4; - break; - case MGMT_MARSHALL_LONG: - if (remain < 8) { - goto nospace; - } - ptr.m_long = va_arg(ap, MgmtMarshallLong *); - memcpy(buf, ptr.m_long, 8); - nwritten = 8; - break; - case MGMT_MARSHALL_STRING: { - MgmtMarshallData data; - ptr.m_string = va_arg(ap, MgmtMarshallString *); - if (*ptr.m_string == nullptr) { - ptr.m_string = ∅ - } - - data.ptr = *ptr.m_string; - data.len = strlen(*ptr.m_string) + 1; - - if (remain < (4 + data.len)) { - goto nospace; - } - - memcpy(buf, &data.len, 4); - memcpy(static_cast(buf) + 4, data.ptr, data.len); - nwritten = 4 + data.len; - break; - } - case MGMT_MARSHALL_DATA: - ptr.m_data = va_arg(ap, MgmtMarshallData *); - if (remain < (4 + ptr.m_data->len)) { - goto nospace; - } - memcpy(buf, &(ptr.m_data->len), 4); - memcpy(static_cast(buf) + 4, ptr.m_data->ptr, ptr.m_data->len); - nwritten = 4 + ptr.m_data->len; - break; - default: - errno = EINVAL; - return -1; - } - - nbytes += nwritten; - buf = static_cast(buf) + nwritten; - remain -= nwritten; - } - - return nbytes; - -nospace: - errno = EMSGSIZE; - return -1; -} - -ssize_t -mgmt_message_parse(const void *buf, size_t len, const MgmtMarshallType *fields, unsigned count, ...) -{ - MgmtMarshallInt nbytes = 0; - va_list ap; - - va_start(ap, count); - nbytes = mgmt_message_parse_v(buf, len, fields, count, ap); - va_end(ap); - - return nbytes; -} - -ssize_t -mgmt_message_parse_v(const void *buf, size_t len, const MgmtMarshallType *fields, unsigned count, va_list ap) -{ - MgmtMarshallAnyPtr ptr; - ssize_t nbytes = 0; - - for (unsigned n = 0; n < count; ++n) { - ssize_t nread; - - switch (fields[n]) { - case MGMT_MARSHALL_INT: - if (len < 4) { - goto nospace; - } - ptr.m_int = va_arg(ap, MgmtMarshallInt *); - memcpy(ptr.m_int, buf, 4); - nread = 4; - break; - case MGMT_MARSHALL_LONG: - if (len < 8) { - goto nospace; - } - ptr.m_long = va_arg(ap, MgmtMarshallLong *); - memcpy(ptr.m_int, buf, 8); - nread = 8; - break; - case MGMT_MARSHALL_STRING: { - MgmtMarshallData data; - nread = buffer_read_buffer(static_cast(buf), len, &data); - if (nread == -1) { - goto nospace; - } - - ink_assert(data_is_nul_terminated(&data)); - - ptr.m_string = va_arg(ap, MgmtMarshallString *); - *ptr.m_string = static_cast(data.ptr); - break; - } - case MGMT_MARSHALL_DATA: - ptr.m_data = va_arg(ap, MgmtMarshallData *); - nread = buffer_read_buffer(static_cast(buf), len, ptr.m_data); - if (nread == -1) { - goto nospace; - } - break; - default: - errno = EINVAL; - return -1; - } - - nbytes += nread; - buf = (uint8_t *)buf + nread; - len -= nread; - } - - return nbytes; - -nospace: - errno = EMSGSIZE; - return -1; -} diff --git a/mgmt/utils/MgmtMarshall.h b/mgmt/utils/MgmtMarshall.h deleted file mode 100644 index 91bc257bd69..00000000000 --- a/mgmt/utils/MgmtMarshall.h +++ /dev/null @@ -1,77 +0,0 @@ -/** @file - - Management packet marshalling. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include - -#define MAX_TIME_WAIT 60 // num secs for a timeout on a select call (remote only) - -// Simple message marshalling. -// -// MGMT_MARSHALL_INT -// Wire size is 4 bytes signed. This type is used for enum and boolean values, as well as embedded lengths and general -// integer values. -// -// MGMT_MARSHALL_LONG -// Wire size is 8 bytes signed. -// -// MGMT_MARSHALL_STRING -// Wire size is a 4 byte length followed by N bytes. The trailing NUL is always sent and NULL strings are sent as empty -// strings. This means that the minimum wire size for a string is 5 bytes (4 byte length + NUL byte). The unmarshalled -// string point is guaranteed to be non-NULL. -// -// MGMT_MARSHALL_DATA -// Wire size is 4 byte length followed by N data bytes. If the length is 0, no subsequent bytes are sent. In this case -// the unmarshalled data pointer is guaranteed to be NULL. -// -enum MgmtMarshallType { - MGMT_MARSHALL_INT, // int32_t - MGMT_MARSHALL_LONG, // int64_t - MGMT_MARSHALL_STRING, // NUL-terminated string - MGMT_MARSHALL_DATA // byte buffer -}; - -typedef int32_t MgmtMarshallInt; -typedef int64_t MgmtMarshallLong; -typedef char *MgmtMarshallString; - -struct MgmtMarshallData { - void *ptr; - size_t len; -}; - -MgmtMarshallInt mgmt_message_length(const MgmtMarshallType *fields, unsigned count, ...); -MgmtMarshallInt mgmt_message_length_v(const MgmtMarshallType *fields, unsigned count, va_list ap); - -ssize_t mgmt_message_read(int fd, const MgmtMarshallType *fields, unsigned count, ...); -ssize_t mgmt_message_read_v(int fd, const MgmtMarshallType *fields, unsigned count, va_list ap); - -ssize_t mgmt_message_write(int fd, const MgmtMarshallType *fields, unsigned count, ...); -ssize_t mgmt_message_write_v(int fd, const MgmtMarshallType *fields, unsigned count, va_list ap); - -ssize_t mgmt_message_parse(const void *ptr, size_t len, const MgmtMarshallType *fields, unsigned count, ...); -ssize_t mgmt_message_parse_v(const void *ptr, size_t len, const MgmtMarshallType *fields, unsigned count, va_list ap); - -ssize_t mgmt_message_marshall(void *ptr, size_t len, const MgmtMarshallType *fields, unsigned count, ...); -ssize_t mgmt_message_marshall_v(void *ptr, size_t len, const MgmtMarshallType *fields, unsigned count, va_list ap); diff --git a/mgmt/utils/MgmtProcessCleanup.cc b/mgmt/utils/MgmtProcessCleanup.cc deleted file mode 100644 index e46e2be562f..00000000000 --- a/mgmt/utils/MgmtProcessCleanup.cc +++ /dev/null @@ -1,30 +0,0 @@ -/** @file - - Management cleanup for the process manager. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "MgmtUtils.h" - -void -mgmt_cleanup() -{ - // No cleanup to do with a process manager -} diff --git a/mgmt/utils/MgmtUtils.cc b/mgmt/utils/MgmtUtils.cc index c7eb7b572a6..f073660d7c3 100644 --- a/mgmt/utils/MgmtUtils.cc +++ b/mgmt/utils/MgmtUtils.cc @@ -26,8 +26,6 @@ #include "MgmtSocket.h" #include "tscore/Diags.h" -#include "LocalManager.h" - static int use_syslog = 0; /* mgmt_use_syslog() @@ -221,112 +219,14 @@ mgmt_write_pipe(int fd, char *buf, int bytes_to_write) return bytes_written; } -void -mgmt_log(const char *message_format, ...) -{ - va_list ap; - char extended_format[4096], message[4096]; - - va_start(ap, message_format); - if (diags()) { - NoteV(message_format, ap); - } else { - if (use_syslog) { - snprintf(extended_format, sizeof(extended_format), "log ==> %s", message_format); - vsprintf(message, extended_format, ap); - syslog(LOG_WARNING, "%s", message); - } else { - snprintf(extended_format, sizeof(extended_format), "[E. Mgmt] log ==> %s", message_format); - vsprintf(message, extended_format, ap); - ink_assert(fwrite(message, strlen(message), 1, stderr) == 1); - } - } - - va_end(ap); - return; -} /* End mgmt_log */ - -void -mgmt_elog(const int lerrno, const char *message_format, ...) -{ - va_list ap; - char extended_format[4096], message[4096]; - - va_start(ap, message_format); - - if (diags()) { - ErrorV(message_format, ap); - if (lerrno != 0) { - Error("last system error %d: %s", lerrno, strerror(lerrno)); - } - } else { - if (use_syslog) { - snprintf(extended_format, sizeof(extended_format), "ERROR ==> %s", message_format); - vsprintf(message, extended_format, ap); - syslog(LOG_ERR, "%s", message); - if (lerrno != 0) { - syslog(LOG_ERR, " (last system error %d: %s)", lerrno, strerror(lerrno)); - } - } else { - snprintf(extended_format, sizeof(extended_format), "Manager ERROR: %s", message_format); - vsprintf(message, extended_format, ap); - ink_assert(fwrite(message, strlen(message), 1, stderr) == 1); - if (lerrno != 0) { - snprintf(message, sizeof(message), "(last system error %d: %s)", lerrno, strerror(lerrno)); - ink_assert(fwrite(message, strlen(message), 1, stderr) == 1); - } - } - } - va_end(ap); - return; -} /* End mgmt_elog */ - -void -mgmt_fatal(const int lerrno, const char *message_format, ...) -{ - va_list ap; - - va_start(ap, message_format); - - if (diags()) { - if (lerrno != 0) { - Error("last system error %d: %s", lerrno, strerror(lerrno)); - } - - FatalV(message_format, ap); - } else { - char extended_format[4096], message[4096]; - snprintf(extended_format, sizeof(extended_format), "FATAL ==> %s", message_format); - vsprintf(message, extended_format, ap); - - ink_assert(fwrite(message, strlen(message), 1, stderr) == 1); - - if (use_syslog) { - syslog(LOG_ERR, "%s", message); - } - - if (lerrno != 0) { - fprintf(stderr, "[E. Mgmt] last system error %d: %s", lerrno, strerror(lerrno)); - - if (use_syslog) { - syslog(LOG_ERR, " (last system error %d: %s)", lerrno, strerror(lerrno)); - } - } - } - - va_end(ap); - - mgmt_cleanup(); - ::exit(1); -} /* End mgmt_fatal */ - static inline int get_interface_mtu(int sock_fd, struct ifreq *ifr) { if (ioctl(sock_fd, SIOCGIFMTU, ifr) < 0) { - mgmt_log("[getAddrForIntr] Unable to obtain MTU for " - "interface '%s'", - ifr->ifr_name); + Debug("mgmt_utils", + "[getAddrForIntr] Unable to obtain MTU for " + "interface '%s'", + ifr->ifr_name); return 0; } else { #if defined(solaris) || defined(hpux) @@ -357,7 +257,7 @@ mgmt_getAddrForIntr(char *intrName, sockaddr *addr, int *mtu) memset(addr, 0, sizeof(struct in_addr)); if ((fakeSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - mgmt_fatal(errno, "[getAddrForIntr] Unable to create socket\n"); + Fatal("[getAddrForIntr] Unable to create socket: %d\n", errno); } // INKqa06739 // Fetch the list of network interfaces @@ -372,7 +272,7 @@ mgmt_getAddrForIntr(char *intrName, sockaddr *addr, int *mtu) ifc.ifc_buf = ifbuf; if (ioctl(fakeSocket, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) { - mgmt_fatal(errno, "[getAddrForIntr] Unable to read network interface configuration\n"); + Fatal("[getAddrForIntr] Unable to read network interface configuration: %d\n", errno); } } else { if (ifc.ifc_len == lastlen) { @@ -391,7 +291,7 @@ mgmt_getAddrForIntr(char *intrName, sockaddr *addr, int *mtu) if (ifr->ifr_addr.sa_family == AF_INET && strcmp(ifr->ifr_name, intrName) == 0) { // Get the address of the interface if (ioctl(fakeSocket, SIOCGIFADDR, reinterpret_cast(ifr)) < 0) { - mgmt_log("[getAddrForIntr] Unable obtain address for network interface %s\n", intrName); + Debug("mgmt_utils", "[getAddrForIntr] Unable obtain address for network interface %s\n", intrName); } else { // Only look at the address if it an internet address if (ifr->ifr_ifru.ifru_addr.sa_family == AF_INET) { @@ -404,7 +304,7 @@ mgmt_getAddrForIntr(char *intrName, sockaddr *addr, int *mtu) break; } else { - mgmt_log("[getAddrForIntr] Interface %s is not configured for IP.\n", intrName); + Debug("mgmt_utils", "[getAddrForIntr] Interface %s is not configured for IP.\n", intrName); } } } diff --git a/mgmt/utils/MgmtUtils.h b/mgmt/utils/MgmtUtils.h index 15721f903cd..9c658b813ea 100644 --- a/mgmt/utils/MgmtUtils.h +++ b/mgmt/utils/MgmtUtils.h @@ -50,12 +50,6 @@ void mgmt_cleanup(); struct in_addr *mgmt_sortipaddrs(int num, struct in_addr **list); bool mgmt_getAddrForIntr(char *intrName, sockaddr *addr, int *mtu = nullptr); -/* the following functions are all DEPRECATED. The Diags - interface should be used exclusively in the future */ -void mgmt_log(const char *message_format, ...); -void mgmt_elog(const int lerrno, const char *message_format, ...); -void mgmt_fatal(const int lerrno, const char *message_format, ...) TS_NORETURN; - void mgmt_sleep_sec(int); void mgmt_sleep_msec(int); diff --git a/mgmt/utils/unit_tests/test_marshall.cc b/mgmt/utils/unit_tests/test_marshall.cc deleted file mode 100644 index b2bef2db069..00000000000 --- a/mgmt/utils/unit_tests/test_marshall.cc +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -namespace -{ -bool -check_eq(char const *expr_as_str, MgmtMarshallInt rcvd, MgmtMarshallInt len) -{ - if (rcvd == len) { - return true; - } - std::cout << expr_as_str << " returned length " << rcvd << ", expected " << len << '\n'; - return false; -} - -#define CHECK_EQ(expr, len) CHECK(check_eq(#expr, static_cast(expr), static_cast(len))) - -template -bool -check_value(V_t value, E_t expect) -{ - if (sizeof(V_t) > sizeof(E_t) ? (value == static_cast(expect)) : (static_cast(value) == expect)) { - return true; - } - std::cout << "received marshalled value " << value << ", expected " << expect << '\n'; - return false; -} - -bool -check_value(void *value, void *expect) -{ - if (value == expect) { - return true; - } - std::cout << std::hex << "received marshalled value " << reinterpret_cast(value) << ", expected " - << reinterpret_cast(expect) << '\n' - << std::dec; - return false; -} - -#define CHECK_VALUE(value, expect) CHECK(check_value((value), (expect))) - -bool -check_str(char const *value, char const *expect) -{ - if (!value) { - value = ""; - } - if (std::string_view(value) == expect) { - return true; - } - std::cout << "received marshalled value " << value << ", expected " << expect << '\n'; - return false; -} - -#define CHECK_STR(value, expect) CHECK(check_str((value), (expect))) - -const MgmtMarshallType inval[] = {static_cast(1568)}; - -const MgmtMarshallType ifields[] = {MGMT_MARSHALL_INT, MGMT_MARSHALL_LONG}; - -const MgmtMarshallType sfields[] = { - MGMT_MARSHALL_STRING, -}; - -const MgmtMarshallType dfields[] = { - MGMT_MARSHALL_DATA, -}; - -const MgmtMarshallType afields[] = { - MGMT_MARSHALL_DATA, MGMT_MARSHALL_INT, MGMT_MARSHALL_LONG, MGMT_MARSHALL_STRING, MGMT_MARSHALL_LONG, MGMT_MARSHALL_LONG, -}; - -const char alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789"; -const char *stringvals[] = {nullptr, "", "randomstring"}; - -bool -errno_is_continue() -{ - return errno == EALREADY || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EAGAIN || mgmt_transient_error(); -} - -int -message_connect_channel(int listenfd, int clientfd, int serverport) -{ - // bool need_connect = true; - bool need_accept = true; - int serverfd = -1; - - struct sockaddr_in in; - - ink_zero(in); - in.sin_family = AF_INET; - in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - in.sin_port = htons(serverport); - - fcntl(clientfd, F_SETFL, O_NONBLOCK); - fcntl(listenfd, F_SETFL, O_NONBLOCK); - - connect(clientfd, reinterpret_cast(&in), sizeof(in)); - - while (need_accept) { - serverfd = accept(listenfd, nullptr, nullptr); - if (serverfd == -1) { - std::cout << "accepting, " << errno << ' ' << strerror(errno) << '\n'; - if (!errno_is_continue()) { - return -1; - } - ink_thr_yield(); - } else { - need_accept = false; - } - } - - return serverfd; -} - -int -message_listen(int &port) -{ - IpEndpoint sa; - socklen_t slen; - int fd; - - fd = mgmt_socket(AF_INET, SOCK_STREAM, 0); - if (fd >= 0) { - sa.setToAnyAddr(AF_INET); - if (bind(fd, &sa.sa, sizeof(sa.sin)) >= 0) { - slen = sizeof(sa); - if (getsockname(fd, &sa.sa, &slen) >= -1) { - port = ntohs(ats_ip_port_cast(&sa.sa)); - - listen(fd, 5); - - return fd; - } - } - close(fd); - } - return -1; -} - -} // end anonymous namespace - -TEST_CASE("MessageReadWriteA", "[mgmt_utils][msg_rd_wr_a]") -{ - int listenfd = -1; - int serverfd = -1; - int clientfd = -1; - int serverport = 0; - - MgmtMarshallInt mint = 0; - MgmtMarshallLong mlong = 0; - MgmtMarshallString mstring = nullptr; - MgmtMarshallData mdata = {nullptr, 0}; - - clientfd = mgmt_socket(AF_INET, SOCK_STREAM, 0); - listenfd = message_listen(serverport); - serverfd = message_connect_channel(listenfd, clientfd, serverport); - std::cout << "listenfd=" << listenfd << " clientfd=" << clientfd << " serverfd=" << serverfd << " port=" << serverport << '\n'; - - fcntl(clientfd, F_SETFL, O_NDELAY); - fcntl(serverfd, F_SETFL, O_NDELAY); - - mint = 99; - mlong = reinterpret_cast(&listenfd); - - // Check invalid Fd write. ToDo: Commented out, see TS-3052. - // CHECK_EQ(mgmt_message_write(FD_SETSIZE - 1, ifields, countof(ifields), &mint, &mlong), -1); - - CHECK_EQ(mgmt_message_write(clientfd, ifields, countof(ifields), &mint, &mlong), 12); - - mint = 0; - mlong = 0; - CHECK_EQ(mgmt_message_read(serverfd, ifields, countof(ifields), &mint, &mlong), 12); - CHECK_VALUE(mint, 99); - CHECK_VALUE(mlong, reinterpret_cast(&listenfd)); - - // Marshall a string. - for (unsigned i = 0; i < countof(stringvals); ++i) { - const char *s = stringvals[i]; - std::size_t len = 4 /* length */ + (s ? std::strlen(s) : 0) /* bytes */ + 1 /* NULL */; - - mstring = s ? ats_strdup(s) : nullptr; - CHECK_EQ(mgmt_message_write(clientfd, sfields, countof(sfields), &mstring), len); - ats_free(mstring); - mstring = nullptr; - - CHECK_EQ(mgmt_message_read(serverfd, sfields, countof(sfields), &mstring), len); - CHECK_STR(s, mstring); - ats_free(mstring); - mstring = nullptr; - } - - // Marshall data. - mdata.ptr = ats_strdup(alpha); - mdata.len = std::strlen(alpha); - CHECK_EQ(mgmt_message_write(clientfd, dfields, countof(dfields), &mdata), 4 + std::strlen(alpha)); - ats_free(mdata.ptr); - ink_zero(mdata); - - CHECK_EQ(mgmt_message_read(serverfd, dfields, countof(dfields), &mdata), 4 + std::strlen(alpha)); - CHECK_VALUE(mdata.len, std::strlen(alpha)); - if (std::memcmp(mdata.ptr, alpha, std::strlen(alpha)) != 0) { - std::cout << "unexpected mdata contents\n"; - CHECK(false); - } - ats_free(mdata.ptr); - ink_zero(mdata); - - close(clientfd); - close(listenfd); - close(serverfd); -} - -TEST_CASE("MessageMarshall", "[mgmt_utils][msg_marshall]") -{ - char msgbuf[4096]; - - MgmtMarshallInt mint = 0; - MgmtMarshallLong mlong = 0; - MgmtMarshallString mstring = nullptr; - MgmtMarshallData mdata = {nullptr, 0}; - - // Parse empty message. - CHECK_EQ(mgmt_message_parse(nullptr, 0, nullptr, 0), 0); - - // Marshall empty message. - CHECK_EQ(mgmt_message_marshall(nullptr, 0, nullptr, 0), 0); - - // Marshall some integral types. - mint = -156; - mlong = UINT32_MAX; - CHECK_EQ(mgmt_message_marshall(msgbuf, 1, ifields, countof(ifields), &mint, &mlong), -1); - CHECK_EQ(mgmt_message_marshall(msgbuf, sizeof(msgbuf), ifields, countof(ifields), &mint, &mlong), 12); - CHECK_EQ(mgmt_message_parse(msgbuf, 1, ifields, countof(ifields), &mint, &mlong), -1); - CHECK_EQ(mgmt_message_parse(msgbuf, sizeof(msgbuf), ifields, countof(ifields), &mint, &mlong), 12); - CHECK_VALUE(mint, -156); - CHECK_VALUE(mlong, static_cast(UINT32_MAX)); - - // Marshall a string. - for (unsigned i = 0; i < countof(stringvals); ++i) { - const char *s = stringvals[i]; - size_t len = 4 /* length */ + (s ? std::strlen(s) : 0) /* bytes */ + 1 /* NULL */; - - mstring = s ? ats_strdup(s) : nullptr; - CHECK_EQ(mgmt_message_marshall(msgbuf, 1, sfields, countof(sfields), &mstring), -1); - CHECK_EQ(mgmt_message_marshall(msgbuf, sizeof(msgbuf), sfields, countof(sfields), &mstring), len); - ats_free(mstring); - mstring = nullptr; - - CHECK_EQ(mgmt_message_parse(msgbuf, 1, sfields, countof(sfields), &mstring), -1); - CHECK_EQ(mgmt_message_parse(msgbuf, sizeof(msgbuf), sfields, countof(sfields), &mstring), len); - CHECK_STR(s, mstring); - ats_free(mstring); - mstring = nullptr; - } - - // Marshall data. - mdata.ptr = ats_strdup(alpha); - mdata.len = std::strlen(alpha); - CHECK_EQ(mgmt_message_marshall(msgbuf, 10, dfields, countof(dfields), &mdata), -1); - CHECK_EQ(mgmt_message_marshall(msgbuf, sizeof(msgbuf), dfields, countof(dfields), &mdata), 4 + std::strlen(alpha)); - ats_free(mdata.ptr); - ink_zero(mdata); - - CHECK_EQ(mgmt_message_parse(msgbuf, std::strlen(alpha), dfields, countof(dfields), &mdata), -1); - CHECK_EQ(mgmt_message_parse(msgbuf, std::strlen(alpha) + 4, dfields, countof(dfields), &mdata), 4 + std::strlen(alpha)); - CHECK_VALUE(mdata.len, std::strlen(alpha)); - if (std::memcmp(mdata.ptr, alpha, std::strlen(alpha)) != 0) { - std::cout << "unexpected mdata contents\n"; - CHECK(false); - } - ats_free(mdata.ptr); - ink_zero(mdata); - - // Marshall empty data. - CHECK_EQ(mgmt_message_marshall(msgbuf, sizeof(msgbuf), dfields, countof(dfields), &mdata), 4); - - mdata.ptr = reinterpret_cast(99); - mdata.len = 1000; - CHECK_EQ(mgmt_message_parse(msgbuf, sizeof(msgbuf), dfields, countof(dfields), &mdata), 4); - CHECK_VALUE(mdata.ptr, static_cast(nullptr)); - CHECK_VALUE(mdata.len, 0); -} - -TEST_CASE("MessageLemgth", "[mgmt_utils][msg_len]") -{ - MgmtMarshallInt mint = 0; - MgmtMarshallLong mlong = 0; - MgmtMarshallString mstring = nullptr; - MgmtMarshallData mdata = {nullptr, 0}; - - // Check invalid marshall type. - CHECK_EQ(mgmt_message_length(inval, countof(inval), NULL), -1); - - // Check empty types array. - CHECK_EQ(mgmt_message_length(nullptr, 0), 0); - - CHECK_EQ(mgmt_message_length(ifields, countof(ifields), &mint, &mlong), 12); - - // string messages include a 4-byte length and the NULL - mstring = const_cast("foo"); - CHECK_EQ(mgmt_message_length(sfields, countof(sfields), &mstring), sizeof("foo") + 4); - - // NULL strings are the same as empty strings ... - mstring = nullptr; - CHECK_EQ(mgmt_message_length(sfields, countof(sfields), &mstring), 4 + 1); - mstring = const_cast(""); - CHECK_EQ(mgmt_message_length(sfields, countof(sfields), &mstring), 4 + 1); - - // data fields include a 4-byte length. We don't go looking at the data in this case. - mdata.len = 99; - mdata.ptr = nullptr; - CHECK_EQ(mgmt_message_length(dfields, countof(dfields), &mdata), 99 + 4); - - mstring = (char *)"all fields"; - mdata.len = 31; - CHECK_EQ(mgmt_message_length(afields, countof(afields), &mdata, &mint, &mlong, &mstring, &mlong, &mlong), - 31 + 4 + 4 + 8 + sizeof("all fields") + 4 + 8 + 8); - - mdata.ptr = nullptr; - mdata.len = 0; - CHECK_EQ(mgmt_message_length(dfields, countof(dfields), &mdata), 4); -} diff --git a/proxy/ControlMatcher.cc b/proxy/ControlMatcher.cc index f5a3c603d14..3866c8f88f8 100644 --- a/proxy/ControlMatcher.cc +++ b/proxy/ControlMatcher.cc @@ -783,7 +783,6 @@ ControlMatcher::BuildTableFromString(char *file_buf) int line_num = 0; int second_pass = 0; int numEntries = 0; - bool alarmAlready = false; // type counts int hostDomain = 0; @@ -817,7 +816,7 @@ ControlMatcher::BuildTableFromString(char *file_buf) if (config_tags != &socks_server_tags) { Result error = Result::failure("%s discarding %s entry at line %d : %s", matcher_name, config_file_path, line_num, errptr); - SignalError(error.message(), alarmAlready); + Error("%s", error.message()); } ats_free(current); } else { @@ -915,7 +914,7 @@ ControlMatcher::BuildTableFromString(char *file_buf) // Check to see if there was an error in creating the NewEntry if (error.failed()) { - SignalError(error.message(), alarmAlready); + Error("%s", error.message()); } // Deallocate the parsing structure diff --git a/proxy/ControlMatcher.h b/proxy/ControlMatcher.h index 6365ee0ed49..394841fdd5c 100644 --- a/proxy/ControlMatcher.h +++ b/proxy/ControlMatcher.h @@ -102,14 +102,6 @@ #include #endif -#define SignalError(_buf, _already) \ - { \ - if (_already == false) \ - pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, _buf); \ - _already = true; \ - Error("%s", _buf); \ - } - class HostLookup; struct HttpApiInfo; struct matcher_line; diff --git a/proxy/IPAllow.cc b/proxy/IPAllow.cc index c2e0fb6bfd1..33917af148c 100644 --- a/proxy/IPAllow.cc +++ b/proxy/IPAllow.cc @@ -42,7 +42,6 @@ SignalError(ts::BufferWriter &w, bool &flag) { if (!flag) { flag = true; - pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, w.data()); } Error("%s", w.data()); } diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc index 9d5546e2e4b..cc0e4b2c7d7 100644 --- a/proxy/ParentSelection.cc +++ b/proxy/ParentSelection.cc @@ -598,7 +598,6 @@ ParentRecord::DefaultInit(char *val) { const char *errPtr; char *errBuf; - bool alarmAlready = false; this->go_direct = true; this->ignore_query = false; @@ -609,7 +608,7 @@ ParentRecord::DefaultInit(char *val) if (errPtr != nullptr) { errBuf = static_cast(ats_malloc(1024)); snprintf(errBuf, 1024, "%s %s for default parent proxy", modulePrefix, errPtr); - SignalError(errBuf, alarmAlready); + Error("%s", errBuf); ats_free(errBuf); return false; } else { diff --git a/proxy/hdrs/HdrTSOnly.cc b/proxy/hdrs/HdrTSOnly.cc index 3a32c3bc56a..5acf807e7b5 100644 --- a/proxy/hdrs/HdrTSOnly.cc +++ b/proxy/hdrs/HdrTSOnly.cc @@ -28,11 +28,10 @@ Description: IRIX compiler is rather annoying and likes to use symbols from inline code that is not called in the file. Thus to make our libhdrs.a - library link with traffic_manager and test_header, we can't - include IOBuffer.h in any file where the corresponding object file - gets linked in for these two targets. Thus HdrTSOnly.cc is where - we put the functions that only traffic_server uses since they - need to know about IOBuffers. + library link with test_header, we can't include IOBuffer.h in any + file where the corresponding object file gets linked in for these + two targets. Thus HdrTSOnly.cc is where we put the functions that + only traffic_server uses since they need to know about IOBuffers. ****************************************************************************/ diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index d1e92392d4d..132bbadf18c 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -28,7 +28,6 @@ #include #include "HttpConfig.h" #include "HTTP.h" -#include "ProcessManager.h" #include "ProxyConfig.h" #include "P_Net.h" #include "records/P_RecUtils.h" diff --git a/proxy/http/remap/NextHopSelectionStrategy.h b/proxy/http/remap/NextHopSelectionStrategy.h index 54c0df5fcef..e63a3a4f23c 100644 --- a/proxy/http/remap/NextHopSelectionStrategy.h +++ b/proxy/http/remap/NextHopSelectionStrategy.h @@ -22,6 +22,7 @@ */ #pragma once +#include #include diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index b6c596f6b01..6b8a3ee4c8b 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -914,7 +914,6 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) const char *errStr; Tokenizer whiteTok(" \t"); - bool alarm_already = false; // Vars to parse line in file char *tok_state, *cur_line, *cur_line_tmp; @@ -1153,7 +1152,7 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) if (refinfo_error) { snprintf(errStrBuf, sizeof(errStrBuf), "%s Incorrect Referer regular expression \"%s\" at line %d - %s", modulePrefix, bti->paramv[j - 1], cln + 1, refinfo_error_buf); - SignalError(errStrBuf, alarm_already); + Error("%s", errStrBuf); delete ri; ri = nullptr; } @@ -1335,7 +1334,7 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) MAP_ERROR: snprintf(errBuf, sizeof(errBuf), "%s failed to add remap rule at %s line %d: %s", modulePrefix, path, cln + 1, errStr); - SignalError(errBuf, alarm_already); + Error("%s", errBuf); delete reg_map; delete new_mapping; diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc index fcd4f39ae14..3ae99791b8e 100644 --- a/proxy/http/remap/UrlRewrite.cc +++ b/proxy/http/remap/UrlRewrite.cc @@ -58,7 +58,6 @@ UrlRewrite::load() config_file_path = RecConfigReadConfigPath("proxy.config.url_remap.filename", ts::filename::REMAP); if (!config_file_path) { - pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to find proxy.config.url_remap.filename"); Warning("%s Unable to locate %s. No remappings in effect", modulePrefix, ts::filename::REMAP); return false; } @@ -66,7 +65,6 @@ UrlRewrite::load() this->ts_name = nullptr; REC_ReadConfigStringAlloc(this->ts_name, "proxy.config.proxy_name"); if (this->ts_name == nullptr) { - pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to read proxy.config.proxy_name"); Warning("%s Unable to determine proxy name. Incorrect redirects could be generated", modulePrefix); this->ts_name = ats_strdup(""); } @@ -74,7 +72,6 @@ UrlRewrite::load() this->http_default_redirect_url = nullptr; REC_ReadConfigStringAlloc(this->http_default_redirect_url, "proxy.config.http.referer_default_redirect"); if (this->http_default_redirect_url == nullptr) { - pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to read proxy.config.http.referer_default_redirect"); Warning("%s Unable to determine default redirect url for \"referer\" filter.", modulePrefix); this->http_default_redirect_url = ats_strdup("http://www.apache.org"); } diff --git a/proxy/http2/Http2CommonSession.h b/proxy/http2/Http2CommonSession.h index c59a5d75ee3..7d4066f7059 100644 --- a/proxy/http2/Http2CommonSession.h +++ b/proxy/http2/Http2CommonSession.h @@ -23,6 +23,8 @@ #pragma once +#include + #include "HTTP2.h" #include "ProxySession.h" #include "Http2ConnectionState.h" diff --git a/proxy/logging/Log.cc b/proxy/logging/Log.cc index 7c27f14a232..58d19facf64 100644 --- a/proxy/logging/Log.cc +++ b/proxy/logging/Log.cc @@ -53,6 +53,8 @@ #include "tscore/ink_apidefs.h" +#include "MgmtDefs.h" + #define PERIODIC_TASKS_INTERVAL_FALLBACK 5 // Log global objects @@ -1081,8 +1083,6 @@ Log::init_when_enabled() LogConfig::register_config_callbacks(); } - LogConfig::register_mgmt_callbacks(); - // create the flush thread create_threads(); eventProcessor.schedule_every(new PeriodicWakeup(preproc_threads, 1), HRTIME_SECOND, ET_CALL); diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc index 7b8a171cc01..1772a130c6f 100644 --- a/proxy/logging/LogConfig.cc +++ b/proxy/logging/LogConfig.cc @@ -554,19 +554,6 @@ LogConfig::register_stat_callbacks() (int)log_stat_log_files_space_used_stat, RecRawStatSyncSum); } -/*------------------------------------------------------------------------- - LogConfig::register_mgmt_callbacks - - This static function is called by Log::init to register the mgmt callback - function for each of the logging mgmt messages. - -------------------------------------------------------------------------*/ - -void -LogConfig::register_mgmt_callbacks() -{ - RecRegisterManagerCb(REC_EVENT_ROLL_LOG_FILES, &LogConfig::reconfigure_mgmt_variables); -} - /*------------------------------------------------------------------------- LogConfig::space_to_write @@ -632,7 +619,6 @@ LogConfig::update_space_used() if (!logfile_dir) { const char *msg = "Logging directory not specified"; Error("%s", msg); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, "%s", msg); m_log_directory_inaccessible = true; return; } @@ -646,7 +632,6 @@ LogConfig::update_space_used() if (err < 0) { const char *msg = "Error accessing logging directory %s: %s."; Error(msg, logfile_dir, strerror(errno)); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, logfile_dir, strerror(errno)); m_log_directory_inaccessible = true; return; } @@ -655,7 +640,6 @@ LogConfig::update_space_used() if (ld == nullptr) { const char *msg = "Error opening logging directory %s to perform a space check: %s."; Error(msg, logfile_dir, strerror(errno)); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, logfile_dir, strerror(errno)); m_log_directory_inaccessible = true; return; } @@ -778,7 +762,6 @@ LogConfig::update_space_used() if (m_space_used >= max_space) { if (!m_disk_full) { m_disk_full = true; - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, DISK_IS_CONFIG_FULL_MESSAGE); Warning(DISK_IS_CONFIG_FULL_MESSAGE); } } @@ -788,7 +771,6 @@ LogConfig::update_space_used() else if (m_partition_space_left <= 0) { if (!m_partition_full) { m_partition_full = true; - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, DISK_IS_ACTUAL_FULL_MESSAGE); Warning(DISK_IS_ACTUAL_FULL_MESSAGE); } } @@ -798,13 +780,11 @@ LogConfig::update_space_used() else if (m_space_used + headroom >= max_space) { if (!m_disk_low) { m_disk_low = true; - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, DISK_IS_CONFIG_LOW_MESSAGE); Warning(DISK_IS_CONFIG_LOW_MESSAGE); } } else { if (!m_partition_low) { m_partition_low = true; - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, DISK_IS_ACTUAL_LOW_MESSAGE); Warning(DISK_IS_ACTUAL_LOW_MESSAGE); } } diff --git a/proxy/logging/LogConfig.h b/proxy/logging/LogConfig.h index b0278d02ba6..0b544dfa66a 100644 --- a/proxy/logging/LogConfig.h +++ b/proxy/logging/LogConfig.h @@ -116,7 +116,6 @@ class LogConfig : public ConfigInfo static void register_config_callbacks(); static void register_stat_callbacks(); - static void register_mgmt_callbacks(); bool space_to_write(int64_t bytes_to_write) const; diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index c575a08d2af..7327fac3296 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -763,7 +763,6 @@ LogFile::check_fd() // XXX if open_file() returns, LOG_FILE_FILESYSTEM_CHECKS_FAILED, raise a more informative alarm ... if (err != LOG_FILE_NO_ERROR && err != LOG_FILE_NO_PIPE_READERS) { if (!failure_last_call) { - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, "Traffic Server could not open logfile %s.", m_name); Warning("Traffic Server could not open logfile %s: %s.", m_name, strerror(errno)); } failure_last_call = true; diff --git a/proxy/logging/LogObject.cc b/proxy/logging/LogObject.cc index f9a4e2ce0fa..22db84a3a4d 100644 --- a/proxy/logging/LogObject.cc +++ b/proxy/logging/LogObject.cc @@ -889,7 +889,6 @@ LogObjectManager::_solve_filename_conflicts(LogObject *log_object, int maxConfli const char *se = strerror(errno); Error(msg, filename, se); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename, se); retVal = ERROR_ACCESSING_LOG_FILE; } } else { @@ -922,7 +921,6 @@ LogObjectManager::_solve_filename_conflicts(LogObject *log_object, int maxConfli const char *msg = "Cannot solve filename conflicts for log file %s"; Error(msg, filename); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename); retVal = CANNOT_SOLVE_FILENAME_CONFLICTS; } else { // Either the meta file could not be read, or the new object's @@ -943,7 +941,6 @@ LogObjectManager::_solve_filename_conflicts(LogObject *log_object, int maxConfli char *se = strerror(errno); Error(msg, filename, se); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename, se); retVal = ERROR_DETERMINING_FILE_INFO; roll_file = false; } else { @@ -985,7 +982,6 @@ LogObjectManager::_filename_resolution_abort(const char *filename) "conflicts (filename or log format): %s"; const char *err = strerror(errno); Error(msg, filename, err); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename, err); } bool @@ -1023,7 +1019,6 @@ LogObjectManager::_solve_internal_filename_conflicts(LogObject *log_object, int const char *msg = "Cannot solve filename conflicts for log file %s"; Error(msg, filename); - LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename); retVal = CANNOT_SOLVE_FILENAME_CONFLICTS; } } diff --git a/proxy/logging/LogStandalone.cc b/proxy/logging/LogStandalone.cc index f147cb5b546..b5369dd6fb5 100644 --- a/proxy/logging/LogStandalone.cc +++ b/proxy/logging/LogStandalone.cc @@ -36,7 +36,6 @@ #include "P_EventSystem.h" #include "records/P_RecProcess.h" -#include "ProcessManager.h" #include "MgmtUtils.h" // Needs LibRecordsConfigInit() #include "RecordsConfig.h" @@ -97,25 +96,13 @@ initialize_process_manager() { mgmt_use_syslog(); - // Temporary Hack to Enable Communication with LocalManager - if (getenv("PROXY_REMOTE_MGMT")) { - remote_management_flag = true; - } - // diags should have been initialized by caller, e.g.: sac.cc ink_assert(diags()); - RecProcessInit(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE, diags()); + RecProcessInit(RECM_STAND_ALONE, diags()); LibRecordsConfigInit(); - // Start up manager - pmgmt = new ProcessManager(remote_management_flag); - - pmgmt->start(); - - RecProcessInitMessage(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE); - - pmgmt->reconfigure(); + RecProcessInitMessage(RECM_STAND_ALONE); // // Define version info records diff --git a/proxy/logging/LogUtils.cc b/proxy/logging/LogUtils.cc index ee64f32e942..3364f7a250f 100644 --- a/proxy/logging/LogUtils.cc +++ b/proxy/logging/LogUtils.cc @@ -57,8 +57,6 @@ #include #include "records/P_RecProcess.h" -// REC_SIGNAL_LOGGING_ERROR is defined in I_RecSignals.h -// REC_SIGNAL_LOGGING_WARNING is defined in I_RecSignals.h #include "LogUtils.h" #include "LogLimits.h" @@ -208,46 +206,6 @@ LogUtils::timestamp_to_time_str(long timestamp) return timebuf; } -/*------------------------------------------------------------------------- - LogUtils::manager_alarm - - This routine provides a convenient abstraction for sending the traffic - server manager process an alarm. The logging system can send - LOG_ALARM_N_TYPES different types of alarms, as defined in LogUtils.h. - Subsequent alarms of the same type will override the previous alarm - entry. - -------------------------------------------------------------------------*/ - -void -LogUtils::manager_alarm(LogUtils::AlarmType alarm_type, const char *msg, ...) -{ - char msg_buf[LOG_MAX_FORMATTED_LINE]; - - ink_assert(alarm_type >= 0 && alarm_type < LogUtils::LOG_ALARM_N_TYPES); - - if (msg == nullptr) { - snprintf(msg_buf, sizeof(msg_buf), "No Message"); - } else { - va_list ap; - va_start(ap, msg); - vsnprintf(msg_buf, LOG_MAX_FORMATTED_LINE, msg, ap); - va_end(ap); - } - - switch (alarm_type) { - case LogUtils::LOG_ALARM_ERROR: - RecSignalManager(REC_SIGNAL_LOGGING_ERROR, msg_buf); - break; - - case LogUtils::LOG_ALARM_WARNING: - RecSignalManager(REC_SIGNAL_LOGGING_WARNING, msg_buf); - break; - - default: - ink_assert(false); - } -} - /*------------------------------------------------------------------------- LogUtils::strip_trailing_newline diff --git a/proxy/logging/LogUtils.h b/proxy/logging/LogUtils.h index ade74181593..ffd3de941da 100644 --- a/proxy/logging/LogUtils.h +++ b/proxy/logging/LogUtils.h @@ -49,7 +49,6 @@ char *timestamp_to_netscape_str(long timestamp); char *timestamp_to_date_str(long timestamp); char *timestamp_to_time_str(long timestamp); unsigned ip_from_host(char *host); -void manager_alarm(AlarmType alarm_type, const char *msg, ...) TS_PRINTFLIKE(2, 3); void strip_trailing_newline(char *buf); char *escapify_url(Arena *arena, char *url, size_t len_in, int *len_out, char *dst = nullptr, size_t dst_size = 0, const unsigned char *map = nullptr); diff --git a/proxy/logging/unit-tests/test_LogUtils.cc b/proxy/logging/unit-tests/test_LogUtils.cc index 341d58af6c5..a38be6d1b2d 100644 --- a/proxy/logging/unit-tests/test_LogUtils.cc +++ b/proxy/logging/unit-tests/test_LogUtils.cc @@ -125,12 +125,6 @@ _ink_assert(const char *a, const char *f, int line) std::exit(1); } -void -RecSignalManager(int, char const *, std::size_t) -{ - ink_release_assert(false); -} - TEST_CASE("get_unrolled_filename parses possible log files as expected", "[get_unrolled_filename]") { // Rolled log inputs. diff --git a/proxy/logging/unit-tests/test_RolledLogDeleter.cc b/proxy/logging/unit-tests/test_RolledLogDeleter.cc index d0e51cd73c1..83f96bac22c 100644 --- a/proxy/logging/unit-tests/test_RolledLogDeleter.cc +++ b/proxy/logging/unit-tests/test_RolledLogDeleter.cc @@ -307,13 +307,4 @@ TEST_CASE("verify priority enforcement", "[RolledLogDeleter]") verify_there_are_no_candidates(deleter); } -} - -// -// Stub -// -void -RecSignalManager(int, const char *, unsigned long) -{ - ink_release_assert(false); -} +} \ No newline at end of file diff --git a/rc/trafficserver.xml.in b/rc/trafficserver.xml.in index 0430cc505c2..e076fc90b4b 100644 --- a/rc/trafficserver.xml.in +++ b/rc/trafficserver.xml.in @@ -60,12 +60,6 @@ value='svc:/milestone/multi-user-server' /> - - (ptr); - } -}; - -using CtrlAlarmList = CtrlMgmtList; - -void -CtrlEngine::alarm_list() -{ - TSMgmtError error; - CtrlAlarmList alarms; - - error = TSActiveEventGetMlt(alarms.list); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch active alarms"); - status_code = CTRL_EX_ERROR; - return; - } - - while (!alarms.empty()) { - char *a = alarms.next(); - std::cout << a << std::endl; - TSfree(a); - } -} - -void -CtrlEngine::alarm_clear() -{ - TSMgmtError error; - CtrlAlarmList alarms; - - // First get the active alarms ... - error = TSActiveEventGetMlt(alarms.list); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch active alarms"); - status_code = CTRL_EX_ERROR; - return; - } - - // Now resolve them all ... - while (!alarms.empty()) { - char *a = alarms.next(); - - error = TSEventResolve(a); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to resolve %s", a); - TSfree(a); - status_code = CTRL_EX_ERROR; - return; - } - - TSfree(a); - } -} - -void -CtrlEngine::alarm_resolve() -{ - TSMgmtError error; - CtrlAlarmList alarms; - - for (const auto &it : arguments.get("resolve")) { - error = TSEventResolve(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to resolve %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - } -} diff --git a/src/traffic_ctl/config.cc b/src/traffic_ctl/config.cc deleted file mode 100644 index e3433392310..00000000000 --- a/src/traffic_ctl/config.cc +++ /dev/null @@ -1,463 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" -#include -#include "records/I_RecDefs.h" -#include "records/P_RecUtils.h" -#include "ts/apidefs.h" -#include "HTTP.h" -#include "HttpConnectionCount.h" -#include "shared/overridable_txn_vars.h" -#include - -struct RecordDescriptionPolicy { - using entry_type = TSConfigRecordDescription *; - - static void - free(entry_type e) - { - TSConfigRecordDescriptionDestroy(e); - } - - static entry_type - cast(void *ptr) - { - return (entry_type)ptr; - } -}; - -struct CtrlMgmtRecordDescriptionList : CtrlMgmtList { - TSMgmtError - match(const char *regex) - { - return TSConfigRecordDescribeMatchMlt(regex, 0u /* flags */, this->list); - } -}; - -// Record data type names, indexed by TSRecordT. -static const char * -rec_typeof(int rec_type) -{ - switch (rec_type) { - case TS_REC_INT: - return "INT"; - case TS_REC_COUNTER: - return "COUNTER"; - case TS_REC_FLOAT: - return "FLOAT"; - case TS_REC_STRING: - return "STRING"; - case TS_REC_UNDEFINED: /* fallthrough */ - default: - return "UNDEFINED"; - } -} - -// Record type name, indexed by RecT. -static const char * -rec_classof(int rec_class) -{ - switch (rec_class) { - case RECT_CONFIG: - return "standard config"; - case RECT_LOCAL: - return "local config"; - case RECT_PROCESS: - return "process metric"; - case RECT_NODE: - return "node metric"; - case RECT_PLUGIN: - return "plugin metric"; - default: - return "undefined"; - } -} - -// Record access control, indexed by RecAccessT. -static const char * -rec_accessof(int rec_access) -{ - switch (rec_access) { - case RECA_NO_ACCESS: - return "no access"; - case RECA_READ_ONLY: - return "read only"; - case RECA_NULL: /* fallthrough */ - default: - return "default"; - } -} - -// Record access control, indexed by RecUpdateT. -static const char * -rec_updateof(int rec_updatetype) -{ - switch (rec_updatetype) { - case RECU_DYNAMIC: - return "dynamic, no restart"; - case RECU_RESTART_TS: - return "static, restart traffic_server"; - case RECU_RESTART_TM: - return "static, restart traffic_manager"; - case RECU_NULL: /* fallthrough */ - default: - return "none"; - } -} - -// Record check type, indexed by RecCheckT. -static const char * -rec_checkof(int rec_checktype) -{ - switch (rec_checktype) { - case RECC_STR: - return "string matching a regular expression"; - case RECC_INT: - return "integer with a specified range"; - case RECC_IP: - return "IP address"; - case RECC_NULL: /* fallthrough */ - default: - return "none"; - } -} - -static const char * -rec_sourceof(int rec_source) -{ - switch (rec_source) { - case REC_SOURCE_DEFAULT: - return "built in default"; - case REC_SOURCE_EXPLICIT: - return "administratively set"; - case REC_SOURCE_PLUGIN: - return "plugin default"; - case REC_SOURCE_ENV: - return "environment"; - default: - return "unknown"; - } -} - -static const char * -rec_labelof(int rec_class) -{ - switch (rec_class) { - case RECT_CONFIG: - return "CONFIG"; - case RECT_LOCAL: - return "LOCAL"; - default: - return nullptr; - } -} - -static const char * -rec_datatypeof(TSRecordDataType dt) -{ - switch (dt) { - case TS_RECORDDATATYPE_INT: - return "int"; - case TS_RECORDDATATYPE_NULL: - return "null"; - case TS_RECORDDATATYPE_FLOAT: - return "float"; - case TS_RECORDDATATYPE_STRING: - return "string"; - case TS_RECORDDATATYPE_COUNTER: - return "counter"; - case TS_RECORDDATATYPE_STAT_CONST: - return "constant stat"; - case TS_RECORDDATATYPE_STAT_FX: - return "stat fx"; - case TS_RECORDDATATYPE_MAX: - return "*"; - } - return "?"; -} - -static std::string -timestr(time_t tm) -{ - char buf[32]; - return std::string(ctime_r(&tm, buf)); -} - -static void -format_record(const CtrlMgmtRecord &record, bool recfmt) -{ - CtrlMgmtRecordValue value(record); - - if (recfmt) { - std::cout << rec_labelof(record.rclass()) << ' ' << record.name() << ' ' << rec_typeof(record.type()) << ' ' << value.c_str() - << std::endl; - } else { - std::cout << record.name() << ": " << value.c_str() << std::endl; - } -} - -void -CtrlEngine::config_get() -{ - for (const auto &it : arguments.get("get")) { - CtrlMgmtRecord record; - TSMgmtError error; - - error = record.fetch(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - if (REC_TYPE_IS_CONFIG(record.rclass())) { - format_record(record, arguments.get("records")); - } - } -} - -void -CtrlEngine::config_describe() -{ - for (const auto &it : arguments.get("describe")) { - TSConfigRecordDescription desc; - TSMgmtError error; - - ink_zero(desc); - error = TSConfigRecordDescribe(it.c_str(), 0 /* flags */, &desc); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to describe %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - auto ov_iter = ts::Overridable_Txn_Vars.find(it); - bool overridable_p = (ov_iter != ts::Overridable_Txn_Vars.end()); - - std::string text; - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Name", desc.rec_name); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Current Value ", CtrlMgmtRecordValue(desc.rec_type, desc.rec_value).c_str()); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Default Value ", CtrlMgmtRecordValue(desc.rec_type, desc.rec_default).c_str()); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Record Type ", rec_classof(desc.rec_class)); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Data Type ", rec_typeof(desc.rec_type)); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Access Control ", rec_accessof(desc.rec_access)); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Update Type ", rec_updateof(desc.rec_updatetype)); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Update Status ", desc.rec_update); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Source ", rec_sourceof(desc.rec_source)); - std::cout << ts::bwprint(text, "{:16s}: {} {}\n", "Overridable", overridable_p ? "yes" : "no", - overridable_p ? rec_datatypeof(std::get<1>(ov_iter->second)) : ""); - - if (strlen(desc.rec_checkexpr)) { - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Syntax Check ", rec_checkof(desc.rec_checktype), desc.rec_checkexpr); - } else { - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Syntax Check ", rec_checkof(desc.rec_checktype)); - } - - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Version ", desc.rec_version); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Order ", desc.rec_order); - std::cout << ts::bwprint(text, "{:16s}: {}\n", "Raw Stat Block ", desc.rec_rsb); - - TSConfigRecordDescriptionFree(&desc); - } -} - -void -CtrlEngine::config_set() -{ - TSMgmtError error; - TSActionNeedT action; - auto set_data = arguments.get("set"); - const char *rec_name = set_data[0].c_str(); - const char *rec_val = set_data[1].c_str(); - error = TSRecordSet(rec_name, rec_val, &action); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to set %s", rec_name); - status_code = CTRL_EX_ERROR; - return; - } - - switch (action) { - case TS_ACTION_SHUTDOWN: - std::cout << "set " << rec_name << ", full shutdown required" << std::endl; - break; - case TS_ACTION_RESTART: - std::cout << "set " << rec_name << ", restart required" << std::endl; - break; - case TS_ACTION_RECONFIGURE: - std::cout << "set " << rec_name << ", please wait 10 seconds for traffic server to sync configuration, restart is not required" - << std::endl; - break; - case TS_ACTION_DYNAMIC: - default: - printf("set %s\n", rec_name); - break; - } -} - -void -CtrlEngine::config_match() -{ - for (const auto &it : arguments.get("match")) { - CtrlMgmtRecordList reclist; - TSMgmtError error; - - // XXX filter the results to only match configuration records. - - error = reclist.match(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - while (!reclist.empty()) { - CtrlMgmtRecord record(reclist.next()); - if (REC_TYPE_IS_CONFIG(record.rclass())) { - format_record(record, arguments.get("records")); - } - } - } -} - -void -CtrlEngine::config_reload() -{ - TSMgmtError error = TSReconfigure(); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "configuration reload request failed"); - status_code = CTRL_EX_ERROR; - return; - } -} - -void -CtrlEngine::config_status() -{ - CtrlMgmtRecord version; - CtrlMgmtRecord configtime; - CtrlMgmtRecord starttime; - CtrlMgmtRecord reconfig; - CtrlMgmtRecord proxy; - CtrlMgmtRecord manager; - - CTRL_MGMT_CHECK(version.fetch("proxy.process.version.server.long")); - CTRL_MGMT_CHECK(starttime.fetch("proxy.node.restarts.proxy.start_time")); - CTRL_MGMT_CHECK(configtime.fetch("proxy.node.config.reconfigure_time")); - CTRL_MGMT_CHECK(reconfig.fetch("proxy.node.config.reconfigure_required")); - CTRL_MGMT_CHECK(proxy.fetch("proxy.node.config.restart_required.proxy")); - CTRL_MGMT_CHECK(manager.fetch("proxy.node.config.restart_required.manager")); - - std::cout << CtrlMgmtRecordValue(version).c_str() << std::endl; - std::cout << "Started at " << timestr(static_cast(starttime.as_int())).c_str(); - std::cout << "Last reconfiguration at " << timestr(static_cast(configtime.as_int())).c_str(); - std::cout << (reconfig.as_int() ? "Reconfiguration required" : "Configuration is current") << std::endl; - - if (proxy.as_int()) { - std::cout << "traffic_server requires restarting" << std::endl; - } - if (manager.as_int()) { - std::cout << "traffic_manager requires restarting\n" << std::endl; - } -} - -void -CtrlEngine::config_defaults() -{ - TSMgmtError error; - CtrlMgmtRecordDescriptionList descriptions; - - error = descriptions.match(".*"); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch record metadata"); - status_code = CTRL_EX_ERROR; - return; - } - - while (!descriptions.empty()) { - TSConfigRecordDescription *desc = descriptions.next(); - CtrlMgmtRecordValue deflt(desc->rec_type, desc->rec_default); - - if (arguments.get("records")) { - std::cout << rec_labelof(desc->rec_class) << ' ' << desc->rec_name << ' ' << rec_typeof(desc->rec_type) << ' ' - << deflt.c_str() << std::endl; - } else { - std::cout << desc->rec_name << ": " << deflt.c_str() << std::endl; - } - TSConfigRecordDescriptionDestroy(desc); - } -} - -void -CtrlEngine::config_diff() -{ - TSMgmtError error; - CtrlMgmtRecordDescriptionList descriptions; - - error = descriptions.match(".*"); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch record metadata"); - status_code = CTRL_EX_ERROR; - return; - } - - while (!descriptions.empty()) { - TSConfigRecordDescription *desc; - bool changed = false; - - desc = descriptions.next(); - - switch (desc->rec_type) { - case TS_REC_INT: - changed = (desc->rec_value.int_val != desc->rec_default.int_val); - break; - case TS_REC_COUNTER: - changed = (desc->rec_value.counter_val != desc->rec_default.counter_val); - break; - case TS_REC_FLOAT: - changed = (desc->rec_value.float_val != desc->rec_default.float_val); - break; - case TS_REC_STRING: - changed = (strcmp(desc->rec_value.string_val, desc->rec_default.string_val) != 0); - break; - default: - break; - } - - if (changed) { - CtrlMgmtRecordValue current(desc->rec_type, desc->rec_value); - CtrlMgmtRecordValue deflt(desc->rec_type, desc->rec_default); - - if (arguments.get("records")) { - std::cout << rec_labelof(desc->rec_class) << ' ' << desc->rec_name << ' ' << rec_typeof(desc->rec_type) << ' ' - << current.c_str() << " # default: " << deflt.c_str() << std::endl; - } else { - std::cout << desc->rec_name << " has changed" << std::endl; - std::cout << "\tCurrent Value: " << current.c_str() << std::endl; - std::cout << "\tDefault Value: " << deflt.c_str() << std::endl; - } - } - - TSConfigRecordDescriptionDestroy(desc); - } -} diff --git a/src/traffic_ctl/host.cc b/src/traffic_ctl/host.cc deleted file mode 100644 index 1834104eb7d..00000000000 --- a/src/traffic_ctl/host.cc +++ /dev/null @@ -1,120 +0,0 @@ -/** @file - - host.cc - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" -#include "HostStatus.h" -#include "records/P_RecUtils.h" - -void -CtrlEngine::status_get() -{ - for (const auto &it : arguments.get("status")) { - CtrlMgmtRecord record; - TSMgmtError error; - std::string str = stat_prefix + it; - - error = record.fetch(str.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - if (REC_TYPE_IS_STAT(record.rclass())) { - std::cout << record.name() << ' ' << CtrlMgmtRecordValue(record).c_str() << std::endl; - } - } -} - -void -CtrlEngine::status_down() -{ - const char *usage = "traffic_ctl host down --reason 'active | local | manual' --time seconds host ...."; - unsigned int down_time = 0; - std::string reason = arguments.get("reason").value(); - std::string down = arguments.get("time").value(); - - // if reason is not set, set it to manual (default) - if (reason.empty()) { - reason = Reason::MANUAL; - } - if (!down.empty()) { - down_time = atoi(down.c_str()); - } - - if (!Reason::validReason(reason.c_str())) { - fprintf(stderr, "\nInvalid reason: '%s'\n\n", reason.c_str()); - fprintf(stderr, "Usage: %s\n\n", usage); - status_code = CTRL_EX_ERROR; - return; - } - - TSMgmtError error = TS_ERR_OKAY; - for (const auto &it : arguments.get("down")) { - if (strncmp(it.c_str(), "--", 2) == 0) { - fprintf(stderr, "\nInvalid option: %s\n", it.c_str()); - fprintf(stderr, "Usage: %s\n\n", usage); - status_code = CTRL_EX_ERROR; - return; - } - error = TSHostStatusSetDown(it.c_str(), down_time, reason.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to set %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - } -} -void -CtrlEngine::status_up() -{ - const char *usage = "traffic_ctl host up --reason 'active | local | manual' host ...."; - std::string reason = arguments.get("reason").value(); - - // if reason is not set, set it to manual (default) - if (reason.empty()) { - reason = Reason::MANUAL; - } - - if (!Reason::validReason(reason.c_str())) { - fprintf(stderr, "\nInvalid reason: '%s'\n\n", reason.c_str()); - fprintf(stderr, "Usage: %s\n\n", usage); - status_code = CTRL_EX_ERROR; - return; - } - - TSMgmtError error; - for (const auto &it : arguments.get("up")) { - error = TSHostStatusSetUp(it.c_str(), 0, reason.c_str()); - if (strncmp("--", it.c_str(), 2) == 0) { - fprintf(stderr, "\nInvalid option: %s\n", it.c_str()); - fprintf(stderr, "Usage: %s\n\n", usage); - status_code = CTRL_EX_ERROR; - } - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to set %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - } -} diff --git a/src/traffic_ctl_jsonrpc/jsonrpc/CtrlRPCRequests.h b/src/traffic_ctl/jsonrpc/CtrlRPCRequests.h similarity index 100% rename from src/traffic_ctl_jsonrpc/jsonrpc/CtrlRPCRequests.h rename to src/traffic_ctl/jsonrpc/CtrlRPCRequests.h diff --git a/src/traffic_ctl_jsonrpc/jsonrpc/ctrl_yaml_codecs.h b/src/traffic_ctl/jsonrpc/ctrl_yaml_codecs.h similarity index 100% rename from src/traffic_ctl_jsonrpc/jsonrpc/ctrl_yaml_codecs.h rename to src/traffic_ctl/jsonrpc/ctrl_yaml_codecs.h diff --git a/src/traffic_ctl/metric.cc b/src/traffic_ctl/metric.cc deleted file mode 100644 index 1076aceb293..00000000000 --- a/src/traffic_ctl/metric.cc +++ /dev/null @@ -1,95 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" -#include "records/P_RecUtils.h" - -void -CtrlEngine::metric_get() -{ - for (const auto &it : arguments.get("get")) { - CtrlMgmtRecord record; - TSMgmtError error; - - error = record.fetch(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - if (REC_TYPE_IS_STAT(record.rclass())) { - std::cout << record.name() << ' ' << CtrlMgmtRecordValue(record).c_str() << std::endl; - } - } -} - -void -CtrlEngine::metric_match() -{ - for (const auto &it : arguments.get("match")) { - CtrlMgmtRecordList reclist; - TSMgmtError error; - - error = reclist.match(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to fetch %s", it.c_str()); - status_code = CTRL_EX_ERROR; - return; - } - - while (!reclist.empty()) { - CtrlMgmtRecord record(reclist.next()); - if (REC_TYPE_IS_STAT(record.rclass())) { - std::cout << record.name() << ' ' << CtrlMgmtRecordValue(record).c_str() << std::endl; - } - } - } -} - -void -CtrlEngine::metric_clear() -{ - TSMgmtError error; - - error = TSStatsReset(nullptr); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to clear metrics"); - status_code = CTRL_EX_ERROR; - return; - } -} - -void -CtrlEngine::metric_zero() -{ - TSMgmtError error; - - for (const auto &it : arguments.get("zero")) { - error = TSStatsReset(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to clear %s", it.c_str()); - status_code = CTRL_EX_ERROR; - } - } -} diff --git a/src/traffic_ctl/plugin.cc b/src/traffic_ctl/plugin.cc deleted file mode 100644 index a9eb08bfa40..00000000000 --- a/src/traffic_ctl/plugin.cc +++ /dev/null @@ -1,43 +0,0 @@ -/** @file - - Plugin related sub commands. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" - -void -CtrlEngine::plugin_msg() -{ - TSMgmtError error; - auto msg_data = arguments.get("msg"); - - if (msg_data.size() == 1) { // no data provided, just the tag - error = TSLifecycleMessage(msg_data[0].c_str(), nullptr, 0); - } else { - error = TSLifecycleMessage(msg_data[0].c_str(), msg_data[1].c_str(), msg_data[1].size() + 1); - } - - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "message '%s' not sent", msg_data[0].c_str()); - status_code = CTRL_EX_ERROR; - return; - } -} diff --git a/src/traffic_ctl/server.cc b/src/traffic_ctl/server.cc deleted file mode 100644 index 58271ba4de4..00000000000 --- a/src/traffic_ctl/server.cc +++ /dev/null @@ -1,136 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" - -void -CtrlEngine::server_restart() -{ - TSMgmtError error; - unsigned flags = TS_RESTART_OPT_NONE; - - if (arguments.get("drain")) { - flags |= TS_RESTART_OPT_DRAIN; - } - - if (arguments.get("manager")) { - error = TSRestart(flags); - } else { - error = TSBounce(flags); - } - - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "server restart failed"); - status_code = CTRL_EX_ERROR; - return; - } -} - -void -CtrlEngine::server_backtrace() -{ - TSMgmtError error; - TSString trace = nullptr; - - error = TSProxyBacktraceGet(0, &trace); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "server backtrace failed"); - status_code = CTRL_EX_ERROR; - return; - } - - std::cout << trace << std::endl; - TSfree(trace); -} - -void -CtrlEngine::server_status() -{ - switch (TSProxyStateGet()) { - case TS_PROXY_ON: - std::cout << "Proxy -- on" << std::endl; - break; - case TS_PROXY_OFF: - std::cout << "Proxy -- off" << std::endl; - break; - case TS_PROXY_UNDEFINED: - std::cout << "Proxy status undefined" << std::endl; - break; - } -} - -void -CtrlEngine::server_stop() -{ - TSMgmtError error; - unsigned flags = TS_RESTART_OPT_NONE; - - if (arguments.get("drain")) { - flags |= TS_STOP_OPT_DRAIN; - } - - error = TSStop(flags); - - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "server stop failed"); - status_code = CTRL_EX_ERROR; - return; - } -} - -void -CtrlEngine::server_start() -{ - TSMgmtError error; - unsigned clear = TS_CACHE_CLEAR_NONE; - - clear |= arguments.get("clear-cache") ? TS_CACHE_CLEAR_CACHE : TS_CACHE_CLEAR_NONE; - clear |= arguments.get("clear-hostdb") ? TS_CACHE_CLEAR_HOSTDB : TS_CACHE_CLEAR_NONE; - - error = TSProxyStateSet(TS_PROXY_ON, clear); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "server start failed"); - status_code = CTRL_EX_ERROR; - return; - } -} - -void -CtrlEngine::server_drain() -{ - TSMgmtError error; - - if (arguments.get("undo")) { - error = TSDrain(TS_DRAIN_OPT_UNDO); - } else if (arguments.get("no-new-connection")) { - error = TSDrain(TS_DRAIN_OPT_IDLE); - } else { - error = TSDrain(TS_DRAIN_OPT_NONE); - } - - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "server drain failed"); - status_code = CTRL_EX_ERROR; - return; - } -} diff --git a/src/traffic_ctl/storage.cc b/src/traffic_ctl/storage.cc deleted file mode 100644 index 1e55bc94fde..00000000000 --- a/src/traffic_ctl/storage.cc +++ /dev/null @@ -1,40 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "traffic_ctl.h" - -void -CtrlEngine::storage_offline() -{ - auto offline_data = arguments.get("offline"); - for (const auto &it : offline_data) { - TSMgmtError error; - - error = TSStorageDeviceCmdOffline(it.c_str()); - if (error != TS_ERR_OKAY) { - CtrlMgmtError(error, "failed to take %s offline", offline_data[0].c_str()); - status_code = CTRL_EX_ERROR; - return; - } - } -} diff --git a/src/traffic_ctl/traffic_ctl.cc b/src/traffic_ctl/traffic_ctl.cc index 6c6ef2be6ea..c1b28e92ddf 100644 --- a/src/traffic_ctl/traffic_ctl.cc +++ b/src/traffic_ctl/traffic_ctl.cc @@ -21,281 +21,177 @@ limitations under the License. */ -#include "traffic_ctl.h" +#include -#include "records/I_RecProcess.h" -#include "RecordsConfig.h" #include "tscore/I_Layout.h" #include "tscore/runroot.h" +#include "tscore/ArgParser.h" -const char * -CtrlMgmtRecord::name() const -{ - return this->ele->rec_name; -} - -TSRecordT -CtrlMgmtRecord::type() const -{ - return this->ele->rec_type; -} - -int -CtrlMgmtRecord::rclass() const -{ - return this->ele->rec_class; -} - -int64_t -CtrlMgmtRecord::as_int() const -{ - switch (this->ele->rec_type) { - case TS_REC_INT: - return this->ele->valueT.int_val; - case TS_REC_COUNTER: - return this->ele->valueT.counter_val; - default: - return 0; - } -} - -TSMgmtError -CtrlMgmtRecord::fetch(const char *name) -{ - return TSRecordGet(name, this->ele); -} - -TSMgmtError -CtrlMgmtRecordList::match(const char *name) -{ - return TSRecordGetMatchMlt(name, this->list); -} +#include "CtrlCommands.h" -CtrlMgmtRecordValue::CtrlMgmtRecordValue(const CtrlMgmtRecord &rec) -{ - this->init(rec.ele->rec_type, rec.ele->valueT); -} +constexpr int CTRL_EX_OK = 0; +constexpr int CTRL_EX_ERROR = 2; +constexpr int CTRL_EX_UNIMPLEMENTED = 3; -CtrlMgmtRecordValue::CtrlMgmtRecordValue(const TSRecordEle *ele) -{ - this->init(ele->rec_type, ele->valueT); -} - -CtrlMgmtRecordValue::CtrlMgmtRecordValue(TSRecordT _t, TSRecordValueT _v) -{ - this->init(_t, _v); -} - -void -CtrlMgmtRecordValue::init(TSRecordT _t, TSRecordValueT _v) -{ - this->rec_type = _t; - switch (this->rec_type) { - case TS_REC_INT: - snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.int_val); - break; - case TS_REC_COUNTER: - snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.counter_val); - break; - case TS_REC_FLOAT: - snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%f", _v.float_val); - break; - case TS_REC_STRING: - if (strcmp(_v.string_val, "") == 0) { - this->fmt.str = "\"\""; - } else { - this->fmt.str = _v.string_val; - } - break; - default: - rec_type = TS_REC_STRING; - this->fmt.str = "(invalid)"; - } -} - -const char * -CtrlMgmtRecordValue::c_str() const -{ - switch (this->rec_type) { - case TS_REC_STRING: - return this->fmt.str; - default: - return this->fmt.nbuf; - } -} - -void -CtrlMgmtError(TSMgmtError err, const char *fmt, ...) -{ - ats_scoped_str msg(TSGetErrorMessage(err)); - - if (fmt) { - va_list ap; - - fprintf(stderr, "%s: ", program_name); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - fprintf(stderr, ": %s\n", (const char *)msg); - } else { - fprintf(stderr, "%s: %s\n", program_name, (const char *)msg); - } -} - -void -CtrlEngine::CtrlUnimplementedCommand(std::string_view command) -{ - fprintf(stderr, "'%s' command is not implemented\n", command.data()); - status_code = CTRL_EX_UNIMPLEMENTED; -} +int status_code{CTRL_EX_OK}; int main(int argc, const char **argv) { - CtrlEngine engine; + ts::ArgParser parser; - engine.parser.add_global_usage("traffic_ctl [OPTIONS] CMD [ARGS ...]"); - engine.parser.require_commands(); + std::shared_ptr command; - engine.parser.add_option("--debug", "", "Enable debugging output") - .add_option("--version", "-V", "Print version string") - .add_option("--help", "-h", "Print usage information") - .add_option("--run-root", "", "using TS_RUNROOT as sandbox", "TS_RUNROOT", 1); + auto CtrlUnimplementedCommand = [](std::string_view cmd) { + std::cout << "Command " << cmd << " unimplemented.\n"; + status_code = CTRL_EX_UNIMPLEMENTED; + }; - auto &alarm_command = engine.parser.add_command("alarm", "Manipulate alarms").require_commands(); - auto &config_command = engine.parser.add_command("config", "Manipulate configuration records").require_commands(); - auto &metric_command = engine.parser.add_command("metric", "Manipulate performance metrics").require_commands(); - auto &server_command = engine.parser.add_command("server", "Stop, restart and examine the server").require_commands(); - auto &storage_command = engine.parser.add_command("storage", "Manipulate cache storage").require_commands(); - auto &plugin_command = engine.parser.add_command("plugin", "Interact with plugins").require_commands(); - auto &host_command = engine.parser.add_command("host", "Interact with host status").require_commands(); + parser.add_description("Apache Traffic Server RPC CLI"); + parser.add_global_usage("traffic_ctl [OPTIONS] CMD [ARGS ...]"); + parser.require_commands(); - // alarm commands - alarm_command.add_command("clear", "Clear all current alarms", [&]() { engine.alarm_clear(); }) - .add_example_usage("traffic_ctl alarm clear"); - alarm_command.add_command("list", "List all current alarms", [&]() { engine.alarm_list(); }) - .add_example_usage("traffic_ctl alarm list"); - alarm_command.add_command("resolve", "Resolve the listed alarms", "", MORE_THAN_ONE_ARG_N, [&]() { engine.alarm_resolve(); }) - .add_example_usage("traffic_ctl alarm resolve ALARM [ALARM ...]"); + parser.add_option("--debug", "", "Enable debugging output - unimplemented") + .add_option("--version", "-V", "Print version string") + .add_option("--help", "-h", "Print usage information") + .add_option("--run-root", "", "using TS_RUNROOT as sandbox", "TS_RUNROOT", 1) + .add_option("--format", "-f", "Use a specific output format {legacy|pretty|json|data:{req|resp|all}}", "", 1, "legacy", + "format"); + + auto &config_command = parser.add_command("config", "Manipulate configuration records").require_commands(); + auto &metric_command = parser.add_command("metric", "Manipulate performance metrics").require_commands(); + auto &server_command = parser.add_command("server", "Stop, restart and examine the server").require_commands(); + auto &storage_command = parser.add_command("storage", "Manipulate cache storage").require_commands(); + auto &plugin_command = parser.add_command("plugin", "Interact with plugins").require_commands(); + auto &host_command = parser.add_command("host", "Interact with host status").require_commands(); + auto &direct_rpc_command = parser.add_command("rpc", "Interact with the rpc api").require_commands(); // config commands - config_command.add_command("defaults", "Show default information configuration values", [&]() { engine.config_defaults(); }) + config_command.add_command("defaults", "Show default information configuration values", [&]() { command->execute(); }) .add_example_usage("traffic_ctl config defaults [OPTIONS]") .add_option("--records", "", "Emit output in records.config format"); config_command .add_command("describe", "Show detailed information about configuration values", "", MORE_THAN_ONE_ARG_N, - [&]() { engine.config_describe(); }) + [&]() { command->execute(); }) .add_example_usage("traffic_ctl config describe RECORD [RECORD ...]"); - config_command.add_command("diff", "Show non-default configuration values", [&]() { engine.config_diff(); }) + config_command.add_command("diff", "Show non-default configuration values", [&]() { command->execute(); }) .add_example_usage("traffic_ctl config diff [OPTIONS]") .add_option("--records", "", "Emit output in records.config format"); - config_command.add_command("get", "Get one or more configuration values", "", MORE_THAN_ONE_ARG_N, [&]() { engine.config_get(); }) + config_command.add_command("get", "Get one or more configuration values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl config get [OPTIONS] RECORD [RECORD ...]") .add_option("--records", "", "Emit output in records.config format"); config_command - .add_command("match", "Get configuration matching a regular expression", "", MORE_THAN_ONE_ARG_N, - [&]() { engine.config_match(); }) + .add_command("match", "Get configuration matching a regular expression", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl config match [OPTIONS] REGEX [REGEX ...]") .add_option("--records", "", "Emit output in records.config format"); - config_command.add_command("reload", "Request a configuration reload", [&]() { engine.config_reload(); }) + config_command.add_command("reload", "Request a configuration reload", [&]() { command->execute(); }) .add_example_usage("traffic_ctl config reload"); - config_command.add_command("status", "Check the configuration status", [&]() { engine.config_status(); }) + config_command.add_command("status", "Check the configuration status", [&]() { command->execute(); }) .add_example_usage("traffic_ctl config status"); - config_command.add_command("set", "Set a configuration value", "", 2, [&]() { engine.config_set(); }) + config_command.add_command("set", "Set a configuration value", "", 2, [&]() { command->execute(); }) .add_example_usage("traffic_ctl config set RECORD VALUE"); + config_command.add_command("registry", "Show configuration file registry", [&]() { command->execute(); }) + .add_example_usage("traffic_ctl config registry"); // host commands - host_command.add_command("status", "Get one or more host statuses", "", MORE_THAN_ONE_ARG_N, [&]() { engine.status_get(); }) + host_command.add_command("status", "Get one or more host statuses", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl host status HOST [HOST ...]"); - host_command.add_command("down", "Set down one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { engine.status_down(); }) + host_command.add_command("down", "Set down one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl host down HOST [OPTIONS]") - .add_option("--time", "-I", "number of seconds that a host is marked down", "", 1) - .add_option("--reason", "", "reason for marking the host down, one of 'manual|active|local", "", 1); - host_command.add_command("up", "Set up one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { engine.status_up(); }) + .add_option("--time", "-I", "number of seconds that a host is marked down", "", 1, "0") + .add_option("--reason", "", "reason for marking the host down, one of 'manual|active|local", "", 1, "manual"); + host_command.add_command("up", "Set up one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl host up METRIC value") - .add_option("--reason", "", "reason for marking the host up, one of 'manual|active|local", "", 1); + .add_option("--reason", "", "reason for marking the host up, one of 'manual|active|local", "", 1, "manual"); // metric commands - metric_command.add_command("get", "Get one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { engine.metric_get(); }) + metric_command.add_command("get", "Get one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("traffic_ctl metric get METRIC [METRIC ...]"); - metric_command.add_command("clear", "Clear all metric values", [&]() { engine.metric_clear(); }); + metric_command.add_command("clear", "Clear all metric values", [&]() { command->execute(); }); metric_command.add_command("describe", "Show detailed information about one or more metric values", "", MORE_THAN_ONE_ARG_N, - [&]() { engine.CtrlUnimplementedCommand("describe"); }); // not implemented + [&]() { command->execute(); }); // not implemented metric_command.add_command("match", "Get metrics matching a regular expression", "", MORE_THAN_ZERO_ARG_N, - [&]() { engine.metric_match(); }); + [&]() { command->execute(); }); metric_command.add_command("monitor", "Display the value of a metric over time", "", MORE_THAN_ZERO_ARG_N, - [&]() { engine.CtrlUnimplementedCommand("monitor"); }); // not implemented - metric_command.add_command("zero", "Clear one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { engine.metric_zero(); }); + [&]() { CtrlUnimplementedCommand("monitor"); }); // not implemented + metric_command.add_command("zero", "Clear one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }); // plugin command - plugin_command - .add_command("msg", "Send message to plugins - a TAG and the message DATA(optional)", "", MORE_THAN_ONE_ARG_N, - [&]() { engine.plugin_msg(); }) + plugin_command.add_command("msg", "Send message to plugins - a TAG and the message DATA", "", 2, [&]() { command->execute(); }) .add_example_usage("traffic_ctl plugin msg TAG DATA"); // server commands server_command.add_command("backtrace", "Show a full stack trace of the traffic_server process", - [&]() { engine.server_backtrace(); }); - server_command.add_command("restart", "Restart Traffic Server", [&]() { engine.server_restart(); }) + [&]() { CtrlUnimplementedCommand("backtrace"); }); + server_command.add_command("restart", "Restart Traffic Server", [&]() { CtrlUnimplementedCommand("restart"); }) .add_example_usage("traffic_ctl server restart [OPTIONS]") - .add_option("--drain", "", "Wait for client connections to drain before restarting") - .add_option("--manager", "", "Restart traffic_manager as well as traffic_server"); - server_command.add_command("start", "Start the proxy", [&]() { engine.server_start(); }) + .add_option("--drain", "", "Wait for client connections to drain before restarting"); + server_command.add_command("start", "Start the proxy", [&]() { CtrlUnimplementedCommand("start"); }) .add_example_usage("traffic_ctl server start [OPTIONS]") .add_option("--clear-cache", "", "Clear the disk cache on startup") .add_option("--clear-hostdb", "", "Clear the DNS cache on startup"); - server_command.add_command("status", "Show the proxy status", [&]() { engine.server_status(); }) + server_command.add_command("status", "Show the proxy status", [&]() { CtrlUnimplementedCommand("status"); }) .add_example_usage("traffic_ctl server status"); - server_command.add_command("stop", "Stop the proxy", [&]() { engine.server_stop(); }) + server_command.add_command("stop", "Stop the proxy", [&]() { CtrlUnimplementedCommand("stop"); }) .add_example_usage("traffic_ctl server stop [OPTIONS]") .add_option("--drain", "", "Wait for client connections to drain before stopping"); - server_command.add_command("drain", "Drain the requests", [&]() { engine.server_drain(); }) + server_command.add_command("drain", "Drain the requests", [&]() { command->execute(); }) .add_example_usage("traffic_ctl server drain [OPTIONS]") .add_option("--no-new-connection", "-N", "Wait for new connections down to threshold before starting draining") .add_option("--undo", "-U", "Recover server from the drain mode"); // storage commands storage_command - .add_command("offline", "Take one or more storage volumes offline", "", MORE_THAN_ONE_ARG_N, - [&]() { engine.storage_offline(); }) + .add_command("offline", "Take one or more storage volumes offline", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) .add_example_usage("storage offline DEVICE [DEVICE ...]"); - storage_command.add_command("status", "Show the storage configuration", "", MORE_THAN_ZERO_ARG_N, - [&]() { engine.CtrlUnimplementedCommand("status"); }); // not implemented - - // parse the arguments - engine.arguments = engine.parser.parse(argv); - - BaseLogFile *base_log_file = new BaseLogFile("stderr"); - DiagsPtr::set(new Diags("traffic_ctl", "" /* tags */, "" /* actions */, base_log_file)); - - if (engine.arguments.get("debug")) { - diags()->activate_taglist("traffic_ctl", DiagsTagType_Debug); - diags()->config.enabled(DiagsTagType_Debug, 1); - diags()->show_location = SHOW_LOCATION_DEBUG; + storage_command.add_command("status", "Show the storage configuration", "", MORE_THAN_ONE_ARG_N, + [&]() { command->execute(); }); // not implemented + + // direct rpc commands, handy for debug and trouble shooting + direct_rpc_command + .add_command("file", "Send direct JSONRPC request to the server from a passed file(s)", "", MORE_THAN_ONE_ARG_N, + [&]() { command->execute(); }) + .add_example_usage("traffic_ctl rpc file request.yaml"); + direct_rpc_command.add_command("get-api", "Request full API from server", "", 0, [&]() { command->execute(); }) + .add_example_usage("traffic_ctl rpc get-api"); + direct_rpc_command + .add_command("input", "Read from standard input. Ctrl-D to send the request", "", 0, [&]() { command->execute(); }) + .add_option("--raw", "-r", + "No json/yaml parse validation will take place, the raw content will be directly send to the server.", "", 0, "", + "raw") + .add_example_usage("traffic_ctl rpc input "); + direct_rpc_command + .add_command("invoke", "Call a method by using the method name as input parameter", "", MORE_THAN_ONE_ARG_N, + [&]() { command->execute(); }) + .add_option("--params", "-p", "Parameters to be passed in the request, YAML or JSON format", "", MORE_THAN_ONE_ARG_N, "", "") + .add_example_usage("traffic_ctl rpc invoke foo_bar -p \"numbers: [1, 2, 3]\""); + + try { + auto args = parser.parse(argv); + argparser_runroot_handler(args.get("run-root").value(), argv[0]); + Layout::create(); + + if (args.get("config")) { + command = std::make_shared(args); + } else if (args.get("metric")) { + command = std::make_shared(args); + } else if (args.get("server")) { + command = std::make_shared(args); + } else if (args.get("storage")) { + command = std::make_shared(args); + } else if (args.get("plugin")) { + command = std::make_shared(args); + } else if (args.get("host")) { + command = std::make_shared(args); + } else if (args.get("rpc")) { + command = std::make_shared(args); + } + // Execute + args.invoke(); + } catch (std::exception const &ex) { + status_code = CTRL_EX_ERROR; + std::cerr << "Error found.\n" << ex.what() << '\n'; } - argparser_runroot_handler(engine.arguments.get("run-root").value(), argv[0]); - Layout::create(); - - // This is a little bit of a hack, for now it'll suffice. - max_records_entries = 262144; - RecProcessInit(RECM_STAND_ALONE, diags()); - LibRecordsConfigInit(); - - ats_scoped_str rundir(RecConfigReadRuntimeDir()); - - // Make a best effort to connect the control socket. If it turns out we are - // just displaying help or something then it - // doesn't matter that we failed. If we end up performing some operation then - // that operation will fail and display the - // error. - TSInit(rundir, static_cast(TS_MGMT_OPT_NO_EVENTS | TS_MGMT_OPT_NO_SOCK_TESTS)); - - engine.arguments.invoke(); - - // Done with the mgmt API. - TSTerminate(); - - return engine.status_code; + return status_code; } diff --git a/src/traffic_ctl/traffic_ctl.h b/src/traffic_ctl/traffic_ctl.h deleted file mode 100644 index 94073f6323e..00000000000 --- a/src/traffic_ctl/traffic_ctl.h +++ /dev/null @@ -1,220 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include "tscore/ink_platform.h" -#include "tscore/Diags.h" -#include "tscore/ink_memory.h" -#include "mgmtapi.h" -#include "tscore/ink_args.h" -#include "tscore/I_Version.h" -#include "tscore/BaseLogFile.h" -#include "tscore/ArgParser.h" - -#include -#include -#include - -// Exit status codes, following BSD's sysexits(3) -constexpr int CTRL_EX_OK = 0; -constexpr int CTRL_EX_ERROR = 2; -constexpr int CTRL_EX_UNIMPLEMENTED = 3; -constexpr int CTRL_EX_USAGE = EX_USAGE; -constexpr int CTRL_EX_UNAVAILABLE = 69; - -#define CtrlDebug(...) Debug("traffic_ctl", __VA_ARGS__) - -void CtrlMgmtError(TSMgmtError err, const char *fmt, ...) TS_PRINTFLIKE(2, 3); - -#define CTRL_MGMT_CHECK(expr) \ - do { \ - TSMgmtError e = (expr); \ - if (e != TS_ERR_OKAY) { \ - CtrlDebug("%s failed with status %d", #expr, e); \ - CtrlMgmtError(e, nullptr); \ - status_code = CTRL_EX_ERROR; \ - return; \ - } \ - } while (0) - -struct CtrlMgmtRecord { - explicit CtrlMgmtRecord(TSRecordEle *e) : ele(e) {} - CtrlMgmtRecord() : ele(TSRecordEleCreate()) {} - ~CtrlMgmtRecord() - { - if (this->ele) { - TSRecordEleDestroy(this->ele); - } - } - - TSMgmtError fetch(const char *); - - const char *name() const; - TSRecordT type() const; - int rclass() const; - int64_t as_int() const; - - // noncopyable - CtrlMgmtRecord(const CtrlMgmtRecord &) = delete; // disabled - CtrlMgmtRecord &operator=(const CtrlMgmtRecord &) = delete; // disabled - -private: - TSRecordEle *ele; - - friend struct CtrlMgmtRecordValue; -}; - -struct CtrlMgmtRecordValue { - explicit CtrlMgmtRecordValue(const TSRecordEle *); - explicit CtrlMgmtRecordValue(const CtrlMgmtRecord &); - - CtrlMgmtRecordValue(TSRecordT, TSRecordValueT); - const char *c_str() const; - - // noncopyable - CtrlMgmtRecordValue(const CtrlMgmtRecordValue &) = delete; // disabled - CtrlMgmtRecordValue &operator=(const CtrlMgmtRecordValue &) = delete; // disabled - -private: - void init(TSRecordT, TSRecordValueT); - - TSRecordT rec_type; - union { - const char *str; - char nbuf[32]; - } fmt; -}; - -struct RecordListPolicy { - typedef TSRecordEle *entry_type; - - static void - free(entry_type e) - { - TSRecordEleDestroy(e); - } - - static entry_type - cast(void *ptr) - { - return (entry_type)ptr; - } -}; - -template struct CtrlMgmtList { - CtrlMgmtList() : list(TSListCreate()) {} - ~CtrlMgmtList() - { - this->clear(); - TSListDestroy(this->list); - } - - bool - empty() const - { - return TSListIsEmpty(this->list); - } - - void - clear() const - { - while (!this->empty()) { - T::free(T::cast(TSListDequeue(this->list))); - } - } - - // Return (ownership of) the next list entry. - typename T::entry_type - next() - { - return T::cast(TSListDequeue(this->list)); - } - - TSList list; - - // noncopyable - CtrlMgmtList(const CtrlMgmtList &) = delete; // disabled - CtrlMgmtList &operator=(const CtrlMgmtList &) = delete; // disabled -}; - -struct CtrlMgmtRecordList : CtrlMgmtList { - TSMgmtError match(const char *); -}; - -// this is a engine for traffic_ctl containing the ArgParser and all the methods -// it also has a status code which can be set by these methods to return -struct CtrlEngine { - // the parser for traffic_ctl - ts::ArgParser parser; - // parsed arguments - ts::Arguments arguments; - // the return status code from functions - // By default it is set to CTRL_EX_OK so we don't need to set it - // in each method when they finish successfully. - int status_code = CTRL_EX_OK; - - // All traffic_ctl methods: - // unimplemented command - void CtrlUnimplementedCommand(std::string_view command); - - // alarm methods - void alarm_list(); - void alarm_clear(); - void alarm_resolve(); - - // config methods - void config_defaults(); - void config_diff(); - void config_status(); - void config_reload(); - void config_match(); - void config_get(); - void config_set(); - void config_describe(); - - // host methods - void status_get(); - void status_down(); - void status_up(); - - // metric methods - void metric_get(); - void metric_match(); - void metric_clear(); - void metric_zero(); - - // metric methods - void plugin_msg(); - - // server methods - void server_restart(); - void server_backtrace(); - void server_status(); - void server_stop(); - void server_start(); - void server_drain(); - - // storage methods - void storage_offline(); -}; diff --git a/src/traffic_ctl_jsonrpc/Makefile.inc b/src/traffic_ctl_jsonrpc/Makefile.inc deleted file mode 100644 index bb47533cca0..00000000000 --- a/src/traffic_ctl_jsonrpc/Makefile.inc +++ /dev/null @@ -1,37 +0,0 @@ -# -# Makefile.am for the Enterprise Management module. -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -bin_PROGRAMS += traffic_ctl_jsonrpc/traffic_ctl - -traffic_ctl_jsonrpc_traffic_ctl_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(TS_INCLUDES) \ - -I$(abs_top_srcdir)/mgmt2 \ - -I$(abs_top_srcdir)/include \ - @YAMLCPP_INCLUDES@ - -traffic_ctl_jsonrpc_traffic_ctl_SOURCES = \ - traffic_ctl_jsonrpc/traffic_ctl.cc \ - traffic_ctl_jsonrpc/CtrlPrinters.cc \ - traffic_ctl_jsonrpc/CtrlCommands.cc \ - shared/rpc/IPCSocketClient.cc - -traffic_ctl_jsonrpc_traffic_ctl_LDADD = \ - $(top_builddir)/src/tscore/libtscore.la \ - @HWLOC_LIBS@ @YAMLCPP_LIBS@ diff --git a/src/traffic_ctl_jsonrpc/traffic_ctl.cc b/src/traffic_ctl_jsonrpc/traffic_ctl.cc deleted file mode 100644 index 73298806b6c..00000000000 --- a/src/traffic_ctl_jsonrpc/traffic_ctl.cc +++ /dev/null @@ -1,195 +0,0 @@ -/** @file - - traffic_ctl - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include - -#include "tscore/I_Layout.h" -#include "tscore/runroot.h" -#include "tscore/ArgParser.h" - -#include "CtrlCommands.h" - -constexpr int CTRL_EX_OK = 0; -constexpr int CTRL_EX_ERROR = 2; -constexpr int CTRL_EX_UNIMPLEMENTED = 3; - -int status_code{CTRL_EX_OK}; - -int -main(int argc, const char **argv) -{ - ts::ArgParser parser; - - std::shared_ptr command; - - auto CtrlUnimplementedCommand = [](std::string_view cmd) { - std::cout << "Command " << cmd << " unimplemented.\n"; - status_code = CTRL_EX_UNIMPLEMENTED; - }; - - parser.add_description("Apache Traffic Server RPC CLI"); - parser.add_global_usage("traffic_ctl [OPTIONS] CMD [ARGS ...]"); - parser.require_commands(); - - parser.add_option("--debug", "", "Enable debugging output - unimplemented") - .add_option("--version", "-V", "Print version string") - .add_option("--help", "-h", "Print usage information") - .add_option("--run-root", "", "using TS_RUNROOT as sandbox", "TS_RUNROOT", 1) - .add_option("--format", "-f", "Use a specific output format {legacy|pretty|json|rpc}", "", 1, "legacy", "format"); - - auto &config_command = parser.add_command("config", "Manipulate configuration records").require_commands(); - auto &metric_command = parser.add_command("metric", "Manipulate performance metrics").require_commands(); - auto &server_command = parser.add_command("server", "Stop, restart and examine the server").require_commands(); - auto &storage_command = parser.add_command("storage", "Manipulate cache storage").require_commands(); - auto &plugin_command = parser.add_command("plugin", "Interact with plugins").require_commands(); - auto &host_command = parser.add_command("host", "Interact with host status").require_commands(); - auto &direct_rpc_command = parser.add_command("rpc", "Interact with the rpc api").require_commands(); - - // config commands - config_command.add_command("defaults", "Show default information configuration values", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config defaults [OPTIONS]") - .add_option("--records", "", "Emit output in records.config format"); - config_command - .add_command("describe", "Show detailed information about configuration values", "", MORE_THAN_ONE_ARG_N, - [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config describe RECORD [RECORD ...]"); - config_command.add_command("diff", "Show non-default configuration values", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config diff [OPTIONS]") - .add_option("--records", "", "Emit output in records.config format"); - config_command.add_command("get", "Get one or more configuration values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config get [OPTIONS] RECORD [RECORD ...]") - .add_option("--records", "", "Emit output in records.config format"); - config_command - .add_command("match", "Get configuration matching a regular expression", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config match [OPTIONS] REGEX [REGEX ...]") - .add_option("--records", "", "Emit output in records.config format"); - config_command.add_command("reload", "Request a configuration reload", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config reload"); - config_command.add_command("status", "Check the configuration status", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config status"); - config_command.add_command("set", "Set a configuration value", "", 2, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config set RECORD VALUE"); - - config_command.add_command("registry", "Show configuration file registry", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl config registry"); - // host commands - host_command.add_command("status", "Get one or more host statuses", "", MORE_THAN_ZERO_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl host status HOST [HOST ...]"); - host_command.add_command("down", "Set down one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl host down HOST [OPTIONS]") - .add_option("--time", "-I", "number of seconds that a host is marked down", "", 1, "0") - .add_option("--reason", "", "reason for marking the host down, one of 'manual|active|local", "", 1, "manual"); - host_command.add_command("up", "Set up one or more host(s)", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl host up METRIC value") - .add_option("--reason", "", "reason for marking the host up, one of 'manual|active|local", "", 1, "manual"); - - // metric commands - metric_command.add_command("get", "Get one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl metric get METRIC [METRIC ...]"); - metric_command.add_command("clear", "Clear all metric values", [&]() { command->execute(); }); - metric_command.add_command("describe", "Show detailed information about one or more metric values", "", MORE_THAN_ONE_ARG_N, - [&]() { command->execute(); }); // not implemented - metric_command.add_command("match", "Get metrics matching a regular expression", "", MORE_THAN_ZERO_ARG_N, - [&]() { command->execute(); }); - metric_command.add_command("monitor", "Display the value of a metric over time", "", MORE_THAN_ZERO_ARG_N, - [&]() { CtrlUnimplementedCommand("monitor"); }); // not implemented - metric_command.add_command("zero", "Clear one or more metric values", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }); - - // plugin command - plugin_command.add_command("msg", "Send message to plugins - a TAG and the message DATA", "", 2, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl plugin msg TAG DATA"); - - // server commands - server_command.add_command("backtrace", "Show a full stack trace of the traffic_server process", - [&]() { CtrlUnimplementedCommand("backtrace"); }); - server_command.add_command("restart", "Restart Traffic Server", [&]() { CtrlUnimplementedCommand("restart"); }) - .add_example_usage("traffic_ctl server restart [OPTIONS]") - .add_option("--drain", "", "Wait for client connections to drain before restarting"); - server_command.add_command("start", "Start the proxy", [&]() { CtrlUnimplementedCommand("start"); }) - .add_example_usage("traffic_ctl server start [OPTIONS]") - .add_option("--clear-cache", "", "Clear the disk cache on startup") - .add_option("--clear-hostdb", "", "Clear the DNS cache on startup"); - server_command.add_command("status", "Show the proxy status", [&]() { CtrlUnimplementedCommand("status"); }) - .add_example_usage("traffic_ctl server status"); - server_command.add_command("stop", "Stop the proxy", [&]() { CtrlUnimplementedCommand("stop"); }) - .add_example_usage("traffic_ctl server stop [OPTIONS]") - .add_option("--drain", "", "Wait for client connections to drain before stopping"); - server_command.add_command("drain", "Drain the requests", [&]() { command->execute(); }) - .add_example_usage("traffic_ctl server drain [OPTIONS]") - .add_option("--no-new-connection", "-N", "Wait for new connections down to threshold before starting draining") - .add_option("--undo", "-U", "Recover server from the drain mode"); - - // storage commands - storage_command - .add_command("offline", "Take one or more storage volumes offline", "", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); }) - .add_example_usage("storage offline DEVICE [DEVICE ...]"); - storage_command.add_command("status", "Show the storage configuration", "", MORE_THAN_ONE_ARG_N, - [&]() { command->execute(); }); // not implemented - - // direct rpc commands, handy for debug and trouble shooting - direct_rpc_command - .add_command("file", "Send direct JSONRPC request to the server from a passed file(s)", "", MORE_THAN_ONE_ARG_N, - [&]() { command->execute(); }) - .add_example_usage("traffic_ctl rpc file request.yaml"); - direct_rpc_command.add_command("get-api", "Request full API from server", "", 0, [&]() { command->execute(); }) - .add_example_usage("traffic_ctl rpc get-api"); - direct_rpc_command - .add_command("input", "Read from standard input. Ctrl-D to send the request", "", 0, [&]() { command->execute(); }) - .add_option("--raw", "-r", - "No json/yaml parse validation will take place, the raw content will be directly send to the server.", "", 0, "", - "raw") - .add_example_usage("traffic_ctl rpc input "); - direct_rpc_command - .add_command("invoke", "Call a method by using the method name as input parameter", "", MORE_THAN_ONE_ARG_N, - [&]() { command->execute(); }) - .add_option("--params", "-p", "Parameters to be passed in the request, YAML or JSON format", "", MORE_THAN_ONE_ARG_N, "", "") - .add_example_usage("traffic_ctl rpc invoke foo_bar -p \"numbers: [1, 2, 3]\""); - try { - auto args = parser.parse(argv); - argparser_runroot_handler(args.get("run-root").value(), argv[0]); - Layout::create(); - - if (args.get("config")) { - command = std::make_shared(args); - } else if (args.get("metric")) { - command = std::make_shared(args); - } else if (args.get("server")) { - command = std::make_shared(args); - } else if (args.get("storage")) { - command = std::make_shared(args); - } else if (args.get("plugin")) { - command = std::make_shared(args); - } else if (args.get("host")) { - command = std::make_shared(args); - } else if (args.get("rpc")) { - command = std::make_shared(args); - } - // Execute - args.invoke(); - } catch (std::exception const &ex) { - status_code = CTRL_EX_ERROR; - std::cerr << "Error found.\n" << ex.what() << '\n'; - } - - return status_code; -} diff --git a/src/traffic_layout/file_system.cc b/src/traffic_layout/file_system.cc index b56c13c1fb0..ca727d677dd 100644 --- a/src/traffic_layout/file_system.cc +++ b/src/traffic_layout/file_system.cc @@ -41,9 +41,17 @@ static std::string remove_path; CopyStyle copy_style; // list of all executables of traffic server -std::set const executables = {"traffic_crashlog", "traffic_ctl", "traffic_layout", "traffic_logcat", - "traffic_logstats", "traffic_manager", "traffic_server", "traffic_top", - "traffic_via", "trafficserver", "tspush", "tsxs"}; +std::set const executables = {"traffic_crashlog", + "traffic_ctl", + "traffic_layout", + "traffic_logcat", + "traffic_logstats", + "traffic_server", + "traffic_top", + "traffic_via", + "trafficserver", + "tspush", + "tsxs"}; void append_slash(std::string &path) diff --git a/src/traffic_manager/AddConfigFilesHere.cc b/src/traffic_manager/AddConfigFilesHere.cc deleted file mode 100644 index ec2a0f208cc..00000000000 --- a/src/traffic_manager/AddConfigFilesHere.cc +++ /dev/null @@ -1,97 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/Filenames.h" -#include "MgmtUtils.h" -#include "tscore/Diags.h" -#include "FileManager.h" - -extern FileManager *configFiles; - -static constexpr bool REQUIRED{true}; -static constexpr bool NOT_REQUIRED{false}; -/**************************************************************************** - * - * AddConfigFilesHere.cc - Structs for config files and - * - * - ****************************************************************************/ - -void -testcall(char *foo, char * /*configName */) -{ - Debug("lm", "Received Callback that %s has changed", foo); -} - -void -registerFile(const char *configName, const char *defaultName, bool isRequired, bool isElevateNeeded = false) -{ - bool found = false; - char *fname = REC_readString(configName, &found); - if (!found) { - fname = ats_strdup(defaultName); - } - configFiles->addFile(fname, configName, isElevateNeeded, isRequired); - ats_free(fname); -} - -// -// initializeRegistry() -// -// Code to initialize of registry of objects that represent -// Web Editable configuration files -// -// thread-safe: NO! - Should only be executed once from the main -// web interface thread, before any child -// threads have been spawned -void -initializeRegistry() -{ - static int run_already = 0; - - if (run_already == 0) { - run_already = 1; - } else { - ink_assert(!"Configuration Object Registry Initialized More than Once"); - } - - registerFile("proxy.config.log.config.filename", ts::filename::LOGGING, NOT_REQUIRED); - registerFile("", ts::filename::STORAGE, REQUIRED); - registerFile("proxy.config.socks.socks_config_file", ts::filename::SOCKS, NOT_REQUIRED); - registerFile(ts::filename::RECORDS, ts::filename::RECORDS, NOT_REQUIRED); - registerFile("proxy.config.cache.control.filename", ts::filename::CACHE, NOT_REQUIRED); - registerFile("proxy.config.cache.ip_allow.filename", ts::filename::IP_ALLOW, NOT_REQUIRED); - registerFile("proxy.config.http.parent_proxy.file", ts::filename::PARENT, NOT_REQUIRED); - registerFile("proxy.config.url_remap.filename", ts::filename::REMAP, NOT_REQUIRED); - registerFile("", ts::filename::VOLUME, NOT_REQUIRED); - registerFile("proxy.config.cache.hosting_filename", ts::filename::HOSTING, NOT_REQUIRED); - registerFile("", ts::filename::PLUGIN, NOT_REQUIRED); - registerFile("proxy.config.dns.splitdns.filename", ts::filename::SPLITDNS, NOT_REQUIRED); - uint32_t elevate_setting = 0; - REC_ReadConfigInteger(elevate_setting, "proxy.config.ssl.cert.load_elevated"); - registerFile("proxy.config.ssl.server.multicert.filename", ts::filename::SSL_MULTICERT, NOT_REQUIRED, elevate_setting); - registerFile("proxy.config.ssl.servername.filename", ts::filename::SNI, NOT_REQUIRED); - - configFiles->registerCallback(testcall); -} diff --git a/src/traffic_manager/Makefile.inc b/src/traffic_manager/Makefile.inc deleted file mode 100644 index db5a9553e37..00000000000 --- a/src/traffic_manager/Makefile.inc +++ /dev/null @@ -1,61 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -bin_PROGRAMS += traffic_manager/traffic_manager - -traffic_manager_traffic_manager_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(iocore_include_dirs) \ - -I$(abs_top_srcdir)/include \ - -I$(abs_top_srcdir)/lib \ - -I$(abs_top_srcdir)/proxy/hdrs \ - -I$(abs_top_srcdir)/proxy/shared \ - -I$(abs_top_srcdir)/mgmt \ - -I$(abs_top_srcdir)/mgmt/api \ - -I$(abs_top_srcdir)/mgmt/api/include \ - -I$(abs_top_srcdir)/mgmt/utils \ - $(TS_INCLUDES) - -traffic_manager_traffic_manager_LDFLAGS = \ - $(AM_LDFLAGS) \ - @OPENSSL_LDFLAGS@ \ - @YAMLCPP_LDFLAGS@ - -traffic_manager_traffic_manager_SOURCES = \ - traffic_manager/AddConfigFilesHere.cc \ - traffic_manager/traffic_manager.cc - -traffic_manager_traffic_manager_LDADD = \ - $(top_builddir)/mgmt/api/libmgmtapilocal.la \ - $(top_builddir)/mgmt/libmgmt_lm.la \ - $(top_builddir)/proxy/hdrs/libhdrs.a \ - $(top_builddir)/src/tscore/libtscore.la \ - $(top_builddir)/src/tscpp/util/libtscpputil.la \ - $(top_builddir)/iocore/eventsystem/libinkevent.a \ - $(top_builddir)/lib/records/librecords_lm.a \ - $(top_builddir)/proxy/shared/libdiagsconfig.a \ - $(LIBUNWIND_LIBS) \ - @LIBPCRE@ @LIBCAP@ @HWLOC_LIBS@ \ - @YAMLCPP_LIBS@ - -lm - -# Must do it this way or the dependencies aren't detected. -if BUILD_WCCP -traffic_manager_traffic_manager_LDADD += \ - wccp/libwccp.a \ - @OPENSSL_LIBS@ -endif diff --git a/src/traffic_manager/traffic_manager.cc b/src/traffic_manager/traffic_manager.cc deleted file mode 100644 index f04c3df0302..00000000000 --- a/src/traffic_manager/traffic_manager.cc +++ /dev/null @@ -1,1096 +0,0 @@ -/** @file - - Entry point to the traffic manager. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "tscore/ink_platform.h" -#include "tscore/ink_sys_control.h" -#include "tscore/ink_cap.h" -#include "tscore/ink_lockfile.h" -#include "tscore/ink_sock.h" -#include "tscore/ink_args.h" -#include "tscore/ink_syslog.h" -#include "tscore/runroot.h" -#include "tscore/Filenames.h" - -#include "WebMgmtUtils.h" -#include "MgmtUtils.h" -#include "MgmtSocket.h" -#include "NetworkUtilsRemote.h" -#include "FileManager.h" -#include "tscore/I_Layout.h" -#include "tscore/I_Version.h" -#include "tscore/TextBuffer.h" -#include "DiagsConfig.h" -#include "HTTP.h" -#include "CoreAPI.h" - -#include "LocalManager.h" -#include "TSControlMain.h" -#include "EventControlMain.h" - -// Needs LibRecordsConfigInit() -#include "RecordsConfig.h" - -#include "records/P_RecLocal.h" -#include "DerivativeMetrics.h" - -#include - -#if TS_USE_POSIX_CAP -#include -#endif -#include -#include -#include "tscore/bwf_std_format.h" - -#define FD_THROTTLE_HEADROOM (128 + 64) // TODO: consolidate with THROTTLE_FD_HEADROOM -#define DEFAULT_DIAGS_LOG_FILENAME "manager.log" -static char diags_log_filename[PATH_NAME_MAX] = DEFAULT_DIAGS_LOG_FILENAME; - -#if ATOMIC_INT_LOCK_FREE != 2 -#error "Need lock free std::atomic" -#endif - -using namespace std::literals; - -// These globals are still referenced directly by management API. -LocalManager *lmgmt = nullptr; -FileManager *configFiles; - -static void fileUpdated(char *fname, char *configName); -static void runAsUser(const char *userName); - -#if defined(freebsd) -extern "C" int getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, struct passwd **resptr); -#endif - -static AppVersionInfo appVersionInfo; // Build info for this application - -static DiagsConfig *diagsConfig = nullptr; -static char debug_tags[1024] = ""; -static char action_tags[1024] = ""; -static int proxy_off = false; -static int listen_off = false; -static char bind_stdout[512] = ""; -static char bind_stderr[512] = ""; -static const char *mgmt_path = nullptr; - -// By default, set the current directory as base -static const char *recs_conf = ts::filename::RECORDS; - -static int fds_limit; - -// TODO: Use positive instead negative selection -// This should just be #if defined(solaris) -#if !defined(linux) && !defined(freebsd) && !defined(darwin) -static void SignalHandler(int sig, siginfo_t *t, void *f); -static void SignalAlrmHandler(int sig, siginfo_t *t, void *f); -#else -static void SignalHandler(int sig); -static void SignalAlrmHandler(int sig); -#endif - -static std::atomic sigHupNotifier; -static void SigChldHandler(int sig); - -static void -rotateLogs() -{ - // First, let us synchronously update the rolling config values for both diagslog - // and outputlog. Note that the config values for outputlog in traffic_server - // are never updated past the original instantiation of Diags. This shouldn't - // be an issue since we're never rolling outputlog from traffic_server anyways. - // The reason being is that it is difficult to send a notification from TS to - // TM, informing TM that outputlog has been rolled. It is much easier sending - // a notification (in the form of SIGUSR2) from TM -> TS. - int output_log_roll_int = (int)REC_ConfigReadInteger("proxy.config.output.logfile.rolling_interval_sec"); - int output_log_roll_size = (int)REC_ConfigReadInteger("proxy.config.output.logfile.rolling_size_mb"); - int output_log_roll_enable = (int)REC_ConfigReadInteger("proxy.config.output.logfile.rolling_enabled"); - int diags_log_roll_int = (int)REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_interval_sec"); - int diags_log_roll_size = (int)REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_size_mb"); - int diags_log_roll_enable = (int)REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_enabled"); - diags()->config_roll_diagslog((RollingEnabledValues)diags_log_roll_enable, diags_log_roll_int, diags_log_roll_size); - diags()->config_roll_outputlog((RollingEnabledValues)output_log_roll_enable, output_log_roll_int, output_log_roll_size); - - // Now we can actually roll the logs (if necessary) - if (diags()->should_roll_diagslog()) { - mgmt_log("Rotated %s", diags_log_filename); - } - - if (diags()->should_roll_outputlog()) { - // send a signal to TS to reload traffic.out, so the logfile is kept - // synced across processes - mgmt_log("Sending SIGUSR2 to TS"); - pid_t tspid = lmgmt->watched_process_pid; - if (tspid <= 0) { - return; - } - if (kill(tspid, SIGUSR2) != 0) { - mgmt_log("Could not send SIGUSR2 to TS: %s", strerror(errno)); - } else { - mgmt_log("Successfully sent SIGUSR2 to TS!"); - } - } -} - -static bool -is_server_idle() -{ - RecInt active = 0; - RecInt threshold = 0; - - if (RecGetRecordInt("proxy.config.restart.active_client_threshold", &threshold) != REC_ERR_OKAY) { - return false; - } - - if (RecGetRecordInt("proxy.process.http.current_active_client_connections", &active) != REC_ERR_OKAY) { - return false; - } - - Debug("lm", "%" PRId64 " active clients, threshold is %" PRId64, active, threshold); - return active <= threshold; -} - -static bool -is_server_idle_from_new_connection() -{ - RecInt active = 0; - RecInt threshold = 0; - - Debug("lm", "%" PRId64 " active clients, threshold is %" PRId64, active, threshold); - -#if 0 - // TODO implement with the right metric - return active <= threshold; -#else - return true; -#endif -} - -static bool -is_server_draining() -{ - RecInt draining = 0; - if (RecGetRecordInt("proxy.node.config.draining", &draining) != REC_ERR_OKAY) { - return false; - } - return draining != 0; -} - -static bool -waited_enough() -{ - RecInt timeout = 0; - if (RecGetRecordInt("proxy.config.stop.shutdown_timeout", &timeout) != REC_ERR_OKAY) { - return false; - } - - return (timeout ? (lmgmt->mgmt_shutdown_triggered_at + timeout <= time(nullptr)) : false); -} - -static void -check_lockfile() -{ - std::string rundir(RecConfigReadRuntimeDir()); - char lockfile[PATH_NAME_MAX]; - int err; - pid_t holding_pid; - - ////////////////////////////////////// - // test for presence of server lock // - ////////////////////////////////////// - Layout::relative_to(lockfile, sizeof(lockfile), rundir, SERVER_LOCK); - Lockfile server_lockfile(lockfile); - err = server_lockfile.Open(&holding_pid); - if (err == 1) { - server_lockfile.Close(); // no server running - } else { - char *reason = strerror(-err); - if (err == 0) { - fprintf(stderr, "FATAL: Lockfile '%s' says server already running as PID %ld\n", lockfile, static_cast(holding_pid)); - mgmt_log("FATAL: Lockfile '%s' says server already running as PID %d\n", lockfile, holding_pid); - } else { - fprintf(stderr, "FATAL: Can't open server lockfile '%s' (%s)\n", lockfile, (reason ? reason : "Unknown Reason")); - mgmt_log("FATAL: Can't open server lockfile '%s' (%s)\n", lockfile, (reason ? reason : "Unknown Reason")); - } - exit(1); - } - - /////////////////////////////////////////// - // try to get the exclusive manager lock // - /////////////////////////////////////////// - Layout::relative_to(lockfile, sizeof(lockfile), rundir, MANAGER_LOCK); - Lockfile manager_lockfile(lockfile); - err = manager_lockfile.Get(&holding_pid); - if (err != 1) { - char *reason = strerror(-err); - fprintf(stderr, "FATAL: Can't acquire manager lockfile '%s'", lockfile); - mgmt_log("FATAL: Can't acquire manager lockfile '%s'", lockfile); - if (err == 0) { - fprintf(stderr, " (Lock file held by process ID %ld)\n", static_cast(holding_pid)); - mgmt_log(" (Lock file held by process ID %d)\n", holding_pid); - } else if (reason) { - fprintf(stderr, " (%s)\n", reason); - mgmt_log(" (%s)\n", reason); - } else { - fprintf(stderr, "\n"); - } - exit(1); - - fprintf(stderr, "unable to acquire manager lock [%d]\n", -err); - exit(1); - } -} - -static void -initSignalHandlers() -{ - struct sigaction sigHandler, sigChldHandler, sigAlrmHandler; - sigset_t sigsToBlock; - -// Set up the signal handler -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - sigHandler.sa_handler = nullptr; - sigHandler.sa_sigaction = SignalHandler; -#else - sigHandler.sa_handler = SignalHandler; -#endif - sigemptyset(&sigHandler.sa_mask); - - // We want the handler to remain in place on - // SIGHUP to avoid any races with the signals - // coming too quickly. Also restart systems calls - // after the signal since not all calls are wrapped - // to check errno for EINTR - sigHandler.sa_flags = SA_RESTART; - sigaction(SIGHUP, &sigHandler, nullptr); - sigaction(SIGUSR2, &sigHandler, nullptr); - -// Don't block the signal on entry to the signal -// handler so we can reissue it and get a core -// file in the appropriate circumstances -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - sigHandler.sa_flags = SA_RESETHAND | SA_SIGINFO; -#else - sigHandler.sa_flags = SA_RESETHAND; -#endif - sigaction(SIGINT, &sigHandler, nullptr); - sigaction(SIGQUIT, &sigHandler, nullptr); - sigaction(SIGILL, &sigHandler, nullptr); - sigaction(SIGBUS, &sigHandler, nullptr); - sigaction(SIGSEGV, &sigHandler, nullptr); - sigaction(SIGTERM, &sigHandler, nullptr); - -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - sigAlrmHandler.sa_handler = nullptr; - sigAlrmHandler.sa_sigaction = SignalAlrmHandler; -#else - sigAlrmHandler.sa_handler = SignalAlrmHandler; -#endif - - sigemptyset(&sigAlrmHandler.sa_mask); -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - sigAlrmHandler.sa_flags = SA_SIGINFO; -#else - sigAlrmHandler.sa_flags = 0; -#endif - sigaction(SIGALRM, &sigAlrmHandler, nullptr); - - // Block the delivery of any signals we are not catching - // - // except for SIGALRM since we use it - // to break out of deadlock on semaphore - // we share with the proxy - // - sigfillset(&sigsToBlock); - sigdelset(&sigsToBlock, SIGHUP); - sigdelset(&sigsToBlock, SIGUSR2); - sigdelset(&sigsToBlock, SIGINT); - sigdelset(&sigsToBlock, SIGQUIT); - sigdelset(&sigsToBlock, SIGILL); - sigdelset(&sigsToBlock, SIGABRT); - sigdelset(&sigsToBlock, SIGBUS); - sigdelset(&sigsToBlock, SIGSEGV); - sigdelset(&sigsToBlock, SIGTERM); - sigdelset(&sigsToBlock, SIGALRM); - ink_thread_sigsetmask(SIG_SETMASK, &sigsToBlock, nullptr); - - // Set up the SIGCHLD handler so we do not get into - // a problem with Solaris 2.6 and strange waitpid() - // behavior - sigChldHandler.sa_handler = SigChldHandler; - sigChldHandler.sa_flags = SA_RESTART; - sigemptyset(&sigChldHandler.sa_mask); - sigaction(SIGCHLD, &sigChldHandler, nullptr); -} - -static void -init_dirs() -{ - std::string rundir(RecConfigReadRuntimeDir()); - std::string sysconfdir(RecConfigReadConfigDir()); - - if (access(sysconfdir.c_str(), R_OK) == -1) { - mgmt_elog(0, "unable to access() config directory '%s': %d, %s\n", sysconfdir.c_str(), errno, strerror(errno)); - mgmt_elog(0, "please set the 'TS_ROOT' environment variable\n"); - ::exit(1); - } - - if (access(rundir.c_str(), R_OK) == -1) { - mgmt_elog(0, "unable to access() local state directory '%s': %d, %s\n", rundir.c_str(), errno, strerror(errno)); - mgmt_elog(0, "please set 'proxy.config.local_state_dir'\n"); - ::exit(1); - } -} - -static void -chdir_root() -{ - std::string prefix = Layout::get()->prefix; - - if (chdir(prefix.c_str()) < 0) { - mgmt_elog(0, "unable to change to root directory \"%s\" [%d '%s']\n", prefix.c_str(), errno, strerror(errno)); - mgmt_elog(0, " please set correct path in env variable TS_ROOT \n"); - exit(1); - } else { - mgmt_log("[TrafficManager] using root directory '%s'\n", prefix.c_str()); - } -} - -static void -set_process_limits(RecInt fds_throttle) -{ - struct rlimit lim; - rlim_t maxfiles; - - // Set needed rlimits (root) - ink_max_out_rlimit(RLIMIT_NOFILE); - ink_max_out_rlimit(RLIMIT_STACK); - ink_max_out_rlimit(RLIMIT_DATA); - ink_max_out_rlimit(RLIMIT_FSIZE); -#ifdef RLIMIT_RSS - ink_max_out_rlimit(RLIMIT_RSS); -#endif - - maxfiles = ink_get_max_files(); - if (maxfiles != RLIM_INFINITY) { - float file_max_pct = 0.9; - - REC_ReadConfigFloat(file_max_pct, "proxy.config.system.file_max_pct"); - if (file_max_pct > 1.0) { - file_max_pct = 1.0; - } - - lim.rlim_cur = lim.rlim_max = static_cast(maxfiles * file_max_pct); - if (setrlimit(RLIMIT_NOFILE, &lim) == 0 && getrlimit(RLIMIT_NOFILE, &lim) == 0) { - fds_limit = static_cast(lim.rlim_cur); - syslog(LOG_NOTICE, "NOTE: RLIMIT_NOFILE(%d):cur(%d),max(%d)", RLIMIT_NOFILE, static_cast(lim.rlim_cur), - static_cast(lim.rlim_max)); - } - } - - if (getrlimit(RLIMIT_NOFILE, &lim) == 0) { - if (fds_throttle > (int)(lim.rlim_cur + FD_THROTTLE_HEADROOM)) { - lim.rlim_cur = (lim.rlim_max = (rlim_t)fds_throttle); - if (!setrlimit(RLIMIT_NOFILE, &lim) && !getrlimit(RLIMIT_NOFILE, &lim)) { - fds_limit = static_cast(lim.rlim_cur); - syslog(LOG_NOTICE, "NOTE: RLIMIT_NOFILE(%d):cur(%d),max(%d)", RLIMIT_NOFILE, static_cast(lim.rlim_cur), - static_cast(lim.rlim_max)); - } - } - } -} - -#if TS_HAS_WCCP -static void -Errata_Logger(ts::Errata const &err) -{ - size_t n; - static size_t const SIZE = 4096; - char buff[SIZE]; - if (err.size()) { - ts::Errata::Code code = err.top().getCode(); - n = err.write(buff, SIZE, 1, 0, 2, "> "); - // strip trailing newlines. - while (n && (buff[n - 1] == '\n' || buff[n - 1] == '\r')) - buff[--n] = 0; - // log it. - if (code > 1) - mgmt_elog(0, "[WCCP]%s", buff); - else if (code > 0) - mgmt_log("[WCCP]%s", buff); - else - Debug("WCCP", "%s", buff); - } -} - -static void -Init_Errata_Logging() -{ - ts::Errata::registerSink(&Errata_Logger); -} -#endif - -static void -millisleep(int ms) -{ - struct timespec ts; - - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms - ts.tv_sec * 1000) * 1000 * 1000; - nanosleep(&ts, nullptr); // we use nanosleep instead of sleep because it does not interact with signals -} - -bool -api_socket_is_restricted() -{ - RecInt intval; - - // If the socket is not administratively restricted, check whether we have platform - // support. Otherwise, default to making it restricted. - if (RecGetRecordInt("proxy.config.admin.api.restricted", &intval) == REC_ERR_OKAY) { - if (intval == 0) { - return !mgmt_has_peereid(); - } - } - - return true; -} - -int -main(int argc, const char **argv) -{ - const long MAX_LOGIN = ink_login_name_max(); - - runroot_handler(argv); - - // Before accessing file system initialize Layout engine - Layout::create(); - mgmt_path = Layout::get()->sysconfdir.c_str(); - - // Set up the application version info - appVersionInfo.setup(PACKAGE_NAME, "traffic_manager", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, ""); - - bool found = false; - int just_started = 0; - // TODO: This seems completely incomplete, disabled for now - // int dump_config = 0, dump_process = 0, dump_node = 0, dump_local = 0; - char *proxy_port = nullptr; - char *tsArgs = nullptr; - int disable_syslog = false; - char userToRunAs[MAX_LOGIN + 1]; - RecInt fds_throttle = -1; - bool printed_unrecoverable = false; - - ArgumentDescription argument_descriptions[] = { - {"proxyOff", '-', "Disable proxy", "F", &proxy_off, nullptr, nullptr}, - {"listenOff", '-', "Disable traffic manager listen to proxy ports", "F", &listen_off, nullptr, nullptr}, - {"path", '-', "Path to the management socket", "S*", &mgmt_path, nullptr, nullptr}, - {"recordsConf", '-', "Path to records.config", "S*", &recs_conf, nullptr, nullptr}, - {"tsArgs", '-', "Additional arguments for traffic_server", "S*", &tsArgs, nullptr, nullptr}, - {"proxyPort", '-', "HTTP port descriptor", "S*", &proxy_port, nullptr, nullptr}, - {"maxRecords", 'm', "Max number of librecords metrics and configurations (default & minimum: 1600)", "I", &max_records_entries, - "PROXY_MAX_RECORDS", nullptr}, - {TM_OPT_BIND_STDOUT, '-', "Regular file to bind stdout to", "S512", &bind_stdout, "PROXY_BIND_STDOUT", nullptr}, - {TM_OPT_BIND_STDERR, '-', "Regular file to bind stderr to", "S512", &bind_stderr, "PROXY_BIND_STDERR", nullptr}, -#if TS_USE_DIAGS - {"debug", 'T', "Vertical-bar-separated Debug Tags", "S1023", debug_tags, nullptr, nullptr}, - {"action", 'B', "Vertical-bar-separated Behavior Tags", "S1023", action_tags, nullptr, nullptr}, -#endif - {"nosyslog", '-', "Do not log to syslog", "F", &disable_syslog, nullptr, nullptr}, - HELP_ARGUMENT_DESCRIPTION(), - VERSION_ARGUMENT_DESCRIPTION(), - RUNROOT_ARGUMENT_DESCRIPTION() - }; - - // Process command line arguments and dump into variables - process_args(&appVersionInfo, argument_descriptions, countof(argument_descriptions), argv); - - // change the directory to the "root" directory - chdir_root(); - - // Line buffer standard output & standard error - int status; - status = setvbuf(stdout, nullptr, _IOLBF, 0); - if (status != 0) { - perror("WARNING: can't line buffer stdout"); - } - status = setvbuf(stderr, nullptr, _IOLBF, 0); - if (status != 0) { - perror("WARNING: can't line buffer stderr"); - } - - initSignalHandlers(); - - // Bootstrap with LOG_DAEMON until we've read our configuration - if (!disable_syslog) { - openlog("traffic_manager", LOG_PID | LOG_NDELAY | LOG_NOWAIT, LOG_DAEMON); - mgmt_use_syslog(); - syslog(LOG_NOTICE, "NOTE: --- Manager Starting ---"); - syslog(LOG_NOTICE, "NOTE: Manager Version: %s", appVersionInfo.FullVersionInfoStr); - } - - // Bootstrap the Diags facility so that we can use it while starting - // up the manager - diagsConfig = new DiagsConfig("Manager", DEFAULT_DIAGS_LOG_FILENAME, debug_tags, action_tags, false); - diags()->set_std_output(StdStream::STDOUT, bind_stdout); - diags()->set_std_output(StdStream::STDERR, bind_stderr); - - RecLocalInit(); - LibRecordsConfigInit(); - - init_dirs(); // setup critical directories, needs LibRecords - - if (RecGetRecordString("proxy.config.admin.user_id", userToRunAs, sizeof(userToRunAs)) != REC_ERR_OKAY || - strlen(userToRunAs) == 0) { - mgmt_fatal(0, "proxy.config.admin.user_id is not set\n"); - } - - RecGetRecordInt("proxy.config.net.connections_throttle", &fds_throttle); - RecInt listen_per_thread = 0; - RecGetRecordInt("proxy.config.exec_thread.listen", &listen_per_thread); - if (listen_per_thread > 0) { // Turn off listening. Traffic server is going to listen on all the threads. - listen_off = true; - } - - set_process_limits(fds_throttle); // as root - - // A user of #-1 means to not attempt to switch user. Yes, it's documented ;) - if (strcmp(userToRunAs, "#-1") != 0) { - runAsUser(userToRunAs); - } - - EnableCoreFile(true); - check_lockfile(); - - url_init(); - mime_init(); - http_init(); - -#if TS_HAS_WCCP - Init_Errata_Logging(); -#endif - ts_host_res_global_init(); - ts_session_protocol_well_known_name_indices_init(); - lmgmt = new LocalManager(proxy_off == false, listen_off == false); - RecLocalInitMessage(); - lmgmt->initAlarm(); - - // INKqa11968: need to set up callbacks and diags data structures - // using configuration in records.config - REC_ReadConfigString(diags_log_filename, "proxy.node.config.manager_log_filename", sizeof(diags_log_filename)); - if (strnlen(diags_log_filename, sizeof(diags_log_filename)) == 0) { - strncpy(diags_log_filename, DEFAULT_DIAGS_LOG_FILENAME, sizeof(diags_log_filename)); - } - DiagsConfig *old_diagsconfig = diagsConfig; - diagsConfig = new DiagsConfig("Manager", diags_log_filename, debug_tags, action_tags, true); - if (old_diagsconfig) { - delete old_diagsconfig; - old_diagsconfig = nullptr; - } - - RecSetDiags(diags()); - diags()->set_std_output(StdStream::STDOUT, bind_stdout); - diags()->set_std_output(StdStream::STDERR, bind_stderr); - - if (is_debug_tag_set("diags")) { - diags()->dump(); - } - diags()->cleanup_func = mgmt_cleanup; - - // Setup the exported manager version records. - RecSetRecordString("proxy.node.version.manager.short", appVersionInfo.VersionStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.long", appVersionInfo.FullVersionInfoStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.build_number", appVersionInfo.BldNumStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.build_time", appVersionInfo.BldTimeStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.build_date", appVersionInfo.BldDateStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.build_machine", appVersionInfo.BldMachineStr, REC_SOURCE_DEFAULT); - RecSetRecordString("proxy.node.version.manager.build_person", appVersionInfo.BldPersonStr, REC_SOURCE_DEFAULT); - - if (!disable_syslog) { - char sys_var[] = "proxy.config.syslog_facility"; - char *facility_str = nullptr; - int facility_int; - - facility_str = REC_readString(sys_var, &found); - ink_assert(found); - - if (!found) { - mgmt_elog(0, "Could not read %s. Defaulting to LOG_DAEMON\n", sys_var); - facility_int = LOG_DAEMON; - } else { - facility_int = facility_string_to_int(facility_str); - ats_free(facility_str); - if (facility_int < 0) { - mgmt_elog(0, "Bad syslog facility specified. Defaulting to LOG_DAEMON\n"); - facility_int = LOG_DAEMON; - } - } - - // NOTE: do NOT call closelog() here. Solaris gets confused. - openlog("traffic_manager", LOG_PID | LOG_NDELAY | LOG_NOWAIT, facility_int); - - lmgmt->syslog_facility = facility_int; - } else { - lmgmt->syslog_facility = -1; - } - - // Find out our hostname so we can use it as part of the initialization - setHostnameVar(); - - // Initialize the Config Object bindings before - // starting any other threads - lmgmt->configFiles = configFiles = new FileManager(); - initializeRegistry(); - configFiles->registerCallback(fileUpdated); - - // RecLocal's 'sync_thr' depends on 'configFiles', so we can't - // stat the 'sync_thr' until 'configFiles' has been initialized. - RecLocalStart(configFiles); - - // TS needs to be started up with the same outputlog bindings each time, - // so we append the outputlog location to the persistent proxy options - // - // TS needs them to be able to create BaseLogFiles for each value - ts::bwprint(lmgmt->proxy_options, "{}{}{}", ts::bwf::OptionalAffix(tsArgs), - ts::bwf::OptionalAffix(bind_stdout, " "sv, "--bind_stdout "sv), - ts::bwf::OptionalAffix(bind_stderr, " "sv, "--bind_stderr "sv)); - - if (proxy_port) { - HttpProxyPort::loadValue(lmgmt->m_proxy_ports, proxy_port); - } - - lmgmt->initMgmtProcessServer(); /* Setup p-to-p process server */ - - lmgmt->listenForProxy(); - - // Setup the API and event sockets - std::string rundir(RecConfigReadRuntimeDir()); - std::string apisock(Layout::relative_to(rundir, MGMTAPI_MGMT_SOCKET_NAME)); - std::string eventsock(Layout::relative_to(rundir, MGMTAPI_EVENT_SOCKET_NAME)); - - Debug("lm", "using main socket file '%s'", apisock.c_str()); - Debug("lm", "using event socket file '%s'", eventsock.c_str()); - - mode_t oldmask = umask(0); - mode_t newmode = api_socket_is_restricted() ? 00700 : 00777; - - int mgmtapiFD = -1; // FD for the api interface to issue commands - int eventapiFD = -1; // FD for the api and clients to handle event callbacks - - mgmtapiFD = bind_unix_domain_socket(apisock.c_str(), newmode); - if (mgmtapiFD == -1) { - mgmt_log("[WebIntrMain] Unable to set up socket for handling management API calls. API socket path = %s\n", apisock.c_str()); - } - - eventapiFD = bind_unix_domain_socket(eventsock.c_str(), newmode); - if (eventapiFD == -1) { - mgmt_log("[WebIntrMain] Unable to set up so for handling management API event calls. Event Socket path: %s\n", - eventsock.c_str()); - } - - umask(oldmask); - ink_thread_create(nullptr, ts_ctrl_main, &mgmtapiFD, 0, 0, nullptr); - ink_thread_create(nullptr, event_callback_main, &eventapiFD, 0, 0, nullptr); - - mgmt_log("[TrafficManager] Setup complete\n"); - - RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_time", time(nullptr), RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_required", 0, RECP_NON_PERSISTENT); - - RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.proxy", 0, RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.manager", 0, RECP_NON_PERSISTENT); - - RecRegisterStatInt(RECT_NODE, "proxy.node.config.draining", 0, RECP_NON_PERSISTENT); - - int sleep_time = 0; // sleep_time given in sec - uint64_t last_start_epoc_s = 0; // latest start attempt in seconds since epoc - - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution<> dis(0.0, 0.5); - - RecInt sleep_ceiling = 60; - RecGetRecordInt("proxy.node.config.manager_exponential_sleep_ceiling", &sleep_ceiling); - RecInt retry_cap = 0; // 0 means no cap. - RecGetRecordInt("proxy.node.config.manager_retry_cap", &retry_cap); - bool ignore_retry_cap{retry_cap <= 0}; - - DerivativeMetrics derived; // This is simple class to calculate some useful derived metrics - - for (;;) { - lmgmt->processEventQueue(); - lmgmt->pollMgmtProcessServer(); - - // Handle rotation of output log (aka traffic.out) as well as DEFAULT_DIAGS_LOG_FILENAME (aka manager.log) - rotateLogs(); - - // Check for a SIGHUP - if (sigHupNotifier) { - mgmt_log("[main] Reading Configuration Files due to SIGHUP\n"); - Reconfigure(); - sigHupNotifier = 0; - mgmt_log("[main] Reading Configuration Files Reread\n"); - } - - // Update the derived metrics. ToDo: this runs once a second, that might be excessive, maybe it should be - // done more like every config_update_interval_ms (proxy.config.config_update_interval_ms) ? - derived.Update(); - - if (lmgmt->mgmt_shutdown_outstanding != MGMT_PENDING_NONE) { - Debug("lm", "pending shutdown %d", lmgmt->mgmt_shutdown_outstanding); - } - switch (lmgmt->mgmt_shutdown_outstanding) { - case MGMT_PENDING_RESTART: - lmgmt->mgmtShutdown(); - ::exit(0); - break; - case MGMT_PENDING_IDLE_RESTART: - if (!is_server_draining()) { - lmgmt->processDrain(); - } - if (is_server_idle() || waited_enough()) { - lmgmt->mgmtShutdown(); - ::exit(0); - } - break; - case MGMT_PENDING_BOUNCE: - lmgmt->processBounce(); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - break; - case MGMT_PENDING_IDLE_BOUNCE: - if (!is_server_draining()) { - lmgmt->processDrain(); - } - if (is_server_idle() || waited_enough()) { - lmgmt->processBounce(); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - } - break; - case MGMT_PENDING_STOP: - lmgmt->processShutdown(); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - break; - case MGMT_PENDING_IDLE_STOP: - if (!is_server_draining()) { - lmgmt->processDrain(); - } - if (is_server_idle() || waited_enough()) { - lmgmt->processShutdown(); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - } - break; - case MGMT_PENDING_DRAIN: - if (!is_server_draining()) { - lmgmt->processDrain(); - } - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - break; - case MGMT_PENDING_IDLE_DRAIN: - if (is_server_idle_from_new_connection()) { - lmgmt->processDrain(); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - } - break; - case MGMT_PENDING_UNDO_DRAIN: - if (is_server_draining()) { - lmgmt->processDrain(0); - lmgmt->mgmt_shutdown_outstanding = MGMT_PENDING_NONE; - } - break; - default: - break; - } - - if (lmgmt->run_proxy && !lmgmt->processRunning() && lmgmt->proxy_recoverable && - (retry_cap > 0 || ignore_retry_cap)) { /* Make sure we still have a proxy up */ - const uint64_t now = static_cast(time(nullptr)); - if (sleep_time && ((now - last_start_epoc_s) < static_cast(sleep_ceiling))) { - const auto variance = dis(gen); - // We add a bit of variance to the regular sleep time. - const int mod_sleep_time = sleep_time + static_cast(sleep_time * variance); - mgmt_log("Relaunching proxy after %d sec..", mod_sleep_time); - if (!ignore_retry_cap && sleep_time >= sleep_ceiling) { - --retry_cap; - } - millisleep((1000 * mod_sleep_time)); // we use millisleep instead of sleep because it doesnt interfere with signals - sleep_time = std::min(sleep_time * 2, sleep_ceiling); - } else { - sleep_time = 1; - } - if (ProxyStateSet(TS_PROXY_ON, TS_CACHE_CLEAR_NONE) == TS_ERR_OKAY) { - just_started = 0; - last_start_epoc_s = static_cast(time(nullptr)); - } else { - just_started++; - } - } else { - // Even if we shouldn't try to start the proxy again, leave manager around to - // avoid external automated restarts - if (!lmgmt->proxy_recoverable && !printed_unrecoverable) { - mgmt_log("[main] Proxy is un-recoverable. Proxy will not be relaunched.\n"); - printed_unrecoverable = true; - } - - just_started++; - } - - /* This will catch the case were the proxy dies before it can connect to manager */ - if (lmgmt->proxy_launch_outstanding && !lmgmt->processRunning() && just_started >= 120) { - just_started = 0; - lmgmt->proxy_launch_outstanding = false; - if (lmgmt->proxy_launch_pid != -1) { - int res; - kill(lmgmt->proxy_launch_pid, 9); - waitpid(lmgmt->proxy_launch_pid, &res, 0); - if (WIFSIGNALED(res)) { - int sig = WTERMSIG(res); -#ifdef NEED_PSIGNAL - mgmt_log("[main] Proxy terminated due to Sig %d. Relaunching after %d sec...\n", sig, sleep_time); -#else - mgmt_log("[main] Proxy terminated due to Sig %d: %s. Relaunching after %d sec...\n", sig, strsignal(sig), sleep_time); -#endif /* NEED_PSIGNAL */ - } - } - mgmt_log("[main] Proxy launch failed, retrying after %d sec...\n", sleep_time); - } - } - - // ToDo: Here we should delete anything related to calculated metrics. - -#ifndef MGMT_SERVICE - return 0; -#endif - -} /* End main */ - -#if !defined(linux) && !defined(freebsd) && !defined(darwin) -static void -SignalAlrmHandler(int /* sig ATS_UNUSED */, siginfo_t *t, void * /* c ATS_UNUSED */) -#else -static void -SignalAlrmHandler(int /* sig ATS_UNUSED */) -#endif -{ -/* - fprintf("[TrafficManager] ==> SIGALRM received\n"); - mgmt_elog(0, "[TrafficManager] ==> SIGALRM received\n"); - */ -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - if (t) { - if (t->si_code <= 0) { - fprintf(stderr, "[TrafficManager] ==> User Alarm from pid: %ld uid: %d\n", (long)t->si_pid, t->si_uid); - mgmt_log("[TrafficManager] ==> User Alarm from pid: %d uid: %d\n", t->si_pid, t->si_uid); - } else { - fprintf(stderr, "[TrafficManager] ==> Kernel Alarm Reason: %d\n", t->si_code); - mgmt_log("[TrafficManager] ==> Kernel Alarm Reason: %d\n", t->si_code); - } - } -#endif - - return; -} - -#if !defined(linux) && !defined(freebsd) && !defined(darwin) -static void -SignalHandler(int sig, siginfo_t *t, void *c) -#else -static void -SignalHandler(int sig) -#endif -{ - static int clean = 0; - int status; - -#if !defined(linux) && !defined(freebsd) && !defined(darwin) - if (t) { - if (t->si_code <= 0) { - fprintf(stderr, "[TrafficManager] ==> User Sig %d from pid: %ld uid: %d\n", sig, (long)t->si_pid, t->si_uid); - mgmt_log("[TrafficManager] ==> User Sig %d from pid: %ld uid: %d\n", sig, (long)t->si_pid, t->si_uid); - } else { - fprintf(stderr, "[TrafficManager] ==> Kernel Sig %d; Reason: %d\n", sig, t->si_code); - mgmt_log("[TrafficManager] ==> Kernel Sig %d; Reason: %d\n", sig, t->si_code); - } - } -#endif - - if (sig == SIGHUP) { - sigHupNotifier = 1; - return; - } - - if (sig == SIGUSR2) { - fprintf(stderr, "[TrafficManager] ==> received SIGUSR2, rotating the logs.\n"); - mgmt_log("[TrafficManager] ==> received SIGUSR2, rotating the logs.\n"); - if (lmgmt && lmgmt->watched_process_pid != -1) { - kill(lmgmt->watched_process_pid, sig); - } - diags()->set_std_output(StdStream::STDOUT, bind_stdout); - diags()->set_std_output(StdStream::STDERR, bind_stderr); - if (diags()->reseat_diagslog()) { - Note("Reseated %s", diags_log_filename); - } else { - Note("Could not reseat %s", diags_log_filename); - } - return; - } - - fprintf(stderr, "[TrafficManager] ==> Cleaning up and reissuing signal #%d\n", sig); - mgmt_log("[TrafficManager] ==> Cleaning up and reissuing signal #%d\n", sig); - - if (lmgmt && !clean) { - clean = 1; - if (lmgmt->watched_process_pid != -1) { - if (sig == SIGTERM || sig == SIGINT) { - kill(lmgmt->watched_process_pid, sig); - waitpid(lmgmt->watched_process_pid, &status, 0); - } - } - lmgmt->mgmtCleanup(); - } - - switch (sig) { - case SIGQUIT: - case SIGILL: - case SIGTRAP: -#if !defined(linux) - case SIGEMT: - case SIGSYS: -#endif - case SIGFPE: - case SIGBUS: - case SIGSEGV: - case SIGXCPU: - case SIGXFSZ: - abort(); - case SIGTERM: - ::exit(0); - default: - fprintf(stderr, "[TrafficManager] ==> signal #%d\n", sig); - mgmt_log("[TrafficManager] ==> signal #%d\n", sig); - ::exit(sig); - } - fprintf(stderr, "[TrafficManager] ==> signal2 #%d\n", sig); - mgmt_log("[TrafficManager] ==> signal2 #%d\n", sig); - ::exit(sig); -} /* End SignalHandler */ - -// void SigChldHandler(int sig) -// -// An empty handler needed so that we catch SIGCHLD -// With Solaris 2.6, ignoring sig child changes the behavior -// of waitpid() so that if there are no unwaited children, -// waitpid() blocks until all child are transformed into -// zombies which is bad for us -// -static void -SigChldHandler(int /* sig ATS_UNUSED */) -{ -} - -void -fileUpdated(char *fname, char *configName) -{ - // If there is no config name recorded, assume this file is not reloadable - // Just log a message - if (configName == nullptr || configName[0] == '\0') { - mgmt_log("[fileUpdated] %s changed, need restart", fname); - } else { - // Signal based on the config entry that has the changed file name - lmgmt->signalFileChange(configName); - } - return; -} /* End fileUpdate */ - -#if TS_USE_POSIX_CAP -/** Restore capabilities after user id change. - This manipulates LINUX capabilities so that this process - can perform certain privileged operations even if it is - no longer running as a privilege user. - - @internal - I tried using - @code - prctl(PR_SET_KEEPCAPS, 1); - @endcode - but that had no effect even though the call reported success. - Only explicit capability manipulation was effective. - - It does not appear to be necessary to set the capabilities on the - executable if originally run as root. That may be needed if - started as a user without that capability. - */ - -int -restoreCapabilities() -{ - int zret = 0; // return value. - cap_t cap_set = cap_get_proc(); // current capabilities - // Make a list of the capabilities we want turned on. - cap_value_t cap_list[] = { - CAP_NET_ADMIN, ///< Set socket transparency. - CAP_NET_BIND_SERVICE, ///< Low port (e.g. 80) binding. - CAP_IPC_LOCK ///< Lock IPC objects. - }; - static int const CAP_COUNT = sizeof(cap_list) / sizeof(*cap_list); - - for (int i = 0; i < CAP_COUNT; i++) { - if (cap_set_flag(cap_set, CAP_EFFECTIVE, 1, cap_list + i, CAP_SET) < 0) { - Warning("restore CAP_EFFECTIVE failed for option %d", i); - } - if (cap_set_proc(cap_set) == -1) { // it failed, back out - cap_set_flag(cap_set, CAP_EFFECTIVE, 1, cap_list + i, CAP_CLEAR); - } - } - for (int i : cap_list) { - cap_flag_value_t val; - if (cap_get_flag(cap_set, i, CAP_EFFECTIVE, &val) < 0) { - } else { - Warning("CAP_EFFECTIVE offiset %d is %s", i, val == CAP_SET ? "set" : "unset"); - } - } - zret = cap_set_proc(cap_set); - cap_free(cap_set); - return zret; -} -#endif - -// void runAsUser(...) -// -// If we are root, switched to user to run as -// specified in records.config -// -// If we are not root, do nothing -// -void -runAsUser(const char *userName) -{ - if (getuid() == 0 || geteuid() == 0) { - ImpersonateUser(userName, IMPERSONATE_EFFECTIVE); - -#if TS_USE_POSIX_CAP - if (0 != restoreCapabilities()) { - mgmt_log("[runAsUser] Error: Failed to restore capabilities after switch to user %s.\n", userName); - } -#endif - } -} /* End runAsUser() */ diff --git a/src/traffic_server/EventName.cc b/src/traffic_server/EventName.cc index ae0c5993213..a062c4af71d 100644 --- a/src/traffic_server/EventName.cc +++ b/src/traffic_server/EventName.cc @@ -29,7 +29,6 @@ #include "I_Cache.h" #include "I_Net.h" #include "I_HostDB.h" -#include "BaseManager.h" #include "P_RefCountCache.h" /*------------------------------------------------------------------------- @@ -44,100 +43,5 @@ const char * event_int_to_string(int event, int blen, char *buffer) { - switch (event) { - case -1: - return ""; - case VC_EVENT_READ_READY: - return "VC_EVENT_READ_READY"; - case VC_EVENT_WRITE_READY: - return "VC_EVENT_WRITE_READY"; - case VC_EVENT_READ_COMPLETE: - return "VC_EVENT_READ_COMPLETE"; - case VC_EVENT_WRITE_COMPLETE: - return "VC_EVENT_WRITE_COMPLETE"; - case VC_EVENT_EOS: - return "VC_EVENT_EOS"; - case VC_EVENT_INACTIVITY_TIMEOUT: - return "VC_EVENT_INACTIVITY_TIMEOUT"; - case VC_EVENT_ACTIVE_TIMEOUT: - return "VC_EVENT_ACTIVE_TIMEOUT"; - - case NET_EVENT_OPEN: - return "NET_EVENT_OPEN"; - case NET_EVENT_OPEN_FAILED: - return "NET_EVENT_OPEN_FAILED"; - case NET_EVENT_ACCEPT: - return "NET_EVENT_ACCEPT"; - case NET_EVENT_ACCEPT_SUCCEED: - return "NET_EVENT_ACCEPT_SUCCEED"; - case NET_EVENT_ACCEPT_FAILED: - return "NET_EVENT_ACCEPT_FAILED"; - - case EVENT_HOST_DB_LOOKUP: - return "EVENT_HOST_DB_LOOKUP"; - case EVENT_HOST_DB_GET_RESPONSE: - return "EVENT_HOST_DB_GET_RESPONSE"; - - case DNS_EVENT_EVENTS_START: - return "DNS_EVENT_EVENTS_START"; - - case REFCOUNT_CACHE_EVENT_SYNC: - return "REFCOUNT_CACHE_EVENT_SYNC"; - - case CACHE_EVENT_LOOKUP: - return "CACHE_EVENT_LOOKUP"; - case CACHE_EVENT_LOOKUP_FAILED: - return "CACHE_EVENT_LOOKUP_FAILED"; - case CACHE_EVENT_OPEN_READ: - return "CACHE_EVENT_OPEN_READ"; - case CACHE_EVENT_OPEN_READ_FAILED: - return "CACHE_EVENT_OPEN_READ_FAILED"; - case CACHE_EVENT_OPEN_WRITE: - return "CACHE_EVENT_OPEN_WRITE"; - case CACHE_EVENT_OPEN_WRITE_FAILED: - return "CACHE_EVENT_OPEN_WRITE_FAILED"; - case CACHE_EVENT_REMOVE: - return "CACHE_EVENT_REMOVE"; - case CACHE_EVENT_REMOVE_FAILED: - return "CACHE_EVENT_REMOVE_FAILED"; - case CACHE_EVENT_UPDATE: - return "CACHE_EVENT_UPDATE"; - case CACHE_EVENT_UPDATE_FAILED: - return "CACHE_EVENT_UPDATE_FAILED"; - case CACHE_EVENT_LINK: - return "CACHE_EVENT_LINK"; - case CACHE_EVENT_LINK_FAILED: - return "CACHE_EVENT_LINK_FAILED"; - case CACHE_EVENT_DEREF: - return "CACHE_EVENT_DEREF"; - case CACHE_EVENT_DEREF_FAILED: - return "CACHE_EVENT_DEREF_FAILED"; - case CACHE_EVENT_RESPONSE: - return "CACHE_EVENT_RESPONSE"; - case CACHE_EVENT_RESPONSE_MSG: - return "CACHE_EVENT_RESPONSE_MSG"; - - case MGMT_EVENT_SHUTDOWN: - return "MGMT_EVENT_SHUTDOWN"; - case MGMT_EVENT_RESTART: - return "MGMT_EVENT_RESTART"; - case MGMT_EVENT_BOUNCE: - return "MGMT_EVENT_BOUNCE"; - case MGMT_EVENT_CONFIG_FILE_UPDATE: - return "MGMT_EVENT_CONFIG_FILE_UPDATE"; - case MGMT_EVENT_CLEAR_STATS: - return "MGMT_EVENT_CLEAR_STATS"; - case MGMT_EVENT_HOST_STATUS_UP: - return "MGMT_EVENT_HOST_STATUS_UP"; - case MGMT_EVENT_HOST_STATUS_DOWN: - return "MGMT_EVENT_HOST_STATUS_DOWN"; - - default: - if (buffer != nullptr) { - snprintf(buffer, blen, "%d", event); - return buffer; - } else { - return "UNKNOWN_EVENT"; - } - } + return "UNKNOWN_EVENT"; } diff --git a/src/traffic_server/HostStatus.cc b/src/traffic_server/HostStatus.cc index 31c3c107b3a..b496cdc936f 100644 --- a/src/traffic_server/HostStatus.cc +++ b/src/traffic_server/HostStatus.cc @@ -23,7 +23,6 @@ #include #include "HostStatus.h" #include "I_Tasks.h" -#include "ProcessManager.h" #include "tscore/BufferWriter.h" #include "rpc/jsonrpc/JsonRPC.h" diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 5f999410823..9f907da9421 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -8017,25 +8017,7 @@ TSMatcherLineValue(TSMatcherLine ml, int element) TSReturnCode TSMgmtConfigIntSet(const char *var_name, TSMgmtInt value) { - TSMgmtInt result; - char *buffer; - - // is this a valid integer? - if (TSMgmtIntGet(var_name, &result) != TS_SUCCESS) { - return TS_ERROR; - } - - // construct a buffer - int buffer_size = strlen(var_name) + 1 + 32 + 1 + 64 + 1; - - buffer = static_cast(alloca(buffer_size)); - snprintf(buffer, buffer_size, "%s %d %" PRId64 "", var_name, MGMT_INT, value); - - // tell manager to set the configuration; note that this is not - // transactional (e.g. we return control to the plugin before the - // value is committed to disk by the manager) - RecSignalManager(MGMT_SIGNAL_PLUGIN_SET_CONFIG, buffer); - + Warning("This API is no longer supported."); return TS_SUCCESS; } diff --git a/src/traffic_server/Makefile.inc b/src/traffic_server/Makefile.inc index 92cb5972ed7..1c448ad4c2e 100644 --- a/src/traffic_server/Makefile.inc +++ b/src/traffic_server/Makefile.inc @@ -32,7 +32,6 @@ traffic_server_traffic_server_CPPFLAGS = \ -I$(abs_top_srcdir)/proxy/http/remap \ -I$(abs_top_srcdir)/proxy/hdrs \ -I$(abs_top_srcdir)/proxy/shared \ - -I$(abs_top_srcdir)/mgmt2 \ -I$(abs_top_srcdir)/mgmt \ -I$(abs_top_srcdir)/mgmt/utils \ $(TS_INCLUDES) \ @@ -86,10 +85,10 @@ traffic_server_traffic_server_LDADD = \ $(top_builddir)/iocore/net/libinknet.a \ $(top_builddir)/lib/records/librecords_p.a \ $(top_builddir)/iocore/eventsystem/libinkevent.a \ - $(top_builddir)/mgmt2/rpc/libjsonrpc_server.la \ - $(top_builddir)/mgmt2/rpc/libjsonrpc_protocol.la \ - $(top_builddir)/mgmt2/config/libconfigmanager.la \ - $(top_builddir)/mgmt2/rpc/librpcpublichandlers.la \ + $(top_builddir)/mgmt/rpc/libjsonrpc_server.la \ + $(top_builddir)/mgmt/rpc/libjsonrpc_protocol.la \ + $(top_builddir)/mgmt/config/libconfigmanager.la \ + $(top_builddir)/mgmt/rpc/librpcpublichandlers.la \ @HWLOC_LIBS@ \ @LIBPCRE@ \ @LIBRESOLV@ \ diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index b87f3926375..dea006b8cda 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -79,7 +79,6 @@ extern "C" int plock(int); #include "RecordsConfig.h" #include "records/I_RecProcess.h" #include "Transform.h" -#include "ProcessManager.h" #include "ProxyConfig.h" #include "HttpProxyServerMain.h" #include "HttpBodyFactory.h" @@ -130,16 +129,11 @@ extern "C" int plock(int); // #define DEFAULT_COMMAND_FLAG 0 -#define DEFAULT_REMOTE_MANAGEMENT_FLAG 0 #define DEFAULT_DIAGS_LOG_FILENAME "diags.log" static char diags_log_filename[PATH_NAME_MAX] = DEFAULT_DIAGS_LOG_FILENAME; static const long MAX_LOGIN = ink_login_name_max(); -static void mgmt_restart_shutdown_callback(ts::MemSpan); -static void mgmt_drain_callback(ts::MemSpan); -static void mgmt_storage_device_cmd_callback(int cmd, std::string_view const &arg); -static void mgmt_lifecycle_msg_callback(ts::MemSpan); static void init_ssl_ctx_callback(void *ctx, bool server); static void load_ssl_file_callback(const char *ssl_file); static void task_threads_started_callback(); @@ -169,7 +163,6 @@ extern int fds_limit; static char command_string[512] = ""; static char conf_dir[512] = ""; -int remote_management_flag = DEFAULT_REMOTE_MANAGEMENT_FLAG; static char bind_stdout[512] = ""; static char bind_stderr[512] = ""; @@ -225,7 +218,6 @@ static ArgumentDescription argument_descriptions[] = { #endif {"interval", 'i', "Statistics Interval", "I", &show_statistics, "PROXY_STATS_INTERVAL", nullptr}, - {"remote_management", 'M', "Remote Management", "T", &remote_management_flag, "PROXY_REMOTE_MANAGEMENT", nullptr}, {"command", 'C', "Maintenance Command to Execute\n" " Commands: list, check, clear, clear_cache, clear_hostdb, verify_config, verify_global_plugin, verify_remap_plugin, help", @@ -256,8 +248,6 @@ struct AutoStopCont : public Continuation { hook = hook->next(); } - pmgmt->stop(); - // if the jsonrpc feature was disabled, the object will not be created. if (jsonrpcServer != nullptr) { jsonrpcServer->stop_thread(); @@ -311,12 +301,10 @@ class SignalContinuation : public Continuation if (RecGetRecordInt("proxy.config.stop.shutdown_timeout", &timeout) == REC_ERR_OKAY && timeout) { RecSetRecordInt("proxy.node.config.draining", 1, REC_SOURCE_DEFAULT); TSSystemState::drain(true); - if (!remote_management_flag) { - // Close listening sockets here only if TS is running standalone - RecInt close_sockets = 0; - if (RecGetRecordInt("proxy.config.restart.stop_listening", &close_sockets) == REC_ERR_OKAY && close_sockets) { - stop_HttpProxyServer(); - } + // Close listening sockets here only if TS is running standalone + RecInt close_sockets = 0; + if (RecGetRecordInt("proxy.config.restart.stop_listening", &close_sockets) == REC_ERR_OKAY && close_sockets) { + stop_HttpProxyServer(); } } @@ -397,13 +385,7 @@ class DiagsLogContinuation : public Continuation { Debug("log", "in DiagsLogContinuation, checking on diags.log"); - // First, let us update the rolling config values for diagslog. We - // do not need to update the config values for outputlog because - // traffic_server never actually rotates outputlog. outputlog is always - // rotated in traffic_manager. The reason being is that it is difficult - // to send a notification from TS to TM, informing TM that outputlog has - // been rolled. It is much easier sending a notification (in the form - // of SIGUSR2) from TM -> TS. + // First, let us update the rolling config values for diagslog. int diags_log_roll_int = static_cast(REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_interval_sec")); int diags_log_roll_size = static_cast(REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_size_mb")); int diags_log_roll_enable = static_cast(REC_ConfigReadInteger("proxy.config.diags.logfile.rolling_enabled")); @@ -414,18 +396,14 @@ class DiagsLogContinuation : public Continuation Note("Rolled %s", diags_log_filename); } - // If we are using the JSONRPC service, then there is no traffic_manager - // and we are responsible for rolling traffic.out. - if (jsonrpcServer != nullptr) { - int output_log_roll_int = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_interval_sec")); - int output_log_roll_size = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_size_mb")); - int output_log_roll_enable = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_enabled")); - diags()->config_roll_outputlog(static_cast(output_log_roll_enable), output_log_roll_int, - output_log_roll_size); - - if (diags()->should_roll_outputlog()) { - Note("Rolled %s", traffic_out_name.c_str()); - } + int output_log_roll_int = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_interval_sec")); + int output_log_roll_size = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_size_mb")); + int output_log_roll_enable = static_cast(REC_ConfigReadInteger("proxy.config.output.logfile.rolling_enabled")); + diags()->config_roll_outputlog(static_cast(output_log_roll_enable), output_log_roll_int, + output_log_roll_size); + + if (diags()->should_roll_outputlog()) { + Note("Rolled %s", traffic_out_name.c_str()); } return EVENT_CONT; } @@ -682,28 +660,10 @@ initialize_process_manager() { mgmt_use_syslog(); - // Temporary Hack to Enable Communication with LocalManager - if (getenv("PROXY_REMOTE_MGMT")) { - remote_management_flag = true; - } - - if (remote_management_flag) { - // We are being managed by traffic_manager, TERM ourselves if it goes away. - EnableDeathSignal(SIGTERM); - } - - RecProcessInit(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE, diags()); + RecProcessInit(RECM_STAND_ALONE, diags()); LibRecordsConfigInit(); - // Start up manager - pmgmt = new ProcessManager(remote_management_flag); - - // Lifecycle callbacks can potentially be invoked from this thread, so force thread initialization - // to make the TS API work. - pmgmt->start(TSThreadInit, TSThreadDestroy); - - RecProcessInitMessage(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE); - pmgmt->reconfigure(); + RecProcessInitMessage(RECM_STAND_ALONE); check_config_directories(); // @@ -964,7 +924,7 @@ cmd_verify(char * /* cmd ATS_UNUSED */) // initialize logging since a plugin // might call TS_ERROR which needs // log_rsb to be init'ed - Log::init(DEFAULT_REMOTE_MANAGEMENT_FLAG); + Log::init(); if (*conf_dir) { fprintf(stderr, "NOTE: VERIFY config dir: %s...\n\n", conf_dir); @@ -1279,7 +1239,7 @@ check_fd_limit() "%d (throttle) + %d (internal use) > %d (file descriptor limit), " "using throttle of %d", fds_throttle, THROTTLE_FD_HEADROOM, fds_limit, new_fds_throttle); - SignalWarning(MGMT_SIGNAL_SYSTEM_ERROR, msg); + Warning("%s", msg); } } @@ -1858,16 +1818,14 @@ main(int /* argc ATS_UNUSED */, const char **argv) // Restart syslog now that we have configuration info syslog_log_configure(); - // Register stats if standalone - if (DEFAULT_REMOTE_MANAGEMENT_FLAG == remote_management_flag) { - RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_time", time(nullptr), RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_required", 0, RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.proxy", 0, RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.manager", 0, RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.config.draining", 0, RECP_NON_PERSISTENT); - RecRegisterStatInt(RECT_NODE, "proxy.node.proxy_running", 1, RECP_NON_PERSISTENT); - RecSetRecordInt("proxy.node.restarts.proxy.start_time", time(nullptr), REC_SOURCE_DEFAULT); - } + // Register stats + RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_time", time(nullptr), RECP_NON_PERSISTENT); + RecRegisterStatInt(RECT_NODE, "proxy.node.config.reconfigure_required", 0, RECP_NON_PERSISTENT); + RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.proxy", 0, RECP_NON_PERSISTENT); + RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.manager", 0, RECP_NON_PERSISTENT); + RecRegisterStatInt(RECT_NODE, "proxy.node.config.draining", 0, RECP_NON_PERSISTENT); + RecRegisterStatInt(RECT_NODE, "proxy.node.proxy_running", 1, RECP_NON_PERSISTENT); + RecSetRecordInt("proxy.node.restarts.proxy.start_time", time(nullptr), REC_SOURCE_DEFAULT); // init huge pages int enabled; @@ -2004,9 +1962,6 @@ main(int /* argc ATS_UNUSED */, const char **argv) RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.uuid", (char *)Machine::instance()->uuid.getString(), RECP_NON_PERSISTENT); - // pmgmt->start() must occur after initialization of Diags but - // before calling RecProcessInit() - REC_ReadConfigInteger(res_track_memory, "proxy.config.res_track_memory"); init_http_header(); @@ -2142,10 +2097,10 @@ main(int /* argc ATS_UNUSED */, const char **argv) dnsProcessor.start(0, stacksize); if (hostDBProcessor.start() < 0) - SignalWarning(MGMT_SIGNAL_SYSTEM_ERROR, "bad hostdb or storage configuration, hostdb disabled"); + Warning("bad hostdb or storage configuration, hostdb disabled"); // initialize logging (after event and net processor) - Log::init(remote_management_flag ? 0 : Log::NO_REMOTE_MANAGEMENT); + Log::init(Log::NO_REMOTE_MANAGEMENT); (void)parsePluginConfig(); @@ -2158,7 +2113,6 @@ main(int /* argc ATS_UNUSED */, const char **argv) #if TS_USE_QUIC == 1 quic_NetProcessor.start(-1, stacksize); #endif - pmgmt->registerPluginCallbacks(global_config_cbs); FileManager::instance().registerConfigPluginCallbacks(global_config_cbs); cacheProcessor.afterInitCallbackSet(&CB_After_Cache_Init); cacheProcessor.start(); @@ -2244,18 +2198,6 @@ main(int /* argc ATS_UNUSED */, const char **argv) start_SocksProxy(netProcessor.socks_conf_stuff->accept_port); } - pmgmt->registerMgmtCallback(MGMT_EVENT_SHUTDOWN, &mgmt_restart_shutdown_callback); - pmgmt->registerMgmtCallback(MGMT_EVENT_RESTART, &mgmt_restart_shutdown_callback); - pmgmt->registerMgmtCallback(MGMT_EVENT_DRAIN, &mgmt_drain_callback); - - // Callback for various storage commands. These all go to the same function so we - // pass the event code along so it can do the right thing. We cast that to first - // just to be safe because the value is a #define, not a typed value. - pmgmt->registerMgmtCallback(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, [](ts::MemSpan span) -> void { - mgmt_storage_device_cmd_callback(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, span.view()); - }); - pmgmt->registerMgmtCallback(MGMT_EVENT_LIFECYCLE_MESSAGE, &mgmt_lifecycle_msg_callback); - ink_set_thread_name("[TS_MAIN]"); Note("traffic server running"); @@ -2286,59 +2228,6 @@ main(int /* argc ATS_UNUSED */, const char **argv) delete main_thread; } -static void mgmt_restart_shutdown_callback(ts::MemSpan) -{ - sync_cache_dir_on_shutdown(); -} - -static void -mgmt_drain_callback(ts::MemSpan span) -{ - char *arg = span.rebind().data(); - TSSystemState::drain(span.size() == 2 && arg[0] == '1'); - RecSetRecordInt("proxy.node.config.draining", TSSystemState::is_draining() ? 1 : 0, REC_SOURCE_DEFAULT); -} - -static void -mgmt_storage_device_cmd_callback(int cmd, std::string_view const &arg) -{ - // data is the device name to control - CacheDisk *d = cacheProcessor.find_by_path(arg.data(), int(arg.size())); - - if (d) { - switch (cmd) { - case MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE: - Debug("server", "Marking %.*s offline", int(arg.size()), arg.data()); - cacheProcessor.mark_storage_offline(d, /* admin */ true); - break; - } - } -} - -static void -mgmt_lifecycle_msg_callback(ts::MemSpan span) -{ - APIHook *hook = lifecycle_hooks->get(TS_LIFECYCLE_MSG_HOOK); - TSPluginMsg msg; - MgmtInt op; - MgmtMarshallString tag; - MgmtMarshallData payload; - static const MgmtMarshallType fields[] = {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA}; - - if (mgmt_message_parse(span.data(), span.size(), fields, countof(fields), &op, &tag, &payload) == -1) { - Error("Plugin message - RPC parsing error - message discarded."); - } else { - msg.tag = tag; - msg.data = payload.ptr; - msg.data_size = payload.len; - while (hook) { - TSPluginMsg tmp(msg); // Just to make sure plugins don't mess this up for others. - hook->invoke(TS_EVENT_LIFECYCLE_MSG, &tmp); - hook = hook->next(); - } - } -} - static void init_ssl_ctx_callback(void *ctx, bool server) { @@ -2355,15 +2244,12 @@ init_ssl_ctx_callback(void *ctx, bool server) static void load_ssl_file_callback(const char *ssl_file) { - pmgmt->signalConfigFileChild(ts::filename::SSL_MULTICERT, ssl_file); FileManager::instance().configFileChild(ts::filename::SSL_MULTICERT, ssl_file); } void load_config_file_callback(const char *parent_file, const char *remap_file) { - pmgmt->signalConfigFileChild(parent_file, remap_file); - // TODO: for now in both FileManager::instance().configFileChild(parent_file, remap_file); } diff --git a/src/traffic_via/traffic_via.cc b/src/traffic_via/traffic_via.cc index 65fb617e465..33df12e5ed4 100644 --- a/src/traffic_via/traffic_via.cc +++ b/src/traffic_via/traffic_via.cc @@ -24,7 +24,6 @@ #include "tscore/ink_platform.h" #include "tscore/ink_args.h" #include "tscore/I_Version.h" -#include "mgmtapi.h" #include #include #include @@ -219,7 +218,7 @@ printViaHeader(std::string_view header) } // Check validity of via header and then decode it -static TSMgmtError +static bool decodeViaHeader(std::string_view text) { // Via header inside square brackets @@ -228,7 +227,7 @@ decodeViaHeader(std::string_view text) text.remove_suffix(1); } if (text.empty()) { - return TS_ERR_FAIL; + return false; } printf("Via header is [%.*s], Length is %zu\n", int(text.size()), text.data(), text.size()); @@ -243,18 +242,18 @@ decodeViaHeader(std::string_view text) if (text.size() == 22 || text.size() == 6) { // Decode via header printViaHeader(text); - return TS_ERR_OKAY; + return true; } // Invalid header size, come out. printf("\nInvalid VIA header. VIA header length should be 6 or 22 characters\n"); printf("Valid via header format is " "[ucsfpe:tc<" "cache type>ps]\n"); - return TS_ERR_FAIL; + return false; } // Read user input from stdin -static TSMgmtError +static bool filterViaHeader() { const pcre *compiledReg; @@ -273,7 +272,7 @@ filterViaHeader() if (compiledReg == nullptr) { printf("PCRE regex compilation failed with error %s at offset %d\n", err, errOffset); - return TS_ERR_FAIL; + return false; } // Read all lines from stdin @@ -299,13 +298,13 @@ filterViaHeader() decodeViaHeader(match); } } - return TS_ERR_OKAY; + return true; } int main(int /* argc ATS_UNUSED */, const char **argv) { - TSMgmtError status; + bool opStatus; // build the application information structure appVersionInfo.setup(PACKAGE_NAME, "traffic_via", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, ""); @@ -321,12 +320,12 @@ main(int /* argc ATS_UNUSED */, const char **argv) for (unsigned i = 0; i < n_file_arguments; ++i) { if (strcmp(file_arguments[i], "-") == 0) { // Filter arguments provided from stdin - status = filterViaHeader(); + opStatus = filterViaHeader(); } else { - status = decodeViaHeader(std::string_view{file_arguments[i], strlen(file_arguments[i])}); + opStatus = decodeViaHeader(std::string_view{file_arguments[i], strlen(file_arguments[i])}); } - if (status != TS_ERR_OKAY) { + if (!opStatus) { return 1; } } diff --git a/src/tscore/BaseLogFile.cc b/src/tscore/BaseLogFile.cc index 0882c2baf39..1d9fe67088a 100644 --- a/src/tscore/BaseLogFile.cc +++ b/src/tscore/BaseLogFile.cc @@ -391,9 +391,7 @@ BaseLogFile::display(FILE *fd) * instance of Diags is ready, we cannot simply call something like Debug(). * However, we still need to log the creation of BaseLogFile, since the * information is still useful. This function will print out log messages - * into traffic.out if we happen to be bootstrapping Diags. Since - * traffic_manager redirects stdout/stderr into traffic.out, that - * redirection is inherited by way of exec()/fork() all the way here. + * into traffic.out if we happen to be bootstrapping Diags. * * TODO use Debug() for non bootstrap instances */ diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext b/tests/gold_tests/autest-site/trafficserver.test.ext index 3d4b5197fd1..dfec8d21ed0 100755 --- a/tests/gold_tests/autest-site/trafficserver.test.ext +++ b/tests/gold_tests/autest-site/trafficserver.test.ext @@ -84,19 +84,11 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, if block_for_debug: ts_args += ' --block' - if 'traffic_manager' in command: - if '--tsArgs' in command: - # None of our tests do this, but if we eventually pass in --tsArgs - # at some point from a test, we'll need to figure out how to mix - # that with the arguments we're assembling for --tsArgs here. - host.WriteError('Do not know how to assemble --tsArgs.') - if ts_args: - command += f' --tsArgs "{ts_args}"' - elif 'traffic_server' in command: - command += ts_args - + # Have the full command including arguments in the cmdline so tool scripts + # can eventually use some keyword from the path to trace a particular TS instance + process_cmd = f"{os.path.join(ts_dir, bin_dir)}/{command} {ts_args}" # create process - p = obj.Processes.Process(name, command) + p = obj.Processes.Process(name, process_cmd) #p_debug = obj.Processes.Process("port-debug", "ss --listen --tcp --process") #p_debug.Env['PATH'] = "/usr/sbin" + os.pathsep + p.ComposeEnv()['PATH'] # p.StartBefore(p_debug) @@ -177,9 +169,6 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, p.Setup.MakeDir(runtime_dir) p.chownForATSProcess(runtime_dir) - # will need this for traffic_manager is it runs - p.Setup.MakeDir(os.path.join(config_dir, 'snapshots')) - p.Env['PROXY_CONFIG_SNAPSHOT_DIR'] = os.path.join(config_dir, 'snapshots') ########################################################## # create subdirectories that need to exist (but are empty) # ssl directory has to be created for keeping certs and keys @@ -241,16 +230,6 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, tmpname = os.path.join(log_dir, fname) p.Disk.File(tmpname, id='traffic_out') - if "traffic_manager" in command: - fname = log_data['manager'] - if fname == 'stdout': - p.Disk.manager_log = p.Streams.stdout - elif fname == 'stderr': - p.Disk.manager_log = p.Streams.stderr - else: - tmpname = os.path.join(log_dir, fname) - p.Disk.File(tmpname, id='manager_log') - # config files def MakeConfigFile(self, fname): tmpname = os.path.join(config_dir, fname) @@ -405,10 +384,7 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, p.Env['PROXY_CONFIG_ADMIN_AUTOCONF_PORT'] = str( p.Variables.admin_port) # support pre ATS 6.x - if 'traffic_manager' in command: - p.ReturnCode = 2 - else: - p.ReturnCode = 0 + p.ReturnCode = 0 if block_for_debug: p.Env['PROXY_BLOCK'] = '1' diff --git a/tests/gold_tests/basic/basic-manager.test.py b/tests/gold_tests/basic/basic-manager.test.py deleted file mode 100644 index c9dddefdb4c..00000000000 --- a/tests/gold_tests/basic/basic-manager.test.py +++ /dev/null @@ -1,33 +0,0 @@ -''' -''' -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -Test.Summary = ''' -Test that Trafficserver starts with default configurations. -''' - -Test.SkipIf(Condition.true("We do not need to test traffic_manager (JSONRPC)")) - -ts = Test.MakeATSProcess("ts", command="traffic_manager", select_ports=True) - -t = Test.AddTestRun("Test traffic server started properly") -t.StillRunningAfter = Test.Processes.ts - -p = t.Processes.Default -p.Command = "curl http://127.0.0.1:{0}".format(ts.Variables.port) -p.ReturnCode = 0 -p.StartBefore(Test.Processes.ts) diff --git a/tests/gold_tests/jsonrpc/jsonrpc_api_schema.test.py b/tests/gold_tests/jsonrpc/jsonrpc_api_schema.test.py index cf052a5f919..a93a1821eef 100644 --- a/tests/gold_tests/jsonrpc/jsonrpc_api_schema.test.py +++ b/tests/gold_tests/jsonrpc/jsonrpc_api_schema.test.py @@ -27,7 +27,7 @@ # set the schema folder. -schema_folder = os.path.join(Test.TestDirectory, '..', '..', '..', "mgmt2", "rpc", "schema") +schema_folder = os.path.join(Test.TestDirectory, '..', '..', '..', "mgmt", "rpc", "schema") def substitute_context_in_file(process, file, context): diff --git a/tests/gold_tests/logging/log-filenames.test.py b/tests/gold_tests/logging/log-filenames.test.py index 5f94f3236df..e94068adad5 100644 --- a/tests/gold_tests/logging/log-filenames.test.py +++ b/tests/gold_tests/logging/log-filenames.test.py @@ -35,8 +35,7 @@ class LogFilenamesTest: # The default log names for the various system logs. default_log_data = { 'diags': 'diags.log', - 'error': 'error.log', - 'manager': 'manager.log' + 'error': 'error.log' } def __init__(self, description, log_data=default_log_data): @@ -50,11 +49,11 @@ def __init__(self, description, log_data=default_log_data): MakeATSProcess extension. ''' self.__description = description - self.ts = self.__configure_traffic_manager(log_data) + self.ts = self.__configure_traffic_server(log_data) self.tr = self.__configure_traffic_TestRun(description) self.__configure_await_TestRun(self.sentinel_log_path) - def __configure_traffic_manager(self, log_data): + def __configure_traffic_server(self, log_data): ''' Common ATS configuration logic. Args: @@ -62,12 +61,11 @@ def __configure_traffic_manager(self, log_data): MakeATSProcess extension. Return: - The traffic_manager process. + The traffic_server process. ''' self._ts_name = f"ts{LogFilenamesTest.__ts_counter}" LogFilenamesTest.__ts_counter += 1 - self.ts = Test.MakeATSProcess(self._ts_name, command="traffic_manager", - use_traffic_out=False, log_data=log_data) + self.ts = Test.MakeATSProcess(self._ts_name, use_traffic_out=False, log_data=log_data) self.ts.Disk.records_config.update({ 'proxy.config.diags.debug.enabled': 0, 'proxy.config.diags.debug.tags': 'log', @@ -159,13 +157,9 @@ def configure_named_custom_log(self, custom_log_filename): return self.custom_log_path def set_log_expectations(self): - ''' Configure sanity checks for each of the log types (manager, error, + ''' Configure sanity checks for each of the log types (diags, error, etc.) to verify they are emitting the expected content. ''' - manager_path = self.ts.Disk.manager_log.AbsPath - self.ts.Disk.manager_log.Content += Testers.ContainsExpression( - "Launching ts process", - f"{manager_path} should contain traffic_manager log messages") diags_path = self.ts.Disk.diags_log.AbsPath self.ts.Disk.diags_log.Content += Testers.ContainsExpression( @@ -185,47 +179,33 @@ def set_log_expectations(self): class DefaultNamedTest(LogFilenamesTest): ''' Verify that if custom names are not configured, then the default - 'diags.log', 'manager.log', and 'error.log' are written to. + 'diags.log' and 'error.log' are written to. ''' def __init__(self): super().__init__('default log filename configuration') - # For these tests, more important than the listening port is the - # existence of the log files. In particular, it can take a few seconds - # for traffic_manager to open diags.log. - self.diags_log = self.ts.Disk.diags_log.AbsPath - self.ts.Ready = When.FileExists(self.diags_log) - self.configure_named_custom_log('my_custom_log') self.set_log_expectations() class CustomNamedTest(LogFilenamesTest): - ''' Verify that the user can assign custom filenames to manager.log, etc. + ''' Verify that the user can assign custom filenames to diags.log, etc. ''' def __init__(self): log_data = { 'diags': 'my_diags.log', - 'error': 'my_error.log', - 'manager': 'my_manager.log' + 'error': 'my_error.log' } super().__init__('specify log filename configuration', log_data) - # Configure custom names for manager.log, etc. + # Configure custom names for diags.log, etc. self.ts.Disk.records_config.update({ - 'proxy.node.config.manager_log_filename': 'my_manager.log', 'proxy.config.diags.logfile.filename': 'my_diags.log', 'proxy.config.error.logfile.filename': 'my_error.log', }) - # For these tests, more important than the listening port is the - # existence of the log files. In particular, it can take a few seconds - # for traffic_manager to open diags.log. - self.diags_log = self.ts.Disk.diags_log.AbsPath - self.ts.Ready = When.FileExists(self.diags_log) - self.configure_named_custom_log('my_custom_log') self.set_log_expectations() @@ -238,14 +218,12 @@ def __init__(self): log_data = { 'diags': 'stdout', - 'error': 'stdout', - 'manager': 'stdout' + 'error': 'stdout' } super().__init__('specify logs to go to stdout', log_data) - # Configure custom names for manager.log, etc. + # Configure custom names for diags.log, etc. self.ts.Disk.records_config.update({ - 'proxy.node.config.manager_log_filename': 'stdout', 'proxy.config.diags.logfile.filename': 'stdout', 'proxy.config.error.logfile.filename': 'stdout', }) @@ -267,14 +245,12 @@ def __init__(self): log_data = { 'diags': 'stderr', - 'error': 'stderr', - 'manager': 'stderr' + 'error': 'stderr' } super().__init__('specify logs to go to stderr', log_data) - # Configure custom names for manager.log, etc. + # Configure custom names for diags.log, etc. self.ts.Disk.records_config.update({ - 'proxy.node.config.manager_log_filename': 'stderr', 'proxy.config.diags.logfile.filename': 'stderr', 'proxy.config.error.logfile.filename': 'stderr', }) diff --git a/tests/gold_tests/logging/sigusr2.test.py b/tests/gold_tests/logging/sigusr2.test.py index fae67e051c4..f644e766d36 100644 --- a/tests/gold_tests/logging/sigusr2.test.py +++ b/tests/gold_tests/logging/sigusr2.test.py @@ -20,8 +20,7 @@ import os import sys - -TRAFFIC_MANAGER_PID_SCRIPT = 'ts_process_handler.py' +TS_PID_SCRIPT = 'ts_process_handler.py' class Sigusr2Test: @@ -34,12 +33,12 @@ class Sigusr2Test: def __init__(self): self.server = self.__configure_server() - self.ts = self.__configure_traffic_manager() + self.ts = self.__configure_traffic_server() - def __configure_traffic_manager(self): + def __configure_traffic_server(self): self._ts_name = "sigusr2_ts{}".format(Sigusr2Test.__ts_counter) Sigusr2Test.__ts_counter += 1 - self.ts = Test.MakeATSProcess(self._ts_name, command="traffic_manager") + self.ts = Test.MakeATSProcess(self._ts_name) self.ts.Disk.records_config.update({ 'proxy.config.http.wait_for_cache': 1, 'proxy.config.diags.debug.enabled': 1, @@ -51,20 +50,13 @@ def __configure_traffic_manager(self): 'proxy.config.log.auto_delete_rolled_files': 0, }) - # For this test, more important than the listening port is the existence of the - # log files. In particular, it can take a few seconds for traffic_manager to - # open diags.log. self.diags_log = self.ts.Disk.diags_log.AbsPath - self.ts.Ready = When.FileExists(self.diags_log) # Add content handles for the rotated logs. self.rotated_diags_log = self.diags_log + "_old" self.ts.Disk.File(self.rotated_diags_log, id="diags_log_old") self.log_dir = os.path.dirname(self.diags_log) - self.manager_log = os.path.join(self.log_dir, "manager.log") - self.rotated_manager_log = self.manager_log + "_old" - self.ts.Disk.File(self.rotated_manager_log, id="manager_log_old") self.ts.Disk.remap_config.AddLine( 'map http://127.0.0.1:{0} http://127.0.0.1:{1}'.format( @@ -105,10 +97,10 @@ def __configure_server(self): def get_sigusr2_signal_command(self): """ - Return the command that will send a USR2 signal to the traffic manager + Return the command that will send a USR2 signal to the traffic server process. """ - return (f"{sys.executable} {TRAFFIC_MANAGER_PID_SCRIPT} --parent " + return (f"{sys.executable} {TS_PID_SCRIPT} " f"--signal SIGUSR2 {self._ts_name}") @@ -116,44 +108,31 @@ def get_sigusr2_signal_command(self): Verify support of external log rotation via SIGUSR2. ''' -Test.Setup.CopyAs(TRAFFIC_MANAGER_PID_SCRIPT, Test.RunDirectory) +Test.Setup.CopyAs(TS_PID_SCRIPT, Test.RunDirectory) # # Test 1: Verify SIGUSR2 behavior for system logs. # -tr1 = Test.AddTestRun("Verify system logs (manager.log, etc.) can be rotated") +tr1 = Test.AddTestRun("Verify system logs can be rotated") -# Configure Traffic Manager/Server. +# Configure Server. diags_test = Sigusr2Test() # Configure our rotation processes. rotate_diags_log = tr1.Processes.Process("rotate_diags_log", "mv {} {}".format( diags_test.diags_log, diags_test.rotated_diags_log)) -rotate_manager_log = tr1.Processes.Process("rotate_manager_log", "mv {} {}".format( - diags_test.manager_log, diags_test.rotated_manager_log)) -# Configure the signaling of SIGUSR2 to traffic_manager. +# Configure the signaling of SIGUSR2 to traffic_server. tr1.Processes.Default.Command = diags_test.get_sigusr2_signal_command() tr1.Processes.Default.Return = 0 tr1.Processes.Default.Ready = When.FileExists(diags_test.diags_log) # Configure process order. tr1.Processes.Default.StartBefore(rotate_diags_log) -rotate_diags_log.StartBefore(rotate_manager_log) -rotate_manager_log.StartBefore(diags_test.ts) +rotate_diags_log.StartBefore(diags_test.ts) tr1.StillRunningAfter = diags_test.ts tr1.StillRunningAfter = diags_test.server -# manager.log should have been rotated. Check for the expected content in the -# old file and the newly created file. -diags_test.ts.Disk.manager_log_old.Content += Testers.ContainsExpression( - "received SIGUSR2, rotating the logs", - "manager.log_old should explain that SIGUSR2 was passed to it") - -diags_test.ts.Disk.manager_log.Content += Testers.ContainsExpression( - "Reseated manager.log", - "The new manager.log should indicate the newly opened manager.log") - # diags.log should have been rotated. The old one had the reference to traffic # server running, this new one shouldn't. But it should indicate that the new # diags.log was opened. @@ -215,7 +194,7 @@ def get_sigusr2_signal_command(self): # 1. curl /first. The entry should be logged to current log which will be _old. # 2. mv the log to _old. # 3. curl /second. The entry should end up in _old log. -# 4. Send a SIGUSR2 to traffic_manager. The log should be recreated. +# 4. Send a SIGUSR2 to traffic_server. The log should be recreated. # 5. curl /third. The entry should end up in the new, non-old, log file. # tr2.Processes.Default.StartBefore(third_curl_ready) diff --git a/tests/gold_tests/pluginTest/lua/lua_debug_tags.test.py b/tests/gold_tests/pluginTest/lua/lua_debug_tags.test.py index 4803b9efaa1..cdb890386c8 100644 --- a/tests/gold_tests/pluginTest/lua/lua_debug_tags.test.py +++ b/tests/gold_tests/pluginTest/lua/lua_debug_tags.test.py @@ -28,7 +28,7 @@ Test.ContinueOnFail = False # Define default ATS -ts = Test.MakeATSProcess("ts", command="traffic_manager") +ts = Test.MakeATSProcess("ts", command="traffic_server") ts.Disk.remap_config.AddLine( 'map http://test http://127.0.0.1/ @plugin=tslua.so @pparam=tags.lua' diff --git a/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_state.test.py b/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_state.test.py index 04433cc5f71..f737916efd9 100644 --- a/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_state.test.py +++ b/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_state.test.py @@ -35,7 +35,7 @@ server = Test.MakeOriginServer("server") # Define ATS and configure -ts = Test.MakeATSProcess("ts", command="traffic_manager") +ts = Test.MakeATSProcess("ts", command="traffic_server") # **testname is required** testName = "regex_revalidate_state" diff --git a/tests/gold_tests/pluginTest/remap_stats/remap_stats_post.test.py b/tests/gold_tests/pluginTest/remap_stats/remap_stats_post.test.py index 93e9e996e34..5687bda2bf5 100644 --- a/tests/gold_tests/pluginTest/remap_stats/remap_stats_post.test.py +++ b/tests/gold_tests/pluginTest/remap_stats/remap_stats_post.test.py @@ -30,7 +30,7 @@ "timestamp": "1469733493.993", "body": ""} server.addResponse("sessionlog.json", request_header, response_header) -ts = Test.MakeATSProcess("ts", command="traffic_manager", select_ports=True) +ts = Test.MakeATSProcess("ts", select_ports=True) ts.Disk.plugin_config.AddLine('remap_stats.so --post-remap-host') diff --git a/tests/gold_tests/remap/remap_reload.test.py b/tests/gold_tests/remap/remap_reload.test.py index 57ac1a58a48..bfb90967c7f 100644 --- a/tests/gold_tests/remap/remap_reload.test.py +++ b/tests/gold_tests/remap/remap_reload.test.py @@ -25,7 +25,7 @@ replay_file_3 = "reload_3.replay.yaml" replay_file_4 = "reload_4.replay.yaml" -tm = Test.MakeATSProcess("tm", select_ports=True) +tm = Test.MakeATSProcess("ts", select_ports=True) tm.Disk.diags_log.Content = Testers.ContainsExpression("remap.config failed to load", "Remap should fail to load") remap_cfg_path = os.path.join(tm.Variables.CONFIGDIR, 'remap.config') diff --git a/tests/gold_tests/runroot/runroot_manager.test.py b/tests/gold_tests/runroot/runroot_manager.test.py deleted file mode 100644 index 90023fda4a8..00000000000 --- a/tests/gold_tests/runroot/runroot_manager.test.py +++ /dev/null @@ -1,54 +0,0 @@ -''' -''' -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -Test.Summary = ''' -Test for using of runroot of traffic_manager. -''' -Test.ContinueOnFail = False - -# create runroot for testing -runroot_path = os.path.join(Test.RunDirectory, "runroot") -rr_file = os.path.join(Test.RunDirectory, "rr_tmp") - -tr = Test.AddTestRun("create runroot and deal with it") -tr.Processes.Default.Command = "$ATS_BIN/traffic_layout init --path " + runroot_path + " --absolute; " + \ - "mkdir " + rr_file + "; mv " + \ - os.path.join(runroot_path, "runroot.yaml") + " " + \ - os.path.join(rr_file, "runroot.yaml") -f = tr.Disk.File(os.path.join(rr_file, "runroot.yaml")) -f.Exists = True - - -def StopProcess(event, time): - if event.TotalRunTime > time: - event.object.Stop() - return 0, "stop manager process", "manager will be killed" - - -tr = Test.AddTestRun("manager runroot test") - -trafficserver_dir = os.path.join(runroot_path, 'var', 'trafficserver') -tr.ChownForATSProcess(trafficserver_dir) - -p = tr.Processes.Default -p.Command = "$ATS_BIN/traffic_server --run-root=" + rr_file -p.RunningEvent.Connect(Testers.Lambda(lambda ev: StopProcess(ev, 10))) -p.Streams.All = Testers.ContainsExpression("traffic_server: using root directory '" + - runroot_path + "'", "check if the right runroot is passed down")