~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to plugin/logging_stats/scoreboard.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-10-02 14:17:48 UTC
  • mfrom: (1.1.1 upstream)
  • mto: (2.1.17 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101002141748-m6vbfbfjhrw1153e
Tags: 2010.09.1802-1
* New upstream release.
* Removed pid-file argument hack.
* Updated GPL-2 address to be new address.
* Directly copy in drizzledump.1 since debian doesn't have sphinx 1.0 yet.
* Link to jquery from libjs-jquery. Add it as a depend.
* Add drizzled.8 symlink to the install files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010, Joseph Daly <skinny.moey@gmail.com>
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
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.
 
16
 *
 
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.
 
28
 *
 
29
 */
 
30
 
 
31
/**
 
32
 * @details
 
33
 *
 
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. 
 
39
 * 
 
40
 * Locking  
 
41
 *   
 
42
 * Each bucket has a its own lock this allows a search of bucket 1 and bucket 2
 
43
 * to happen concurrently.  
 
44
 *
 
45
 */
 
46
 
 
47
#include "config.h"
 
48
#include <drizzled/plugin.h>
 
49
#include "scoreboard.h"
 
50
 
 
51
#include <math.h>
 
52
 
 
53
using namespace drizzled;
 
54
using namespace std;
 
55
 
 
56
Scoreboard::Scoreboard(uint32_t in_number_sessions, uint32_t in_number_buckets)
 
57
  :
 
58
    number_sessions(in_number_sessions),
 
59
    number_buckets(in_number_buckets)
 
60
{
 
61
 
 
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) ) );
 
64
 
 
65
  /* populate the vector of scoreboard vectors */
 
66
  for (uint32_t j= 0; j < number_buckets; ++j)
 
67
  {
 
68
    vector<ScoreboardSlot* > *scoreboard_vector= new vector<ScoreboardSlot* >();
 
69
 
 
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)
 
73
    {
 
74
      ScoreboardSlot *scoreboard_slot= new ScoreboardSlot();
 
75
      scoreboard_vector_iterator= scoreboard_vector->insert(scoreboard_vector_iterator, scoreboard_slot);
 
76
    }  
 
77
    scoreboard_vector->resize(number_per_bucket);
 
78
 
 
79
 
 
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();
 
83
 
 
84
    vector_of_scoreboard_vectors_iterator= 
 
85
      vector_of_scoreboard_vectors.insert(vector_of_scoreboard_vectors_iterator, scoreboard_vector); 
 
86
  }
 
87
  vector_of_scoreboard_vectors.resize(number_buckets);
 
88
  
 
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)
 
92
  {
 
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);   
 
96
  } 
 
97
  vector_of_scoreboard_locks.resize(number_buckets);
 
98
 
 
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;
 
102
 
 
103
  scoreboard_size_bytes= (statusVarsSize + userCommandsSize) * number_per_bucket * number_buckets;
 
104
}
 
105
 
 
106
Scoreboard::~Scoreboard()
 
107
{
 
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();
 
110
 
 
111
  for (; v_of_scoreboard_v_begin_it != v_of_scoreboard_v_end_it; ++v_of_scoreboard_v_begin_it)
 
112
  {
 
113
    vector<ScoreboardSlot* > *scoreboard_vector= *v_of_scoreboard_v_begin_it; 
 
114
 
 
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)
 
118
    {
 
119
      delete *scoreboard_vector_it; 
 
120
    }
 
121
    
 
122
    scoreboard_vector->clear();
 
123
    delete scoreboard_vector;
 
124
  } // vector_of_scoreboard_vectors is not on the stack and does not deletion
 
125
  
 
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();
 
128
 
 
129
  for (; vector_of_scoreboard_locks_it != vector_of_scoreboard_locks_end; ++vector_of_scoreboard_locks_it)
 
130
  {
 
131
    boost::shared_mutex* lock= *vector_of_scoreboard_locks_it;
 
132
    delete lock;
 
133
  }
 
134
}
 
135
 
 
136
uint32_t Scoreboard::getBucketNumber(Session *session)
 
137
{
 
138
  return (session->getSessionId() % number_buckets);
 
139
}
 
140
 
 
141
ScoreboardSlot* Scoreboard::findScoreboardSlotToLog(Session *session) 
 
142
{
 
143
  /* our bucket */
 
144
  uint32_t bucket_number= getBucketNumber(session);
 
145
 
 
146
  /* our vector corresponding to bucket_number */
 
147
  vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
 
148
 
 
149
  /* Check if this session has already claimed a slot */
 
150
  int32_t session_scoreboard_slot= session->getScoreboardIndex();
 
151
 
 
152
  if (session_scoreboard_slot == -1)
 
153
  {
 
154
    boost::shared_mutex* LOCK_scoreboard_vector= vector_of_scoreboard_locks.at(bucket_number);
 
155
    LOCK_scoreboard_vector->lock();
 
156
 
 
157
    ScoreboardSlot *scoreboard_slot= NULL;
 
158
 
 
159
    int32_t slot_index= 0;
 
160
    for (vector<ScoreboardSlot *>::iterator it= scoreboard_vector->begin();
 
161
         it != scoreboard_vector->end(); ++it, ++slot_index)
 
162
    {
 
163
      scoreboard_slot= *it;
 
164
 
 
165
      if (scoreboard_slot->isInUse() == false)
 
166
      {
 
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; 
 
174
      }
 
175
    }
 
176
  
 
177
    LOCK_scoreboard_vector->unlock(); 
 
178
  } 
 
179
  else // already claimed a slot just do a lookup
 
180
  {
 
181
    ScoreboardSlot *scoreboard_slot= scoreboard_vector->at(session_scoreboard_slot);
 
182
    return scoreboard_slot;  
 
183
  }
 
184
 
 
185
  /* its possible we did not claim a slot if the scoreboard size is somehow smaller then the 
 
186
     active connections */ 
 
187
  return NULL; 
 
188
}
 
189
 
 
190
ScoreboardSlot* Scoreboard::findOurScoreboardSlot(Session *session)
 
191
{
 
192
  /* our bucket */
 
193
  uint32_t bucket_number= getBucketNumber(session);
 
194
 
 
195
  /* our vector corresponding to bucket_number */
 
196
  vector<ScoreboardSlot* > *scoreboard_vector= vector_of_scoreboard_vectors.at(bucket_number);
 
197
 
 
198
  /* Check if this session has already claimed a slot */
 
199
  int32_t session_scoreboard_slot= session->getScoreboardIndex();
 
200
 
 
201
  if (session_scoreboard_slot == -1) 
 
202
  {
 
203
    return NULL;
 
204
  }
 
205
 
 
206
  ScoreboardSlot *scoreboard_slot= scoreboard_vector->at(session_scoreboard_slot);
 
207
  return scoreboard_slot;
 
208
}