00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdClientReadAheadCVSID = "$Id: XrdClientReadAhead.cc 30949 2009-11-02 16:37:58Z ganis $";
00014
00015 #include "XrdClientReadAhead.hh"
00016 #include "XrdClientConst.hh"
00017 #include "XrdClientVector.hh"
00018
00019
00020
00021 bool XrdClientReadAheadMgr::TrimReadRequest(long long &offs, long &len, long rasize, long blksz) {
00022
00023 if (!blksz) return true;
00024
00025 long long newoffs;
00026 long newlen;
00027
00028 long long lastbyte;
00029
00030 newoffs = (long long)(offs / blksz);
00031 newoffs *= blksz;
00032
00033 lastbyte = offs+len+blksz-1;
00034 lastbyte = (long long)(lastbyte / blksz);
00035 lastbyte *= blksz;
00036
00037 newlen = lastbyte-newoffs;
00038
00039
00040 offs = newoffs;
00041 len = newlen;
00042 return true;
00043
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 class XrdClientReadAhead_pureseq : public XrdClientReadAheadMgr {
00059
00060 protected:
00061 long long RALast;
00062
00063 public:
00064
00065 XrdClientReadAhead_pureseq() {
00066 RALast = 0;
00067 }
00068
00069 virtual int GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz);
00070
00071 virtual int Reset() {
00072 RALast = 0;
00073 return 0;
00074 }
00075
00076 };
00077
00078
00079
00080
00081
00082 int XrdClientReadAhead_pureseq::GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz) {
00083
00084 if (!blksz) blksz = 128*1024;
00085
00086
00087 if ( (RALast - (offset+len) < RASize) &&
00088 (RALast - (offset+len) > -RASize) &&
00089 (RASize > 0) ) {
00090
00091
00092
00093
00094 raoffset = xrdmax(RALast, offset + len);
00095 ralen = xrdmin(RASize,
00096 offset + len + RASize - raoffset);
00097
00098 if (ralen > 0) {
00099 TrimReadRequest(raoffset, ralen, RASize, blksz);
00100 RALast = raoffset + ralen;
00101 return 0;
00102 }
00103 }
00104
00105 return 1;
00106
00107 };
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 class XrdClientReadAhead_slidingavg : public XrdClientReadAheadMgr {
00120
00121 protected:
00122 long long RALast;
00123
00124 long long LastOffsSum, LastOffsSum2;
00125 long long LastOffsSumsq, LastOffsSumsq2;
00126 XrdClientVector<long long> LastOffs;
00127 XrdClientVector<long long> LastAvgApprox, LastAvgApprox2;
00128 public:
00129
00130 XrdClientReadAhead_slidingavg() {
00131 RALast = 0;
00132 LastOffsSum = LastOffsSum2 = 0;
00133 LastOffsSumsq = LastOffsSumsq2 = 0;
00134
00135
00136 }
00137
00138 virtual int GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz);
00139
00140 virtual int Reset() {
00141 RALast = 0;
00142 LastOffsSum = LastOffsSum2 = 0;
00143 LastOffsSumsq = LastOffsSumsq2 = 0;
00144 return 0;
00145 }
00146
00147 };
00148
00149
00150
00151
00152
00153 int XrdClientReadAhead_slidingavg::GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz) {
00154
00155 if (!blksz) blksz = 128*1024;
00156
00157
00158 LastOffsSum += offset;
00159 LastOffsSum2 += offset;
00160 LastOffs.Push_back(offset);
00161
00162 if (LastOffs.GetSize() >= 50) {
00163 LastOffsSum2 -= LastOffs[LastOffs.GetSize()-50];
00164 }
00165 if (LastOffs.GetSize() >= 1000) {
00166 LastOffsSum -= LastOffs[0];
00167 }
00168
00169 long long lastavg = LastOffsSum / LastOffs.GetSize();
00170 long long lastavg2 = LastOffsSum2 / xrdmin(LastOffs.GetSize(), 50);
00171
00172
00173
00174 long long sqerr = (((offset >> 20) - (lastavg >> 20))*((offset >> 20) - (lastavg >> 20)));
00175 LastOffsSumsq += sqerr;
00176 long long sqerr2 = ( ((offset - lastavg2) >> 20) * ((offset - lastavg2) >> 20) );
00177 LastOffsSumsq2 += sqerr2;
00178
00179 LastAvgApprox.Push_back(sqerr);
00180 LastAvgApprox2.Push_back(sqerr2);
00181
00182 if (LastAvgApprox2.GetSize() >= 50) {
00183 LastOffsSumsq2 -= LastAvgApprox2[0];
00184 LastAvgApprox2.Erase(0);
00185 }
00186
00187 if (LastAvgApprox.GetSize() >= 1000) {
00188 LastOffsSumsq -= LastAvgApprox[0];
00189 LastAvgApprox.Erase(0);
00190 }
00191
00192 if (LastOffs.GetSize() >= 1000) {
00193 LastOffs.Erase(0);
00194 }
00195
00196 long long stddevi = LastOffsSumsq / LastOffs.GetSize();
00197 long long stddevi2 = LastOffsSumsq2 / LastAvgApprox2.GetSize();
00198
00199
00200
00201
00202
00203
00204
00205 if ((stddevi << 20) < 3*RASize) {
00206 raoffset = xrdmax(RALast, lastavg - RASize/2);
00207
00208 ralen = xrdmin(RASize,
00209 lastavg + RASize/2 - raoffset);
00210
00211 if (ralen > (1024*1024)) {
00212 TrimReadRequest(raoffset, ralen, RASize, blksz);
00213 RALast = raoffset + ralen;
00214
00215 return 0;
00216 }
00217
00218 } else
00219
00220 if ((stddevi2 << 20) < 3*RASize) {
00221 raoffset = xrdmax(RALast, lastavg2 - RASize/2);
00222
00223 ralen = xrdmin(RASize,
00224 lastavg2 + RASize/2 - raoffset);
00225
00226
00227 if (ralen > (1024*1024)) {
00228 TrimReadRequest(raoffset, ralen, RASize, blksz);
00229 RALast = raoffset + ralen;
00230
00231 return 0;
00232 }
00233
00234 }
00235
00236
00237 return 1;
00238
00239
00240 };
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 XrdClientReadAheadMgr *XrdClientReadAheadMgr::CreateReadAheadMgr(XrdClient_RAStrategy strategy) {
00255 XrdClientReadAheadMgr *ramgr = 0;
00256
00257 switch (strategy) {
00258
00259 case RAStr_none:
00260 break;
00261
00262 case RAStr_pureseq: {
00263 ramgr = new XrdClientReadAhead_pureseq();
00264 break;
00265 }
00266 case RAStr_SlidingAvg: {
00267 ramgr = new XrdClientReadAhead_slidingavg();
00268 break;
00269 }
00270
00271 }
00272
00273 if (ramgr) ramgr->currstrategy = strategy;
00274 return ramgr;
00275 }