00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "NetErrors.h"
00050 #include "TCastorFile.h"
00051 #include "TError.h"
00052
00053 #include <stdlib.h>
00054 #include <errno.h>
00055
00056 #ifdef _WIN32
00057 #include <WinDef.h>
00058 #include <WinSock2.h>
00059 #endif
00060
00061 #ifdef R__CASTOR2
00062 #include <stager_api.h>
00063 #endif
00064 #define RFIO_KERNEL // Get access to extra symbols in the headers
00065 #include <stage_api.h>
00066 #include <rfio_api.h>
00067 #include <Cns_api.h>
00068 #include <Cglobals.h>
00069 #include <rfio_constants.h>
00070
00071 #define RFIO_USE_CASTOR_V2 "RFIO_USE_CASTOR_V2"
00072 #define RFIO_HSM_BASETYPE 0x0
00073 #define RFIO_HSM_CNS RFIO_HSM_BASETYPE+1
00074
00075 extern "C" { int rfio_HsmIf_reqtoput (char *); }
00076 extern "C" { int DLL_DECL rfio_parse(char *, char **, char **); }
00077 extern "C" { int rfio_HsmIf_IsHsmFile (const char *); }
00078 extern "C" { char *getconfent(char *, char *, int); }
00079
00080 #ifdef R__CASTOR2
00081 extern int tStageHostKey;
00082 extern int tStagePortKey;
00083 extern int tSvcClassKey;
00084 extern int tCastorVersionKey;
00085 extern "C" { int DLL_DECL use_castor2_api(); }
00086
00087
00088 static int UseCastor2API()
00089 {
00090
00091
00092 int version = use_castor2_api();
00093 return version;
00094 }
00095
00096 #else
00097
00098
00099 static int UseCastor2API()
00100 {
00101
00102
00103 char *p;
00104
00105 if (((p = getenv(RFIO_USE_CASTOR_V2)) == 0) &&
00106 ((p = getconfent("RFIO","USE_CASTOR_V2",0)) == 0)) {
00107
00108 return 0;
00109 }
00110 if ((strcmp(p,"YES") == 0) || (strcmp(p,"yes") == 0) || (atoi(p) == 1)) {
00111
00112 static int once = 0;
00113 if (!once) {
00114 ::Warning("UseCastor2API", "asked to use CASTOR 2, but linked with CASTOR 1");
00115 once = 1;
00116 }
00117 return 0;
00118 }
00119
00120 return 0;
00121 }
00122
00123 #endif
00124
00125
00126 static const char *GetAuthProto(TString &url)
00127 {
00128
00129
00130
00131 const Int_t rootNumSec = 6;
00132 const char *protoSec[rootNumSec] = {"rootup", "roots", "rootk",
00133 "rootg", "rooth", "rootug" };
00134 TString p = url;
00135 Int_t ii = p.Index("&rootAuth=");
00136 if (ii != kNPOS) {
00137 Int_t jj = p.Index("&", ii+1);
00138 if (jj != kNPOS)
00139 p.Remove(jj);
00140 p.Remove(0,ii);
00141 url.ReplaceAll(p, "");
00142 p.ReplaceAll("&rootAuth=", "");
00143 }
00144 if (p.Length() <= 0)
00145
00146 p = getenv("ROOTCASTORAUTH");
00147
00148 Int_t sec = -1;
00149 if (p.Length() > 0 && p.IsDigit()) {
00150 sec = p.Atoi();
00151 if (sec < 0 || sec > (rootNumSec - 1))
00152 sec = -1;
00153 }
00154
00155
00156 return ((sec > -1 && sec < rootNumSec) ? protoSec[sec] : "root");
00157 }
00158
00159 ClassImp(TCastorFile)
00160
00161
00162 TCastorFile::TCastorFile(const char *url, Option_t *option, const char *ftitle,
00163 Int_t compress, Int_t netopt)
00164 : TNetFile(url, ftitle, compress, kFALSE)
00165 {
00166
00167
00168
00169
00170
00171
00172
00173 fIsCastor = kFALSE;
00174 fWrittenTo = kFALSE;
00175
00176
00177 TString u(url);
00178 fAuthProto = GetAuthProto(u);
00179 fUrl.SetUrl(u);
00180
00181 if (gDebug > 0)
00182 Info("TCastorFile","fAuthProto = %s, u: %s", fAuthProto.Data(), u.Data());
00183
00184
00185
00186 TString opt = option;
00187 opt.ToUpper();
00188 if (opt == "NEW" || opt == "CREATE")
00189 opt = "RECREATE";
00190
00191 Create(url, opt, netopt);
00192 }
00193
00194
00195 void TCastorFile::FindServerAndPath()
00196 {
00197
00198
00199
00200
00201 TString castorturl;
00202 char *host=0;
00203 char *name=0;
00204
00205
00206 if (!strcmp(fUrl.GetProtocol(),"castor"))
00207 castorturl = Form("%s://%s", "rfio", fUrl.GetFile());
00208 else
00209 castorturl = Form("%s://%s", fUrl.GetProtocol(), fUrl.GetFile());
00210 if (strlen(fUrl.GetOptions()) > 0)
00211 castorturl += Form("?%s", fUrl.GetOptions());
00212
00213
00214 TString fname = castorturl;
00215 if (::rfio_parse((char *)fname.Data(), &host, &name)>=0) {
00216 castorturl = Form("%s",(!name || !strstr(name,"/castor"))?fname.Data():name);
00217 fname = castorturl.Data();
00218
00219 } else {
00220 Error("FindServerAndPath", "error parsing %s", fUrl.GetUrl());
00221 return;
00222 }
00223
00224 if (!UseCastor2API()) {
00225
00226 struct stgcat_entry *stcp_output = 0;
00227 if (rfio_HsmIf_IsHsmFile(fUrl.GetFile()) == RFIO_HSM_CNS) {
00228
00229 int flags = O_RDONLY;
00230 struct Cns_filestat st;
00231 int rc;
00232 char stageoutbuf[1025];
00233 char stageerrbuf[1025];
00234
00235
00236 if (strlen(fUrl.GetFile()) > STAGE_MAX_HSMLENGTH) {
00237 serrno = ENAMETOOLONG;
00238 Error("FindServerAndPath", "can't open %s, error %d (%s)", fUrl.GetFile(), serrno, sstrerror(serrno));
00239 return;
00240 }
00241
00242
00243 if (fOption == "CREATE" || fOption == "RECREATE" || fOption == "UPDATE")
00244 flags |= O_RDWR;
00245 if (fOption == "CREATE" || fOption == "RECREATE")
00246 flags |= O_CREAT | O_TRUNC;
00247
00248
00249 memset(&st, 0, sizeof(st));
00250 rc = Cns_stat(fUrl.GetFile(), &st);
00251
00252
00253
00254 if (rc == -1 || ((flags & O_TRUNC) != 0))
00255 st.filesize = 0;
00256
00257
00258 if (stage_setoutbuf(stageoutbuf, 1024) != 0) {
00259 Error("FindServerAndPath", "can't open %s, stage_setoutbuf, error %d (%s)",
00260 fUrl.GetFile(), serrno, sstrerror(serrno));
00261 return;
00262 }
00263 if (stage_seterrbuf(stageerrbuf, 1024) != 0) {
00264 Error("FindServerAndPath", "can't open %s, stage_seterrbuf, error %d (%s)",
00265 fUrl.GetFile(), serrno, sstrerror(serrno));
00266 return;
00267 }
00268
00269 struct stgcat_entry stcp_input;
00270 int nstcp_output;
00271
00272 memset(&stcp_input, 0, sizeof(struct stgcat_entry));
00273 strlcpy(stcp_input.u1.h.xfile, fUrl.GetFile(), sizeof(stcp_input.u1.h.xfile));
00274 if (flags == O_RDONLY || st.filesize > 0) {
00275
00276 if (stage_in_hsm((u_signed64) 0,
00277 (int) flags,
00278 (char *) 0,
00279 (char *) 0,
00280 (int) 1,
00281 (struct stgcat_entry *) &stcp_input,
00282 (int *) &nstcp_output,
00283 (struct stgcat_entry **) &stcp_output,
00284 (int) 0,
00285 (struct stgpath_entry *) 0
00286 ) != 0) {
00287 Error("FindServerAndPath", "can't open %s, stage_in_hsm error %d (%s)",
00288 fUrl.GetFile(), serrno, sstrerror(serrno));
00289 return;
00290 }
00291 } else {
00292
00293 if (stage_out_hsm((u_signed64) 0,
00294 (int) flags,
00295 (mode_t) 0666,
00296
00297 (char *) 0,
00298 (char *) 0,
00299 (int) 1,
00300 (struct stgcat_entry *) &stcp_input,
00301 (int *) &nstcp_output,
00302 (struct stgcat_entry **) &stcp_output,
00303 (int) 0,
00304 (struct stgpath_entry *) 0
00305 ) != 0) {
00306 Error("FindServerAndPath", "can't open %s, stage_out_hsm error %d (%s)",
00307 fUrl.GetFile(), serrno, sstrerror(serrno));
00308 return;
00309 }
00310 }
00311 if ((nstcp_output != 1) || (stcp_output == 0) ||
00312 (*(stcp_output->ipath) == '\0')) {
00313
00314 serrno = SEINTERNAL;
00315 if (stcp_output != 0) free(stcp_output);
00316 Error("FindServerAndPath", "can't open %s, error %d (%s)",
00317 fUrl.GetFile(), serrno, sstrerror(serrno));
00318 return;
00319 }
00320
00321
00322 char *filename;
00323 char *realhost = 0;
00324
00325 rfio_parse(stcp_output->ipath, &realhost, &filename);
00326 if (realhost == 0) {
00327 serrno = SEINTERNAL;
00328 Error("FindServerAndPath", "can't open %s, get disk server hostname from %s error %d (%s)",
00329 fUrl.GetFile(), stcp_output->ipath, errno, sstrerror(serrno));
00330 free(stcp_output);
00331 return;
00332 }
00333
00334 fDiskServer = realhost;
00335 if (filename[0] != '/') {
00336
00337 fInternalPath = "/";
00338 fInternalPath += filename;
00339 } else {
00340 fInternalPath = filename;
00341 }
00342
00343 if (st.filesize == 0) {
00344
00345 fWrittenTo = kTRUE;
00346 }
00347 }
00348
00349
00350
00351
00352
00353
00354 TString r = fAuthProto;
00355 if (fAuthProto == "root") {
00356 TString fqdn;
00357 TInetAddress addr = gSystem->GetHostByName(fDiskServer);
00358 if (addr.IsValid()) {
00359 fqdn = addr.GetHostName();
00360 if (fqdn.EndsWith(".cern.ch") || fqdn.BeginsWith("137.138."))
00361 r = "rootug://";
00362 else
00363 r = "root://";
00364 } else
00365 r = "root://";
00366 } else {
00367
00368 r += "://";
00369 }
00370
00371
00372 r += fDiskServer + "/";
00373 r += fInternalPath;
00374 TUrl rurl(r);
00375 fUrl = rurl;
00376
00377 if (gDebug > 0)
00378 Info("FindServerAndPath"," fDiskServer: %s, r: %s", fDiskServer.Data(), r.Data());
00379
00380
00381
00382 fInternalPath = stcp_output==0?0:stcp_output->ipath;
00383 if (stcp_output)
00384 free(stcp_output);
00385 } else {
00386
00387 #ifdef R__CASTOR2
00388
00389
00390
00391
00392 int flags = O_RDONLY;
00393 int rc;
00394 struct stage_io_fileresp *response = 0;
00395 char *requestId = 0, *url = 0;
00396 char stageerrbuf[1025];
00397
00398
00399 if (fOption == "CREATE" || fOption == "RECREATE" || fOption == "UPDATE")
00400 flags |= O_RDWR;
00401 if (fOption == "CREATE" || fOption == "RECREATE")
00402 flags |= O_CREAT | O_TRUNC;
00403
00404 stage_seterrbuf(stageerrbuf, 1024);
00405
00406 int* auxVal;
00407 char ** auxPoint;
00408 struct stage_options opts;
00409 opts.stage_host=0;
00410 opts.stage_port=0;
00411 opts.service_class=0;
00412 opts.stage_version=0;
00413
00414 void *ptrPoint = &auxPoint;
00415 void *ptrVal = &auxVal;
00416 int ret=Cglobals_get(& tStageHostKey, (void**)ptrPoint,sizeof(void*));
00417 if(ret==0){
00418 opts.stage_host=*auxPoint;
00419 }
00420 ret=Cglobals_get(& tStagePortKey, (void**)ptrVal,sizeof(int));
00421 if(ret==0){
00422 opts.stage_port=*auxVal;
00423 }
00424 opts.stage_version=2;
00425 ret=Cglobals_get(& tSvcClassKey, (void**)ptrPoint,sizeof(void*));
00426 if (ret==0){
00427 opts.service_class=*auxPoint;
00428 }
00429
00430
00431 rc = stage_open(0,
00432 MOVER_PROTOCOL_ROOT,
00433 (char *)fname.Data(),
00434 flags,
00435 (mode_t) 0666,
00436 0,
00437 &response,
00438 &requestId,
00439 &opts);
00440
00441 if (rc != 0) {
00442 Error("FindServerAndPath", "stage_open failed: %s (%s)",
00443 sstrerror(serrno), stageerrbuf);
00444 if (response) free(response);
00445 if (requestId) free(requestId);
00446 return;
00447 }
00448
00449 if (response == 0) {
00450 Error("FindServerAndPath", "response was null for %s (Request %s) %d/%s",
00451 fname.Data(), requestId,
00452 serrno, sstrerror(serrno));
00453 if (requestId) free(requestId);
00454 return;
00455 }
00456
00457 if (response->errorCode != 0) {
00458 serrno = response->errorCode;
00459 Error("FindServerAndPath", "error getting file %s (Request %s) %d/%s",
00460 fname.Data(), requestId,
00461 serrno, sstrerror(serrno));
00462 free(response);
00463 if (requestId) free(requestId);
00464 return;
00465 }
00466
00467 url = stage_geturl(response);
00468
00469 if (url == 0) {
00470 Error("FindServerAndPath", "error getting file %s (Request %s) %d/%s",
00471 fname.Data(), requestId,
00472 serrno, sstrerror(serrno));
00473 free(response);
00474 if (requestId) free(requestId);
00475 return;
00476 }
00477
00478 TUrl rurl(url);
00479
00480
00481
00482
00483
00484 TString p = fAuthProto;
00485 if (fAuthProto == "root") {
00486 TString fqdn = rurl.GetHostFQDN();
00487 if (fqdn.EndsWith(".cern.ch") || fqdn.BeginsWith("137.138."))
00488 fAuthProto = "rootug";
00489 }
00490
00491
00492 rurl.SetProtocol(fAuthProto);
00493 fUrl = rurl;
00494
00495 if (response) free(response);
00496 if (url) free(url);
00497 if (requestId) free(requestId);
00498 #endif
00499
00500 }
00501
00502 fIsCastor = kTRUE;
00503 }
00504
00505
00506 Int_t TCastorFile::SysClose(Int_t fd)
00507 {
00508
00509
00510 Int_t r = TNetFile::SysClose(fd);
00511
00512 if (!UseCastor2API()) {
00513 if (fIsCastor && fWrittenTo) {
00514
00515 rfio_HsmIf_reqtoput((char *)fInternalPath.Data());
00516 fWrittenTo = kFALSE;
00517 }
00518 }
00519
00520 return r;
00521 }
00522
00523
00524 Bool_t TCastorFile::WriteBuffer(const char *buf, Int_t len)
00525 {
00526
00527
00528
00529 if (TNetFile::WriteBuffer(buf, len))
00530 return kTRUE;
00531
00532 if (!UseCastor2API()) {
00533 if (fIsCastor && !fWrittenTo && len > 0) {
00534 stage_hsm_t hsmfile;
00535
00536
00537 memset(&hsmfile, 0, sizeof(hsmfile));
00538 hsmfile.upath = StrDup(fInternalPath);
00539 if (stage_updc_filchg(0, &hsmfile) < 0) {
00540 Error("WriteBuffer", "error calling stage_updc_filchg");
00541 delete [] hsmfile.upath;
00542 return kTRUE;
00543 }
00544 delete [] hsmfile.upath;
00545 fWrittenTo = kTRUE;
00546 }
00547 }
00548
00549 return kFALSE;
00550 }
00551
00552
00553 void TCastorFile::ConnectServer(Int_t *stat, EMessageTypes *kind, Int_t netopt,
00554 Int_t tcpwindowsize, Bool_t forceOpen,
00555 Bool_t forceRead)
00556 {
00557
00558
00559 FindServerAndPath();
00560
00561
00562 if (fIsCastor) {
00563 TNetFile::ConnectServer(stat, kind, netopt, tcpwindowsize, forceOpen, forceRead);
00564 } else {
00565
00566 *stat = kErrFileOpen;
00567 *kind = kROOTD_ERR;
00568 }
00569 }