XrdClientSid.cc

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////
00002 //                                                                      //
00003 // XrdClientMessage                                                     //
00004 //                                                                      //
00005 // Author: Fabrizio Furano (INFN Padova, 2005)                          //
00006 //                                                                      //
00007 // Utility classes to handle the mapping between xrootd streamids.      //
00008 //  A single streamid can have multiple "parallel" streamids.           //
00009 //  Their use is typically to support the client to submit multiple     //
00010 // parallel requests (belonging to the same LogConnectionID),           //
00011 // which are to be processed asynchronously when the answers arrive.    //
00012 //                                                                      //
00013 ////////////////////////////////////////////////////////////////////////// 
00014 
00015 
00016 //       $Id: XrdClientSid.cc 30949 2009-11-02 16:37:58Z ganis $
00017 
00018 const char *XrdClientSidCVSID = "$Id: XrdClientSid.cc 30949 2009-11-02 16:37:58Z ganis $";
00019 
00020 
00021 #include "XrdClient/XrdClientSid.hh"
00022 #include "XrdClient/XrdClientEnv.hh"
00023 #include "XrdClient/XrdClientConst.hh"
00024 
00025 XrdClientSid::XrdClientSid() {
00026 
00027    freesids.Resize(65536);
00028 
00029    // We populate the free sids queue
00030    for (kXR_unt16 i = 65535; i >= 1; i--)
00031       freesids.Push_back(i);
00032 }
00033 
00034 XrdClientSid::~XrdClientSid() {
00035    freesids.Clear();
00036    childsidnfo.Purge();
00037 
00038 }
00039 
00040 
00041 // Gets an available sid
00042 // From now on it will be no more available.
00043 // A retval of 0 means that there are no more available sids
00044 kXR_unt16 XrdClientSid::GetNewSid() {
00045    XrdSysMutexHelper l(fMutex);
00046 
00047    if (!freesids.GetSize()) return 0;
00048       
00049    return (freesids.Pop_back());
00050 
00051 };
00052 
00053 // Gets an available sid for a request which is to be outstanding
00054 // This means that this sid will be inserted into the Rash
00055 // The request gets inserted the new sid in the right place
00056 // Also the one passed as parameter gets the new sid, as should be expected
00057 kXR_unt16 XrdClientSid::GetNewSid(kXR_unt16 sid, ClientRequest *req) {
00058   XrdSysMutexHelper l(fMutex);
00059 
00060   if (!freesids.GetSize()) return 0;
00061       
00062   kXR_unt16 nsid = freesids.Pop_back();
00063   
00064   if (nsid) {
00065     struct SidInfo si;
00066     
00067     memcpy(req->header.streamid, &nsid, sizeof(req->header.streamid));
00068 
00069     si.fathersid = sid;
00070     si.outstandingreq = *req;
00071     si.reqbyteprogress = 0;
00072     si.sendtime = time(0);
00073 
00074     si.rspstatuscode = 0;
00075     si.rsperrno = kXR_noErrorYet;
00076     si.rsperrmsg = 0;
00077 
00078     childsidnfo.Add(nsid, si);
00079   }
00080   
00081   
00082   
00083   return nsid;
00084   
00085 };
00086 
00087 // Report the response for an outstanding request
00088 // Typically this is used to keep track of the received errors, expecially
00089 // for async writes
00090 void XrdClientSid::ReportSidResp(kXR_unt16 sid, kXR_unt16 statuscode, kXR_unt32 errcode, char *errmsg) {
00091   XrdSysMutexHelper l(fMutex);
00092   struct SidInfo *si = childsidnfo.Find(sid);
00093   
00094   if (si) {
00095      si->rspstatuscode = statuscode;
00096      si->rsperrno = errcode;
00097      if (si->rsperrmsg) free(si->rsperrmsg);
00098 
00099      if (errmsg) si->rsperrmsg = strdup(errmsg);
00100      else si->rsperrmsg = 0;
00101   }
00102     
00103 };
00104 
00105 // Releases a sid.
00106 // It is re-inserted into the available set
00107 // Its info is rmeoved from the tree
00108 void XrdClientSid::ReleaseSid(kXR_unt16 sid) {
00109    XrdSysMutexHelper l(fMutex);
00110 
00111    childsidnfo.Del(sid);
00112    freesids.Push_back(sid);
00113 };
00114 
00115 
00116 
00117 //_____________________________________________________________________________
00118 struct ReleaseSidTreeItem_data {
00119   kXR_unt16 fathersid;
00120   XrdClientVector<kXR_unt16> *freesids;
00121 };
00122 int ReleaseSidTreeItem(kXR_unt16 key,
00123                        struct SidInfo si, void *arg) {
00124 
00125   ReleaseSidTreeItem_data *data = (ReleaseSidTreeItem_data *)arg;
00126 
00127   // If the sid we have is a son of the given father then delete it
00128   if (si.fathersid == data->fathersid) {
00129      free(si.rsperrmsg);
00130      data->freesids->Push_back(key);
00131      return -1;
00132   }
00133 
00134   return 0;
00135 }
00136 
00137 // Releases a sid and all its childs
00138 void XrdClientSid::ReleaseSidTree(kXR_unt16 fathersid) {
00139    XrdSysMutexHelper l(fMutex);
00140 
00141    ReleaseSidTreeItem_data data;
00142    data.fathersid = fathersid;
00143    data.freesids = &freesids;
00144 
00145    childsidnfo.Apply(ReleaseSidTreeItem, static_cast<void *>(&data));
00146    freesids.Push_back(fathersid);
00147 }
00148 
00149 
00150 
00151 
00152 
00153 static int printoutreq(kXR_unt16,
00154                        struct SidInfo p, void *) {
00155 
00156   smartPrintClientHeader(&p.outstandingreq);
00157   return 0;
00158 }
00159 
00160 void XrdClientSid::PrintoutOutstandingRequests() {
00161   cerr << "-------------------------------------------------- start outstanding reqs dump. freesids: " << freesids.GetSize() << endl;
00162 
00163   childsidnfo.Apply(printoutreq, this);
00164   cerr << "++++++++++++++++++++++++++++++++++++++++++++++++++++ end  outstanding reqs dump." << endl;
00165 }
00166 
00167 
00168 struct sniffOutstandingFailedWriteReq_data {
00169   XrdClientVector<ClientRequest> *reqs;
00170   kXR_unt16 fathersid;
00171   XrdClientVector<kXR_unt16> *freesids;
00172 };
00173 static int sniffOutstandingFailedWriteReq(kXR_unt16 sid,
00174                                     struct SidInfo p, void *d) {
00175 
00176   sniffOutstandingFailedWriteReq_data *data = (sniffOutstandingFailedWriteReq_data *)d;
00177   if ((p.fathersid == data->fathersid) &&
00178       (p.outstandingreq.header.requestid == kXR_write)) {
00179 
00180     // If it went into timeout or got a negative response
00181     // we add this req to the vector
00182     if ( (time(0) - p.sendtime > EnvGetLong(NAME_REQUESTTIMEOUT)) ||
00183          (p.rspstatuscode != kXR_ok) ) {
00184       data->reqs->Push_back(p.outstandingreq);
00185 
00186       // And we release the failed sid
00187       free(p.rsperrmsg);
00188       data->freesids->Push_back(sid);
00189       return -1;
00190     }
00191 
00192   }
00193 
00194   //  smartPrintClientHeader(&p.outstandingreq);
00195   return 0;
00196 }
00197 
00198 static int sniffOutstandingAllWriteReq(kXR_unt16 sid,
00199                                     struct SidInfo p, void *d) {
00200 
00201   sniffOutstandingFailedWriteReq_data *data = (sniffOutstandingFailedWriteReq_data *)d;
00202   if ((p.fathersid == data->fathersid) &&
00203       (p.outstandingreq.header.requestid == kXR_write)) {
00204 
00205       // we add this req to the vector
00206       data->reqs->Push_back(p.outstandingreq);
00207 
00208       // And we release the failed sid
00209       free(p.rsperrmsg);
00210       data->freesids->Push_back(sid);
00211       return -1;
00212   }
00213 
00214   //  smartPrintClientHeader(&p.outstandingreq);
00215   return 0;
00216 }
00217 
00218 struct countOutstandingWriteReq_data {
00219   int cnt;
00220   kXR_unt16 fathersid;
00221 };
00222 static int countOutstandingWriteReq(kXR_unt16 sid,
00223                                     struct SidInfo p, void *c) {
00224 
00225   countOutstandingWriteReq_data *data = (countOutstandingWriteReq_data *)c;
00226 
00227   if ((p.fathersid == data->fathersid) && (p.outstandingreq.header.requestid == kXR_write))
00228     data->cnt++;
00229 
00230   //  smartPrintClientHeader(&p.outstandingreq);
00231   return 0;
00232 }
00233 
00234 int XrdClientSid::GetFailedOutstandingWriteRequests(kXR_unt16 fathersid, XrdClientVector<ClientRequest> &reqvect) {
00235   sniffOutstandingFailedWriteReq_data data;
00236   data.reqs = &reqvect;
00237   data.fathersid = fathersid;
00238   data.freesids = &freesids;
00239 
00240   childsidnfo.Apply(sniffOutstandingFailedWriteReq, (void *)&data);
00241   return reqvect.GetSize();
00242 }
00243 
00244 int XrdClientSid::GetOutstandingWriteRequestCnt(kXR_unt16 fathersid) {
00245   countOutstandingWriteReq_data data;
00246   data.fathersid = fathersid;
00247   data.cnt = 0;
00248   childsidnfo.Apply(countOutstandingWriteReq, (void *)&data);
00249   return data.cnt;
00250 }
00251 
00252 
00253 
00254 int XrdClientSid::GetAllOutstandingWriteRequests(kXR_unt16 fathersid, XrdClientVector<ClientRequest> &reqvect) {
00255   sniffOutstandingFailedWriteReq_data data;
00256   data.reqs = &reqvect;
00257   data.fathersid = fathersid;
00258   data.freesids = &freesids;
00259 
00260   childsidnfo.Apply(sniffOutstandingAllWriteReq, (void *)&data);
00261   return reqvect.GetSize();
00262 }

Generated on Tue Jul 5 14:46:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1