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.
34
* The scoreboard is a pre-allocated vector of vectors of ScoreBoardSlots. It
35
* can be thought of as a vector of buckets where each bucket contains
36
* pre-allocated ScoreBoardSlots. To determine which bucket gets used for
37
* recording statistics the modulus operator is used on the session_id. This
38
* will result in a bucket to search for a unused ScoreBoardSlot.
42
* Each bucket has a its own lock this allows a search of bucket 1 and bucket 2
43
* to happen concurrently.
48
#include <drizzled/plugin.h>
49
#include "scoreboard.h"
53
using namespace drizzled;
56
Scoreboard::Scoreboard(uint32_t in_number_sessions, uint32_t in_number_buckets)
58
number_sessions(in_number_sessions),
59
number_buckets(in_number_buckets)
62
/* calculate the number of elements in each bucket */
63
number_per_bucket= static_cast<uint32_t> ( ceil( static_cast<double>(number_sessions) / static_cast<double>(number_buckets) ) );
65
/* populate the vector of scoreboard vectors */
66
for (uint32_t j= 0; j < number_buckets; ++j)
68
vector<ScoreboardSlot* > *scoreboard_vector= new vector<ScoreboardSlot* >();
70
/* preallocate the individual vectors */
71
vector<ScoreboardSlot* >::iterator scoreboard_vector_iterator= scoreboard_vector->begin();
72
for (uint32_t h= 0; h < number_per_bucket; ++h)
74
ScoreboardSlot *scoreboard_slot= new ScoreboardSlot();
75
scoreboard_vector_iterator= scoreboard_vector->insert(scoreboard_vector_iterator, scoreboard_slot);
77
scoreboard_vector->resize(number_per_bucket);
80
/* insert the vector into the vector of scoreboard vectors */
81
vector<vector<ScoreboardSlot* >* >::iterator vector_of_scoreboard_vectors_iterator=
82
vector_of_scoreboard_vectors.begin();
84
vector_of_scoreboard_vectors_iterator=
85
vector_of_scoreboard_vectors.insert(vector_of_scoreboard_vectors_iterator, scoreboard_vector);
87
vector_of_scoreboard_vectors.resize(number_buckets);
89
/* populate the scoreboard locks vector each ScoreboardSlot vector gets a lock */
90
vector<boost::shared_mutex* >::iterator vector_of_scoreboard_locks_iterator= vector_of_scoreboard_locks.begin();
91
for (uint32_t k= 0; k < number_buckets; ++k)
93
boost::shared_mutex* lock= new boost::shared_mutex();
94
vector_of_scoreboard_locks_iterator=
95
vector_of_scoreboard_locks.insert(vector_of_scoreboard_locks_iterator, lock);
97
vector_of_scoreboard_locks.resize(number_buckets);
99
/* calculate the approximate memory allocation of the scoreboard */
100
size_t statusVarsSize= sizeof(StatusVars) + sizeof(system_status_var);
101
size_t userCommandsSize= sizeof(UserCommands) + sizeof(uint64_t) * SQLCOM_END;
103
scoreboard_size_bytes= (statusVarsSize + userCommandsSize) * number_per_bucket * number_buckets;
106
Scoreboard::~Scoreboard()
108
vector<vector<ScoreboardSlot* >* >::iterator v_of_scoreboard_v_begin_it= vector_of_scoreboard_vectors.begin();
109
vector<vector<ScoreboardSlot* >* >::iterator v_of_scoreboard_v_end_it= vector_of_scoreboard_vectors.end();
111
for (; v_of_scoreboard_v_begin_it != v_of_scoreboard_v_end_it; ++v_of_scoreboard_v_begin_it)
113
vector<ScoreboardSlot* > *scoreboard_vector= *v_of_scoreboard_v_begin_it;
115
vector<ScoreboardSlot* >::iterator scoreboard_vector_it= scoreboard_vector->begin();
116
vector<ScoreboardSlot* >::iterator scoreboard_vector_end= scoreboard_vector->end();
117
for (; scoreboard_vector_it != scoreboard_vector_end; ++scoreboard_vector_it)
119
delete *scoreboard_vector_it;
122
scoreboard_vector->clear();
123
delete scoreboard_vector;
124
} // vector_of_scoreboard_vectors is not on the stack and does not deletion
126
vector<boost::shared_mutex* >::iterator vector_of_scoreboard_locks_it= vector_of_scoreboard_locks.begin();
127
vector<boost::shared_mutex* >::iterator vector_of_scoreboard_locks_end= vector_of_scoreboard_locks.end();
129
for (; vector_of_scoreboard_locks_it != vector_of_scoreboard_locks_end; ++vector_of_scoreboard_locks_it)
131
boost::shared_mutex* lock= *vector_of_scoreboard_locks_it;
136
uint32_t Scoreboard::getBucketNumber(Session *session)
138
return (session->getSessionId() % number_buckets);
141
ScoreboardSlot* Scoreboard::findScoreboardSlotToLog(Session *session)
144
uint32_t bucket_number= getBucketNumber(session);
146
/* our vector corresponding to bucket_number */
147
vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
149
/* Check if this session has already claimed a slot */
150
int32_t session_scoreboard_slot= session->getScoreboardIndex();
152
if (session_scoreboard_slot == -1)
154
boost::shared_mutex* LOCK_scoreboard_vector= vector_of_scoreboard_locks.at(bucket_number);
155
LOCK_scoreboard_vector->lock();
157
ScoreboardSlot *scoreboard_slot= NULL;
159
int32_t slot_index= 0;
160
for (vector<ScoreboardSlot *>::iterator it= scoreboard_vector->begin();
161
it != scoreboard_vector->end(); ++it, ++slot_index)
163
scoreboard_slot= *it;
165
if (scoreboard_slot->isInUse() == false)
167
scoreboard_slot->setInUse(true);
168
scoreboard_slot->setSessionId(session->getSessionId());
169
scoreboard_slot->setUser(session->getSecurityContext().getUser());
170
scoreboard_slot->setIp(session->getSecurityContext().getIp());
171
session->setScoreboardIndex(slot_index);
172
LOCK_scoreboard_vector->unlock();
173
return scoreboard_slot;
177
LOCK_scoreboard_vector->unlock();
179
else // already claimed a slot just do a lookup
181
ScoreboardSlot *scoreboard_slot= scoreboard_vector->at(session_scoreboard_slot);
182
return scoreboard_slot;
185
/* its possible we did not claim a slot if the scoreboard size is somehow smaller then the
186
active connections */
190
ScoreboardSlot* Scoreboard::findOurScoreboardSlot(Session *session)
193
uint32_t bucket_number= getBucketNumber(session);
195
/* our vector corresponding to bucket_number */
196
vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
198
/* Check if this session has already claimed a slot */
199
int32_t session_scoreboard_slot= session->getScoreboardIndex();
201
if (session_scoreboard_slot == -1)
206
ScoreboardSlot *scoreboard_slot= scoreboard_vector->at(session_scoreboard_slot);
207
return scoreboard_slot;