// @(#)root/netx:$Id$
/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// TNetXNGFileStager                                                          //
//                                                                            //
// Authors: Justin Salmon, Lukasz Janyst                                      //
//          CERN, 2013                                                        //
//                                                                            //
// Enables access to XRootD staging capabilities using the new client.        //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#include "TNetXNGFileStager.h"
#include "TNetXNGSystem.h"
#include "THashList.h"
#include "TFileInfo.h"
#include "TFileCollection.h"
#include <XrdCl/XrdClFileSystem.hh>

ClassImp( TNetXNGFileStager);

//______________________________________________________________________________
TNetXNGFileStager::TNetXNGFileStager(const char *url) :
      TFileStager("xrd")
{
   // Constructor
   //
   // param url: the URL of the entry-point server

   fSystem = new TNetXNGSystem(url);
}

//______________________________________________________________________________
TNetXNGFileStager::~TNetXNGFileStager()
{
   // Destructor

   delete fSystem;
}

//______________________________________________________________________________
Bool_t TNetXNGFileStager::IsStaged(const char *path)
{
   // Check if a file is staged
   //
   // param path: the URL of the file

   FileStat_t st;
   if (fSystem->GetPathInfo(path, st) != 0) {
      if (gDebug > 0)
         Info("IsStaged", "path %s cannot be stat'ed", path);
      return kFALSE;
   }

   if (R_ISOFF(st.fMode)) {
      if (gDebug > 0)
         Info("IsStaged", "path '%s' is offline", path);
      return kFALSE;
   }

   return kTRUE;
}

//______________________________________________________________________________
Int_t TNetXNGFileStager::Locate(const char *path, TString &url)
{
   // Get actual endpoint URL
   //
   // param path:    the entry-point URL
   // param endpath: the actual endpoint URL
   // returns:       0 in the case of success and 1 if any error occurred

   return fSystem->Locate(path, url);
}

//______________________________________________________________________________
Int_t TNetXNGFileStager::LocateCollection(TFileCollection *fc,
                                          Bool_t addDummyUrl)
{
   // Bulk locate request for a collection of files
   //
   // param fc:          collection of files to be located
   // param addDummyUrl: append a dummy noop URL if the file is not staged or
   //                    redirector == endpoint
   // returns:           < 0 in case of errors, number of files processed
   //                    otherwise

   if (!fc) {
      Error("LocateCollection", "No input collection given");
      return -1;
   }

   int numFiles = 0;
   TFileInfo *info;
   TIter it(fc->GetList());
   TString startUrl, endUrl;

   while ((info = dynamic_cast<TFileInfo *>(it.Next())) != NULL) {
      startUrl = info->GetCurrentUrl()->GetUrl();

      // File not staged
      if (fSystem->Locate(startUrl.Data(), endUrl)) {
         info->ResetBit(TFileInfo::kStaged);

         if (addDummyUrl)
            info->AddUrl("noop://none", kTRUE);

         if (gDebug > 1)
            Info("LocateCollection", "Not found: %s", startUrl.Data());
      }

      // File staged
      else {
         info->SetBit(TFileInfo::kStaged);

         if (startUrl != endUrl) {
            info->AddUrl(endUrl.Data(), kTRUE);
         } else if (addDummyUrl) {
            // Returned URL identical to redirector URL
            info->AddUrl("noop://redir", kTRUE);
         }

         if (gDebug > 1)
            Info("LocateCollection", "Found: %s --> %s", startUrl.Data(),
                                      endUrl.Data());
      }
      numFiles++;
   }

   return numFiles;
}

//______________________________________________________________________________
Bool_t TNetXNGFileStager::Matches(const char *s)
{
   // Returns kTRUE if stager 's' is compatible with current stager. Avoids
   // multiple instantiations of the potentially the same TNetXNGFileStager.

   return ((s && (fName == s)) ? kTRUE : kFALSE);
}

//______________________________________________________________________________
Bool_t TNetXNGFileStager::Stage(const char *path, Option_t *opt)
{
   // Issue a stage request for a single file
   //
   // param path: the path of the file to stage
   // param opt:  defines 'option' and 'priority' for 'Prepare': the format is
   //             opt = "option=o priority=p"

   Int_t priority = ParseStagePriority(opt);
   return fSystem->Stage(path, priority);
}

//______________________________________________________________________________
Bool_t TNetXNGFileStager::Stage(TCollection *paths, Option_t *opt)
{
   // Issue stage requests for multiple files
   //
   // param pathlist: list of paths of files to stage
   // param opt:      defines 'option' and 'priority' for 'Prepare': the
   //                 format is opt = "option=o priority=p"

   Int_t priority = ParseStagePriority(opt);
   return fSystem->Stage(paths, priority);
}

//______________________________________________________________________________
UChar_t TNetXNGFileStager::ParseStagePriority(Option_t *opt)
{
   // Get a staging priority value from an option string

   UChar_t priority = 0;
   Ssiz_t from = 0;
   TString token;

   while (TString(opt).Tokenize(token, from, "[ ,|]")) {
      if (token.Contains("priority=")) {
         token.ReplaceAll("priority=", "");
         if (token.IsDigit()) {
            priority = token.Atoi();
         }
      }
   }

   return priority;
}
 TNetXNGFileStager.cxx:1
 TNetXNGFileStager.cxx:2
 TNetXNGFileStager.cxx:3
 TNetXNGFileStager.cxx:4
 TNetXNGFileStager.cxx:5
 TNetXNGFileStager.cxx:6
 TNetXNGFileStager.cxx:7
 TNetXNGFileStager.cxx:8
 TNetXNGFileStager.cxx:9
 TNetXNGFileStager.cxx:10
 TNetXNGFileStager.cxx:11
 TNetXNGFileStager.cxx:12
 TNetXNGFileStager.cxx:13
 TNetXNGFileStager.cxx:14
 TNetXNGFileStager.cxx:15
 TNetXNGFileStager.cxx:16
 TNetXNGFileStager.cxx:17
 TNetXNGFileStager.cxx:18
 TNetXNGFileStager.cxx:19
 TNetXNGFileStager.cxx:20
 TNetXNGFileStager.cxx:21
 TNetXNGFileStager.cxx:22
 TNetXNGFileStager.cxx:23
 TNetXNGFileStager.cxx:24
 TNetXNGFileStager.cxx:25
 TNetXNGFileStager.cxx:26
 TNetXNGFileStager.cxx:27
 TNetXNGFileStager.cxx:28
 TNetXNGFileStager.cxx:29
 TNetXNGFileStager.cxx:30
 TNetXNGFileStager.cxx:31
 TNetXNGFileStager.cxx:32
 TNetXNGFileStager.cxx:33
 TNetXNGFileStager.cxx:34
 TNetXNGFileStager.cxx:35
 TNetXNGFileStager.cxx:36
 TNetXNGFileStager.cxx:37
 TNetXNGFileStager.cxx:38
 TNetXNGFileStager.cxx:39
 TNetXNGFileStager.cxx:40
 TNetXNGFileStager.cxx:41
 TNetXNGFileStager.cxx:42
 TNetXNGFileStager.cxx:43
 TNetXNGFileStager.cxx:44
 TNetXNGFileStager.cxx:45
 TNetXNGFileStager.cxx:46
 TNetXNGFileStager.cxx:47
 TNetXNGFileStager.cxx:48
 TNetXNGFileStager.cxx:49
 TNetXNGFileStager.cxx:50
 TNetXNGFileStager.cxx:51
 TNetXNGFileStager.cxx:52
 TNetXNGFileStager.cxx:53
 TNetXNGFileStager.cxx:54
 TNetXNGFileStager.cxx:55
 TNetXNGFileStager.cxx:56
 TNetXNGFileStager.cxx:57
 TNetXNGFileStager.cxx:58
 TNetXNGFileStager.cxx:59
 TNetXNGFileStager.cxx:60
 TNetXNGFileStager.cxx:61
 TNetXNGFileStager.cxx:62
 TNetXNGFileStager.cxx:63
 TNetXNGFileStager.cxx:64
 TNetXNGFileStager.cxx:65
 TNetXNGFileStager.cxx:66
 TNetXNGFileStager.cxx:67
 TNetXNGFileStager.cxx:68
 TNetXNGFileStager.cxx:69
 TNetXNGFileStager.cxx:70
 TNetXNGFileStager.cxx:71
 TNetXNGFileStager.cxx:72
 TNetXNGFileStager.cxx:73
 TNetXNGFileStager.cxx:74
 TNetXNGFileStager.cxx:75
 TNetXNGFileStager.cxx:76
 TNetXNGFileStager.cxx:77
 TNetXNGFileStager.cxx:78
 TNetXNGFileStager.cxx:79
 TNetXNGFileStager.cxx:80
 TNetXNGFileStager.cxx:81
 TNetXNGFileStager.cxx:82
 TNetXNGFileStager.cxx:83
 TNetXNGFileStager.cxx:84
 TNetXNGFileStager.cxx:85
 TNetXNGFileStager.cxx:86
 TNetXNGFileStager.cxx:87
 TNetXNGFileStager.cxx:88
 TNetXNGFileStager.cxx:89
 TNetXNGFileStager.cxx:90
 TNetXNGFileStager.cxx:91
 TNetXNGFileStager.cxx:92
 TNetXNGFileStager.cxx:93
 TNetXNGFileStager.cxx:94
 TNetXNGFileStager.cxx:95
 TNetXNGFileStager.cxx:96
 TNetXNGFileStager.cxx:97
 TNetXNGFileStager.cxx:98
 TNetXNGFileStager.cxx:99
 TNetXNGFileStager.cxx:100
 TNetXNGFileStager.cxx:101
 TNetXNGFileStager.cxx:102
 TNetXNGFileStager.cxx:103
 TNetXNGFileStager.cxx:104
 TNetXNGFileStager.cxx:105
 TNetXNGFileStager.cxx:106
 TNetXNGFileStager.cxx:107
 TNetXNGFileStager.cxx:108
 TNetXNGFileStager.cxx:109
 TNetXNGFileStager.cxx:110
 TNetXNGFileStager.cxx:111
 TNetXNGFileStager.cxx:112
 TNetXNGFileStager.cxx:113
 TNetXNGFileStager.cxx:114
 TNetXNGFileStager.cxx:115
 TNetXNGFileStager.cxx:116
 TNetXNGFileStager.cxx:117
 TNetXNGFileStager.cxx:118
 TNetXNGFileStager.cxx:119
 TNetXNGFileStager.cxx:120
 TNetXNGFileStager.cxx:121
 TNetXNGFileStager.cxx:122
 TNetXNGFileStager.cxx:123
 TNetXNGFileStager.cxx:124
 TNetXNGFileStager.cxx:125
 TNetXNGFileStager.cxx:126
 TNetXNGFileStager.cxx:127
 TNetXNGFileStager.cxx:128
 TNetXNGFileStager.cxx:129
 TNetXNGFileStager.cxx:130
 TNetXNGFileStager.cxx:131
 TNetXNGFileStager.cxx:132
 TNetXNGFileStager.cxx:133
 TNetXNGFileStager.cxx:134
 TNetXNGFileStager.cxx:135
 TNetXNGFileStager.cxx:136
 TNetXNGFileStager.cxx:137
 TNetXNGFileStager.cxx:138
 TNetXNGFileStager.cxx:139
 TNetXNGFileStager.cxx:140
 TNetXNGFileStager.cxx:141
 TNetXNGFileStager.cxx:142
 TNetXNGFileStager.cxx:143
 TNetXNGFileStager.cxx:144
 TNetXNGFileStager.cxx:145
 TNetXNGFileStager.cxx:146
 TNetXNGFileStager.cxx:147
 TNetXNGFileStager.cxx:148
 TNetXNGFileStager.cxx:149
 TNetXNGFileStager.cxx:150
 TNetXNGFileStager.cxx:151
 TNetXNGFileStager.cxx:152
 TNetXNGFileStager.cxx:153
 TNetXNGFileStager.cxx:154
 TNetXNGFileStager.cxx:155
 TNetXNGFileStager.cxx:156
 TNetXNGFileStager.cxx:157
 TNetXNGFileStager.cxx:158
 TNetXNGFileStager.cxx:159
 TNetXNGFileStager.cxx:160
 TNetXNGFileStager.cxx:161
 TNetXNGFileStager.cxx:162
 TNetXNGFileStager.cxx:163
 TNetXNGFileStager.cxx:164
 TNetXNGFileStager.cxx:165
 TNetXNGFileStager.cxx:166
 TNetXNGFileStager.cxx:167
 TNetXNGFileStager.cxx:168
 TNetXNGFileStager.cxx:169
 TNetXNGFileStager.cxx:170
 TNetXNGFileStager.cxx:171
 TNetXNGFileStager.cxx:172
 TNetXNGFileStager.cxx:173
 TNetXNGFileStager.cxx:174
 TNetXNGFileStager.cxx:175
 TNetXNGFileStager.cxx:176
 TNetXNGFileStager.cxx:177
 TNetXNGFileStager.cxx:178
 TNetXNGFileStager.cxx:179
 TNetXNGFileStager.cxx:180
 TNetXNGFileStager.cxx:181
 TNetXNGFileStager.cxx:182
 TNetXNGFileStager.cxx:183
 TNetXNGFileStager.cxx:184
 TNetXNGFileStager.cxx:185
 TNetXNGFileStager.cxx:186
 TNetXNGFileStager.cxx:187
 TNetXNGFileStager.cxx:188
 TNetXNGFileStager.cxx:189
 TNetXNGFileStager.cxx:190
 TNetXNGFileStager.cxx:191
 TNetXNGFileStager.cxx:192
 TNetXNGFileStager.cxx:193
 TNetXNGFileStager.cxx:194
 TNetXNGFileStager.cxx:195