MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TimeQueue.cpp
1 /*
2  Copyright (C) 2003, 2005, 2006 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "TimeQueue.hpp"
20 #include <ErrorHandlingMacros.hpp>
21 #include <GlobalData.hpp>
22 #include <FastScheduler.hpp>
23 #include <VMSignal.hpp>
24 
25 static const int MAX_TIME_QUEUE_VALUE = 32000;
26 
27 TimeQueue::TimeQueue()
28 {
29  clear();
30 }
31 
32 TimeQueue::~TimeQueue()
33 {
34 }
35 
36 void
37 TimeQueue::clear()
38 {
39  globalData.theNextTimerJob = 65535;
40  globalData.theCurrentTimer = 0;
41  globalData.theShortTQIndex = 0;
42  globalData.theLongTQIndex = 0;
43  for (int i = 0; i < MAX_NO_OF_TQ; i++)
44  theFreeIndex[i] = i+1;
45  theFreeIndex[MAX_NO_OF_TQ - 1] = NULL_TQ_ENTRY;
46  globalData.theFirstFreeTQIndex = 0;
47 }
48 
49 void
50 TimeQueue::insert(Signal* signal, BlockNumber bnr,
51  GlobalSignalNumber gsn, Uint32 delayTime)
52 {
53  if (delayTime == 0)
54  delayTime = 1;
55  register Uint32 regCurrentTime = globalData.theCurrentTimer;
56  register Uint32 i;
57  register Uint32 regSave;
58  register TimerEntry newEntry;
59 
60  newEntry.time_struct.delay_time = regCurrentTime + delayTime;
61  newEntry.time_struct.job_index = getIndex();
62  regSave = newEntry.copy_struct;
63 
64  globalScheduler.insertTimeQueue(signal, bnr, gsn,
65  newEntry.time_struct.job_index);
66 
67  if (newEntry.time_struct.delay_time < globalData.theNextTimerJob)
68  globalData.theNextTimerJob = newEntry.time_struct.delay_time;
69  if (delayTime < 100){
70  register Uint32 regShortIndex = globalData.theShortTQIndex;
71  if (regShortIndex == 0){
72  theShortQueue[0].copy_struct = newEntry.copy_struct;
73  } else if (regShortIndex >= MAX_NO_OF_SHORT_TQ - 1) {
74  ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_SHORT,
75  "Too many in Short Time Queue", "TimeQueue.C" );
76  } else {
77  for (i = 0; i < regShortIndex; i++) {
78  if (theShortQueue[i].time_struct.delay_time >
79  newEntry.time_struct.delay_time) {
80 
81  regSave = theShortQueue[i].copy_struct;
82  theShortQueue[i].copy_struct = newEntry.copy_struct;
83  break;
84  }
85  }
86  if (i == regShortIndex) {
87  theShortQueue[regShortIndex].copy_struct = regSave;
88  } else {
89  for (i++; i < regShortIndex; i++) {
90  register Uint32 regTmp = theShortQueue[i].copy_struct;
91  theShortQueue[i].copy_struct = regSave;
92  regSave = regTmp;
93  }
94  theShortQueue[regShortIndex].copy_struct = regSave;
95  }
96  }
97  globalData.theShortTQIndex = regShortIndex + 1;
98  } else if (delayTime <= (unsigned)MAX_TIME_QUEUE_VALUE) {
99  register Uint32 regLongIndex = globalData.theLongTQIndex;
100  if (regLongIndex == 0) {
101  theLongQueue[0].copy_struct = newEntry.copy_struct;
102  } else if (regLongIndex >= MAX_NO_OF_LONG_TQ - 1) {
103  ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_LONG,
104  "Too many in Long Time Queue", "TimeQueue.C" );
105  } else {
106  for (i = 0; i < regLongIndex; i++) {
107  if (theLongQueue[i].time_struct.delay_time >
108  newEntry.time_struct.delay_time) {
109 
110  regSave = theLongQueue[i].copy_struct;
111  theLongQueue[i].copy_struct = newEntry.copy_struct;
112  break;
113  }
114  }
115  if (i == regLongIndex) {
116  theLongQueue[regLongIndex].copy_struct = regSave;
117  } else {
118  for (i++; i < regLongIndex; i++) {
119  register Uint32 regTmp = theLongQueue[i].copy_struct;
120  theLongQueue[i].copy_struct = regSave;
121  regSave = regTmp;
122  }
123  theLongQueue[regLongIndex].copy_struct = regSave;
124  }
125  }
126  globalData.theLongTQIndex = regLongIndex + 1;
127  } else {
128  ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_DELAY,
129  "Too long delay for Time Queue", "TimeQueue.C" );
130  }
131 }
132 
133 // executes the expired signals;
134 void
135 TimeQueue::scanTable()
136 {
137  register Uint32 i, j;
138 
139  globalData.theCurrentTimer++;
140  if (globalData.theCurrentTimer == 32000)
141  recount_timers();
142  if (globalData.theNextTimerJob > globalData.theCurrentTimer)
143  return;
144  globalData.theNextTimerJob = 65535; // If no more timer jobs
145  for (i = 0; i < globalData.theShortTQIndex; i++) {
146  if (theShortQueue[i].time_struct.delay_time > globalData.theCurrentTimer){
147  break;
148  } else {
149  releaseIndex((Uint32)theShortQueue[i].time_struct.job_index);
150  globalScheduler.scheduleTimeQueue(theShortQueue[i].time_struct.job_index);
151  }
152  }
153  if (i > 0) {
154  for (j = i; j < globalData.theShortTQIndex; j++)
155  theShortQueue[j - i].copy_struct = theShortQueue[j].copy_struct;
156  globalData.theShortTQIndex -= i;
157  }
158  if (globalData.theShortTQIndex != 0) // If not empty
159  globalData.theNextTimerJob = theShortQueue[0].time_struct.delay_time;
160  for (i = 0; i < globalData.theLongTQIndex; i++) {
161  if (theLongQueue[i].time_struct.delay_time > globalData.theCurrentTimer) {
162  break;
163  } else {
164  releaseIndex((Uint32)theLongQueue[i].time_struct.job_index);
165  globalScheduler.scheduleTimeQueue(theLongQueue[i].time_struct.job_index);
166  }
167  }
168  if (i > 0) {
169  for (j = i; j < globalData.theLongTQIndex; j++)
170  theLongQueue[j - i].copy_struct = theLongQueue[j].copy_struct;
171  globalData.theLongTQIndex -= i;
172  }
173  if (globalData.theLongTQIndex != 0) // If not empty
174  if (globalData.theNextTimerJob > theLongQueue[0].time_struct.delay_time)
175  globalData.theNextTimerJob = theLongQueue[0].time_struct.delay_time;
176 }
177 
178 void
179 TimeQueue::recount_timers()
180 {
181  Uint32 i;
182 
183  globalData.theCurrentTimer = 0;
184  globalData.theNextTimerJob -= 32000;
185 
186  for (i = 0; i < globalData.theShortTQIndex; i++)
187  theShortQueue[i].time_struct.delay_time -= 32000;
188  for (i = 0; i < globalData.theLongTQIndex; i++)
189  theLongQueue[i].time_struct.delay_time -= 32000;
190 }
191 
192 Uint32
193 TimeQueue::getIndex()
194 {
195  Uint32 retValue = globalData.theFirstFreeTQIndex;
196  globalData.theFirstFreeTQIndex = (Uint32)theFreeIndex[retValue];
197  if (retValue >= MAX_NO_OF_TQ)
198  ERROR_SET(fatal, NDBD_EXIT_TIME_QUEUE_INDEX,
199  "Index out of range", "TimeQueue.C" );
200  return retValue;
201 }
202 
203 void
204 TimeQueue::releaseIndex(Uint32 aIndex)
205 {
206  theFreeIndex[aIndex] = globalData.theFirstFreeTQIndex;
207  globalData.theFirstFreeTQIndex = aIndex;
208 }
209 
210