Skip to content

Commit 0721ac1

Browse files
authored
Merge pull request #10 from little-pan/0.3.29-server-status
Added "show status" statement
2 parents b202bc0 + a112e70 commit 0721ac1

3 files changed

Lines changed: 214 additions & 0 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/**
2+
* Copyright 2019 little-pan. A SQLite server based on the C/S architecture.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.sqlite.server.sql.local;
17+
18+
import java.lang.management.ManagementFactory;
19+
import java.lang.management.MemoryMXBean;
20+
import java.lang.management.MemoryUsage;
21+
import java.lang.management.OperatingSystemMXBean;
22+
import java.lang.management.RuntimeMXBean;
23+
import java.lang.management.ThreadMXBean;
24+
import java.sql.PreparedStatement;
25+
import java.sql.SQLException;
26+
import java.text.DateFormat;
27+
import java.text.SimpleDateFormat;
28+
import java.util.Date;
29+
30+
import org.sqlite.server.SQLiteProcessor;
31+
32+
/** "SHOW STATUS" statement that shows server current status, includes memory,
33+
* thread, runtime and OS information.
34+
*
35+
* @author little-pan
36+
* @since 2019-12-21
37+
*
38+
*/
39+
public class ShowStatusStatement extends LocalStatement {
40+
41+
public static final String TBL_NAME = "status";
42+
43+
public ShowStatusStatement(String sql) {
44+
super(sql, "SHOW STATUS", true);
45+
}
46+
47+
@Override
48+
protected String getSQL(String localSchema) throws SQLException {
49+
final String f =
50+
"select Mem_Committed, Mem_Max, Mem_Used, "
51+
+ "OS_Arch, OS_Name, OS_Version, "
52+
+ "RT_Name, RT_Start_Time, RT_Uptime, RT_Vendor, RT_Version, "
53+
+ "Thread_Count, Thread_Daemon_Count, Thread_Peak_Count, Thread_Started_Count, "
54+
+ "Sys_Load_Average "
55+
+ "from '%s'.%s";
56+
return format(f, localSchema, TBL_NAME);
57+
}
58+
59+
@Override
60+
protected void init() throws SQLException {
61+
super.init();
62+
63+
String localSchema = super.localDb.getSchemaName();
64+
String f, sql;
65+
// CREATE TABLE
66+
f = "create table if not exists '%s'.%s("
67+
+ "`Mem_Committed` bigint null,"
68+
+ "`Mem_Max` bigint not null,"
69+
+ "`Mem_Used` bigint not null,"
70+
+ "`OS_Arch` varchar(80),"
71+
+ "`OS_Name` varchar(64),"
72+
+ "`OS_Version` varchar(64),"
73+
+ "`RT_Name` varchar(64),"
74+
+ "`RT_Start_Time` varchar(20),"
75+
+ "`RT_Uptime` bigint,"
76+
+ "`RT_Vendor` varchar(80),"
77+
+ "`RT_Version` varchar(64),"
78+
+ "`Thread_Count` integer,"
79+
+ "`Thread_Daemon_Count` integer,"
80+
+ "`Thread_Peak_Count` integer,"
81+
+ "`Thread_Started_Count` bigint,"
82+
+ "`Sys_Load_Average` double)";
83+
sql = format(f, localSchema, TBL_NAME);
84+
execute(sql);
85+
}
86+
87+
@Override
88+
public void preExecute(int maxRows) throws SQLException, IllegalStateException {
89+
super.preExecute(maxRows);
90+
91+
String localSchema = super.localDb.getSchemaName(), f, sql;
92+
// DELETE old data
93+
f = "delete from '%s'.%s";
94+
sql = format(f, localSchema, TBL_NAME);
95+
execute(sql);
96+
97+
// Collect processor state
98+
SQLiteProcessor processor = super.getContext();
99+
// INSERT new data for query
100+
f = "insert into '%s'.%s(`Mem_Committed`, `Mem_Max`, `Mem_Used`, `OS_Arch`, `OS_Name`, `OS_Version`, "
101+
+ "`RT_Name`, `RT_Start_Time`, `RT_Uptime`, `RT_Vendor`, `RT_Version`, "
102+
+ "`Thread_Count`, `Thread_Daemon_Count`, `Thread_Peak_Count`, `Thread_Started_Count`, "
103+
+ "`Sys_Load_Average`)"
104+
+ "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
105+
sql = format(f, localSchema, TBL_NAME);
106+
try (PreparedStatement ps = processor.getConnection().prepareStatement(sql)) {
107+
MemoryMXBean memMxBean = ManagementFactory.getMemoryMXBean();
108+
MemoryUsage heapMemUsage = memMxBean.getHeapMemoryUsage();
109+
MemoryUsage nonheapMemUsage = memMxBean.getNonHeapMemoryUsage();
110+
RuntimeMXBean rtMxBean = ManagementFactory.getRuntimeMXBean();
111+
OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean();
112+
ThreadMXBean thrMxBean = ManagementFactory.getThreadMXBean();
113+
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
114+
int i = 0;
115+
long v = -1;
116+
117+
// Memory committed
118+
if (heapMemUsage.getCommitted() > 0) {
119+
v = heapMemUsage.getCommitted();
120+
}
121+
if (nonheapMemUsage.getCommitted() > 0) {
122+
if (v > 0) {
123+
v += nonheapMemUsage.getCommitted();
124+
} else {
125+
v = nonheapMemUsage.getCommitted();
126+
}
127+
}
128+
ps.setLong(++i, v);
129+
// Memory max
130+
v = -1;
131+
if (heapMemUsage.getMax() > 0) {
132+
v = heapMemUsage.getMax();
133+
}
134+
if (nonheapMemUsage.getMax() > 0) {
135+
if (v > 0) {
136+
v += nonheapMemUsage.getMax();
137+
} else {
138+
v = nonheapMemUsage.getMax();
139+
}
140+
}
141+
ps.setLong(++i, v);
142+
// Memory used
143+
v = -1;
144+
if (heapMemUsage.getUsed() > 0) {
145+
v = heapMemUsage.getUsed();
146+
}
147+
if (nonheapMemUsage.getUsed() > 0) {
148+
if (v > 0) {
149+
v += nonheapMemUsage.getUsed();
150+
} else {
151+
v = nonheapMemUsage.getUsed();
152+
}
153+
}
154+
ps.setLong(++i, v);
155+
156+
ps.setString(++i, osMxBean.getArch());
157+
ps.setString(++i, osMxBean.getName());
158+
ps.setString(++i, osMxBean.getVersion());
159+
160+
ps.setString(++i, rtMxBean.getVmName());
161+
ps.setString(++i, df.format(new Date(rtMxBean.getStartTime())));
162+
ps.setLong(++i, rtMxBean.getUptime());
163+
ps.setString(++i, rtMxBean.getVmVendor());
164+
ps.setString(++i, format("Java %s(build %s)",
165+
rtMxBean.getSpecVersion(), rtMxBean.getVmVersion()));
166+
167+
ps.setInt(++i, thrMxBean.getThreadCount());
168+
ps.setInt(++i, thrMxBean.getDaemonThreadCount());
169+
ps.setInt(++i, thrMxBean.getPeakThreadCount());
170+
ps.setLong(++i, thrMxBean.getTotalStartedThreadCount());
171+
172+
ps.setDouble(++i, osMxBean.getSystemLoadAverage());
173+
174+
ps.executeUpdate();
175+
}
176+
}
177+
178+
}

src/main/java/org/sqlite/sql/SQLParser.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.sqlite.server.sql.local.KillStatement;
3636
import org.sqlite.server.sql.local.SetTransactionStatement;
3737
import org.sqlite.server.sql.local.ShowProcesslistStatement;
38+
import org.sqlite.server.sql.local.ShowStatusStatement;
3839
import org.sqlite.server.sql.meta.AlterUserStatement;
3940
import org.sqlite.server.sql.meta.CreateDatabaseStatement;
4041
import org.sqlite.server.sql.meta.CreateUserStatement;
@@ -967,6 +968,8 @@ protected SQLStatement parseShow() {
967968
if (nextStringIf("processlist") != -1) {
968969
return parseShowProcesslist(true);
969970
}
971+
} else if (nextStringIf("status") != -1) {
972+
return parseShowStatus();
970973
} else if (nextStringIf("tables") != -1) {
971974
return parseShowTables();
972975
} else if (nextStringIf("columns") != -1 || nextStringIf("fields") != -1) {
@@ -1204,6 +1207,14 @@ protected SQLStatement parseShowProcesslist(boolean full) {
12041207
throw syntaxError();
12051208
}
12061209

1210+
protected ShowStatusStatement parseShowStatus() {
1211+
if (nextEnd()) {
1212+
return new ShowStatusStatement(this.sql);
1213+
}
1214+
1215+
throw syntaxError();
1216+
}
1217+
12071218
protected ShowTablesStatement parseShowTables() {
12081219
ShowTablesStatement stmt = new ShowTablesStatement(this.sql);
12091220
if (nextEnd()) {

src/test/java/org/sqlite/sql/SQLParserTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.sqlite.server.sql.local.LocalStatement;
3131
import org.sqlite.server.sql.local.SetTransactionStatement;
3232
import org.sqlite.server.sql.local.ShowProcesslistStatement;
33+
import org.sqlite.server.sql.local.ShowStatusStatement;
3334
import org.sqlite.server.sql.meta.AlterUserStatement;
3435
import org.sqlite.server.sql.meta.CreateDatabaseStatement;
3536
import org.sqlite.server.sql.meta.CreateUserStatement;
@@ -911,6 +912,13 @@ protected void doTest() throws SQLException {
911912
showProcesslistTest("SHOW full PROCESSLIST", 1, true);
912913
showProcesslistTest("SHOW FULL PROCESSLIST;", 1, true);
913914

915+
showStatusTest("show status;", 1);
916+
showStatusTest("show status", 1);
917+
showStatusTest("show status ", 1);
918+
showStatusTest("show status; show status;", 2);
919+
showStatusTest("show status;show status ", 2);
920+
showStatusTest("show status; /*show*/show status ", 2);
921+
914922
showTablesTest("show tables; SHOW tables; show TABLES; SHOW TABLES", 4, null, null);
915923
showTablesTest("show tables; SHOW tables; show TABLES; SHOW TABLES", 4, null, null);
916924
showTablesTest("show tables; /**a**/SHOW tables; show TABLES/**a**/;/**a**/SHOW TABLES", 4, null, null);
@@ -1545,6 +1553,23 @@ private void showProcesslistTest(String sqls, int stmts, boolean full) {
15451553
overTest(parser, i, stmts);
15461554
}
15471555

1556+
private void showStatusTest(String sqls, int stmts) {
1557+
SQLParser parser = new SQLParser(sqls);
1558+
int i = 0;
1559+
for (SQLStatement stmt: parser) {
1560+
info("Test SHOW STATUS %s", stmt);
1561+
assertTrue("SHOW STATUS".equals(stmt.getCommand()));
1562+
assertTrue(stmt.isQuery());
1563+
assertTrue(!stmt.isEmpty());
1564+
assertTrue(!stmt.isTransaction());
1565+
assertTrue(!stmt.isComment());
1566+
assertTrue(stmt instanceof ShowStatusStatement);
1567+
++i;
1568+
parser.remove();
1569+
}
1570+
overTest(parser, i, stmts);
1571+
}
1572+
15481573
private void showTablesTest(String sqls, int stmts, String schemaName, String pattern) {
15491574
SQLParser parser = new SQLParser(sqls);
15501575
int i = 0;

0 commit comments

Comments
 (0)