Merge lp:~tjoneslo/akiban-server/add-user-monitor into lp:~akiban-technologies/akiban-server/trunk
- add-user-monitor
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nathan Williams |
Approved revision: | 2644 |
Merged at revision: | 2646 |
Proposed branch: | lp:~tjoneslo/akiban-server/add-user-monitor |
Merge into: | lp:~akiban-technologies/akiban-server/trunk |
Diff against target: |
432 lines (+233/-3) 10 files modified
src/main/java/com/akiban/server/service/is/ServerSchemaTablesServiceImpl.java (+60/-0) src/main/java/com/akiban/server/service/monitor/MonitorService.java (+18/-0) src/main/java/com/akiban/server/service/monitor/MonitorServiceImpl.java (+41/-1) src/main/java/com/akiban/server/service/monitor/SessionMonitor.java (+3/-0) src/main/java/com/akiban/server/service/monitor/SessionMonitorBase.java (+12/-0) src/main/java/com/akiban/server/service/monitor/UserMonitor.java (+32/-0) src/main/java/com/akiban/server/service/security/SecurityServiceImpl.java (+13/-1) src/main/java/com/akiban/server/service/security/UserMonitorImpl.java (+51/-0) src/main/java/com/akiban/sql/pg/PostgresServerConnection.java (+1/-0) src/test/java/com/akiban/server/service/is/SchemaTableServiceIT.java (+2/-1) |
To merge this branch: | bzr merge lp:~tjoneslo/akiban-server/add-user-monitor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nathan Williams | Approve | ||
Thomas Jones-Low | Needs Resubmitting | ||
Review via email: mp+161017@code.launchpad.net |
Commit message
Description of the change
Add a UserMonitor with IS.SERVER_USERS to show how much work each user is doing.
This creates a UserMonitor which is registered with the MontitorService and attached to the SessionMonitor when the user logs in. Currently this only works on the Postgres and InternalJDBC connections. If not using password or SSL security (i.e, security is none) there are no UserMonitors created.
This is mostly infrastructure. The only thing the UserMonitor counts currently is number of SQL statements executed. This can easily be extended, and will be at a later time.
This includes a new I_S.SERVER_USERS table to display the data gathered by the UserMonitor to the user. This table is sensitive to the restricted access security that the SERVER_SESSIONS (and other) tables are.
Thomas Jones-Low (tjoneslo) wrote : | # |
There's a whole chunk of how we capture the session monitor (including the user monitor) data when the user logs out that needs to be captured before the logout is completed. Or the server is restarted. These are known issues that need to be addressed.
I've made the deregister cleaner per your request.
Preview Diff
1 | === modified file 'src/main/java/com/akiban/server/service/is/ServerSchemaTablesServiceImpl.java' | |||
2 | --- src/main/java/com/akiban/server/service/is/ServerSchemaTablesServiceImpl.java 2013-04-23 22:45:16 +0000 | |||
3 | +++ src/main/java/com/akiban/server/service/is/ServerSchemaTablesServiceImpl.java 2013-04-26 00:32:25 +0000 | |||
4 | @@ -44,6 +44,7 @@ | |||
5 | 44 | import com.akiban.server.service.monitor.PreparedStatementMonitor; | 44 | import com.akiban.server.service.monitor.PreparedStatementMonitor; |
6 | 45 | import com.akiban.server.service.monitor.ServerMonitor; | 45 | import com.akiban.server.service.monitor.ServerMonitor; |
7 | 46 | import com.akiban.server.service.monitor.SessionMonitor; | 46 | import com.akiban.server.service.monitor.SessionMonitor; |
8 | 47 | import com.akiban.server.service.monitor.UserMonitor; | ||
9 | 47 | import com.akiban.server.service.security.SecurityService; | 48 | import com.akiban.server.service.security.SecurityService; |
10 | 48 | import com.akiban.server.service.session.Session; | 49 | import com.akiban.server.service.session.Session; |
11 | 49 | import com.akiban.server.store.SchemaManager; | 50 | import com.akiban.server.store.SchemaManager; |
12 | @@ -67,6 +68,7 @@ | |||
13 | 67 | static final TableName SERVER_TAPS = new TableName (SCHEMA_NAME, "server_taps"); | 68 | static final TableName SERVER_TAPS = new TableName (SCHEMA_NAME, "server_taps"); |
14 | 68 | static final TableName SERVER_PREPARED_STATEMENTS = new TableName (SCHEMA_NAME, "server_prepared_statements"); | 69 | static final TableName SERVER_PREPARED_STATEMENTS = new TableName (SCHEMA_NAME, "server_prepared_statements"); |
15 | 69 | static final TableName SERVER_CURSORS = new TableName (SCHEMA_NAME, "server_cursors"); | 70 | static final TableName SERVER_CURSORS = new TableName (SCHEMA_NAME, "server_cursors"); |
16 | 71 | static final TableName SERVER_USERS = new TableName (SCHEMA_NAME, "server_users"); | ||
17 | 70 | 72 | ||
18 | 71 | private final MonitorService monitor; | 73 | private final MonitorService monitor; |
19 | 72 | private final ConfigurationService configService; | 74 | private final ConfigurationService configService; |
20 | @@ -109,6 +111,8 @@ | |||
21 | 109 | attach (ais, true, SERVER_PREPARED_STATEMENTS, PreparedStatements.class); | 111 | attach (ais, true, SERVER_PREPARED_STATEMENTS, PreparedStatements.class); |
22 | 110 | //SERVER_CURSORS | 112 | //SERVER_CURSORS |
23 | 111 | attach (ais, true, SERVER_CURSORS, Cursors.class); | 113 | attach (ais, true, SERVER_CURSORS, Cursors.class); |
24 | 114 | //SERVER_USERS | ||
25 | 115 | attach(ais, true, SERVER_USERS, Users.class); | ||
26 | 112 | } | 116 | } |
27 | 113 | 117 | ||
28 | 114 | @Override | 118 | @Override |
29 | @@ -136,6 +140,18 @@ | |||
30 | 136 | } | 140 | } |
31 | 137 | } | 141 | } |
32 | 138 | 142 | ||
33 | 143 | protected Collection<UserMonitor> getAccessibleUsers (Session session) { | ||
34 | 144 | if (securityService.hasRestrictedAccess(session)) { | ||
35 | 145 | return monitor.getUserMonitors(); | ||
36 | 146 | } else { | ||
37 | 147 | UserMonitor um = monitor.getUserMonitor(session); | ||
38 | 148 | if (um == null) { | ||
39 | 149 | return Collections.emptyList(); | ||
40 | 150 | } else { | ||
41 | 151 | return Collections.singletonList(um); | ||
42 | 152 | } | ||
43 | 153 | } | ||
44 | 154 | } | ||
45 | 139 | private class InstanceSummary extends BasicFactoryBase { | 155 | private class InstanceSummary extends BasicFactoryBase { |
46 | 140 | 156 | ||
47 | 141 | public InstanceSummary(TableName sourceTable) { | 157 | public InstanceSummary(TableName sourceTable) { |
48 | @@ -565,6 +581,46 @@ | |||
49 | 565 | } | 581 | } |
50 | 566 | } | 582 | } |
51 | 567 | 583 | ||
52 | 584 | private class Users extends BasicFactoryBase { | ||
53 | 585 | |||
54 | 586 | public Users(TableName sourceTable) { | ||
55 | 587 | super(sourceTable); | ||
56 | 588 | } | ||
57 | 589 | |||
58 | 590 | @Override | ||
59 | 591 | public GroupScan getGroupScan(MemoryAdapter adapter) { | ||
60 | 592 | return new Scan (adapter.getSession(), getRowType(adapter)); | ||
61 | 593 | } | ||
62 | 594 | |||
63 | 595 | @Override | ||
64 | 596 | public long rowCount() { | ||
65 | 597 | return monitor.getUserMonitors().size(); | ||
66 | 598 | } | ||
67 | 599 | |||
68 | 600 | private class Scan extends BaseScan { | ||
69 | 601 | final Iterator<UserMonitor> users; | ||
70 | 602 | |||
71 | 603 | public Scan(Session session, RowType rowType) { | ||
72 | 604 | super(rowType); | ||
73 | 605 | users = getAccessibleUsers(session).iterator(); | ||
74 | 606 | } | ||
75 | 607 | |||
76 | 608 | @Override | ||
77 | 609 | public Row next() { | ||
78 | 610 | if (!users.hasNext()) { | ||
79 | 611 | return null; | ||
80 | 612 | } | ||
81 | 613 | UserMonitor user = users.next(); | ||
82 | 614 | ValuesRow row = new ValuesRow (rowType, | ||
83 | 615 | user.getUserName(), | ||
84 | 616 | user.getStatementCount(), | ||
85 | 617 | ++rowCounter); | ||
86 | 618 | return row; | ||
87 | 619 | } | ||
88 | 620 | } | ||
89 | 621 | } | ||
90 | 622 | |||
91 | 623 | |||
92 | 568 | static AkibanInformationSchema createTablesToRegister() { | 624 | static AkibanInformationSchema createTablesToRegister() { |
93 | 569 | NewAISBuilder builder = AISBBasedBuilder.create(); | 625 | NewAISBuilder builder = AISBBasedBuilder.create(); |
94 | 570 | 626 | ||
95 | @@ -635,6 +691,10 @@ | |||
96 | 635 | .colTimestamp("creation_time", true) | 691 | .colTimestamp("creation_time", true) |
97 | 636 | .colBigInt("row_count", true); | 692 | .colBigInt("row_count", true); |
98 | 637 | 693 | ||
99 | 694 | builder.userTable(SERVER_USERS) | ||
100 | 695 | .colString("user_name", IDENT_MAX, false) | ||
101 | 696 | .colBigInt("statement_count", false); | ||
102 | 697 | |||
103 | 638 | return builder.ais(false); | 698 | return builder.ais(false); |
104 | 639 | } | 699 | } |
105 | 640 | } | 700 | } |
106 | 641 | 701 | ||
107 | === modified file 'src/main/java/com/akiban/server/service/monitor/MonitorService.java' | |||
108 | --- src/main/java/com/akiban/server/service/monitor/MonitorService.java 2013-04-23 22:45:16 +0000 | |||
109 | +++ src/main/java/com/akiban/server/service/monitor/MonitorService.java 2013-04-26 00:32:25 +0000 | |||
110 | @@ -58,4 +58,22 @@ | |||
111 | 58 | 58 | ||
112 | 59 | /** Log last statement from given monitor. */ | 59 | /** Log last statement from given monitor. */ |
113 | 60 | void logQuery(SessionMonitor sessionMonitor); | 60 | void logQuery(SessionMonitor sessionMonitor); |
114 | 61 | |||
115 | 62 | /** Register the given User monitor. */ | ||
116 | 63 | void registerUserMonitor (UserMonitor userMonitor); | ||
117 | 64 | |||
118 | 65 | /** Deregister the given user montitor. */ | ||
119 | 66 | void deregisterUserMonitor (UserMonitor userMonitor); | ||
120 | 67 | |||
121 | 68 | /** Deregister the montor for the given user */ | ||
122 | 69 | void deregisterUserMonitor (String userName); | ||
123 | 70 | |||
124 | 71 | /** Get the user monitor for the given user name. */ | ||
125 | 72 | UserMonitor getUserMonitor(String userName); | ||
126 | 73 | |||
127 | 74 | /** Get the user monitor for the session user */ | ||
128 | 75 | UserMonitor getUserMonitor(Session session); | ||
129 | 76 | |||
130 | 77 | /** Get all the user monitors. */ | ||
131 | 78 | Collection<UserMonitor> getUserMonitors(); | ||
132 | 61 | } | 79 | } |
133 | 62 | 80 | ||
134 | === modified file 'src/main/java/com/akiban/server/service/monitor/MonitorServiceImpl.java' | |||
135 | --- src/main/java/com/akiban/server/service/monitor/MonitorServiceImpl.java 2013-04-23 22:45:16 +0000 | |||
136 | +++ src/main/java/com/akiban/server/service/monitor/MonitorServiceImpl.java 2013-04-26 00:32:25 +0000 | |||
137 | @@ -62,6 +62,8 @@ | |||
138 | 62 | private BufferedWriter queryOut; | 62 | private BufferedWriter queryOut; |
139 | 63 | 63 | ||
140 | 64 | private long execTimeThreshold; | 64 | private long execTimeThreshold; |
141 | 65 | |||
142 | 66 | private Map<String, UserMonitor> users; | ||
143 | 65 | 67 | ||
144 | 66 | @Inject | 68 | @Inject |
145 | 67 | public MonitorServiceImpl(ConfigurationService config) { | 69 | public MonitorServiceImpl(ConfigurationService config) { |
146 | @@ -76,6 +78,7 @@ | |||
147 | 76 | 78 | ||
148 | 77 | sessionAllocator = new AtomicInteger(); | 79 | sessionAllocator = new AtomicInteger(); |
149 | 78 | sessions = new ConcurrentHashMap<>(); | 80 | sessions = new ConcurrentHashMap<>(); |
150 | 81 | users = new ConcurrentHashMap<>(); | ||
151 | 79 | 82 | ||
152 | 80 | String enableLog = config.getProperty(QUERY_LOG_PROPERTY); | 83 | String enableLog = config.getProperty(QUERY_LOG_PROPERTY); |
153 | 81 | this.queryLogEnabled = new AtomicBoolean(Boolean.parseBoolean(enableLog)); | 84 | this.queryLogEnabled = new AtomicBoolean(Boolean.parseBoolean(enableLog)); |
154 | @@ -310,5 +313,42 @@ | |||
155 | 310 | logger.debug("Query log file ready for writing."); | 313 | logger.debug("Query log file ready for writing."); |
156 | 311 | return true; | 314 | return true; |
157 | 312 | } | 315 | } |
159 | 313 | 316 | ||
160 | 317 | /** Register the given User monitor. */ | ||
161 | 318 | @Override | ||
162 | 319 | public void registerUserMonitor (UserMonitor userMonitor) { | ||
163 | 320 | UserMonitor monitor = users.put(userMonitor.getUserName(), userMonitor); | ||
164 | 321 | assert (monitor == null || monitor == userMonitor); | ||
165 | 322 | } | ||
166 | 323 | |||
167 | 324 | /** Deregister the monitor for the given user */ | ||
168 | 325 | @Override | ||
169 | 326 | public void deregisterUserMonitor (String userName) { | ||
170 | 327 | users.remove(userName); | ||
171 | 328 | } | ||
172 | 329 | |||
173 | 330 | /** Deregister the given user monitor. */ | ||
174 | 331 | @Override | ||
175 | 332 | public void deregisterUserMonitor (UserMonitor userMonitor) { | ||
176 | 333 | UserMonitor monitor = users.remove(userMonitor.getUserName()); | ||
177 | 334 | assert (monitor== null || monitor == userMonitor); | ||
178 | 335 | } | ||
179 | 336 | |||
180 | 337 | /** Get the user monitor for the given user name. */ | ||
181 | 338 | @Override | ||
182 | 339 | public UserMonitor getUserMonitor(String userName) { | ||
183 | 340 | return users.get(userName); | ||
184 | 341 | } | ||
185 | 342 | |||
186 | 343 | /** Get the user monitor for the session user */ | ||
187 | 344 | @Override | ||
188 | 345 | public UserMonitor getUserMonitor(Session session) { | ||
189 | 346 | return session.get(SESSION_KEY).getUserMonitor(); | ||
190 | 347 | } | ||
191 | 348 | |||
192 | 349 | /** Get all the user monitors. */ | ||
193 | 350 | @Override | ||
194 | 351 | public Collection<UserMonitor> getUserMonitors() { | ||
195 | 352 | return users.values(); | ||
196 | 353 | } | ||
197 | 314 | } | 354 | } |
198 | 315 | 355 | ||
199 | === modified file 'src/main/java/com/akiban/server/service/monitor/SessionMonitor.java' | |||
200 | --- src/main/java/com/akiban/server/service/monitor/SessionMonitor.java 2013-03-22 20:05:57 +0000 | |||
201 | +++ src/main/java/com/akiban/server/service/monitor/SessionMonitor.java 2013-04-26 00:32:25 +0000 | |||
202 | @@ -76,4 +76,7 @@ | |||
203 | 76 | 76 | ||
204 | 77 | /** Get any prepared statements. */ | 77 | /** Get any prepared statements. */ |
205 | 78 | List<PreparedStatementMonitor> getPreparedStatements(); | 78 | List<PreparedStatementMonitor> getPreparedStatements(); |
206 | 79 | |||
207 | 80 | /** Get the user monitor for this session */ | ||
208 | 81 | UserMonitor getUserMonitor(); | ||
209 | 79 | } | 82 | } |
210 | 80 | 83 | ||
211 | === modified file 'src/main/java/com/akiban/server/service/monitor/SessionMonitorBase.java' | |||
212 | --- src/main/java/com/akiban/server/service/monitor/SessionMonitorBase.java 2013-03-22 20:05:57 +0000 | |||
213 | +++ src/main/java/com/akiban/server/service/monitor/SessionMonitorBase.java 2013-04-26 00:32:25 +0000 | |||
214 | @@ -32,6 +32,7 @@ | |||
215 | 32 | private long currentStatementEndTime = -1; | 32 | private long currentStatementEndTime = -1; |
216 | 33 | private int rowsProcessed = 0; | 33 | private int rowsProcessed = 0; |
217 | 34 | private int statementCount = 0; | 34 | private int statementCount = 0; |
218 | 35 | private UserMonitor user = null; | ||
219 | 35 | 36 | ||
220 | 36 | protected SessionMonitorBase(int sessionID) { | 37 | protected SessionMonitorBase(int sessionID) { |
221 | 37 | this.sessionID = sessionID; | 38 | this.sessionID = sessionID; |
222 | @@ -65,6 +66,9 @@ | |||
223 | 65 | public void endStatement(int rowsProcessed) { | 66 | public void endStatement(int rowsProcessed) { |
224 | 66 | currentStatementEndTime = System.currentTimeMillis(); | 67 | currentStatementEndTime = System.currentTimeMillis(); |
225 | 67 | this.rowsProcessed = rowsProcessed; | 68 | this.rowsProcessed = rowsProcessed; |
226 | 69 | if (user != null) { | ||
227 | 70 | user.statementRun(); | ||
228 | 71 | } | ||
229 | 68 | } | 72 | } |
230 | 69 | 73 | ||
231 | 70 | // Caller can sequence all stages and avoid any gaps at the cost of more complicated | 74 | // Caller can sequence all stages and avoid any gaps at the cost of more complicated |
232 | @@ -167,5 +171,13 @@ | |||
233 | 167 | public List<PreparedStatementMonitor> getPreparedStatements() { | 171 | public List<PreparedStatementMonitor> getPreparedStatements() { |
234 | 168 | return Collections.emptyList(); | 172 | return Collections.emptyList(); |
235 | 169 | } | 173 | } |
236 | 174 | |||
237 | 175 | public void setUserMonitor(UserMonitor monitor) { | ||
238 | 176 | this.user = monitor; | ||
239 | 177 | } | ||
240 | 178 | |||
241 | 179 | public UserMonitor getUserMonitor() { | ||
242 | 180 | return this.user; | ||
243 | 181 | } | ||
244 | 170 | 182 | ||
245 | 171 | } | 183 | } |
246 | 172 | 184 | ||
247 | === added file 'src/main/java/com/akiban/server/service/monitor/UserMonitor.java' | |||
248 | --- src/main/java/com/akiban/server/service/monitor/UserMonitor.java 1970-01-01 00:00:00 +0000 | |||
249 | +++ src/main/java/com/akiban/server/service/monitor/UserMonitor.java 2013-04-26 00:32:25 +0000 | |||
250 | @@ -0,0 +1,32 @@ | |||
251 | 1 | /** | ||
252 | 2 | * Copyright (C) 2009-2013 Akiban Technologies, Inc. | ||
253 | 3 | * | ||
254 | 4 | * This program is free software: you can redistribute it and/or modify | ||
255 | 5 | * it under the terms of the GNU Affero General Public License as published by | ||
256 | 6 | * the Free Software Foundation, either version 3 of the License, or | ||
257 | 7 | * (at your option) any later version. | ||
258 | 8 | * | ||
259 | 9 | * This program is distributed in the hope that it will be useful, | ||
260 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
261 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
262 | 12 | * GNU Affero General Public License for more details. | ||
263 | 13 | * | ||
264 | 14 | * You should have received a copy of the GNU Affero General Public License | ||
265 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
266 | 16 | */ | ||
267 | 17 | package com.akiban.server.service.monitor; | ||
268 | 18 | |||
269 | 19 | public interface UserMonitor { | ||
270 | 20 | |||
271 | 21 | /** User name of the user being monitored */ | ||
272 | 22 | String getUserName(); | ||
273 | 23 | |||
274 | 24 | /** The number of queries executed. */ | ||
275 | 25 | long getStatementCount(); | ||
276 | 26 | |||
277 | 27 | /** Get total time in nanoseconds not spent idle. */ | ||
278 | 28 | long getNonIdleTimeNanos(); | ||
279 | 29 | |||
280 | 30 | /** Flag a new statment has been processed */ | ||
281 | 31 | void statementRun(); | ||
282 | 32 | } | ||
283 | 0 | 33 | ||
284 | === modified file 'src/main/java/com/akiban/server/service/security/SecurityServiceImpl.java' | |||
285 | --- src/main/java/com/akiban/server/service/security/SecurityServiceImpl.java 2013-04-23 22:45:16 +0000 | |||
286 | +++ src/main/java/com/akiban/server/service/security/SecurityServiceImpl.java 2013-04-26 00:32:25 +0000 | |||
287 | @@ -27,6 +27,8 @@ | |||
288 | 27 | import com.akiban.server.error.SecurityException; | 27 | import com.akiban.server.error.SecurityException; |
289 | 28 | import com.akiban.server.service.Service; | 28 | import com.akiban.server.service.Service; |
290 | 29 | import com.akiban.server.service.config.ConfigurationService; | 29 | import com.akiban.server.service.config.ConfigurationService; |
291 | 30 | import com.akiban.server.service.monitor.MonitorService; | ||
292 | 31 | import com.akiban.server.service.monitor.UserMonitor; | ||
293 | 30 | import com.akiban.server.service.session.Session; | 32 | import com.akiban.server.service.session.Session; |
294 | 31 | import com.akiban.server.store.SchemaManager; | 33 | import com.akiban.server.store.SchemaManager; |
295 | 32 | import com.akiban.sql.server.ServerCallContextStack; | 34 | import com.akiban.sql.server.ServerCallContextStack; |
296 | @@ -81,6 +83,7 @@ | |||
297 | 81 | 83 | ||
298 | 82 | private final ConfigurationService configService; | 84 | private final ConfigurationService configService; |
299 | 83 | private final SchemaManager schemaManager; | 85 | private final SchemaManager schemaManager; |
300 | 86 | private final MonitorService monitor; | ||
301 | 84 | 87 | ||
302 | 85 | private boolean restrictUserSchema; | 88 | private boolean restrictUserSchema; |
303 | 86 | 89 | ||
304 | @@ -88,9 +91,11 @@ | |||
305 | 88 | 91 | ||
306 | 89 | @Inject | 92 | @Inject |
307 | 90 | public SecurityServiceImpl(ConfigurationService configService, | 93 | public SecurityServiceImpl(ConfigurationService configService, |
309 | 91 | SchemaManager schemaManager) { | 94 | SchemaManager schemaManager, |
310 | 95 | MonitorService monitor) { | ||
311 | 92 | this.configService = configService; | 96 | this.configService = configService; |
312 | 93 | this.schemaManager = schemaManager; | 97 | this.schemaManager = schemaManager; |
313 | 98 | this.monitor = monitor; | ||
314 | 94 | } | 99 | } |
315 | 95 | 100 | ||
316 | 96 | // Connections are not thread safe, and prepared statements remember a Session, | 101 | // Connections are not thread safe, and prepared statements remember a Session, |
317 | @@ -273,6 +278,7 @@ | |||
318 | 273 | throw new SecurityException("Failed to delete user"); | 278 | throw new SecurityException("Failed to delete user"); |
319 | 274 | } | 279 | } |
320 | 275 | conn.commit(); | 280 | conn.commit(); |
321 | 281 | monitor.deregisterUserMonitor(name); | ||
322 | 276 | } | 282 | } |
323 | 277 | catch (SQLException ex) { | 283 | catch (SQLException ex) { |
324 | 278 | throw new SecurityException("Error deleting user", ex); | 284 | throw new SecurityException("Error deleting user", ex); |
325 | @@ -336,6 +342,9 @@ | |||
326 | 336 | if (session != null) { | 342 | if (session != null) { |
327 | 337 | session.put(SESSION_KEY, user); | 343 | session.put(SESSION_KEY, user); |
328 | 338 | } | 344 | } |
329 | 345 | if (monitor.getUserMonitor(user.getName()) == null) { | ||
330 | 346 | monitor.registerUserMonitor(new UserMonitorImpl(user.getName())); | ||
331 | 347 | } | ||
332 | 339 | return user; | 348 | return user; |
333 | 340 | } | 349 | } |
334 | 341 | 350 | ||
335 | @@ -367,6 +376,9 @@ | |||
336 | 367 | if (session != null) { | 376 | if (session != null) { |
337 | 368 | session.put(SESSION_KEY, user); | 377 | session.put(SESSION_KEY, user); |
338 | 369 | } | 378 | } |
339 | 379 | if (monitor.getUserMonitor(user.getName()) == null) { | ||
340 | 380 | monitor.registerUserMonitor(new UserMonitorImpl(user.getName())); | ||
341 | 381 | } | ||
342 | 370 | return user; | 382 | return user; |
343 | 371 | } | 383 | } |
344 | 372 | 384 | ||
345 | 373 | 385 | ||
346 | === added file 'src/main/java/com/akiban/server/service/security/UserMonitorImpl.java' | |||
347 | --- src/main/java/com/akiban/server/service/security/UserMonitorImpl.java 1970-01-01 00:00:00 +0000 | |||
348 | +++ src/main/java/com/akiban/server/service/security/UserMonitorImpl.java 2013-04-26 00:32:25 +0000 | |||
349 | @@ -0,0 +1,51 @@ | |||
350 | 1 | /** | ||
351 | 2 | * Copyright (C) 2009-2013 Akiban Technologies, Inc. | ||
352 | 3 | * | ||
353 | 4 | * This program is free software: you can redistribute it and/or modify | ||
354 | 5 | * it under the terms of the GNU Affero General Public License as published by | ||
355 | 6 | * the Free Software Foundation, either version 3 of the License, or | ||
356 | 7 | * (at your option) any later version. | ||
357 | 8 | * | ||
358 | 9 | * This program is distributed in the hope that it will be useful, | ||
359 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
360 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
361 | 12 | * GNU Affero General Public License for more details. | ||
362 | 13 | * | ||
363 | 14 | * You should have received a copy of the GNU Affero General Public License | ||
364 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
365 | 16 | */ | ||
366 | 17 | package com.akiban.server.service.security; | ||
367 | 18 | |||
368 | 19 | import java.util.concurrent.atomic.AtomicLong; | ||
369 | 20 | |||
370 | 21 | import com.akiban.server.service.monitor.UserMonitor; | ||
371 | 22 | |||
372 | 23 | public class UserMonitorImpl implements UserMonitor { | ||
373 | 24 | private final String userName; | ||
374 | 25 | protected final AtomicLong count = new AtomicLong(); | ||
375 | 26 | |||
376 | 27 | public UserMonitorImpl (String name) { | ||
377 | 28 | this.userName = name; | ||
378 | 29 | } | ||
379 | 30 | @Override | ||
380 | 31 | public String getUserName() { | ||
381 | 32 | return userName; | ||
382 | 33 | } | ||
383 | 34 | |||
384 | 35 | @Override | ||
385 | 36 | public long getStatementCount() { | ||
386 | 37 | return count.get(); | ||
387 | 38 | } | ||
388 | 39 | |||
389 | 40 | @Override | ||
390 | 41 | public void statementRun() { | ||
391 | 42 | count.incrementAndGet(); | ||
392 | 43 | } | ||
393 | 44 | |||
394 | 45 | @Override | ||
395 | 46 | public long getNonIdleTimeNanos() { | ||
396 | 47 | // TODO Auto-generated method stub | ||
397 | 48 | return 0; | ||
398 | 49 | } | ||
399 | 50 | |||
400 | 51 | } | ||
401 | 0 | 52 | ||
402 | === modified file 'src/main/java/com/akiban/sql/pg/PostgresServerConnection.java' | |||
403 | --- src/main/java/com/akiban/sql/pg/PostgresServerConnection.java 2013-04-23 22:45:16 +0000 | |||
404 | +++ src/main/java/com/akiban/sql/pg/PostgresServerConnection.java 2013-04-26 00:32:25 +0000 | |||
405 | @@ -522,6 +522,7 @@ | |||
406 | 522 | } | 522 | } |
407 | 523 | logger.debug("Login {}", (principal != null) ? principal : user); | 523 | logger.debug("Login {}", (principal != null) ? principal : user); |
408 | 524 | authenticationOkay(user); | 524 | authenticationOkay(user); |
409 | 525 | sessionMonitor.setUserMonitor(reqs.monitor().getUserMonitor(user)); | ||
410 | 525 | } | 526 | } |
411 | 526 | 527 | ||
412 | 527 | protected void authenticationOkay(String user) throws IOException { | 528 | protected void authenticationOkay(String user) throws IOException { |
413 | 528 | 529 | ||
414 | === modified file 'src/test/java/com/akiban/server/service/is/SchemaTableServiceIT.java' | |||
415 | --- src/test/java/com/akiban/server/service/is/SchemaTableServiceIT.java 2013-03-22 20:05:57 +0000 | |||
416 | +++ src/test/java/com/akiban/server/service/is/SchemaTableServiceIT.java 2013-04-26 00:32:25 +0000 | |||
417 | @@ -98,7 +98,7 @@ | |||
418 | 98 | 98 | ||
419 | 99 | @Test | 99 | @Test |
420 | 100 | public void serverExamine() { | 100 | public void serverExamine() { |
422 | 101 | assertEquals ("Table count", 10, ServerSchemaTablesServiceImpl.createTablesToRegister().getUserTables().size()); | 101 | assertEquals ("Table count", 11, ServerSchemaTablesServiceImpl.createTablesToRegister().getUserTables().size()); |
423 | 102 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.ERROR_CODES)); | 102 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.ERROR_CODES)); |
424 | 103 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_INSTANCE_SUMMARY)); | 103 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_INSTANCE_SUMMARY)); |
425 | 104 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_SERVERS)); | 104 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_SERVERS)); |
426 | @@ -109,5 +109,6 @@ | |||
427 | 109 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_TAPS)); | 109 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_TAPS)); |
428 | 110 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_PREPARED_STATEMENTS)); | 110 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_PREPARED_STATEMENTS)); |
429 | 111 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_CURSORS)); | 111 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_CURSORS)); |
430 | 112 | assertNotNull (ais.getUserTable(ServerSchemaTablesServiceImpl.SERVER_USERS)); | ||
431 | 112 | } | 113 | } |
432 | 113 | } | 114 | } |
Tiny nit. Diff line 170 can just remove, instead of contains and remove. The string based contract being looser (i.e. not asserting) is fine though.
I'm not sure we'll want to blow away the monitor, diff line 322, if a user is deleted in general. Long term random guess: they still need billed. But I'm hand waving and we can always adjust as we figure out how we want to use it.