00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __XrdThrottleManager_hh_
00021 #define __XrdThrottleManager_hh_
00022
00023 #ifdef __GNUC__
00024 #define likely(x) __builtin_expect(!!(x), 1)
00025 #define unlikely(x) __builtin_expect(!!(x), 0)
00026 #else
00027 #define likely(x) x
00028 #define unlikely(x) x
00029 #endif
00030
00031 #include <string>
00032 #include <vector>
00033 #include <time.h>
00034
00035 #include "XrdSys/XrdSysPthread.hh"
00036
00037 class XrdSysError;
00038 class XrdOucTrace;
00039 class XrdThrottleTimer;
00040
00041 class XrdThrottleManager
00042 {
00043
00044 friend class XrdThrottleTimer;
00045
00046 public:
00047
00048 void Init();
00049
00050 void Apply(int reqsize, int reqops, int uid);
00051
00052 bool IsThrottling() {return (m_ops_per_second > 0) || (m_bytes_per_second > 0);}
00053
00054 void SetThrottles(float reqbyterate, float reqoprate, int concurrency, float interval_length)
00055 {m_interval_length_seconds = interval_length; m_bytes_per_second = reqbyterate;
00056 m_ops_per_second = reqoprate; m_concurrency_limit = concurrency;}
00057
00058 void SetLoadShed(std::string &hostname, unsigned port, unsigned frequency)
00059 {m_loadshed_host = hostname; m_loadshed_port = port; m_loadshed_frequency = frequency;}
00060
00061
00062
00063 static
00064 int GetUid(const char *username);
00065
00066 XrdThrottleTimer StartIOTimer();
00067
00068 void PrepLoadShed(const char *opaque, std::string &lsOpaque);
00069
00070 bool CheckLoadShed(const std::string &opaque);
00071
00072 void PerformLoadShed(const std::string &opaque, std::string &host, unsigned &port);
00073
00074 XrdThrottleManager(XrdSysError *lP, XrdOucTrace *tP);
00075
00076 ~XrdThrottleManager() {}
00077
00078 protected:
00079
00080 void StopIOTimer(struct timespec);
00081
00082 private:
00083
00084 void Recompute();
00085
00086 void RecomputeInternal();
00087
00088 static
00089 void * RecomputeBootstrap(void *pp);
00090
00091 int WaitForShares();
00092
00093 void GetShares(int &shares, int &request);
00094
00095 void StealShares(int uid, int &reqsize, int &reqops);
00096
00097 XrdOucTrace * m_trace;
00098 XrdSysError * m_log;
00099
00100 XrdSysCondVar m_compute_var;
00101
00102
00103 float m_interval_length_seconds;
00104 float m_bytes_per_second;
00105 float m_ops_per_second;
00106 int m_concurrency_limit;
00107
00108
00109 static const
00110 int m_max_users;
00111 std::vector<int> m_primary_bytes_shares;
00112 std::vector<int> m_secondary_bytes_shares;
00113 std::vector<int> m_primary_ops_shares;
00114 std::vector<int> m_secondary_ops_shares;
00115 int m_last_round_allocation;
00116
00117
00118 int m_io_counter;
00119 struct timespec m_io_wait;
00120
00121 int m_stable_io_counter;
00122 struct timespec m_stable_io_wait;
00123
00124
00125 std::string m_loadshed_host;
00126 unsigned m_loadshed_port;
00127 unsigned m_loadshed_frequency;
00128 int m_loadshed_limit_hit;
00129
00130 static const char *TraceID;
00131
00132 };
00133
00134 class XrdThrottleTimer
00135 {
00136
00137 friend class XrdThrottleManager;
00138
00139 public:
00140
00141 void StopTimer()
00142 {
00143 struct timespec end_timer = {0, 0};
00144 #if defined(__linux__)
00145 int retval = clock_gettime(clock_id, &end_timer);
00146 #else
00147 int retval = -1;
00148 #endif
00149 if (likely(retval == 0))
00150 {
00151 end_timer.tv_sec -= m_timer.tv_sec;
00152 end_timer.tv_nsec -= m_timer.tv_nsec;
00153 if (end_timer.tv_nsec < 0)
00154 {
00155 end_timer.tv_sec--;
00156 end_timer.tv_nsec += 1000000000;
00157 }
00158 }
00159 if (m_timer.tv_nsec != -1)
00160 {
00161 m_manager.StopIOTimer(end_timer);
00162 }
00163 m_timer.tv_sec = 0;
00164 m_timer.tv_nsec = -1;
00165 }
00166
00167 ~XrdThrottleTimer()
00168 {
00169 if (!((m_timer.tv_sec == 0) && (m_timer.tv_nsec == -1)))
00170 {
00171 StopTimer();
00172 }
00173 }
00174
00175 protected:
00176
00177 XrdThrottleTimer(XrdThrottleManager & manager) :
00178 m_manager(manager)
00179 {
00180 #if defined(__linux__)
00181 int retval = clock_gettime(clock_id, &m_timer);
00182 #else
00183 int retval = -1;
00184 #endif
00185 if (unlikely(retval == -1))
00186 {
00187 m_timer.tv_sec = 0;
00188 m_timer.tv_nsec = 0;
00189 }
00190 }
00191
00192 private:
00193 XrdThrottleManager &m_manager;
00194 struct timespec m_timer;
00195
00196 static int clock_id;
00197 };
00198
00199 #endif