00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 const char *XrdCmsReqCVSID = "$Id: XrdCmsReq.cc 31508 2009-12-02 19:11:01Z brun $";
00016
00017 #include <stdio.h>
00018 #include <unistd.h>
00019 #include <sys/stat.h>
00020 #include <sys/types.h>
00021 #include <sys/uio.h>
00022 #include <netinet/in.h>
00023 #include <inttypes.h>
00024
00025 #include "XrdCms/XrdCmsNode.hh"
00026 #include "XrdCms/XrdCmsReq.hh"
00027 #include "XrdCms/XrdCmsRRQ.hh"
00028 #include "XrdCms/XrdCmsRTable.hh"
00029 #include "XrdCms/XrdCmsTrace.hh"
00030 #include "XrdSys/XrdSysError.hh"
00031 #include "XrdSys/XrdSysPlatform.hh"
00032 #include "XrdSys/XrdSysPthread.hh"
00033
00034 #include "XProtocol/XProtocol.hh"
00035 #include "XProtocol/YProtocol.hh"
00036
00037 using namespace XrdCms;
00038
00039
00040
00041
00042
00043 XrdCmsReq::XrdCmsReq(XrdCmsNode *nP, unsigned int reqid, char adv)
00044 {
00045 NodeP = nP;
00046 ReqID = reqid;
00047 ReqNnum = nP->getSlot();
00048 ReqNins = nP->Inst();
00049 ReqAdv = adv;
00050 }
00051
00052
00053
00054
00055
00056 XrdCmsReq::XrdCmsReq(XrdCmsReq *Req, unsigned int rn)
00057 {
00058 NodeP = 0;
00059 ReqID = rn;
00060 ReqNnum = Req->ReqNnum;
00061 ReqNins = Req->ReqNins;
00062 }
00063
00064
00065
00066
00067
00068 void XrdCmsReq::Reply_Error(const char *emsg, int elen)
00069 {
00070
00071
00072
00073 if (!elen) elen = strlen(emsg)+1;
00074 else if (emsg[elen]) elen++;
00075
00076
00077
00078 Reply(kYR_error, kYR_EINVAL, emsg, elen);
00079 }
00080
00081
00082
00083
00084
00085 void XrdCmsReq::Reply_Error(const char *ecode, const char *emsg, int elen)
00086 {
00087 unsigned int eval;
00088
00089
00090
00091 if (!strcmp("ENOENT", ecode)) eval = kYR_ENOENT;
00092 else if (!strcmp("EPERM", ecode)) eval = kYR_EPERM;
00093 else if (!strcmp("EACCES", ecode)) eval = kYR_EACCES;
00094 else if (!strcmp("EIO", ecode)) eval = kYR_EIO;
00095 else if (!strcmp("ENOMEM", ecode)) eval = kYR_ENOMEM;
00096 else if (!strcmp("ENOSPC", ecode)) eval = kYR_ENOSPC;
00097 else if (!strcmp("ENAMETOOLONG", ecode)) eval = kYR_ENAMETOOLONG;
00098 else if (!strcmp("ENETUNREACH", ecode)) eval = kYR_ENETUNREACH;
00099 else if (!strcmp("ENOTBLK", ecode)) eval = kYR_ENOTBLK;
00100 else if (!strcmp("EISDIR", ecode)) eval = kYR_EISDIR;
00101 else eval = kYR_EINVAL;
00102
00103
00104
00105 if (!elen) elen = strlen(emsg)+1;
00106 else if (emsg[elen]) elen++;
00107
00108
00109
00110 Reply(kYR_error, eval, emsg, elen);
00111 }
00112
00113
00114
00115 void XrdCmsReq::Reply_Error(int ecode, const char *emsg, int elen)
00116 {
00117 unsigned int eval;
00118
00119
00120
00121 switch(ecode)
00122 {case ENOENT: eval = kYR_ENOENT;
00123 case EPERM: eval = kYR_EPERM;
00124 case EACCES: eval = kYR_EACCES;
00125 case EIO: eval = kYR_EIO;
00126 case ENOMEM: eval = kYR_ENOMEM;
00127 case ENOSPC: eval = kYR_ENOSPC;
00128 case ENAMETOOLONG: eval = kYR_ENAMETOOLONG;
00129 case ENETUNREACH: eval = kYR_ENETUNREACH;
00130 case ENOTBLK: eval = kYR_ENOTBLK;
00131 case EISDIR: eval = kYR_EISDIR;
00132 default: eval = kYR_EINVAL;
00133 };
00134
00135
00136
00137 if (!elen) elen = strlen(emsg)+1;
00138 else if (emsg[elen]) elen++;
00139
00140
00141
00142 Reply(kYR_error, eval, emsg, elen);
00143 }
00144
00145
00146
00147
00148
00149 void XrdCmsReq::Reply_OK()
00150 {
00151
00152
00153
00154 Reply(kYR_data, 0, "", 1);
00155 }
00156
00157
00158
00159 void XrdCmsReq::Reply_OK(const char *data, int dlen)
00160 {
00161
00162
00163
00164 if (!dlen) dlen = strlen(data)+1;
00165 else if (data[dlen]) dlen++;
00166
00167
00168
00169 Reply(kYR_data, 0, data, dlen);
00170 }
00171
00172
00173
00174 void XrdCmsReq::Reply_OK(struct stat &buf)
00175 {
00176 char sbuff[256];
00177
00178 Reply_OK(sbuff, StatGen(buf, sbuff));
00179 }
00180
00181
00182
00183
00184
00185 void XrdCmsReq::Reply_Redirect(const char *sname,
00186 const char *lcgi, const char *ocgi)
00187 {
00188 char hbuff[256], *colon;
00189 const char *hP = hbuff;
00190 int hlen, Port;
00191
00192
00193
00194 if (!(colon = (char *) index(sname, ':')))
00195 {Port = 0;
00196 hP = sname;
00197 } else {
00198 Port = atoi(colon+1);
00199 hlen = colon-sname+1;
00200 if (hlen >= (int)sizeof(hbuff)) hlen = sizeof(hbuff);
00201 strlcpy(hbuff, sname, hlen);
00202 }
00203
00204
00205
00206 Reply_Redirect(hP, Port, lcgi, ocgi);
00207 }
00208
00209
00210
00211 void XrdCmsReq::Reply_Redirect(const char *sname, int Port,
00212 const char *lcgi, const char *ocgi)
00213 {
00214 struct iovec iov[8];
00215 int iovnum, hlen = strlen(sname);
00216
00217
00218
00219 iov[1].iov_base = (char *)sname;
00220 iov[1].iov_len = strlen(sname);
00221 hlen = iov[1].iov_len;
00222
00223
00224
00225 if (!lcgi && !ocgi) iovnum = 2;
00226 else {if (ocgi)
00227 {iov[2].iov_base = (char *)"?";
00228 iov[2].iov_len = 1;
00229 iov[3].iov_base = (char *)ocgi;
00230 iov[3].iov_len = strlen(ocgi);
00231 hlen += iov[3].iov_len + 1;
00232 if (lcgi)
00233 {iov[4].iov_base = (char *)"?";
00234 iov[4].iov_len = 1;
00235 iov[5].iov_base = (char *)lcgi;
00236 iov[5].iov_len = strlen(lcgi);
00237 hlen += iov[5].iov_len + 1;
00238 iovnum = 6;
00239 } else iovnum = 4;
00240 } else {
00241 iov[2].iov_base = (char *)"??";
00242 iov[2].iov_len = 2;
00243 iov[3].iov_base = (char *)lcgi;
00244 iov[3].iov_len = strlen(lcgi);
00245 hlen += iov[3].iov_len + 2;
00246 iovnum = 4;
00247 }
00248 }
00249
00250
00251
00252 iov[iovnum-1].iov_len++; hlen++;
00253
00254
00255
00256 Reply(kYR_redirect, (unsigned int)Port, 0, hlen, iov, iovnum);
00257 }
00258
00259
00260
00261
00262
00263 void XrdCmsReq::Reply_Wait(int sec)
00264 {
00265
00266
00267
00268 Reply(kYR_wait, (unsigned int)sec, "", 1);
00269 }
00270
00271
00272
00273
00274
00275 XrdCmsReq *XrdCmsReq::Reply_WaitResp(int sec)
00276 {
00277 static XrdSysMutex rnMutex;
00278 static unsigned int RequestNum = 0;
00279 unsigned int rnum;
00280 XrdCmsReq *newReq;
00281
00282
00283
00284
00285 if (!NodeP) return (XrdCmsReq *)0;
00286
00287
00288
00289 if (ReqID)
00290 {rnMutex.Lock();
00291 RequestNum++;
00292 rnum = RequestNum;
00293 rnMutex.UnLock();
00294 } else rnum = 0;
00295
00296
00297
00298
00299
00300 newReq = new XrdCmsReq(this, rnum);
00301
00302
00303
00304 if (rnum)
00305 {
00306 Reply(kYR_waitresp, rnum);
00307 }
00308
00309
00310
00311 return newReq;
00312 }
00313
00314
00315
00316
00317
00318 #define XRDXROOTD_STAT_CLASSNAME XrdCmsReq
00319 #include "XrdXrootd/XrdXrootdStat.icc"
00320
00321
00322
00323
00324
00325 void XrdCmsReq::noReply()
00326 {
00327 static int nrNum = 255;
00328
00329
00330
00331
00332 if (ReqNnum < 0)
00333 Say.Emsg("Req", "Attempted reply to twice to a 2way async request.");
00334 else {nrNum++;
00335 if (!(nrNum & 255)) Say.Emsg("Req",
00336 "Attempted reply to a 1way request; "
00337 "probably incorrect ofs forward directive.");
00338 }
00339 }
00340
00341
00342
00343
00344
00345 void XrdCmsReq::Reply( int respCode, unsigned int respVal,
00346 const char *respData, int respLen,
00347 struct iovec *iov, int iovnum)
00348 {
00349 EPNAME("Reply");
00350 CmsResponse Resp = {{ReqID, respCode, 0, 0}, htonl(respVal)};
00351 struct iovec myiov[2], *iovP;
00352 XrdCmsNode *nP;
00353
00354
00355
00356 Resp.Hdr.datalen = htons(static_cast<short>(respLen+sizeof(int)));
00357
00358
00359
00360 if (iov)
00361 { iov->iov_base = (char *)&Resp;
00362 iov->iov_len = sizeof(Resp);
00363 iovP = iov;
00364 } else {
00365 myiov[0].iov_base = (char *)&Resp;
00366 myiov[0].iov_len = sizeof(Resp);
00367 if (respData)
00368 {myiov[1].iov_base = (char *)respData;
00369 myiov[1].iov_len = respLen;
00370 iovnum = 2;
00371 } else iovnum = 1;
00372 iovP = myiov;
00373 }
00374
00375
00376
00377 if (NodeP)
00378 {if (ReqID) NodeP->Send(iovP, iovnum);
00379 else noReply();
00380 return;
00381 }
00382
00383
00384
00385
00386 RTable.Lock();
00387 if ((nP = RTable.Find(ReqNnum, ReqNins)))
00388 {Resp.Hdr.modifier |= CmsResponse::kYR_async;
00389 nP->Send(iovP, iovnum);
00390 }
00391 else {DEBUG("Async resp " <<ReqID <<" discarded; server gone");}
00392 RTable.UnLock();
00393
00394
00395
00396 ReqID = 0;
00397 ReqNnum = -1;
00398 }