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 "scoreboard.h"
52
using namespace drizzled;
55
Scoreboard::Scoreboard(uint32_t in_number_sessions, uint32_t in_number_buckets)
57
number_sessions(in_number_sessions),
58
number_buckets(in_number_buckets)
61
/* calculate the number of elements in each bucket */
62
uint32_t number_per_bucket= static_cast<uint32_t> ( ceil( static_cast<double>(number_sessions) / static_cast<double>(number_buckets) ) );
64
/* populate the vector of scoreboard vectors */
65
for (uint32_t j= 0; j < number_buckets; ++j)
67
vector<ScoreboardSlot* > *scoreboard_vector= new vector<ScoreboardSlot* >();
69
/* preallocate the individual vectors */
70
vector<ScoreboardSlot* >::iterator scoreboard_vector_iterator= scoreboard_vector->begin();
71
for (uint32_t h= 0; h < number_per_bucket; ++h)
73
ScoreboardSlot *scoreboard_slot= new ScoreboardSlot();
74
scoreboard_vector_iterator= scoreboard_vector->insert(scoreboard_vector_iterator, scoreboard_slot);
76
scoreboard_vector->resize(number_per_bucket);
79
/* insert the vector into the vector of scoreboard vectors */
80
vector<vector<ScoreboardSlot* >* >::iterator vector_of_scoreboard_vectors_iterator=
81
vector_of_scoreboard_vectors.begin();
83
vector_of_scoreboard_vectors_iterator=
84
vector_of_scoreboard_vectors.insert(vector_of_scoreboard_vectors_iterator, scoreboard_vector);
86
vector_of_scoreboard_vectors.resize(number_buckets);
88
/* populate the scoreboard locks vector each ScoreboardSlot vector gets a lock */
89
vector<pthread_rwlock_t* >::iterator vector_of_scoreboard_locks_iterator= vector_of_scoreboard_locks.begin();
90
for (uint32_t k= 0; k < number_buckets; ++k)
92
pthread_rwlock_t* lock= new pthread_rwlock_t();
93
(void) pthread_rwlock_init(lock, NULL);
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);
100
Scoreboard::~Scoreboard()
102
vector<vector<ScoreboardSlot* >* >::iterator v_of_scoreboard_v_begin_it= vector_of_scoreboard_vectors.begin();
103
vector<vector<ScoreboardSlot* >* >::iterator v_of_scoreboard_v_end_it= vector_of_scoreboard_vectors.end();
105
for (; v_of_scoreboard_v_begin_it != v_of_scoreboard_v_end_it; ++v_of_scoreboard_v_begin_it)
107
vector<ScoreboardSlot* > *scoreboard_vector= *v_of_scoreboard_v_begin_it;
109
vector<ScoreboardSlot* >::iterator scoreboard_vector_it= scoreboard_vector->begin();
110
vector<ScoreboardSlot* >::iterator scoreboard_vector_end= scoreboard_vector->end();
111
for (; scoreboard_vector_it != scoreboard_vector_end; ++scoreboard_vector_it)
113
delete *scoreboard_vector_it;
116
scoreboard_vector->clear();
117
delete scoreboard_vector;
118
} // vector_of_scoreboard_vectors is not on the stack and does not deletion
120
vector<pthread_rwlock_t* >::iterator vector_of_scoreboard_locks_it= vector_of_scoreboard_locks.begin();
121
vector<pthread_rwlock_t* >::iterator vector_of_scoreboard_locks_end= vector_of_scoreboard_locks.end();
123
for (; vector_of_scoreboard_locks_it != vector_of_scoreboard_locks_end; ++vector_of_scoreboard_locks_it)
125
pthread_rwlock_t* lock= *vector_of_scoreboard_locks_it;
126
(void) pthread_rwlock_destroy(lock);
131
ScoreboardSlot* Scoreboard::findScoreboardSlotToLog(Session *session)
134
uint32_t bucket_number= session->getSessionId() % number_buckets;
136
/* our vector corresponding to bucket_number */
137
vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
139
/* out lock corresponding to bucket_number */
140
pthread_rwlock_t *LOCK_scoreboard_vector= vector_of_scoreboard_locks.at(bucket_number);
142
pthread_rwlock_wrlock(LOCK_scoreboard_vector);
143
ScoreboardSlot *scoreboard_slot= NULL;
144
int32_t our_slot= UNINITIALIZED;
145
int32_t open_slot= UNINITIALIZED;
147
uint32_t current_slot= 0;
148
for (vector<ScoreboardSlot *>::iterator it= scoreboard_vector->begin();
149
it != scoreboard_vector->end(); ++it, current_slot++)
151
scoreboard_slot= *it;
153
if (scoreboard_slot->isInUse() == true)
155
/* Check if this session is the one using this slot */
156
if (scoreboard_slot->getSessionId() == session->getSessionId())
158
our_slot= current_slot;
168
/* save off the open slot */
169
if (open_slot == UNINITIALIZED)
171
open_slot= current_slot;
177
if (our_slot != UNINITIALIZED)
179
pthread_rwlock_unlock(LOCK_scoreboard_vector);
181
else if (open_slot != UNINITIALIZED)
183
scoreboard_slot= scoreboard_vector->at(open_slot);
184
scoreboard_slot->setInUse(true);
185
scoreboard_slot->setSessionId(session->getSessionId());
186
scoreboard_slot->setUser(session->getSecurityContext().getUser());
187
scoreboard_slot->setIp(session->getSecurityContext().getIp());
188
pthread_rwlock_unlock(LOCK_scoreboard_vector);
192
pthread_rwlock_unlock(LOCK_scoreboard_vector);
193
/* there was no available slot for this session */
197
return scoreboard_slot;
200
ScoreboardSlot* Scoreboard::findAndResetScoreboardSlot(Session *session)
203
uint32_t bucket_number= session->getSessionId() % number_buckets;
205
/* our vector corresponding to bucket_number */
206
vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
208
ScoreboardSlot *scoreboard_slot;
209
ScoreboardSlot *return_scoreboard_slot= NULL;
211
for (vector<ScoreboardSlot *>::iterator it= scoreboard_vector->begin();
212
it != scoreboard_vector->end(); ++it)
214
scoreboard_slot= *it;
216
if (scoreboard_slot->getSessionId() == session->getSessionId())
218
return_scoreboard_slot = new ScoreboardSlot(*scoreboard_slot);
219
scoreboard_slot->reset();
224
return return_scoreboard_slot;