2
* Copyright (c) 2010, Joseph Daly <skinny.moey@gmail.com>
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
8
* * Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
* * Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
13
* * Neither the name of Joseph Daly nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27
* THE POSSIBILITY OF SUCH DAMAGE.
33
* This tracks current user commands. The commands are logged using
34
* the post() and postEnd() logging APIs. It uses a scoreboard
35
* approach that initializes the scoreboard size to the value set
36
* by logging_stats_scoreboard_size. Each ScoreBoardSlot wraps
37
* a UserCommand object containing the statistics for a particular
38
* session. As other statistics are added they can then be added
39
* to the ScoreBoardSlot object.
43
* A RW lock is taken to locate a open slot for a session or to locate the
44
* slot that the current session has claimed.
46
* A read lock is taken when the table is queried in the data_dictionary.
50
* To improve as more statistics are added, a pointer to the scoreboard
51
* slot should be added to the Session object. This will avoid the session
52
* having to do multiple lookups in the scoreboard.
54
* Save the statistics off into a vector so you can query by user/ip and get
55
* commands run based on those keys over time.
60
#include "logging_stats.h"
61
#include "stats_schema.h"
62
#include <drizzled/session.h>
64
using namespace drizzled;
65
using namespace plugin;
68
static bool sysvar_logging_stats_enabled= false;
70
static uint32_t sysvar_logging_stats_scoreboard_size= 2000;
72
pthread_rwlock_t LOCK_scoreboard;
74
LoggingStats::LoggingStats(string name_arg) : Logging(name_arg)
76
scoreboard_size= sysvar_logging_stats_scoreboard_size;
77
score_board_slots= new ScoreBoardSlot[scoreboard_size];
78
for (uint32_t j=0; j < scoreboard_size; j++)
80
UserCommands *user_commands= new UserCommands();
81
ScoreBoardSlot *score_board_slot= &score_board_slots[j];
82
score_board_slot->setUserCommands(user_commands);
86
LoggingStats::~LoggingStats()
88
delete[] score_board_slots;
91
bool LoggingStats::isBeingLogged(Session *session)
93
enum_sql_command sql_command= session->lex->sql_command;
100
case SQLCOM_ROLLBACK:
102
case SQLCOM_CREATE_TABLE:
103
case SQLCOM_ALTER_TABLE:
104
case SQLCOM_DROP_TABLE:
112
void LoggingStats::updateScoreBoard(ScoreBoardSlot *score_board_slot,
115
enum_sql_command sql_command= session->lex->sql_command;
117
UserCommands *user_commands= score_board_slot->getUserCommands();
122
user_commands->incrementUpdateCount();
125
user_commands->incrementDeleteCount();
128
user_commands->incrementInsertCount();
130
case SQLCOM_ROLLBACK:
131
user_commands->incrementRollbackCount();
134
user_commands->incrementCommitCount();
136
case SQLCOM_CREATE_TABLE:
137
user_commands->incrementCreateCount();
139
case SQLCOM_ALTER_TABLE:
140
user_commands->incrementAlterCount();
142
case SQLCOM_DROP_TABLE:
143
user_commands->incrementDropCount();
146
user_commands->incrementSelectCount();
153
bool LoggingStats::post(Session *session)
160
/* exit early if we are not logging this type of command */
161
if (isBeingLogged(session) == false)
166
/* Find a slot that is unused */
168
pthread_rwlock_wrlock(&LOCK_scoreboard);
169
ScoreBoardSlot *score_board_slot;
170
int our_slot= UNINITIALIZED;
171
int open_slot= UNINITIALIZED;
173
for (uint32_t j=0; j < scoreboard_size; j++)
175
score_board_slot= &score_board_slots[j];
177
if (score_board_slot->isInUse() == true)
179
/* Check if this session is the one using this slot */
180
if (score_board_slot->getSessionId() == session->getSessionId())
192
/* save off the open slot */
201
if (our_slot != UNINITIALIZED)
203
pthread_rwlock_unlock(&LOCK_scoreboard);
205
else if (open_slot != UNINITIALIZED)
207
score_board_slot= &score_board_slots[open_slot];
208
score_board_slot->setInUse(true);
209
score_board_slot->setSessionId(session->getSessionId());
210
score_board_slot->setUser(session->getSecurityContext().getUser());
211
score_board_slot->setIp(session->getSecurityContext().getIp());
212
pthread_rwlock_unlock(&LOCK_scoreboard);
216
pthread_rwlock_unlock(&LOCK_scoreboard);
217
/* there was no available slot for this session */
221
updateScoreBoard(score_board_slot, session);
226
bool LoggingStats::postEnd(Session *session)
233
ScoreBoardSlot *score_board_slot;
235
pthread_rwlock_wrlock(&LOCK_scoreboard);
237
for (uint32_t j=0; j < scoreboard_size; j++)
239
score_board_slot= &score_board_slots[j];
241
if (score_board_slot->getSessionId() == session->getSessionId())
243
score_board_slot->reset();
248
pthread_rwlock_unlock(&LOCK_scoreboard);
253
/* Plugin initialization and system variables */
255
static LoggingStats *logging_stats= NULL;
257
static CommandsTool *commands_tool= NULL;
259
static void enable(Session *,
266
if (*(bool *)save != false)
268
logging_stats->enable();
269
*(bool *) var_ptr= (bool) true;
273
logging_stats->disable();
274
*(bool *) var_ptr= (bool) false;
279
static bool initTable()
281
commands_tool= new(nothrow)CommandsTool(logging_stats);
291
static int init(drizzled::plugin::Context &context)
293
logging_stats= new LoggingStats("logging_stats");
300
context.add(logging_stats);
301
context.add(commands_tool);
303
if (sysvar_logging_stats_enabled)
305
logging_stats->enable();
311
static DRIZZLE_SYSVAR_UINT(scoreboard_size,
312
sysvar_logging_stats_scoreboard_size,
314
N_("Max number of concurrent sessions that will be logged"),
315
NULL, /* check func */
316
NULL, /* update func */
322
static DRIZZLE_SYSVAR_BOOL(enable,
323
sysvar_logging_stats_enabled,
325
N_("Enable Logging Statistics Collection"),
326
NULL, /* check func */
327
enable, /* update func */
328
false /* default */);
330
static drizzle_sys_var* system_var[]= {
331
DRIZZLE_SYSVAR(scoreboard_size),
332
DRIZZLE_SYSVAR(enable),
336
DRIZZLE_DECLARE_PLUGIN
342
N_("User Statistics as DATA_DICTIONARY tables"),
344
init, /* Plugin Init */
345
system_var, /* system variables */
346
NULL /* config options */
348
DRIZZLE_DECLARE_PLUGIN_END;