XRootD
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 
39 namespace XrdSsi
40 {
41 extern XrdSysError Log;
42 }
43 
44 using 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 
95 void 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 
124 void 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 
154 bool XrdSsiScale::rsvEnt(int xEnt)
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 
175 void XrdSsiScale::setSpread(short sval)
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 
205 bool 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 }
void setSpread(short sval)
Definition: XrdSsiScale.cc:175
int getEnt()
Definition: XrdSsiScale.cc:50
bool rsvEnt(int xEnt)
Definition: XrdSsiScale.cc:154
void retEnt(int xEnt)
Definition: XrdSsiScale.cc:95
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdSysError Log