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
00050
00051
00052
00053
00054
00055
00056
00057
00058
00060
00061 #include <algorithm>
00062 #include <sys/stat.h>
00063 #include <unistd.h>
00064 #include <pwd.h>
00065
00066 #include "TAuthenticate.h"
00067 #include "TString.h"
00068 #include "TSystem.h"
00069 #include "TUrl.h"
00070
00071 #include "MessageService/MsgService.h"
00072 #include "Dispatcher/DDSFileHandler.h"
00073
00074 std::ostream& operator << (std::ostream& ms, DDSFileHandler* dfh)
00075 { return dfh->Print(ms); }
00076
00077 ClassImp(DDSFileHandler)
00078
00079
00080
00081
00082 CVSID("$Id: DDSFileHandler.cxx,v 1.26 2008/11/18 21:16:14 rhatcher Exp $");
00083
00084
00085
00086
00087 Int_t DDSFileHandler::BuildFileIndex() {
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 fFileIndex.clear(); fFileIndexItr = fFileIndex.end();
00101
00102 if ( !IsValid() ) {
00103 MSG("DDS",Msg::kWarning)
00104 << "BuildFileIndex called on InValid FileHandler." << endl;
00105 return 0;
00106 }
00107
00108
00109 void *dir = gSystem -> OpenDirectory(fLocalDataSourceDir.c_str());
00110 if (!dir) {
00111 MSG("DDS",Msg::kWarning) << "Error in open of file source directory "
00112 << fLocalDataSourceDir << ".\nCannot build file index." << endl;
00113 return 0;
00114 }
00115
00116
00117 struct stat keystat;
00118 if ( stat(fLocalDataSourceDir.c_str(),&keystat) >= 0 ) {
00119 fSourceDirModTime = keystat.st_ctime;
00120 }
00121
00122 const char* file;
00123 string filename;
00124 while ((file = gSystem -> GetDirEntry(dir)) ) {
00125 filename = file;
00126
00127 if ( filename.length() > 5
00128 && filename.find(".root") == filename.length()-5 ) {
00129 fFileIndex.push_back(fDataSourceDir+"/"+filename);
00130 }
00131 }
00132
00133 std::sort(fFileIndex.begin(),fFileIndex.end());
00134
00135 gSystem -> FreeDirectory(dir);
00136
00137 fFileIndexItr = fFileIndex.begin();
00138
00139 MsgStream& ms = MSGSTREAM("DDS",Msg::kVerbose);
00140 ms << "CS_" << gSystem->GetPid() << ": "<< "Built new FileIndex: " << endl;
00141 for (FileIndexConstItr citr = fFileIndex.begin();
00142 citr != fFileIndex.end(); citr++) {
00143 ms << " " << *citr << endl;
00144 }
00145 return fFileIndex.size();
00146
00147 }
00148
00149 std::string DDSFileHandler::BuildFullFilePathName(std::string filename) {
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 std::string fullfilepathname = filename;
00167 unsigned int namelen = filename.length();
00168 if ( filename.find(fDataSourceDir) >= namelen ) {
00169
00170 if( filename.find("/") != 0 ) {
00171 fullfilepathname = fDataSourceDir + "/" + fullfilepathname;
00172 }
00173 }
00174
00175
00176
00177 const Int_t bufsize = 512;
00178 char buffer[bufsize];
00179
00180 Int_t len = readlink(fullfilepathname.c_str(),buffer,bufsize);
00181 if ( len >= 0 ) {
00182 buffer[len] = '\0';
00183 fullfilepathname = buffer;
00184 fullfilepathname = this -> BuildFullFilePathName(fullfilepathname);
00185 }
00186 return fullfilepathname;
00187
00188 }
00189
00190
00191 DDSFileHandler::DDSFileHandler(DDS::EDataSource datasource,bool offLine) :
00192 fDataSource(datasource),fDataSourceEnv(""),fDataSourceDir(""),
00193 fLocalDataSourceDir(""),fSymLink(""),fSymLinkTarget(""),fSymLinkModTime(0),
00194 fSourceDirModTime(0),fLastServedFile(""),fValid(true),fFileIndexItr(0),
00195 fOffLine(offLine) {
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 string dataSourceString = DDS::AsString(datasource);
00213 fDataSourceEnv = "DDS_"+dataSourceString+"_DATA_DIR";
00214 const char* sourcedir = getenv(fDataSourceEnv.c_str());
00215 if ( sourcedir == NULL ) {
00216 MSG("DDS",Msg::kWarning) << "Environment variable "
00217 << fDataSourceEnv << " undefined." << endl;
00218 fValid = false;
00219 return;
00220 }
00221 else {
00222 fDataSourceDir = sourcedir;
00223 }
00224
00225
00226 if ( fDataSourceDir.find("root:")==0 || fDataSourceDir.find("roots:")==0 ) {
00227 TUrl url(fDataSourceDir.c_str());
00228
00229
00230
00231
00232 string localDataSourceEnv = dataSourceString+"_DATA_DIR";
00233 const char* localSourceDir = getenv(localDataSourceEnv.c_str());
00234 if (localSourceDir != NULL) {
00235 fLocalDataSourceDir = localSourceDir;
00236 }
00237 else {
00238
00239
00240 string symlink = url.GetFile();
00241 fLocalDataSourceDir = symlink.substr(1,symlink.length()-1);
00242 }
00243
00244
00245 TAuthenticate auth(0,url.GetHost(),url.GetProtocol(),0);
00246
00247 TString tuser;
00248 TString tpasswd;
00249 if ( !auth.CheckNetrc(tuser,tpasswd) ) {
00250 MSG("DDS",Msg::kInfo) << "CS_" << gSystem->GetPid() << ": "
00251 << "No remote login data in ~.netrc. Assuming anonymous rootd usage."
00252 << endl;
00253 TAuthenticate::SetGlobalUser("anonymous");
00254 passwd* pwstruct = getpwuid(getuid());
00255 const char* username = 0;
00256 if (pwstruct) username = pwstruct -> pw_name;
00257 string password;
00258 if (username != NULL)
00259 password = string(username) +"@" + string(gSystem->HostName());
00260 else
00261 password = "minos@" + string(gSystem->HostName());
00262 TAuthenticate::SetGlobalPasswd(password.c_str());
00263 }
00264
00265 }
00266 else {
00267 fLocalDataSourceDir = fDataSourceDir;
00268 }
00269 if ( fOffLine )
00270 fSymLink = fLocalDataSourceDir + "/offlinefile";
00271 else
00272 fSymLink = fLocalDataSourceDir + "/currentfile";
00273
00274 }
00275
00276 DDSFileHandler::~DDSFileHandler() {
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 }
00287
00288 std::string DDSFileHandler::GetCurrentFileName() const {
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 std::string currentFileName;
00300 if (fFileIndexItr != fFileIndex.end() ) currentFileName = *fFileIndexItr;
00301 return currentFileName;
00302
00303 }
00304
00305 std::string DDSFileHandler::GetSymLinkTargetName() {
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 if ( this -> IsModifiedSymLink() ) {
00319 fSymLinkTarget = "";
00320
00321 struct stat keystat;
00322 if ( lstat(fSymLink.c_str(),&keystat) >= 0 ) {
00323 fSymLinkModTime = keystat.st_ctime;
00324 const Int_t bufsize = 512;
00325 char buffer[bufsize];
00326 Int_t len = readlink(fSymLink.c_str(),buffer,bufsize);
00327 if ( len >= 0 ) {
00328 buffer[len] = '\0';
00329 if (buffer[0] == '/')
00330 fSymLinkTarget = buffer;
00331 else
00332 fSymLinkTarget = fDataSourceDir + "/" + buffer;
00333 }
00334 else {
00335 MSG("DDS",Msg::kWarning) << "CS_" << gSystem -> GetPid()
00336 << ": Error in reading symbolic link file:\n"
00337 << fSymLink << "." << endl;
00338 }
00339 }
00340 else {
00341 MSG("DDS",Msg::kWarning) << "CS_" << gSystem->GetPid()
00342 << ": Error in reading symbolic link file:\n"
00343 << fSymLink << " modification time." << endl;
00344 }
00345 }
00346
00347 return fSymLinkTarget;
00348
00349 }
00350
00351 std::string DDSFileHandler::GoToFile(std::string filename) {
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 if ( this -> IsModifiedDirectory() ) this -> BuildFileIndex();
00373
00374 std::string fullFilePathName = this -> BuildFullFilePathName(filename);
00375
00376 if ( filename.empty() ) {
00377 fFileIndexItr = fFileIndex.begin();
00378 }
00379 else {
00380 for ( fFileIndexItr=fFileIndex.begin(); fFileIndexItr!=fFileIndex.end();
00381 fFileIndexItr++ ) {
00382 if ( (*fFileIndexItr) >= fullFilePathName ) {
00383 break;
00384 }
00385 }
00386 }
00387
00388 std::string nextFile = this -> GetCurrentFileName();
00389 if ( !nextFile.empty() ) {
00390 fLastServedFile = nextFile;
00391 }
00392
00393 return nextFile;
00394
00395 }
00396
00397 std::string DDSFileHandler::GoToNextFile() {
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 std::string nextFileName = "";
00416 std::string currentFileName = this -> GetCurrentFileName();
00417
00418 bool isNewBuild = false;
00419 if ( this -> IsModifiedDirectory() ) {
00420 this -> GetSymLinkTargetName();
00421 this -> BuildFileIndex();
00422 isNewBuild = true;
00423 }
00424
00425 if ( fFileIndex.empty() ) {
00426 fFileIndexItr = fFileIndex.end();
00427 return "";
00428 }
00429
00430 if ( fLastServedFile.empty() ) {
00431
00432
00433 nextFileName = fSymLinkTarget;
00434 nextFileName = this -> GoToFile(nextFileName);
00435 }
00436 else {
00437
00438 if ( !isNewBuild ) {
00439 if ( fFileIndexItr != fFileIndex.end() ) fFileIndexItr++;
00440 nextFileName = this -> GetCurrentFileName();
00441 }
00442 else {
00443
00444 nextFileName = this -> GoToFile(fLastServedFile);
00445 if ( strcmp(nextFileName.c_str(),fLastServedFile.c_str()) ) {
00446 MSG("DDS",Msg::kWarning) << "CS_" << gSystem -> GetPid()
00447 << ": The data source directory\n"
00448 << " no longer contains the last served file " << currentFileName
00449 << "\n indicating a potential gap in the files served."
00450 << " Will set index to next file beyond missing file in directory."
00451 << endl;
00452 }
00453 else if ( fFileIndexItr != fFileIndex.end() ) {
00454 fFileIndexItr++;
00455 nextFileName = this->GetCurrentFileName();
00456 }
00457 }
00458 }
00459
00460 if ( !nextFileName.empty() ) {
00461 fLastServedFile = nextFileName;
00462 }
00463
00464 return nextFileName;
00465
00466 }
00467
00468 std::string DDSFileHandler::GoToSymLinkFile() {
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 std::string symLinkTarget = this -> GetSymLinkTargetName();
00482 if ( !symLinkTarget.empty() ) {
00483
00484 this -> GoToFile(symLinkTarget);
00485 }
00486
00487 std::string nextFile = this -> GetCurrentFileName();
00488 if (!nextFile.empty()) {
00489 fLastServedFile = nextFile;
00490 }
00491
00492 return nextFile;
00493
00494 }
00495
00496 bool DDSFileHandler::IsModifiedDirectory() const {
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 if ( IsValid() ) {
00508
00509 struct stat keystat;
00510 if (stat(fLocalDataSourceDir.c_str(),&keystat) >= 0) {
00511 if (fSourceDirModTime != keystat.st_ctime) {
00512 return true;
00513 }
00514 }
00515 }
00516
00517 return false;
00518
00519 }
00520
00521 bool DDSFileHandler::IsModifiedSymLink() const {
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 if ( IsValid() ) {
00534
00535 struct stat keystat;
00536 if (lstat(fSymLink.c_str(),&keystat) >= 0) {
00537 if (fSymLinkModTime != keystat.st_ctime) {
00538 return true;
00539 }
00540 }
00541 }
00542
00543 return false;
00544
00545 }
00546
00547 bool DDSFileHandler::NewFileAvailable() {
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 if ( IsValid() ) {
00560 this -> GetSymLinkTargetName();
00561 if ( !fSymLinkTarget.empty() ) {
00562 if ( strcmp( (this->GetSymLinkTargetName()).c_str(),
00563 (this->GetCurrentFileName()).c_str() ) ) {
00564 return true;
00565 }
00566 }
00567 }
00568
00569 return false;
00570
00571 }
00572
00573 std::ostream& DDSFileHandler::Print(std::ostream& ms) const {
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 if ( IsValid() ) {
00585 ms << "DDSFileHandler is serving files for data source "
00586 << DDS::AsString(fDataSource) << " from directory:\n "
00587 << fDataSourceDir << "." << endl;
00588 ms << "The symbolic link:\n " << fSymLink << "\nshould point to "
00589 << "the most recent " << DDS::AsString(fDataSource)
00590 << " file." << endl;
00591 if ( !fSymLinkTarget.empty() ) {
00592 ms << "This symbolic link file pointed to "
00593 << fSymLinkTarget << " on last check." << endl;
00594 }
00595 else {
00596 ms << "This symbolic link file did not point to a file when last checked."
00597 << endl;
00598 }
00599 ms << "There are " << fFileIndex.size() << " entries in the file index."
00600 << endl;
00601 for (unsigned int i = 0; i < fFileIndex.size(); i++) {
00602 ms << " " << i+1 << ")" << fFileIndex[i] << endl;
00603 }
00604 }
00605 else {
00606 ms << "DDSFileHandler was unable to access the environment variable "
00607 << fDataSourceEnv << "." << endl;
00608 }
00609
00610 return ms;
00611
00612 }
00613
00614
00615
00616
00617
00618
00619
00620