Merge branch 'maxinfo' of https://github.com/mariadb-corporation/MaxScale into maxinfo
This commit is contained in:
@ -28,6 +28,7 @@
|
|||||||
- [Filter Tutorial](Tutorials/Filter-Tutorial.md)
|
- [Filter Tutorial](Tutorials/Filter-Tutorial.md)
|
||||||
- [Galera Cluster Connection Routing Tutorial](Tutorials/Galera-Cluster-Connection-Routing-Tutorial.md)
|
- [Galera Cluster Connection Routing Tutorial](Tutorials/Galera-Cluster-Connection-Routing-Tutorial.md)
|
||||||
- [Galera Cluster Read-Write Splitting Tutorial](Tutorials/Galera-Cluster-Read-Write-Splitting-Tutorial.md)
|
- [Galera Cluster Read-Write Splitting Tutorial](Tutorials/Galera-Cluster-Read-Write-Splitting-Tutorial.md)
|
||||||
|
- [MaxScale Information Schema Tutorial](Tutorials/MaxScale-Informaton-Schema.md)
|
||||||
- [MySQL Replication Connection Routing Tutorial](Tutorials/MySQL-Replication-Connection-Routing-Tutorial.md)
|
- [MySQL Replication Connection Routing Tutorial](Tutorials/MySQL-Replication-Connection-Routing-Tutorial.md)
|
||||||
- [MySQL Replication Read-Write Splitting Tutorial](Tutorials/MySQL-Replication-Read-Write-Splitting-Tutorial.md)
|
- [MySQL Replication Read-Write Splitting Tutorial](Tutorials/MySQL-Replication-Read-Write-Splitting-Tutorial.md)
|
||||||
- [MySQL Cluster Setup](Tutorials/MySQL-Cluster-Setup.md)
|
- [MySQL Cluster Setup](Tutorials/MySQL-Cluster-Setup.md)
|
||||||
|
|||||||
508
Documentation/Tutorials/MaxScale-Information-Schema.md
Normal file
508
Documentation/Tutorials/MaxScale-Information-Schema.md
Normal file
@ -0,0 +1,508 @@
|
|||||||
|
# MaxInfo Plugin
|
||||||
|
The maxinfo plugin is a special router plugin similar to the one used for implementing the server side component of the MaxAdmin interface. The plugin is designed to return data regarding the internals of MaxScale, it provides an information schema approach to monitoring the internals of MaxScale itself.
|
||||||
|
|
||||||
|
The plugin is capable of returning data in one of two ways, either as MySQL result sets or as JSON encoded data. The choice of which mechanism used to return the data is determined by the type of the request the router receives. If a MySQL command is received then the router will return the results as a MySQL result set, if an HTTP request is received then the data will be returned as a JSON document.
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
The plugin is configured in the MaxScale.cnf plugin in much the same way as any other router service is configured, there needs to be a service section in the configuration file and also listeners defined for that service. The service does not however require any backend servers to be associated with it, or any monitors.
|
||||||
|
|
||||||
|
The service entry merely needs to define the service name, the type as service and the router module to load.
|
||||||
|
|
||||||
|
[MaxInfo]
|
||||||
|
type=service
|
||||||
|
router=maxinfo
|
||||||
|
|
||||||
|
The listener section defines the protocol, port and other information needed to create a listener for the service. To listen on a port using the MySQL protocol a section as shown below should be added to the configuration file.
|
||||||
|
|
||||||
|
[MaxInfo Listener]
|
||||||
|
type=listener
|
||||||
|
service=MaxInfo
|
||||||
|
protocol=MySQLClient
|
||||||
|
port=9003
|
||||||
|
|
||||||
|
To listen with the HTTP protocol and hence return JSON documents a section as should below is required.
|
||||||
|
|
||||||
|
[MaxInfo JSON Listener]
|
||||||
|
type=listener
|
||||||
|
service=MaxInfo
|
||||||
|
protocol=HTTPD
|
||||||
|
port=8003
|
||||||
|
|
||||||
|
If both the MySQL and JSON responses are required then a single service can be configured with both types of listener.
|
||||||
|
|
||||||
|
As with any other listeners within MaxScale the listeners can be bound to a particular interface by use of the address= parameter. This allows the access to the maxinfo data to be limited to the localhost by adding an address=localhost parameter in the configuration file.
|
||||||
|
|
||||||
|
[MaxInfo Listener]
|
||||||
|
type=listener
|
||||||
|
service=MaxInfo
|
||||||
|
protocol=MySQLClient
|
||||||
|
address=localhost
|
||||||
|
port=9003
|
||||||
|
|
||||||
|
# MySQL Interface to maxinfo
|
||||||
|
|
||||||
|
The maxinfo supports a small subset of SQL statements in addition to the MySQL status and ping requests. These may be used for simple monitoring of MaxScale.
|
||||||
|
|
||||||
|
% mysqladmin -hmaxscale.mariadb.com -P9003 -umonitor ping
|
||||||
|
mysqld is alive
|
||||||
|
% mysqladmin -hmaxscale.mariadb.com -P9003 -umonitor status
|
||||||
|
Uptime: 72 Threads: 1 Sessions: 11
|
||||||
|
%
|
||||||
|
|
||||||
|
The SQL command used to interact with maxinfo is the show command, a variety of show commands are available and will be described in the following sections.
|
||||||
|
|
||||||
|
## Show variables
|
||||||
|
|
||||||
|
The show variables command will display a set of name and value pairs for a number of MaxScale system variables.
|
||||||
|
|
||||||
|
mysql> show variables;
|
||||||
|
+--------------------+-------------------------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+--------------------+-------------------------+
|
||||||
|
| version | 1.0.6-unstable |
|
||||||
|
| version_comment | MariaDB MaxScale |
|
||||||
|
| basedir | /home/mriddoch/skygate2 |
|
||||||
|
| MAXSCALE_VERSION | 1.0.6-unstable |
|
||||||
|
| MAXSCALE_THREADS | 1 |
|
||||||
|
| MAXSCALE_NBPOLLS | 3 |
|
||||||
|
| MAXSCALE_POLLSLEEP | 1000 |
|
||||||
|
| MAXSCALE_UPTIME | 223 |
|
||||||
|
| MAXSCALE_SESSIONS | 11 |
|
||||||
|
+--------------------+-------------------------+
|
||||||
|
9 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
The show variables command can also accept a limited like clause. This like clause must either be a literal string to match, a pattern starting with a %, a pattern ending with a % or a string with a % at both the start and the end.
|
||||||
|
|
||||||
|
mysql> show variables like 'version';
|
||||||
|
+---------------+----------------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+---------------+----------------+
|
||||||
|
| version | 1.0.6-unstable |
|
||||||
|
+---------------+----------------+
|
||||||
|
1 row in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql> show variables like 'version%';
|
||||||
|
+-----------------+------------------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+-----------------+------------------+
|
||||||
|
| version | 1.0.6-unstable |
|
||||||
|
| version_comment | MariaDB MaxScale |
|
||||||
|
+-----------------+------------------+
|
||||||
|
2 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql> show variables like '%comment';
|
||||||
|
+-----------------+------------------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+-----------------+------------------+
|
||||||
|
| version_comment | MariaDB MaxScale |
|
||||||
|
+-----------------+------------------+
|
||||||
|
1 row in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql> show variables like '%ers%';
|
||||||
|
+------------------+------------------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+------------------+------------------+
|
||||||
|
| version | 1.0.6-unstable |
|
||||||
|
| version_comment | MariaDB MaxScale |
|
||||||
|
| MAXSCALE_VERSION | 1.0.6-unstable |
|
||||||
|
+------------------+------------------+
|
||||||
|
3 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
## Show status
|
||||||
|
|
||||||
|
The show status command displays a set of status counters, as with show variables the show status command can be passed a simplifed like clause to limit the values returned.
|
||||||
|
|
||||||
|
mysql> show status;
|
||||||
|
+---------------------------+-------+
|
||||||
|
| Variable_name | Value |
|
||||||
|
+---------------------------+-------+
|
||||||
|
| Uptime | 156 |
|
||||||
|
| Uptime_since_flush_status | 156 |
|
||||||
|
| Threads_created | 1 |
|
||||||
|
| Threads_running | 1 |
|
||||||
|
| Threadpool_threads | 1 |
|
||||||
|
| Threads_connected | 11 |
|
||||||
|
| Connections | 11 |
|
||||||
|
| Client_connections | 2 |
|
||||||
|
| Backend_connections | 0 |
|
||||||
|
| Listeners | 9 |
|
||||||
|
| Zombie_connections | 0 |
|
||||||
|
| Internal_descriptors | 2 |
|
||||||
|
| Read_events | 22 |
|
||||||
|
| Write_events | 24 |
|
||||||
|
| Hangup_events | 0 |
|
||||||
|
| Error_events | 0 |
|
||||||
|
| Accept_events | 2 |
|
||||||
|
| Event_queue_length | 1 |
|
||||||
|
| Pending_events | 0 |
|
||||||
|
| Max_event_queue_length | 1 |
|
||||||
|
| Max_event_queue_time | 0 |
|
||||||
|
| Max_event_execution_time | 0 |
|
||||||
|
+---------------------------+-------+
|
||||||
|
22 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
## Show services
|
||||||
|
|
||||||
|
The show services command will return a set of basic statistics regarding each of the configured services within MaxScale.
|
||||||
|
|
||||||
|
mysql> show services;
|
||||||
|
+----------------+----------------+--------------+----------------+
|
||||||
|
| Service Name | Router Module | No. Sessions | Total Sessions |
|
||||||
|
+----------------+----------------+--------------+----------------+
|
||||||
|
| Test Service | readconnroute | 1 | 1 |
|
||||||
|
| Split Service | readwritesplit | 1 | 1 |
|
||||||
|
| Filter Service | readconnroute | 1 | 1 |
|
||||||
|
| Named Service | readwritesplit | 1 | 1 |
|
||||||
|
| QLA Service | readconnroute | 1 | 1 |
|
||||||
|
| Debug Service | debugcli | 1 | 1 |
|
||||||
|
| CLI | cli | 1 | 1 |
|
||||||
|
| MaxInfo | maxinfo | 4 | 4 |
|
||||||
|
+----------------+----------------+--------------+----------------+
|
||||||
|
8 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
The show services command does not accept a like clause and will ignore any like clause that is given.
|
||||||
|
|
||||||
|
## Show listeners
|
||||||
|
|
||||||
|
The show listeners command will return a set of status information for every listener defined within the MaxScale configuration file.
|
||||||
|
|
||||||
|
mysql> show listeners;
|
||||||
|
+----------------+-----------------+-----------+------+---------+
|
||||||
|
| Service Name | Protocol Module | Address | Port | State |
|
||||||
|
+----------------+-----------------+-----------+------+---------+
|
||||||
|
| Test Service | MySQLClient | * | 4006 | Running |
|
||||||
|
| Split Service | MySQLClient | * | 4007 | Running |
|
||||||
|
| Filter Service | MySQLClient | * | 4008 | Running |
|
||||||
|
| Named Service | MySQLClient | * | 4010 | Running |
|
||||||
|
| QLA Service | MySQLClient | * | 4009 | Running |
|
||||||
|
| Debug Service | telnetd | localhost | 4242 | Running |
|
||||||
|
| CLI | maxscaled | localhost | 6603 | Running |
|
||||||
|
| MaxInfo | MySQLClient | * | 9003 | Running |
|
||||||
|
| MaxInfo | HTTPD | * | 8003 | Running |
|
||||||
|
+----------------+-----------------+-----------+------+---------+
|
||||||
|
9 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
The show listeners command will ignore any like clause passed to it.
|
||||||
|
|
||||||
|
## Show sessions
|
||||||
|
|
||||||
|
The show sessions command returns information on every active session within MaxScale. It will ignore any like clause passed to it.
|
||||||
|
|
||||||
|
mysql> show sessions;
|
||||||
|
+-----------+---------------+----------------+---------------------------+
|
||||||
|
| Session | Client | Service | State |
|
||||||
|
+-----------+---------------+----------------+---------------------------+
|
||||||
|
| 0x1a92a60 | 127.0.0.1 | MaxInfo | Session ready for routing |
|
||||||
|
| 0x1a92100 | 80.240.130.35 | MaxInfo | Session ready for routing |
|
||||||
|
| 0x1a76a00 | | MaxInfo | Listener Session |
|
||||||
|
| 0x1a76020 | | MaxInfo | Listener Session |
|
||||||
|
| 0x1a75d40 | | CLI | Listener Session |
|
||||||
|
| 0x1a75220 | | Debug Service | Listener Session |
|
||||||
|
| 0x1a774b0 | | QLA Service | Listener Session |
|
||||||
|
| 0x1a78630 | | Named Service | Listener Session |
|
||||||
|
| 0x1a60270 | | Filter Service | Listener Session |
|
||||||
|
| 0x1a606f0 | | Split Service | Listener Session |
|
||||||
|
| 0x19b0380 | | Test Service | Listener Session |
|
||||||
|
+-----------+---------------+----------------+---------------------------+
|
||||||
|
11 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
## Show clients
|
||||||
|
|
||||||
|
The show clients command reports a row for every client application connected to MaxScale. Like clauses are not available of the show clients command.
|
||||||
|
|
||||||
|
mysql> show clients;
|
||||||
|
+-----------+---------------+---------+---------------------------+
|
||||||
|
| Session | Client | Service | State |
|
||||||
|
+-----------+---------------+---------+---------------------------+
|
||||||
|
| 0x1a92a60 | 127.0.0.1 | MaxInfo | Session ready for routing |
|
||||||
|
| 0x1a92100 | 80.240.130.35 | MaxInfo | Session ready for routing |
|
||||||
|
+-----------+---------------+---------+---------------------------+
|
||||||
|
2 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
## Show servers
|
||||||
|
|
||||||
|
The show servers command returns data for each backend server configured within the MaxScale configuration file. This data includes the current number of connections MaxScale has to that server and the state of that server as monitored by MaxScale.
|
||||||
|
|
||||||
|
mysql> show servers;
|
||||||
|
+---------+-----------+------+-------------+---------+
|
||||||
|
| Server | Address | Port | Connections | Status |
|
||||||
|
+---------+-----------+------+-------------+---------+
|
||||||
|
| server1 | 127.0.0.1 | 3306 | 0 | Running |
|
||||||
|
| server2 | 127.0.0.1 | 3307 | 0 | Down |
|
||||||
|
| server3 | 127.0.0.1 | 3308 | 0 | Down |
|
||||||
|
| server4 | 127.0.0.1 | 3309 | 0 | Down |
|
||||||
|
+---------+-----------+------+-------------+---------+
|
||||||
|
4 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
## Show modules
|
||||||
|
|
||||||
|
The show modules command reports the information on the modules currently loaded into MaxScale. This includes the name type and version of each module. It also includes the API version the module has been written against and the current release status of the module.
|
||||||
|
|
||||||
|
mysql> show modules;
|
||||||
|
+----------------+-------------+---------+-------------+----------------+
|
||||||
|
| Module Name | Module Type | Version | API Version | Status |
|
||||||
|
+----------------+-------------+---------+-------------+----------------+
|
||||||
|
| HTTPD | Protocol | V1.0.1 | 1.0.0 | In Development |
|
||||||
|
| maxscaled | Protocol | V1.0.0 | 1.0.0 | GA |
|
||||||
|
| telnetd | Protocol | V1.0.1 | 1.0.0 | GA |
|
||||||
|
| MySQLClient | Protocol | V1.0.0 | 1.0.0 | GA |
|
||||||
|
| mysqlmon | Monitor | V1.4.0 | 1.0.0 | GA |
|
||||||
|
| readwritesplit | Router | V1.0.2 | 1.0.0 | GA |
|
||||||
|
| readconnroute | Router | V1.1.0 | 1.0.0 | GA |
|
||||||
|
| debugcli | Router | V1.1.1 | 1.0.0 | GA |
|
||||||
|
| cli | Router | V1.0.0 | 1.0.0 | GA |
|
||||||
|
| maxinfo | Router | V1.0.0 | 1.0.0 | Alpha |
|
||||||
|
+----------------+-------------+---------+-------------+----------------+
|
||||||
|
10 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
|
||||||
|
## Show monitors
|
||||||
|
|
||||||
|
The show monitors command reports each monitor configured within the system and the state of that monitor.
|
||||||
|
|
||||||
|
mysql> show monitors;
|
||||||
|
+---------------+---------+
|
||||||
|
| Monitor | Status |
|
||||||
|
+---------------+---------+
|
||||||
|
| MySQL Monitor | Running |
|
||||||
|
+---------------+---------+
|
||||||
|
1 row in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
|
||||||
|
## Show eventTimes
|
||||||
|
|
||||||
|
The show eventTimes command returns a table of statistics that reflect the performance of the event queuing and execution portion of the MaxScale core.
|
||||||
|
|
||||||
|
mysql> show eventTimes;
|
||||||
|
+---------------+-------------------+---------------------+
|
||||||
|
| Duration | No. Events Queued | No. Events Executed |
|
||||||
|
+---------------+-------------------+---------------------+
|
||||||
|
| < 100ms | 460 | 456 |
|
||||||
|
| 100 - 200ms | 0 | 3 |
|
||||||
|
| 200 - 300ms | 0 | 0 |
|
||||||
|
| 300 - 400ms | 0 | 0 |
|
||||||
|
| 400 - 500ms | 0 | 0 |
|
||||||
|
| 500 - 600ms | 0 | 0 |
|
||||||
|
| 600 - 700ms | 0 | 0 |
|
||||||
|
| 700 - 800ms | 0 | 0 |
|
||||||
|
| 800 - 900ms | 0 | 0 |
|
||||||
|
| 900 - 1000ms | 0 | 0 |
|
||||||
|
| 1000 - 1100ms | 0 | 0 |
|
||||||
|
| 1100 - 1200ms | 0 | 0 |
|
||||||
|
| 1200 - 1300ms | 0 | 0 |
|
||||||
|
| 1300 - 1400ms | 0 | 0 |
|
||||||
|
| 1400 - 1500ms | 0 | 0 |
|
||||||
|
| 1500 - 1600ms | 0 | 0 |
|
||||||
|
| 1600 - 1700ms | 0 | 0 |
|
||||||
|
| 1700 - 1800ms | 0 | 0 |
|
||||||
|
| 1800 - 1900ms | 0 | 0 |
|
||||||
|
| 1900 - 2000ms | 0 | 0 |
|
||||||
|
| 2000 - 2100ms | 0 | 0 |
|
||||||
|
| 2100 - 2200ms | 0 | 0 |
|
||||||
|
| 2200 - 2300ms | 0 | 0 |
|
||||||
|
| 2300 - 2400ms | 0 | 0 |
|
||||||
|
| 2400 - 2500ms | 0 | 0 |
|
||||||
|
| 2500 - 2600ms | 0 | 0 |
|
||||||
|
| 2600 - 2700ms | 0 | 0 |
|
||||||
|
| 2700 - 2800ms | 0 | 0 |
|
||||||
|
| 2800 - 2900ms | 0 | 0 |
|
||||||
|
| > 3000ms | 0 | 0 |
|
||||||
|
+---------------+-------------------+---------------------+
|
||||||
|
30 rows in set (0.02 sec)
|
||||||
|
|
||||||
|
mysql>
|
||||||
|
|
||||||
|
Each row represents a time interval, in 100ms increments, with the counts representing the number of events that were in the event queue for the length of time that row represents and the number of events that were executing of the time indicated by the row.
|
||||||
|
|
||||||
|
# JSON Interface
|
||||||
|
|
||||||
|
The simplified JSON interface takes the URL of the request made to maxinfo and maps that to a show command in the above section.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
The /variables URL will return the MaxScale variables, these variables can not be filtered via this interface.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/variables
|
||||||
|
[ { "Variable_name" : "version", "Value" : "1.0.6-unstable"},
|
||||||
|
{ "Variable_name" : "version_comment", "Value" : "MariaDB MaxScale"},
|
||||||
|
{ "Variable_name" : "basedir", "Value" : "/home/mriddoch/skygate2"},
|
||||||
|
{ "Variable_name" : "MAXSCALE_VERSION", "Value" : "1.0.6-unstable"},
|
||||||
|
{ "Variable_name" : "MAXSCALE_THREADS", "Value" : 1},
|
||||||
|
{ "Variable_name" : "MAXSCALE_NBPOLLS", "Value" : 3},
|
||||||
|
{ "Variable_name" : "MAXSCALE_POLLSLEEP", "Value" : 1000},
|
||||||
|
{ "Variable_name" : "MAXSCALE_UPTIME", "Value" : 3948},
|
||||||
|
{ "Variable_name" : "MAXSCALE_SESSIONS", "Value" : 12}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Use of the /status URI will return the status information that would normally be returned by the show status command. No filtering of the status information is available via this interface
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/status
|
||||||
|
[ { "Variable_name" : "Uptime", "Value" : 3831},
|
||||||
|
{ "Variable_name" : "Uptime_since_flush_status", "Value" : 3831},
|
||||||
|
{ "Variable_name" : "Threads_created", "Value" : 1},
|
||||||
|
{ "Variable_name" : "Threads_running", "Value" : 1},
|
||||||
|
{ "Variable_name" : "Threadpool_threads", "Value" : 1},
|
||||||
|
{ "Variable_name" : "Threads_connected", "Value" : 12},
|
||||||
|
{ "Variable_name" : "Connections", "Value" : 12},
|
||||||
|
{ "Variable_name" : "Client_connections", "Value" : 3},
|
||||||
|
{ "Variable_name" : "Backend_connections", "Value" : 0},
|
||||||
|
{ "Variable_name" : "Listeners", "Value" : 9},
|
||||||
|
{ "Variable_name" : "Zombie_connections", "Value" : 0},
|
||||||
|
{ "Variable_name" : "Internal_descriptors", "Value" : 3},
|
||||||
|
{ "Variable_name" : "Read_events", "Value" : 469},
|
||||||
|
{ "Variable_name" : "Write_events", "Value" : 479},
|
||||||
|
{ "Variable_name" : "Hangup_events", "Value" : 12},
|
||||||
|
{ "Variable_name" : "Error_events", "Value" : 0},
|
||||||
|
{ "Variable_name" : "Accept_events", "Value" : 15},
|
||||||
|
{ "Variable_name" : "Event_queue_length", "Value" : 1},
|
||||||
|
{ "Variable_name" : "Pending_events", "Value" : 0},
|
||||||
|
{ "Variable_name" : "Max_event_queue_length", "Value" : 1},
|
||||||
|
{ "Variable_name" : "Max_event_queue_time", "Value" : 0},
|
||||||
|
{ "Variable_name" : "Max_event_execution_time", "Value" : 1}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
The /services URI returns the data regarding the services defined within the configuration of MaxScale. Two counters are returned, the current number of sessions attached to this service and the total number connected since the service started.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/services
|
||||||
|
[ { "Service Name" : "Test Service", "Router Module" : "readconnroute", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "Split Service", "Router Module" : "readwritesplit", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "Filter Service", "Router Module" : "readconnroute", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "Named Service", "Router Module" : "readwritesplit", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "QLA Service", "Router Module" : "readconnroute", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "Debug Service", "Router Module" : "debugcli", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "CLI", "Router Module" : "cli", "No. Sessions" : 1, "Total Sessions" : 1},
|
||||||
|
{ "Service Name" : "MaxInfo", "Router Module" : "maxinfo", "No. Sessions" : 5, "Total Sessions" : 20}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Listeners
|
||||||
|
|
||||||
|
The /listeners URI will return a JSON array with one entry per listener, each entry is a JSON object that describes the configuration and state of that listener.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/listeners
|
||||||
|
[ { "Service Name" : "Test Service", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 4006, "State" : "Running"},
|
||||||
|
{ "Service Name" : "Split Service", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 4007, "State" : "Running"},
|
||||||
|
{ "Service Name" : "Filter Service", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 4008, "State" : "Running"},
|
||||||
|
{ "Service Name" : "Named Service", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 4010, "State" : "Running"},
|
||||||
|
{ "Service Name" : "QLA Service", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 4009, "State" : "Running"},
|
||||||
|
{ "Service Name" : "Debug Service", "Protocol Module" : "telnetd", "Address" : "localhost", "Port" : 4242, "State" : "Running"},
|
||||||
|
{ "Service Name" : "CLI", "Protocol Module" : "maxscaled", "Address" : "localhost", "Port" : 6603, "State" : "Running"},
|
||||||
|
{ "Service Name" : "MaxInfo", "Protocol Module" : "MySQLClient", "Address" : "*", "Port" : 9003, "State" : "Running"},
|
||||||
|
{ "Service Name" : "MaxInfo", "Protocol Module" : "HTTPD", "Address" : "*", "Port" : 8003, "State" : "Running"}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
The /modules URI returns data for each plugin that has been loaded into MaxScale. The plugin name, type and version are returned as is the version of the plugin API that the plugin was built against and the release status of the plugin.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/modules
|
||||||
|
[ { "Module Name" : "HTTPD", "Module Type" : "Protocol", "Version" : "V1.0.1", "API Version" : "1.0.0", "Status" : "In Development"},
|
||||||
|
{ "Module Name" : "maxscaled", "Module Type" : "Protocol", "Version" : "V1.0.0", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "telnetd", "Module Type" : "Protocol", "Version" : "V1.0.1", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "MySQLClient", "Module Type" : "Protocol", "Version" : "V1.0.0", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "mysqlmon", "Module Type" : "Monitor", "Version" : "V1.4.0", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "readwritesplit", "Module Type" : "Router", "Version" : "V1.0.2", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "readconnroute", "Module Type" : "Router", "Version" : "V1.1.0", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "debugcli", "Module Type" : "Router", "Version" : "V1.1.1", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "cli", "Module Type" : "Router", "Version" : "V1.0.0", "API Version" : "1.0.0", "Status" : "GA"},
|
||||||
|
{ "Module Name" : "maxinfo", "Module Type" : "Router", "Version" : "V1.0.0", "API Version" : "1.0.0", "Status" : "Alpha"}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Sessions
|
||||||
|
|
||||||
|
The /sessions URI returns a JSON array with an object for each active session within MaxScale.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/sessions
|
||||||
|
[ { "Session" : "0x1a8e9a0", "Client" : "80.176.79.245", "Service" : "MaxInfo", "State" : "Session ready for routing"},
|
||||||
|
{ "Session" : "0x1a8e6d0", "Client" : "80.240.130.35", "Service" : "MaxInfo", "State" : "Session ready for routing"},
|
||||||
|
{ "Session" : "0x1a8ddd0", "Client" : , "Service" : "MaxInfo", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a92da0", "Client" : , "Service" : "MaxInfo", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a92ac0", "Client" : , "Service" : "CLI", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a70e90", "Client" : , "Service" : "Debug Service", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a758d0", "Client" : , "Service" : "QLA Service", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a73a90", "Client" : , "Service" : "Named Service", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a5c0b0", "Client" : , "Service" : "Filter Service", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x1a5c530", "Client" : , "Service" : "Split Service", "State" : "Listener Session"},
|
||||||
|
{ "Session" : "0x19ac1c0", "Client" : , "Service" : "Test Service", "State" : "Listener Session"}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Clients
|
||||||
|
|
||||||
|
The /clients URI is a limited version of the /sessions, in this case it only returns an entry for a session that represents a client connection.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/clients
|
||||||
|
[ { "Session" : "0x1a90be0", "Client" : "80.176.79.245", "Service" : "MaxInfo", "State" : "Session ready for routing"},
|
||||||
|
{ "Session" : "0x1a8e9a0", "Client" : "127.0.0.1", "Service" : "MaxInfo", "State" : "Session ready for routing"},
|
||||||
|
{ "Session" : "0x1a8e6d0", "Client" : "80.240.130.35", "Service" : "MaxInfo", "State" : "Session ready for routing"}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Servers
|
||||||
|
|
||||||
|
The /servers URI is used to retrieve information for each of the servers defined within the MaxScale configuration. This information includes the connection count and the current status as monitored by MaxScale. The connection count is only those connections made by MaxScale to those servers.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/servers
|
||||||
|
[ { "Server" : "server1", "Address" : "127.0.0.1", "Port" : 3306, "Connections" : 0, "Status" : "Running"},
|
||||||
|
{ "Server" : "server2", "Address" : "127.0.0.1", "Port" : 3307, "Connections" : 0, "Status" : "Down"},
|
||||||
|
{ "Server" : "server3", "Address" : "127.0.0.1", "Port" : 3308, "Connections" : 0, "Status" : "Down"},
|
||||||
|
{ "Server" : "server4", "Address" : "127.0.0.1", "Port" : 3309, "Connections" : 0, "Status" : "Down"}]
|
||||||
|
$
|
||||||
|
|
||||||
|
## Event Times
|
||||||
|
|
||||||
|
The /event/times URI returns an array of statistics that reflect the performance of the event queuing and execution portion of the MaxScale core. Each element is an object that represents a time bucket, in 100ms increments, with the counts representing the number of events that were in the event queue for the length of time that row represents and the number of events that were executing of the time indicated by the object.
|
||||||
|
|
||||||
|
$ curl http://maxscale.mariadb.com:8003/event/times
|
||||||
|
[ { "Duration" : "< 100ms", "No. Events Queued" : 64, "No. Events Executed" : 63},
|
||||||
|
{ "Duration" : " 100 - 200ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 200 - 300ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 300 - 400ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 400 - 500ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 500 - 600ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 600 - 700ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 700 - 800ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 800 - 900ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : " 900 - 1000ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1000 - 1100ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1100 - 1200ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1200 - 1300ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1300 - 1400ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1400 - 1500ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1500 - 1600ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1600 - 1700ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1700 - 1800ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1800 - 1900ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "1900 - 2000ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2000 - 2100ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2100 - 2200ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2200 - 2300ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2300 - 2400ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2400 - 2500ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2500 - 2600ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2600 - 2700ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2700 - 2800ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "2800 - 2900ms", "No. Events Queued" : 0, "No. Events Executed" : 0},
|
||||||
|
{ "Duration" : "> 3000ms", "No. Events Queued" : 0, "No. Events Executed" : 0}]
|
||||||
@ -1583,8 +1583,10 @@ va_list args;
|
|||||||
int
|
int
|
||||||
dcb_isclient(DCB *dcb)
|
dcb_isclient(DCB *dcb)
|
||||||
{
|
{
|
||||||
if(dcb->session) {
|
if (dcb->state != DCB_STATE_LISTENING && dcb->session)
|
||||||
if (dcb->session->client) {
|
{
|
||||||
|
if (dcb->session->client)
|
||||||
|
{
|
||||||
return (dcb->session && dcb == dcb->session->client);
|
return (dcb->session && dcb == dcb->session->client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2168,3 +2170,52 @@ dcb_null_auth(DCB *dcb, SERVER *server, SESSION *session, GWBUF *buf)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return DCB counts optionally filtered by usage
|
||||||
|
*
|
||||||
|
* @param usage The usage of the DCB
|
||||||
|
* @return A count of DCBs in the desired state
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dcb_count_by_usage(DCB_USAGE usage)
|
||||||
|
{
|
||||||
|
int rval = 0;
|
||||||
|
DCB *ptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&dcbspin);
|
||||||
|
ptr = allDCBs;
|
||||||
|
while (ptr)
|
||||||
|
{
|
||||||
|
switch (usage)
|
||||||
|
{
|
||||||
|
case DCB_USAGE_CLIENT:
|
||||||
|
if (dcb_isclient(ptr))
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
case DCB_USAGE_LISTENER:
|
||||||
|
if (ptr->state == DCB_STATE_LISTENING)
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
case DCB_USAGE_BACKEND:
|
||||||
|
if (dcb_isclient(ptr) == 0
|
||||||
|
&& ptr->dcb_role == DCB_ROLE_REQUEST_HANDLER)
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
case DCB_USAGE_INTERNAL:
|
||||||
|
if (ptr->dcb_role == DCB_ROLE_REQUEST_HANDLER)
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
case DCB_USAGE_ZOMBIE:
|
||||||
|
if (DCB_ISZOMBIE(ptr))
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
case DCB_USAGE_ALL:
|
||||||
|
rval++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
spinlock_release(&dcbspin);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|||||||
@ -408,3 +408,80 @@ MODULES *ptr = registered;
|
|||||||
}
|
}
|
||||||
dcb_printf(dcb, "----------------+-------------+---------+-------+-------------------------\n\n");
|
dcb_printf(dcb, "----------------+-------------+---------+-------+-------------------------\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of modules
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
moduleRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
int i = 0;;
|
||||||
|
char *stat, buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
MODULES *ptr;
|
||||||
|
|
||||||
|
ptr = registered;
|
||||||
|
while (i < *rowno && ptr)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(*rowno)++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
resultset_row_set(row, 0, ptr->module);
|
||||||
|
resultset_row_set(row, 1, ptr->type);
|
||||||
|
resultset_row_set(row, 2, ptr->version);
|
||||||
|
sprintf(buf, "%d.%d.%d", ptr->info->api_version.major,
|
||||||
|
ptr->info->api_version.minor,
|
||||||
|
ptr->info->api_version.patch);
|
||||||
|
resultset_row_set(row, 3, buf);
|
||||||
|
resultset_row_set(row, 4, ptr->info->status == MODULE_IN_DEVELOPMENT
|
||||||
|
? "In Development"
|
||||||
|
: (ptr->info->status == MODULE_ALPHA_RELEASE
|
||||||
|
? "Alpha"
|
||||||
|
: (ptr->info->status == MODULE_BETA_RELEASE
|
||||||
|
? "Beta"
|
||||||
|
: (ptr->info->status == MODULE_GA
|
||||||
|
? "GA"
|
||||||
|
: (ptr->info->status == MODULE_EXPERIMENTAL
|
||||||
|
? "Experimental" : "Unknown")))));
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of modules in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
moduleGetList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(moduleRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Module Name", 18, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Module Type", 12, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Version", 10, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "API Version", 8, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Status", 15, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -362,3 +362,66 @@ monitorSetNetworkTimeout(MONITOR *mon, int type, int value) {
|
|||||||
mon->module->setNetworkTimeout(mon->handle, type, value);
|
mon->module->setNetworkTimeout(mon->handle, type, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of monitors
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
monitorRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
int i = 0;;
|
||||||
|
char buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
MONITOR *ptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&monLock);
|
||||||
|
ptr = allMonitors;
|
||||||
|
while (i < *rowno && ptr)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&monLock);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(*rowno)++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
resultset_row_set(row, 0, ptr->name);
|
||||||
|
resultset_row_set(row, 1, ptr->state & MONITOR_STATE_RUNNING
|
||||||
|
? "Running" : "Stopped");
|
||||||
|
spinlock_release(&monLock);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of monitors in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
monitorGetList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(monitorRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Monitor", 20, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Status", 10, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -31,7 +31,9 @@
|
|||||||
#include <gw.h>
|
#include <gw.h>
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <housekeeper.h>
|
#include <housekeeper.h>
|
||||||
|
#include <config.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
#define PROFILE_POLL 0
|
#define PROFILE_POLL 0
|
||||||
|
|
||||||
@ -152,8 +154,8 @@ static struct {
|
|||||||
int n_hup; /*< Number of hangup events */
|
int n_hup; /*< Number of hangup events */
|
||||||
int n_accept; /*< Number of accept events */
|
int n_accept; /*< Number of accept events */
|
||||||
int n_polls; /*< Number of poll cycles */
|
int n_polls; /*< Number of poll cycles */
|
||||||
int n_pollev; /*< Number of polls returnign events */
|
int n_pollev; /*< Number of polls returning events */
|
||||||
int n_nbpollev; /*< Number of polls returnign events */
|
int n_nbpollev; /*< Number of polls returning events */
|
||||||
int n_nothreads; /*< Number of times no threads are polling */
|
int n_nothreads; /*< Number of times no threads are polling */
|
||||||
int n_fds[MAXNFDS]; /*< Number of wakeups with particular
|
int n_fds[MAXNFDS]; /*< Number of wakeups with particular
|
||||||
n_fds value */
|
n_fds value */
|
||||||
@ -1525,3 +1527,104 @@ int i;
|
|||||||
dcb_printf(pdcb, " > %2d00ms | %-10d | %-10d\n", N_QUEUE_TIMES,
|
dcb_printf(pdcb, " > %2d00ms | %-10d | %-10d\n", N_QUEUE_TIMES,
|
||||||
queueStats.qtimes[N_QUEUE_TIMES], queueStats.exectimes[N_QUEUE_TIMES]);
|
queueStats.qtimes[N_QUEUE_TIMES], queueStats.exectimes[N_QUEUE_TIMES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a poll statistic from the polling subsystem
|
||||||
|
*
|
||||||
|
* @param stat The required statistic
|
||||||
|
* @return The value of that statistic
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
poll_get_stat(POLL_STAT stat)
|
||||||
|
{
|
||||||
|
switch (stat)
|
||||||
|
{
|
||||||
|
case POLL_STAT_READ:
|
||||||
|
return pollStats.n_read;
|
||||||
|
case POLL_STAT_WRITE:
|
||||||
|
return pollStats.n_write;
|
||||||
|
case POLL_STAT_ERROR:
|
||||||
|
return pollStats.n_error;
|
||||||
|
case POLL_STAT_HANGUP:
|
||||||
|
return pollStats.n_hup;
|
||||||
|
case POLL_STAT_ACCEPT:
|
||||||
|
return pollStats.n_accept;
|
||||||
|
case POLL_STAT_EVQ_LEN:
|
||||||
|
return pollStats.evq_length;
|
||||||
|
case POLL_STAT_EVQ_PENDING:
|
||||||
|
return pollStats.evq_pending;
|
||||||
|
case POLL_STAT_EVQ_MAX:
|
||||||
|
return pollStats.evq_max;
|
||||||
|
case POLL_STAT_MAX_QTIME:
|
||||||
|
return (int)queueStats.maxqtime;
|
||||||
|
case POLL_STAT_MAX_EXECTIME:
|
||||||
|
return (int)queueStats.maxexectime;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the event queue statistics
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
eventTimesRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
char buf[40];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
|
||||||
|
if (*rowno >= N_QUEUE_TIMES)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
if (*rowno == 0)
|
||||||
|
resultset_row_set(row, 0, "< 100ms");
|
||||||
|
else if (*rowno == N_QUEUE_TIMES - 1)
|
||||||
|
{
|
||||||
|
sprintf(buf, "> %2d00ms", N_QUEUE_TIMES);
|
||||||
|
resultset_row_set(row, 0, buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(buf, "%2d00 - %2d00ms", *rowno, (*rowno) + 1);
|
||||||
|
resultset_row_set(row, 0, buf);
|
||||||
|
}
|
||||||
|
sprintf(buf, "%d", queueStats.qtimes[*rowno]);
|
||||||
|
resultset_row_set(row, 1, buf);
|
||||||
|
sprintf(buf, "%d", queueStats.exectimes[*rowno]);
|
||||||
|
resultset_row_set(row, 2, buf);
|
||||||
|
(*rowno)++;
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of services in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
eventTimesGetList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(eventTimesRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Duration", 20, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "No. Events Queued", 12, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "No. Events Executed", 12, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <resultset.h>
|
#include <resultset.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
@ -153,7 +154,7 @@ int i;
|
|||||||
if ((row = (RESULT_ROW *)malloc(sizeof(RESULT_ROW))) == NULL)
|
if ((row = (RESULT_ROW *)malloc(sizeof(RESULT_ROW))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
row->n_cols = set->n_cols;
|
row->n_cols = set->n_cols;
|
||||||
if ((row->cols = (char **)malloc(sizeof(char *))) == NULL)
|
if ((row->cols = (char **)malloc(row->n_cols * sizeof(char *))) == NULL)
|
||||||
{
|
{
|
||||||
free(row);
|
free(row);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -401,3 +402,66 @@ uint8_t *ptr;
|
|||||||
|
|
||||||
return dcb->func.write(dcb, pkt);
|
return dcb->func.write(dcb, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the string only contains numerics
|
||||||
|
*
|
||||||
|
* @param value String to test
|
||||||
|
* @return Non-zero if the string is made of of numeric values
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
value_is_numeric(char *value)
|
||||||
|
{
|
||||||
|
while (*value)
|
||||||
|
{
|
||||||
|
if (!isdigit(*value))
|
||||||
|
return 0;
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream a result set encoding it as a JSON object
|
||||||
|
* Each row is retrieved by calling the function passed in the
|
||||||
|
* argument list.
|
||||||
|
*
|
||||||
|
* @param set The result set to stream
|
||||||
|
* @param dcb The connection to stream the result set to
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
resultset_stream_json(RESULTSET *set, DCB *dcb)
|
||||||
|
{
|
||||||
|
RESULT_COLUMN *col;
|
||||||
|
RESULT_ROW *row;
|
||||||
|
int rowno = 0;
|
||||||
|
|
||||||
|
|
||||||
|
dcb_printf(dcb, "[ ");
|
||||||
|
while ((row = (*set->fetchrow)(set, set->userdata)) != NULL)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
if (rowno++ > 0)
|
||||||
|
dcb_printf(dcb, ",\n");
|
||||||
|
dcb_printf(dcb, "{ ");
|
||||||
|
col = set->column;
|
||||||
|
while (col)
|
||||||
|
{
|
||||||
|
|
||||||
|
dcb_printf(dcb, "\"%s\" : ", col->name);
|
||||||
|
if (row->cols[i] && value_is_numeric(row->cols[i]))
|
||||||
|
dcb_printf(dcb, "%s", row->cols[i]);
|
||||||
|
else if (row->cols[i])
|
||||||
|
dcb_printf(dcb, "\"%s\"", row->cols[i]);
|
||||||
|
else
|
||||||
|
dcb_printf(dcb, "NULL");
|
||||||
|
i++;
|
||||||
|
col = col->next;
|
||||||
|
if (col)
|
||||||
|
dcb_printf(dcb, ", ");
|
||||||
|
}
|
||||||
|
resultset_free_row(row);
|
||||||
|
dcb_printf(dcb, "}");
|
||||||
|
}
|
||||||
|
dcb_printf(dcb, "]\n");
|
||||||
|
}
|
||||||
|
|||||||
@ -575,3 +575,75 @@ SERVER_PARAM *param = server->parameters;
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of servers
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
serverRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
int i = 0;;
|
||||||
|
char *stat, buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
SERVER *ptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&server_spin);
|
||||||
|
ptr = allServers;
|
||||||
|
while (i < *rowno && ptr)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&server_spin);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(*rowno)++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
resultset_row_set(row, 0, ptr->unique_name);
|
||||||
|
resultset_row_set(row, 1, ptr->name);
|
||||||
|
sprintf(buf, "%d", ptr->port);
|
||||||
|
resultset_row_set(row, 2, buf);
|
||||||
|
sprintf(buf, "%d", ptr->stats.n_current);
|
||||||
|
resultset_row_set(row, 3, buf);
|
||||||
|
stat = server_status(ptr);
|
||||||
|
resultset_row_set(row, 4, stat);
|
||||||
|
free(stat);
|
||||||
|
spinlock_release(&server_spin);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of servers in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
serverGetList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(serverRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Server", 20, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Address", 15, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Port", 5, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Connections", 8, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Status", 20, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
* 09/09/14 Massimiliano Pinto Added service option for localhost authentication
|
* 09/09/14 Massimiliano Pinto Added service option for localhost authentication
|
||||||
* 13/10/14 Massimiliano Pinto Added hashtable for resources (i.e database names for MySQL services)
|
* 13/10/14 Massimiliano Pinto Added hashtable for resources (i.e database names for MySQL services)
|
||||||
* 06/02/15 Mark Riddoch Added caching of authentication data
|
* 06/02/15 Mark Riddoch Added caching of authentication data
|
||||||
|
* 18/02/15 Mark Riddoch Added result set management
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -57,6 +58,7 @@
|
|||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
/** Defined in log_manager.cc */
|
/** Defined in log_manager.cc */
|
||||||
extern int lm_enabled_logfiles_bitmask;
|
extern int lm_enabled_logfiles_bitmask;
|
||||||
@ -1533,3 +1535,157 @@ int rval = 0;
|
|||||||
spinlock_release(&service_spin);
|
spinlock_release(&service_spin);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of service
|
||||||
|
* listeners
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
serviceListenerRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
int i = 0;;
|
||||||
|
char buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
SERVICE *ptr;
|
||||||
|
SERV_PROTOCOL *lptr = NULL;
|
||||||
|
|
||||||
|
spinlock_acquire(&service_spin);
|
||||||
|
ptr = allServices;
|
||||||
|
if (ptr)
|
||||||
|
lptr = ptr->ports;
|
||||||
|
while (i < *rowno && ptr)
|
||||||
|
{
|
||||||
|
lptr = ptr->ports;
|
||||||
|
while (i < *rowno && lptr)
|
||||||
|
{
|
||||||
|
if ((lptr = lptr->next) != NULL)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i < *rowno)
|
||||||
|
{
|
||||||
|
ptr = ptr->next;
|
||||||
|
if (ptr && (lptr = ptr->ports) != NULL)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lptr == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&service_spin);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(*rowno)++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
resultset_row_set(row, 0, ptr->name);
|
||||||
|
resultset_row_set(row, 1, lptr->protocol);
|
||||||
|
resultset_row_set(row, 2, (lptr && lptr->address) ? lptr->address : "*");
|
||||||
|
sprintf(buf, "%d", lptr->port);
|
||||||
|
resultset_row_set(row, 3, buf);
|
||||||
|
resultset_row_set(row, 4,
|
||||||
|
(!lptr->listener || !lptr->listener->session ||
|
||||||
|
lptr->listener->session->state == SESSION_STATE_LISTENER_STOPPED) ?
|
||||||
|
"Stopped" : "Running");
|
||||||
|
spinlock_release(&service_spin);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of services in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
serviceGetListenerList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(serviceListenerRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Service Name", 25, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Protocol Module", 20, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Address", 15, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Port", 5, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "State", 8, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of services
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
serviceRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
int *rowno = (int *)data;
|
||||||
|
int i = 0;;
|
||||||
|
char buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
SERVICE *ptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&service_spin);
|
||||||
|
ptr = allServices;
|
||||||
|
while (i < *rowno && ptr)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&service_spin);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(*rowno)++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
resultset_row_set(row, 0, ptr->name);
|
||||||
|
resultset_row_set(row, 1, ptr->routerModule);
|
||||||
|
sprintf(buf, "%d", ptr->stats.n_current);
|
||||||
|
resultset_row_set(row, 2, buf);
|
||||||
|
sprintf(buf, "%d", ptr->stats.n_sessions);
|
||||||
|
resultset_row_set(row, 3, buf);
|
||||||
|
spinlock_release(&service_spin);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of services in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
serviceGetList()
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
int *data;
|
||||||
|
|
||||||
|
if ((data = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
*data = 0;
|
||||||
|
if ((set = resultset_create(serviceRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Service Name", 25, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Router Module", 20, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "No. Sessions", 10, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Total Sessions", 10, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -909,3 +909,101 @@ SESSION *get_all_sessions()
|
|||||||
{
|
{
|
||||||
return allSessions;
|
return allSessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback structure for the session lsit extraction
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int index;
|
||||||
|
SESSIONLISTFILTER filter;
|
||||||
|
} SESSIONFILTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a row to the result set that defines the set of sessions
|
||||||
|
*
|
||||||
|
* @param set The result set
|
||||||
|
* @param data The index of the row to send
|
||||||
|
* @return The next row or NULL
|
||||||
|
*/
|
||||||
|
static RESULT_ROW *
|
||||||
|
sessionRowCallback(RESULTSET *set, void *data)
|
||||||
|
{
|
||||||
|
SESSIONFILTER *cbdata = (SESSIONFILTER *)data;
|
||||||
|
int i = 0;
|
||||||
|
char buf[20];
|
||||||
|
RESULT_ROW *row;
|
||||||
|
SESSION *ptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&session_spin);
|
||||||
|
ptr = allSessions;
|
||||||
|
/* Skip to the first non-listener if not showing listeners */
|
||||||
|
while (ptr && cbdata->filter == SESSION_LIST_CONNECTION &&
|
||||||
|
ptr->state == SESSION_STATE_LISTENER)
|
||||||
|
{
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
while (i < cbdata->index && ptr)
|
||||||
|
{
|
||||||
|
if (cbdata->filter == SESSION_LIST_CONNECTION &&
|
||||||
|
ptr->state != SESSION_STATE_LISTENER)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (cbdata->filter == SESSION_LIST_ALL)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
/* Skip to the next non-listener if not showing listeners */
|
||||||
|
while (ptr && cbdata->filter == SESSION_LIST_CONNECTION &&
|
||||||
|
ptr->state == SESSION_STATE_LISTENER)
|
||||||
|
{
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&session_spin);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cbdata->index++;
|
||||||
|
row = resultset_make_row(set);
|
||||||
|
sprintf(buf, "%p", ptr);
|
||||||
|
resultset_row_set(row, 0, buf);
|
||||||
|
resultset_row_set(row, 1, ((ptr->client && ptr->client->remote)
|
||||||
|
? ptr->client->remote : ""));
|
||||||
|
resultset_row_set(row, 2, (ptr->service && ptr->service->name
|
||||||
|
? ptr->service->name : ""));
|
||||||
|
resultset_row_set(row, 3, session_state(ptr->state));
|
||||||
|
spinlock_release(&session_spin);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a resultset that has the current set of sessions in it
|
||||||
|
*
|
||||||
|
* @return A Result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
sessionGetList(SESSIONLISTFILTER filter)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
SESSIONFILTER *data;
|
||||||
|
|
||||||
|
if ((data = (SESSIONFILTER *)malloc(sizeof(SESSIONFILTER))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
data->index = 0;
|
||||||
|
data->filter = filter;
|
||||||
|
if ((set = resultset_create(sessionRowCallback, data)) == NULL)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(set, "Session", 16, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Client", 15, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "Service", 15, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(set, "State", 15, COL_TYPE_VARCHAR);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef _CONFIG_H
|
#ifndef _MAXSCALE_CONFIG_H
|
||||||
#define _CONFIG_H
|
#define _MAXSCALE_CONFIG_H
|
||||||
/*
|
/*
|
||||||
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
||||||
* software: you can redistribute it and/or modify it under the terms of the
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
|||||||
@ -271,6 +271,18 @@ typedef struct dcb {
|
|||||||
#endif
|
#endif
|
||||||
} DCB;
|
} DCB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DCB usage filer used for returning DCB's in use for a certain reason
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
DCB_USAGE_CLIENT,
|
||||||
|
DCB_USAGE_LISTENER,
|
||||||
|
DCB_USAGE_BACKEND,
|
||||||
|
DCB_USAGE_INTERNAL,
|
||||||
|
DCB_USAGE_ZOMBIE,
|
||||||
|
DCB_USAGE_ALL
|
||||||
|
} DCB_USAGE;
|
||||||
|
|
||||||
#if defined(FAKE_CODE)
|
#if defined(FAKE_CODE)
|
||||||
unsigned char dcb_fake_write_errno[10240];
|
unsigned char dcb_fake_write_errno[10240];
|
||||||
__int32_t dcb_fake_write_ev[10240];
|
__int32_t dcb_fake_write_ev[10240];
|
||||||
@ -319,6 +331,7 @@ int dcb_add_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void
|
|||||||
int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
||||||
void *);
|
void *);
|
||||||
int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */
|
int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */
|
||||||
|
int dcb_count_by_usage(DCB_USAGE); /* Return counts of DCBs */
|
||||||
|
|
||||||
bool dcb_set_state(DCB* dcb, dcb_state_t new_state, dcb_state_t* old_state);
|
bool dcb_set_state(DCB* dcb, dcb_state_t new_state, dcb_state_t* old_state);
|
||||||
void dcb_call_foreach (DCB_REASON reason);
|
void dcb_call_foreach (DCB_REASON reason);
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file modules.h Utilities for loading modules
|
* @file modules.h Utilities for loading modules
|
||||||
@ -34,6 +35,7 @@
|
|||||||
* 29/05/14 Mark Riddoch Addition of filter modules
|
* 29/05/14 Mark Riddoch Addition of filter modules
|
||||||
* 01/10/14 Mark Riddoch Addition of call to unload all modules on
|
* 01/10/14 Mark Riddoch Addition of call to unload all modules on
|
||||||
* shutdown
|
* shutdown
|
||||||
|
* 19/02/15 Mark Riddoch Addition of moduleGetList
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ extern void unload_module(const char *module);
|
|||||||
extern void unload_all_modules();
|
extern void unload_all_modules();
|
||||||
extern void printModules();
|
extern void printModules();
|
||||||
extern void dprintAllModules(DCB *);
|
extern void dprintAllModules(DCB *);
|
||||||
char* get_maxscale_home(void);
|
extern char *get_maxscale_home(void);
|
||||||
|
extern RESULTSET *moduleGetList();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <server.h>
|
#include <server.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file monitor.h The interface to the monitor module
|
* @file monitor.h The interface to the monitor module
|
||||||
@ -35,6 +36,7 @@
|
|||||||
* 28/08/14 Massimiliano Pinto Addition of detectStaleMaster
|
* 28/08/14 Massimiliano Pinto Addition of detectStaleMaster
|
||||||
* 30/10/14 Massimiliano Pinto Addition of disableMasterFailback
|
* 30/10/14 Massimiliano Pinto Addition of disableMasterFailback
|
||||||
* 07/11/14 Massimiliano Pinto Addition of setNetworkTimeout
|
* 07/11/14 Massimiliano Pinto Addition of setNetworkTimeout
|
||||||
|
* 19/02/15 Mark Riddoch Addition of monitorGetList
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -143,4 +145,5 @@ extern void monitorSetReplicationHeartbeat(MONITOR *, int);
|
|||||||
extern void monitorDetectStaleMaster(MONITOR *, int);
|
extern void monitorDetectStaleMaster(MONITOR *, int);
|
||||||
extern void monitorDisableMasterFailback(MONITOR *, int);
|
extern void monitorDisableMasterFailback(MONITOR *, int);
|
||||||
extern void monitorSetNetworkTimeout(MONITOR *, int, int);
|
extern void monitorSetNetworkTimeout(MONITOR *, int, int);
|
||||||
|
extern RESULTSET *monitorGetList();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <gwbitmask.h>
|
#include <gwbitmask.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file poll.h The poll related functionality
|
* @file poll.h The poll related functionality
|
||||||
@ -33,6 +34,22 @@
|
|||||||
*/
|
*/
|
||||||
#define MAX_EVENTS 1000
|
#define MAX_EVENTS 1000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A statistic identifier that can be returned by poll_get_stat
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
POLL_STAT_READ,
|
||||||
|
POLL_STAT_WRITE,
|
||||||
|
POLL_STAT_ERROR,
|
||||||
|
POLL_STAT_HANGUP,
|
||||||
|
POLL_STAT_ACCEPT,
|
||||||
|
POLL_STAT_EVQ_LEN,
|
||||||
|
POLL_STAT_EVQ_PENDING,
|
||||||
|
POLL_STAT_EVQ_MAX,
|
||||||
|
POLL_STAT_MAX_QTIME,
|
||||||
|
POLL_STAT_MAX_EXECTIME
|
||||||
|
} POLL_STAT;
|
||||||
|
|
||||||
extern void poll_init();
|
extern void poll_init();
|
||||||
extern int poll_add_dcb(DCB *);
|
extern int poll_add_dcb(DCB *);
|
||||||
extern int poll_remove_dcb(DCB *);
|
extern int poll_remove_dcb(DCB *);
|
||||||
@ -46,4 +63,6 @@ extern void dShowThreads(DCB *dcb);
|
|||||||
void poll_add_epollin_event_to_dcb(DCB* dcb, GWBUF* buf);
|
void poll_add_epollin_event_to_dcb(DCB* dcb, GWBUF* buf);
|
||||||
extern void dShowEventQ(DCB *dcb);
|
extern void dShowEventQ(DCB *dcb);
|
||||||
extern void dShowEventStats(DCB *dcb);
|
extern void dShowEventStats(DCB *dcb);
|
||||||
|
extern int poll_get_stat(POLL_STAT stat);
|
||||||
|
extern RESULTSET *eventTimesGetList();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -84,4 +84,5 @@ extern RESULT_ROW *resultset_make_row(RESULTSET *);
|
|||||||
extern void resultset_free_row(RESULT_ROW *);
|
extern void resultset_free_row(RESULT_ROW *);
|
||||||
extern int resultset_row_set(RESULT_ROW *, int, char *);
|
extern int resultset_row_set(RESULT_ROW *, int, char *);
|
||||||
extern void resultset_stream_mysql(RESULTSET *, DCB *);
|
extern void resultset_stream_mysql(RESULTSET *, DCB *);
|
||||||
|
extern void resultset_stream_json(RESULTSET *, DCB *);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
* Copyright MariaDB Corporation Ab 2013-2014
|
* Copyright MariaDB Corporation Ab 2013-2014
|
||||||
*/
|
*/
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file service.h
|
* @file service.h
|
||||||
@ -41,6 +42,7 @@
|
|||||||
* 30/07/14 Massimiliano Pinto Addition of NDB status for MySQL Cluster
|
* 30/07/14 Massimiliano Pinto Addition of NDB status for MySQL Cluster
|
||||||
* 30/08/14 Massimiliano Pinto Addition of SERVER_STALE_STATUS
|
* 30/08/14 Massimiliano Pinto Addition of SERVER_STALE_STATUS
|
||||||
* 27/10/14 Massimiliano Pinto Addition of SERVER_MASTER_STICKINESS
|
* 27/10/14 Massimiliano Pinto Addition of SERVER_MASTER_STICKINESS
|
||||||
|
* 19/02/15 Mark Riddoch Addition of serverGetList
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -186,4 +188,5 @@ extern void serverAddParameter(SERVER *, char *, char *);
|
|||||||
extern char *serverGetParameter(SERVER *, char *);
|
extern char *serverGetParameter(SERVER *, char *);
|
||||||
extern void server_update(SERVER *, char *, char *, char *);
|
extern void server_update(SERVER *, char *, char *, char *);
|
||||||
extern void server_set_unique_name(SERVER *, char *);
|
extern void server_set_unique_name(SERVER *, char *);
|
||||||
|
extern RESULTSET *serverGetList();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include <server.h>
|
#include <server.h>
|
||||||
#include <filter.h>
|
#include <filter.h>
|
||||||
#include <hashtable.h>
|
#include <hashtable.h>
|
||||||
|
#include <resultset.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,4 +195,6 @@ extern void dListListeners(DCB *);
|
|||||||
char* service_get_name(SERVICE* svc);
|
char* service_get_name(SERVICE* svc);
|
||||||
void service_shutdown();
|
void service_shutdown();
|
||||||
extern int serviceSessionCountAll();
|
extern int serviceSessionCountAll();
|
||||||
|
extern RESULTSET *serviceGetList();
|
||||||
|
extern RESULTSET *serviceGetListenerList();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
|
#include <resultset.h>
|
||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
|
|
||||||
@ -99,6 +100,14 @@ typedef struct {
|
|||||||
void *session;
|
void *session;
|
||||||
} SESSION_FILTER;
|
} SESSION_FILTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter type for the sessionGetList call
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SESSION_LIST_ALL,
|
||||||
|
SESSION_LIST_CONNECTION
|
||||||
|
} SESSIONLISTFILTER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The session status block
|
* The session status block
|
||||||
*
|
*
|
||||||
@ -167,5 +176,5 @@ bool session_link_dcb(SESSION *, struct dcb *);
|
|||||||
SESSION* get_session_by_router_ses(void* rses);
|
SESSION* get_session_by_router_ses(void* rses);
|
||||||
void session_enable_log(SESSION* ses, logfile_id_t id);
|
void session_enable_log(SESSION* ses, logfile_id_t id);
|
||||||
void session_disable_log(SESSION* ses, logfile_id_t id);
|
void session_disable_log(SESSION* ses, logfile_id_t id);
|
||||||
|
RESULTSET *sessionGetList(SESSIONLISTFILTER);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -127,5 +127,6 @@ extern void maxinfo_execute(DCB *, MAXINFO_TREE *);
|
|||||||
extern void maxinfo_send_error(DCB *, int, char *);
|
extern void maxinfo_send_error(DCB *, int, char *);
|
||||||
extern void maxinfo_send_parse_error(DCB *, char *, PARSE_ERROR);
|
extern void maxinfo_send_parse_error(DCB *, char *, PARSE_ERROR);
|
||||||
extern void maxinfo_send_error(DCB *, int, char *);
|
extern void maxinfo_send_error(DCB *, int, char *);
|
||||||
|
extern RESULTSET *maxinfo_variables();
|
||||||
|
extern RESULTSET *maxinfo_status();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
#include <gw.h>
|
#include <gw.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
MODULE_INFO info = {
|
MODULE_INFO info = {
|
||||||
MODULE_API_PROTOCOL,
|
MODULE_API_PROTOCOL,
|
||||||
@ -129,10 +130,10 @@ GetModuleObject()
|
|||||||
static int
|
static int
|
||||||
httpd_read_event(DCB* dcb)
|
httpd_read_event(DCB* dcb)
|
||||||
{
|
{
|
||||||
//SESSION *session = dcb->session;
|
SESSION *session = dcb->session;
|
||||||
//ROUTER_OBJECT *router = session->service->router;
|
ROUTER_OBJECT *router = session->service->router;
|
||||||
//ROUTER *router_instance = session->service->router_instance;
|
ROUTER *router_instance = session->service->router_instance;
|
||||||
//void *rsession = session->router_session;
|
void *rsession = session->router_session;
|
||||||
|
|
||||||
int numchars = 1;
|
int numchars = 1;
|
||||||
char buf[HTTPD_REQUESTLINE_MAXLEN-1] = "";
|
char buf[HTTPD_REQUESTLINE_MAXLEN-1] = "";
|
||||||
@ -143,6 +144,7 @@ int cgi = 0;
|
|||||||
size_t i, j;
|
size_t i, j;
|
||||||
int headers_read = 0;
|
int headers_read = 0;
|
||||||
HTTPD_session *client_data = NULL;
|
HTTPD_session *client_data = NULL;
|
||||||
|
GWBUF *uri;
|
||||||
|
|
||||||
client_data = dcb->data;
|
client_data = dcb->data;
|
||||||
|
|
||||||
@ -234,13 +236,11 @@ HTTPD_session *client_data = NULL;
|
|||||||
/* send all the basic headers and close with \r\n */
|
/* send all the basic headers and close with \r\n */
|
||||||
httpd_send_headers(dcb, 1);
|
httpd_send_headers(dcb, 1);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* ToDO: launch proper content handling based on the requested URI, later REST interface
|
* ToDO: launch proper content handling based on the requested URI, later REST interface
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dcb_printf(dcb, "Welcome to HTTPD MaxScale (c) %s\n\n", version_str);
|
|
||||||
|
|
||||||
if (strcmp(url, "/show") == 0) {
|
if (strcmp(url, "/show") == 0) {
|
||||||
if (query_string && strlen(query_string)) {
|
if (query_string && strlen(query_string)) {
|
||||||
if (strcmp(query_string, "dcb") == 0)
|
if (strcmp(query_string, "dcb") == 0)
|
||||||
@ -249,6 +249,21 @@ HTTPD_session *client_data = NULL;
|
|||||||
dprintAllSessions(dcb);
|
dprintAllSessions(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (strcmp(url, "/services") == 0) {
|
||||||
|
RESULTSET *set, *seviceGetList();
|
||||||
|
if ((set = serviceGetList()) != NULL)
|
||||||
|
{
|
||||||
|
resultset_stream_json(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((uri = gwbuf_alloc(strlen(url) + 1)) != NULL)
|
||||||
|
{
|
||||||
|
strcpy((char *)GWBUF_DATA(uri), url);
|
||||||
|
gwbuf_set_type(uri, GWBUF_TYPE_HTTP);
|
||||||
|
SESSION_ROUTE_QUERY(session, uri);
|
||||||
|
}
|
||||||
|
|
||||||
/* force the client connecton close */
|
/* force the client connecton close */
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
@ -345,6 +360,9 @@ int n_connect = 0;
|
|||||||
/* create the session data for HTTPD */
|
/* create the session data for HTTPD */
|
||||||
client_data = (HTTPD_session *)calloc(1, sizeof(HTTPD_session));
|
client_data = (HTTPD_session *)calloc(1, sizeof(HTTPD_session));
|
||||||
client->data = client_data;
|
client->data = client_data;
|
||||||
|
|
||||||
|
client->session =
|
||||||
|
session_alloc(dcb->session->service, client);
|
||||||
|
|
||||||
if (poll_add_dcb(client) == -1)
|
if (poll_add_dcb(client) == -1)
|
||||||
{
|
{
|
||||||
@ -354,7 +372,6 @@ int n_connect = 0;
|
|||||||
n_connect++;
|
n_connect++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(so);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n_connect;
|
return n_connect;
|
||||||
@ -484,7 +501,7 @@ static void httpd_send_headers(DCB *dcb, int final)
|
|||||||
|
|
||||||
strftime(date, sizeof(date), fmt, localtime(&httpd_current_time));
|
strftime(date, sizeof(date), fmt, localtime(&httpd_current_time));
|
||||||
|
|
||||||
dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: text/plain\r\n", date, HTTP_SERVER_STRING);
|
dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: application/json\r\n", date, HTTP_SERVER_STRING);
|
||||||
|
|
||||||
/* close the headers */
|
/* close the headers */
|
||||||
if (final) {
|
if (final) {
|
||||||
|
|||||||
@ -34,10 +34,12 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <service.h>
|
#include <service.h>
|
||||||
#include <session.h>
|
#include <session.h>
|
||||||
|
#include <server.h>
|
||||||
#include <router.h>
|
#include <router.h>
|
||||||
#include <modules.h>
|
#include <modules.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <modutil.h>
|
#include <modutil.h>
|
||||||
|
#include <monitor.h>
|
||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
@ -47,11 +49,12 @@
|
|||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <resultset.h>
|
#include <resultset.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
#include <resultset.h>
|
||||||
|
|
||||||
|
|
||||||
MODULE_INFO info = {
|
MODULE_INFO info = {
|
||||||
MODULE_API_ROUTER,
|
MODULE_API_ROUTER,
|
||||||
MODULE_GA,
|
MODULE_ALPHA_RELEASE,
|
||||||
ROUTER_VERSION,
|
ROUTER_VERSION,
|
||||||
"The MaxScale Information Schema"
|
"The MaxScale Information Schema"
|
||||||
};
|
};
|
||||||
@ -66,6 +69,7 @@ static char *version_str = "V1.0.0";
|
|||||||
static int maxinfo_statistics(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
|
static int maxinfo_statistics(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
|
||||||
static int maxinfo_ping(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
|
static int maxinfo_ping(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
|
||||||
static int maxinfo_execute_query(INFO_INSTANCE *, INFO_SESSION *, char *);
|
static int maxinfo_execute_query(INFO_INSTANCE *, INFO_SESSION *, char *);
|
||||||
|
static int handle_url(INFO_INSTANCE *instance, INFO_SESSION *router_session, GWBUF *queue);
|
||||||
|
|
||||||
|
|
||||||
/* The router entry points */
|
/* The router entry points */
|
||||||
@ -184,11 +188,19 @@ int i;
|
|||||||
instances = inst;
|
instances = inst;
|
||||||
spinlock_release(&instlock);
|
spinlock_release(&instlock);
|
||||||
|
|
||||||
service->users = mysql_users_alloc();
|
/*
|
||||||
add_mysql_users_with_host_ipv4(service->users, "massi", "%", "2CFEB4BD447B9BC5D591249377EF5A7E340D1A1D", "Y", "");
|
* The following adds users to the service.
|
||||||
add_mysql_users_with_host_ipv4(service->users, "massi", "localhost", "2CFEB4BD447B9BC5D591249377EF5A7E340D1A1D", "Y", "");
|
* At some point this must be replaced with proper user management,
|
||||||
add_mysql_users_with_host_ipv4(service->users, "monitor", "%", "", "Y", "");
|
* one option migh tbe to use the admin users having we only have
|
||||||
add_mysql_users_with_host_ipv4(service->users, "monitor", "localhost", "", "Y", "");
|
* the crypt'd version of these. This means we can not creat the
|
||||||
|
* SHA1 of the raw password. Another mechansim is going to be
|
||||||
|
* required to support these users.
|
||||||
|
* As a temporary measure we will allow the user monitor with no
|
||||||
|
* password to be used.
|
||||||
|
*/
|
||||||
|
service->users = (void *)mysql_users_alloc();
|
||||||
|
(void)add_mysql_users_with_host_ipv4(service->users, "monitor", "%", "", "Y", "");
|
||||||
|
(void)add_mysql_users_with_host_ipv4(service->users, "monitor", "localhost", "", "Y", "");
|
||||||
|
|
||||||
return (ROUTER *)inst;
|
return (ROUTER *)inst;
|
||||||
}
|
}
|
||||||
@ -350,6 +362,10 @@ uint8_t *data;
|
|||||||
int length, len, residual;
|
int length, len, residual;
|
||||||
char *sql;
|
char *sql;
|
||||||
|
|
||||||
|
if (GWBUF_TYPE(queue) == GWBUF_TYPE_HTTP)
|
||||||
|
{
|
||||||
|
return handle_url(instance, session, queue);
|
||||||
|
}
|
||||||
if (session->queue)
|
if (session->queue)
|
||||||
{
|
{
|
||||||
queue = gwbuf_append(session->queue, queue);
|
queue = gwbuf_append(session->queue, queue);
|
||||||
@ -542,7 +558,7 @@ static char buf[40];
|
|||||||
{
|
{
|
||||||
(*context)++;
|
(*context)++;
|
||||||
row = resultset_make_row(result);
|
row = resultset_make_row(result);
|
||||||
sprintf(buf, "%u", MaxScaleStarted);
|
sprintf(buf, "%u", (unsigned int)MaxScaleStarted);
|
||||||
resultset_row_set(row, 0, buf);
|
resultset_row_set(row, 0, buf);
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
@ -655,3 +671,74 @@ PARSE_ERROR err;
|
|||||||
maxinfo_execute(session->dcb, tree);
|
maxinfo_execute(session->dcb, tree);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session all result set
|
||||||
|
* @return A resultset for all sessions
|
||||||
|
*/
|
||||||
|
static RESULTSET *
|
||||||
|
maxinfoSessionsAll()
|
||||||
|
{
|
||||||
|
return sessionGetList(SESSION_LIST_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client session result set
|
||||||
|
* @return A resultset for all sessions
|
||||||
|
*/
|
||||||
|
static RESULTSET *
|
||||||
|
maxinfoClientSessions()
|
||||||
|
{
|
||||||
|
return sessionGetList(SESSION_LIST_CONNECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef RESULTSET *(*RESULTSETFUNC)();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table that maps a URI to a function to call to
|
||||||
|
* to obtain the result set related to that URI
|
||||||
|
*/
|
||||||
|
static struct uri_table {
|
||||||
|
char *uri;
|
||||||
|
RESULTSETFUNC func;
|
||||||
|
} supported_uri[] = {
|
||||||
|
{ "/services", serviceGetList },
|
||||||
|
{ "/listeners", serviceGetListenerList },
|
||||||
|
{ "/modules", moduleGetList },
|
||||||
|
{ "/monitors", monitorGetList },
|
||||||
|
{ "/sessions", maxinfoSessionsAll },
|
||||||
|
{ "/clients", maxinfoClientSessions },
|
||||||
|
{ "/servers", serverGetList },
|
||||||
|
{ "/variables", maxinfo_variables },
|
||||||
|
{ "/status", maxinfo_status },
|
||||||
|
{ "/event/times", eventTimesGetList },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We have data from the client, this is a HTTP URL
|
||||||
|
*
|
||||||
|
* @param instance The router instance
|
||||||
|
* @param session The router session returned from the newSession call
|
||||||
|
* @param queue The queue of data buffers to route
|
||||||
|
* @return The number of bytes sent
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
handle_url(INFO_INSTANCE *instance, INFO_SESSION *session, GWBUF *queue)
|
||||||
|
{
|
||||||
|
char *uri;
|
||||||
|
int i;
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
uri = (char *)GWBUF_DATA(queue);
|
||||||
|
for (i = 0; supported_uri[i].uri; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(uri, supported_uri[i].uri) == 0)
|
||||||
|
{
|
||||||
|
set = (*supported_uri[i].func)();
|
||||||
|
resultset_stream_json(set, session->dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include <session.h>
|
#include <session.h>
|
||||||
#include <router.h>
|
#include <router.h>
|
||||||
#include <modules.h>
|
#include <modules.h>
|
||||||
|
#include <monitor.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <modutil.h>
|
#include <modutil.h>
|
||||||
@ -86,12 +87,167 @@ maxinfo_execute(DCB *dcb, MAXINFO_TREE *tree)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of services and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_services(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = serviceGetList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of listeners and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_listeners(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = serviceGetListenerList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of sessions and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_sessions(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = sessionGetList(SESSION_LIST_ALL)) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of client sessions and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_clients(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = sessionGetList(SESSION_LIST_CONNECTION)) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of servers and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_servers(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = serverGetList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of modules and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_modules(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = moduleGetList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the list of monitors and stream as a result set
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_monitors(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = monitorGetList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the event times data
|
||||||
|
*
|
||||||
|
* @param dcb DCB to which to stream result set
|
||||||
|
* @param tree Potential like clause (currently unused)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exec_show_eventTimes(DCB *dcb, MAXINFO_TREE *tree)
|
||||||
|
{
|
||||||
|
RESULTSET *set;
|
||||||
|
|
||||||
|
if ((set = eventTimesGetList()) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resultset_stream_mysql(set, dcb);
|
||||||
|
resultset_free(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table of show commands that are supported
|
||||||
|
*/
|
||||||
static struct {
|
static struct {
|
||||||
char *name;
|
char *name;
|
||||||
void (*func)(DCB *, MAXINFO_TREE *);
|
void (*func)(DCB *, MAXINFO_TREE *);
|
||||||
} show_commands[] = {
|
} show_commands[] = {
|
||||||
{ "variables", exec_show_variables },
|
{ "variables", exec_show_variables },
|
||||||
{ "status", exec_show_status },
|
{ "status", exec_show_status },
|
||||||
|
{ "services", exec_show_services },
|
||||||
|
{ "listeners", exec_show_listeners },
|
||||||
|
{ "sessions", exec_show_sessions },
|
||||||
|
{ "clients", exec_show_clients },
|
||||||
|
{ "servers", exec_show_servers },
|
||||||
|
{ "modules", exec_show_modules },
|
||||||
|
{ "monitors", exec_show_monitors },
|
||||||
|
{ "eventTimes", exec_show_eventTimes },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -220,8 +376,8 @@ char buf[80];
|
|||||||
(char *)(*variables[context->index].func)());
|
(char *)(*variables[context->index].func)());
|
||||||
break;
|
break;
|
||||||
case VT_INT:
|
case VT_INT:
|
||||||
snprintf(buf, 80, "%d",
|
snprintf(buf, 80, "%ld",
|
||||||
(int)(*variables[context->index].func)());
|
(long)(*variables[context->index].func)());
|
||||||
resultset_row_set(row, 1, buf);
|
resultset_row_set(row, 1, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -261,7 +417,174 @@ VARCONTEXT context;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variables that may be sent in a show variables
|
* Return the show variables output a a result set
|
||||||
|
*
|
||||||
|
* @return Variables as a result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
maxinfo_variables()
|
||||||
|
{
|
||||||
|
RESULTSET *result;
|
||||||
|
static VARCONTEXT context;
|
||||||
|
|
||||||
|
context.like = NULL;
|
||||||
|
context.index = 0;
|
||||||
|
|
||||||
|
if ((result = resultset_create(variable_row, &context)) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for all dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_all_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for client dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_client_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for listener dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_listener_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_LISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for backend dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_backend_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_BACKEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for internal dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_internal_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to dcb_count_by_usage for zombie dcbs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_zombie_dcbs()
|
||||||
|
{
|
||||||
|
return dcb_count_by_usage(DCB_USAGE_ZOMBIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for reads
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_read_events()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for writes
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_write_events()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for errors
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_error_events()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for hangup
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_hangup_events()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_HANGUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for accepts
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_accept_events()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_ACCEPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for event queue length
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_event_queue_length()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_EVQ_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for event pending queue length
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_event_pending_queue_length()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_EVQ_PENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for max event queue length
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_max_event_queue_length()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_EVQ_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for max queue time
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_max_event_queue_time()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_MAX_QTIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to poll stats for max event execution time
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
maxinfo_max_event_exec_time()
|
||||||
|
{
|
||||||
|
return poll_get_stat(POLL_STAT_MAX_EXECTIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variables that may be sent in a show status
|
||||||
*/
|
*/
|
||||||
static struct {
|
static struct {
|
||||||
char *name;
|
char *name;
|
||||||
@ -274,6 +597,22 @@ static struct {
|
|||||||
{ "Threads_running", VT_INT, (STATSFUNC)config_threadcount },
|
{ "Threads_running", VT_INT, (STATSFUNC)config_threadcount },
|
||||||
{ "Threadpool_threads", VT_INT, (STATSFUNC)config_threadcount },
|
{ "Threadpool_threads", VT_INT, (STATSFUNC)config_threadcount },
|
||||||
{ "Threads_connected", VT_INT, (STATSFUNC)serviceSessionCountAll },
|
{ "Threads_connected", VT_INT, (STATSFUNC)serviceSessionCountAll },
|
||||||
|
{ "Connections", VT_INT, (STATSFUNC)maxinfo_all_dcbs },
|
||||||
|
{ "Client_connections", VT_INT, (STATSFUNC)maxinfo_client_dcbs },
|
||||||
|
{ "Backend_connections", VT_INT, (STATSFUNC)maxinfo_backend_dcbs },
|
||||||
|
{ "Listeners", VT_INT, (STATSFUNC)maxinfo_listener_dcbs },
|
||||||
|
{ "Zombie_connections", VT_INT, (STATSFUNC)maxinfo_zombie_dcbs },
|
||||||
|
{ "Internal_descriptors", VT_INT, (STATSFUNC)maxinfo_internal_dcbs },
|
||||||
|
{ "Read_events", VT_INT, (STATSFUNC)maxinfo_read_events },
|
||||||
|
{ "Write_events", VT_INT, (STATSFUNC)maxinfo_write_events },
|
||||||
|
{ "Hangup_events", VT_INT, (STATSFUNC)maxinfo_hangup_events },
|
||||||
|
{ "Error_events", VT_INT, (STATSFUNC)maxinfo_error_events },
|
||||||
|
{ "Accept_events", VT_INT, (STATSFUNC)maxinfo_accept_events },
|
||||||
|
{ "Event_queue_length", VT_INT, (STATSFUNC)maxinfo_event_queue_length },
|
||||||
|
{ "Pending_events", VT_INT, (STATSFUNC)maxinfo_event_pending_queue_length },
|
||||||
|
{ "Max_event_queue_length", VT_INT, (STATSFUNC)maxinfo_max_event_queue_length },
|
||||||
|
{ "Max_event_queue_time", VT_INT, (STATSFUNC)maxinfo_max_event_queue_time },
|
||||||
|
{ "Max_event_execution_time", VT_INT, (STATSFUNC)maxinfo_max_event_exec_time },
|
||||||
{ NULL, 0, NULL }
|
{ NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,8 +648,8 @@ char buf[80];
|
|||||||
(char *)(*status[context->index].func)());
|
(char *)(*status[context->index].func)());
|
||||||
break;
|
break;
|
||||||
case VT_INT:
|
case VT_INT:
|
||||||
snprintf(buf, 80, "%d",
|
snprintf(buf, 80, "%ld",
|
||||||
(int)(*status[context->index].func)());
|
(long)(*status[context->index].func)());
|
||||||
resultset_row_set(row, 1, buf);
|
resultset_row_set(row, 1, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -349,6 +688,29 @@ VARCONTEXT context;
|
|||||||
resultset_free(result);
|
resultset_free(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the show status data as a result set
|
||||||
|
*
|
||||||
|
* @return The show status data as a result set
|
||||||
|
*/
|
||||||
|
RESULTSET *
|
||||||
|
maxinfo_status()
|
||||||
|
{
|
||||||
|
RESULTSET *result;
|
||||||
|
static VARCONTEXT context;
|
||||||
|
|
||||||
|
context.like = NULL;
|
||||||
|
context.index = 0;
|
||||||
|
|
||||||
|
if ((result = resultset_create(status_row, &context)) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
|
||||||
|
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a select command parse tree and return the result set
|
* Execute a select command parse tree and return the result set
|
||||||
@ -375,6 +737,7 @@ maxinfo_pattern_match(char *pattern, char *str)
|
|||||||
{
|
{
|
||||||
int anchor, len, trailing;
|
int anchor, len, trailing;
|
||||||
char *fixed;
|
char *fixed;
|
||||||
|
extern char *strcasestr();
|
||||||
|
|
||||||
if (*pattern != '%')
|
if (*pattern != '%')
|
||||||
{
|
{
|
||||||
@ -399,7 +762,8 @@ char *fixed;
|
|||||||
char *portion = malloc(len + 1);
|
char *portion = malloc(len + 1);
|
||||||
int rval;
|
int rval;
|
||||||
strncpy(portion, fixed, len - trailing);
|
strncpy(portion, fixed, len - trailing);
|
||||||
rval = (strcasestr(portion, str) != NULL ? 0 : 1);
|
portion[len - trailing] = 0;
|
||||||
|
rval = (strcasestr(str, portion) != NULL ? 0 : 1);
|
||||||
free(portion);
|
free(portion);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user