1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include "TimeQueue.hpp"
17
#include <ErrorHandlingMacros.hpp>
18
#include <GlobalData.hpp>
19
#include <FastScheduler.hpp>
20
#include <VMSignal.hpp>
22
static const int MAX_TIME_QUEUE_VALUE = 32000;
24
TimeQueue::TimeQueue()
29
TimeQueue::~TimeQueue()
36
globalData.theNextTimerJob = 65535;
37
globalData.theCurrentTimer = 0;
38
globalData.theShortTQIndex = 0;
39
globalData.theLongTQIndex = 0;
40
for (int i = 0; i < MAX_NO_OF_TQ; i++)
41
theFreeIndex[i] = i+1;
42
theFreeIndex[MAX_NO_OF_TQ - 1] = NULL_TQ_ENTRY;
43
globalData.theFirstFreeTQIndex = 0;
47
TimeQueue::insert(Signal* signal, BlockNumber bnr,
48
GlobalSignalNumber gsn, Uint32 delayTime)
52
register Uint32 regCurrentTime = globalData.theCurrentTimer;
54
register Uint32 regSave;
55
register TimerEntry newEntry;
57
newEntry.time_struct.delay_time = regCurrentTime + delayTime;
58
newEntry.time_struct.job_index = getIndex();
59
regSave = newEntry.copy_struct;
61
globalScheduler.insertTimeQueue(signal, bnr, gsn,
62
newEntry.time_struct.job_index);
64
if (newEntry.time_struct.delay_time < globalData.theNextTimerJob)
65
globalData.theNextTimerJob = newEntry.time_struct.delay_time;
67
register Uint32 regShortIndex = globalData.theShortTQIndex;
68
if (regShortIndex == 0){
69
theShortQueue[0].copy_struct = newEntry.copy_struct;
70
} else if (regShortIndex >= MAX_NO_OF_SHORT_TQ - 1) {
71
ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_SHORT,
72
"Too many in Short Time Queue", "TimeQueue.C" );
74
for (i = 0; i < regShortIndex; i++) {
75
if (theShortQueue[i].time_struct.delay_time >
76
newEntry.time_struct.delay_time) {
78
regSave = theShortQueue[i].copy_struct;
79
theShortQueue[i].copy_struct = newEntry.copy_struct;
83
if (i == regShortIndex) {
84
theShortQueue[regShortIndex].copy_struct = regSave;
86
for (i++; i < regShortIndex; i++) {
87
register Uint32 regTmp = theShortQueue[i].copy_struct;
88
theShortQueue[i].copy_struct = regSave;
91
theShortQueue[regShortIndex].copy_struct = regSave;
94
globalData.theShortTQIndex = regShortIndex + 1;
95
} else if (delayTime <= (unsigned)MAX_TIME_QUEUE_VALUE) {
96
register Uint32 regLongIndex = globalData.theLongTQIndex;
97
if (regLongIndex == 0) {
98
theLongQueue[0].copy_struct = newEntry.copy_struct;
99
} else if (regLongIndex >= MAX_NO_OF_LONG_TQ - 1) {
100
ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_LONG,
101
"Too many in Long Time Queue", "TimeQueue.C" );
103
for (i = 0; i < regLongIndex; i++) {
104
if (theLongQueue[i].time_struct.delay_time >
105
newEntry.time_struct.delay_time) {
107
regSave = theLongQueue[i].copy_struct;
108
theLongQueue[i].copy_struct = newEntry.copy_struct;
112
if (i == regLongIndex) {
113
theLongQueue[regLongIndex].copy_struct = regSave;
115
for (i++; i < regLongIndex; i++) {
116
register Uint32 regTmp = theLongQueue[i].copy_struct;
117
theLongQueue[i].copy_struct = regSave;
120
theLongQueue[regLongIndex].copy_struct = regSave;
123
globalData.theLongTQIndex = regLongIndex + 1;
125
ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_DELAY,
126
"Too long delay for Time Queue", "TimeQueue.C" );
130
// executes the expired signals;
132
TimeQueue::scanTable()
134
register Uint32 i, j;
136
globalData.theCurrentTimer++;
137
if (globalData.theCurrentTimer == 32000)
139
if (globalData.theNextTimerJob > globalData.theCurrentTimer)
141
globalData.theNextTimerJob = 65535; // If no more timer jobs
142
for (i = 0; i < globalData.theShortTQIndex; i++) {
143
if (theShortQueue[i].time_struct.delay_time > globalData.theCurrentTimer){
146
releaseIndex((Uint32)theShortQueue[i].time_struct.job_index);
147
globalScheduler.scheduleTimeQueue(theShortQueue[i].time_struct.job_index);
151
for (j = i; j < globalData.theShortTQIndex; j++)
152
theShortQueue[j - i].copy_struct = theShortQueue[j].copy_struct;
153
globalData.theShortTQIndex -= i;
155
if (globalData.theShortTQIndex != 0) // If not empty
156
globalData.theNextTimerJob = theShortQueue[0].time_struct.delay_time;
157
for (i = 0; i < globalData.theLongTQIndex; i++) {
158
if (theLongQueue[i].time_struct.delay_time > globalData.theCurrentTimer) {
161
releaseIndex((Uint32)theLongQueue[i].time_struct.job_index);
162
globalScheduler.scheduleTimeQueue(theLongQueue[i].time_struct.job_index);
166
for (j = i; j < globalData.theLongTQIndex; j++)
167
theLongQueue[j - i].copy_struct = theLongQueue[j].copy_struct;
168
globalData.theLongTQIndex -= i;
170
if (globalData.theLongTQIndex != 0) // If not empty
171
if (globalData.theNextTimerJob > theLongQueue[0].time_struct.delay_time)
172
globalData.theNextTimerJob = theLongQueue[0].time_struct.delay_time;
176
TimeQueue::recount_timers()
180
globalData.theCurrentTimer = 0;
181
globalData.theNextTimerJob -= 32000;
183
for (i = 0; i < globalData.theShortTQIndex; i++)
184
theShortQueue[i].time_struct.delay_time -= 32000;
185
for (i = 0; i < globalData.theLongTQIndex; i++)
186
theLongQueue[i].time_struct.delay_time -= 32000;
190
TimeQueue::getIndex()
192
Uint32 retValue = globalData.theFirstFreeTQIndex;
193
globalData.theFirstFreeTQIndex = (Uint32)theFreeIndex[retValue];
194
if (retValue >= MAX_NO_OF_TQ)
195
ERROR_SET(fatal, NDBD_EXIT_TIME_QUEUE_INDEX,
196
"Index out of range", "TimeQueue.C" );
201
TimeQueue::releaseIndex(Uint32 aIndex)
203
theFreeIndex[aIndex] = globalData.theFirstFreeTQIndex;
204
globalData.theFirstFreeTQIndex = aIndex;