Skip to content

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 {