XRootD
Loading...
Searching...
No Matches
XrdSsiScale.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S s i S c a l e . c c */
4/* */
5/* (c) 2020 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cstdio>
31
32#include "XrdSsi/XrdSsiScale.hh"
33#include "XrdSys/XrdSysError.hh"
34
35/******************************************************************************/
36/* G l o b a l s */
37/******************************************************************************/
38
39namespace XrdSsi
40{
41extern XrdSysError Log;
42}
43
44using namespace XrdSsi;
45
46/******************************************************************************/
47/* g e t E n t */
48/******************************************************************************/
49
51{
52 static const int tuneMLen = 80;
53 char tuneMsg[tuneMLen]; *tuneMsg = 0;
54
55// We assign channel in a round-robbin fashion. This can be across all
56// channels or only the subset that was recently added due to tuning. Note
57// that we apply tuning only if we are working in the partitioned channels
58// as the non-partitioned channels should no longer be getting requests.
59//
60 entMutex.Lock();
61 uint16_t endEnt = curSpread;
62 do {for (uint16_t i = nowEnt; i < endEnt; i++)
63 {if (pendCnt[i] < maxPend)
64 {pendCnt[i]++;
65 nowEnt = i+1;
66 if (!begEnt || i < begEnt) Active++;
67 else reActive++;
68 entMutex.UnLock();
69 if (*tuneMsg) Log.Emsg("Scale", tuneMsg);
70 return int(i);
71 }
72 }
73
74 // If we did a whole round and cannot autotune up, then we have failed.
75 // If we didn't do the whole round or did tune, try again.
76 //
77 if (nowEnt == begEnt)
78 {if (!autoTune || !Tune(tuneMsg, tuneMLen)) break;
79 endEnt = curSpread;
80 } else endEnt = nowEnt;
81 nowEnt = begEnt;
82 } while(true);
83
84// We have no more stream resources left.
85//
86 entMutex.UnLock();
87 if (*tuneMsg) Log.Emsg("Scale", tuneMsg);
88 return -1;
89}
90
91/******************************************************************************/
92/* r e t E n t */
93/******************************************************************************/
94
95void XrdSsiScale::retEnt(int xEnt)
96{
97
98// Perform action only if the specified channel is valid. Retune the channels
99// if necessary.
100//
101 if (xEnt >= 0 && xEnt < int(maxSprd))
102 {entMutex.Lock();
103 if (pendCnt[xEnt])
104 {pendCnt[xEnt]--;
105 if (!begEnt || xEnt < (int)begEnt)
106 {if (Active) Active--;
107 if (begEnt && needTune && Active <= (reActive + (reActive>>1)))
108 {Retune(); // Unlocks the entMutex!
109 return;
110 }
111 } else if (reActive) reActive--;
112 }
113 }
114
115// Unlock the mutex as we are done.
116//
117 entMutex.UnLock();
118}
119
120/******************************************************************************/
121/* private: R e t u n e */
122/******************************************************************************/
123
124void XrdSsiScale::Retune() // entMutex must be held is it released upon return!
125{
126
127// We only want to be called once per expansion.
128//
129 needTune = false;
130
131// We combine the partioned the channel set with the previous set to increase
132// to total available spread.
133//
134 if (begEnt)
135 {uint32_t totReq = Active + reActive, spread = curSpread;
136 char buff[80];
137 Active = totReq;
138 reActive = 0;
139 begEnt = 0;
140
141 // Issue message about this (don't want to hold the mutex for the msg).
142 //
143 entMutex.UnLock();
144 snprintf(buff, sizeof(buff), "retune %u requests; spread %u",
145 totReq, spread);
146 Log.Emsg("Scale", buff);
147 } else entMutex.UnLock();
148}
149
150/******************************************************************************/
151/* r s v E n t */
152/******************************************************************************/
153
155{
156
157// If the channel number is within range see if we can reserve a slot.
158//
159 if (xEnt >= 0 && xEnt < int(maxSprd))
160 {entMutex.Lock();
161 if (pendCnt[xEnt] < maxPend)
162 {pendCnt[xEnt]++;
163 entMutex.UnLock();
164 return true;
165 }
166 entMutex.UnLock();
167 }
168 return false;
169}
170
171/******************************************************************************/
172/* s e t S p r e a d */
173/******************************************************************************/
174
176{
177 entMutex.Lock();
178
179 if (sval <= 0)
180 {autoTune = true;
181 if (sval < 0) sval = -sval;
182 } else {
183 autoTune = needTune = false;
184 begEnt = 0;
185 }
186
187 if (sval)
188 {uint16_t newSpread;
189 if (sval < short(maxSprd)) newSpread = static_cast<uint16_t>(sval);
190 else newSpread = maxSprd;
191 if (autoTune && newSpread < curSpread)
192 {needTune = false;
193 begEnt = 0;
194 }
195 curSpread = newSpread;
196 }
197
198 entMutex.UnLock();
199}
200
201/******************************************************************************/
202/* Private: T u n e */
203/******************************************************************************/
204
205bool XrdSsiScale::Tune(char *buff, int blen) // entMutex must be held!
206{
207 uint16_t n;
208
209// We can only tune up the maximum allowed.
210//
211 if (curSpread >= maxSprd)
212 {begEnt = 0;
213 autoTune = needTune = false;
214 return false;
215 }
216
217// Compute the number of additional channels we should have. This number
218// doubles up until midTune at which point it grows linearly with one bump.
219//
220 if (curSpread < midTune) n = curSpread << 1;
221 else if (curSpread < zipTune) n = curSpread + midTune;
222 else n = curSpread + maxTune;
223
224// If we topped out and we do not have enough new channels then turn auto
225// tuning off and let it rip as it doesn't matter at this point.
226//
227 needTune = true;
228 if (n <= maxSprd) nowEnt = begEnt = curSpread;
229 else {if ((curSpread - maxSprd) < minTune)
230 {begEnt = 0;
231 autoTune = needTune = false;
232 }
233 n = maxSprd;
234 }
235
236// Adjust values to correspond to the new reality
237//
238 curSpread = n;
239 Active += reActive;
240 reActive = 0;
241
242// Document what happened. The caller displays the message when mutex unlocked.
243//
244 snprintf(buff, blen, "tune %u requests; spread %u/%u", Active, n-begEnt, n);
245 return true;
246}
static const uint16_t maxSprd
static const uint16_t zipTune
void setSpread(short sval)
static const uint16_t maxPend
static const uint16_t midTune
static const uint16_t maxTune
bool rsvEnt(int xEnt)
static const uint16_t minTune
void retEnt(int xEnt)
XrdSysError Log