Deprecated
This page is deprecated and may contain information that is no longer up to date.
Implementation¶
The main business logic of the rate limiting mechanism of the EOS MGM is implemented by the following C++ macro:
vi eos/mgm/Macros.hh
...
79 //------------------------------------------------------------------------------
80 //! Stall Macro
81 //------------------------------------------------------------------------------
82 #define MAYSTALL eos::mgm::InFlightRegistration tracker_helper(gOFS->mTracker); \
83 if (gOFS->IsStall) { \
84 XrdOucString stallmsg=""; \
85 int stalltime=0; \
86 if (gOFS->ShouldStall(__FUNCTION__,__AccessMode__, vid, stalltime, stallmsg)) { \
87 if (stalltime) { \
88 return gOFS->Stall(error,stalltime, stallmsg.c_str()); \
89 } else { \
90 return gOFS->Emsg("maystall", error, EPERM, stallmsg.c_str(), ""); \
91 } \
92 } else { \
93 if (!tracker_helper.IsOK()) { \
94 stallmsg="track request, stall the client 5 seconds"; \
95 stalltime = 5; \
96 return gOFS->Stall(error,stalltime, stallmsg.c_str()); \
97 } \
98 } \
99 }
This macro is called at strategic points throughout the EOS MGM code. For example the following code snippet calls the macro when a user has just opened a file:
vi eos/mgm/XrdMgmOfsFile.cc
...
186 /*----------------------------------------------------------------------------*/
187 int
188 XrdMgmOfsFile::open(eos::common::VirtualIdentity* invid,
189 const char* inpath,
190 XrdSfsFileOpenMode open_mode,
191 mode_t Mode,
192 const XrdSecEntity* client,
193 const char* ininfo)
...
349 if (ProcInterface::IsWriteAccess(path, pinfo.c_str())) {
350 SET_ACCESSMODE_W;
351 }
352
353 MAYSTALL;
354 MAYREDIRECT;
The MAYSTALL
macro calls the ShouldStall()
method. The following code
snippet shows that the method stalls the current operation if it finds any
rate:user:*
limit rule that has been exceeded. The method does not
take into account the type of the current operation. The length of the
stall is 5 seconds plus a random number of seconds between 0 and 6.
vi eos/mgm/XrdMgmOfs/ShouldStall.cc
...
31 bool
32 XrdMgmOfs::ShouldStall(const char* function,
33 int __AccessMode__,
34 eos::common::VirtualIdentity& vid,
35 int& stalltime, XrdOucString& stallmsg)
36 {
...
106 } else if (Access::gStallUserGroup) {
107 std::string usermatch = "rate:user:";
108 usermatch += vid.uid_string;
109 std::string groupmatch = "rate:group:";
110 groupmatch += vid.gid_string;
111 std::string userwildcardmatch = "rate:user:*";
...
115 for (it = Access::gStallRules.begin();
116 it != Access::gStallRules.end();
117 it++) {
118 std::string cmd = it->first.substr(it->first.rfind(":") + 1);
119 double cutoff = strtod(it->second.c_str(), 0) * 1.33;
120
121 if ((it->first.find(userwildcardmatch) == 0)) {
122 // catch all rule = global user rate cut
123 XrdSysMutexHelper statLock(gOFS->MgmStats.mMutex);
124
125 if (gOFS->MgmStats.StatAvgUid.count(cmd) &&
126 gOFS->MgmStats.StatAvgUid[cmd].count(vid.uid) &&
127 (gOFS->MgmStats.StatAvgUid[cmd][vid.uid].GetAvg5() > cutoff)) {
128 if (!stalltime) {
129 stalltime = 5;
130 }
131 smsg = Access::gStallComment[it->first];
132 }
133 } else if ((it->first.find(groupwildcardmatch) == 0)) {
...
171 if (stalltime) {
172 // add random offset between 0 and 5 to stalltime
173 int random_stall = rand() % 6;
174 stalltime += random_stall;
175
176 stallmsg = "Attention: you are currently hold in this instance and each"
177 " request is stalled for ";
178 stallmsg += (int) stalltime;
179 stallmsg += " seconds ... ";
180 stallmsg += smsg.c_str();
181 eos_static_info("info=\"stalling access to\" uid=%u gid=%u host=%s stall=%d",
182 vid.uid, vid.gid, vid.host.c_str(), stalltime);
183 gOFS->MgmStats.Add("Stall", vid.uid, vid.gid, 1);
184 return true;
185 }
186 } else {