XRootD
XrdClFileSystem.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // This file is part of the XRootD software suite.
6 //
7 // XRootD is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // XRootD is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19 //
20 // In applying this licence, CERN does not waive the privileges and immunities
21 // granted to it by virtue of its status as an Intergovernmental Organization
22 // or submit itself to any jurisdiction.
23 //------------------------------------------------------------------------------
24 
26 #include "XrdCl/XrdClFileSystem.hh"
27 #include "XrdCl/XrdClDefaultEnv.hh"
28 #include "XrdCl/XrdClLog.hh"
29 #include "XrdCl/XrdClConstants.hh"
30 #include "XrdCl/XrdClMessage.hh"
39 #include "XrdSys/XrdSysE2T.hh"
40 #include "XrdSys/XrdSysPthread.hh"
41 
42 #include <sys/stat.h>
43 
44 #include <memory>
45 #include <algorithm>
46 #include <iterator>
47 
48 namespace
49 {
50 
51  class LocalFS
52  {
53  public:
54 
55  XrdCl::XRootDStatus Stat( const std::string &path,
56  XrdCl::ResponseHandler *handler,
57  uint16_t timeout )
58  {
59  using namespace XrdCl;
60 
61  Log *log = DefaultEnv::GetLog();
62 
63  struct stat ssp;
64  if( stat( path.c_str(), &ssp ) == -1 )
65  {
66  log->Error( FileMsg, "Stat: failed: %s", XrdSysE2T( errno ) );
68  XProtocol::mapError( errno ) );
69  return QueueTask( error, 0, handler );
70  }
71 
72  // TODO support other mode options
73  uint32_t flags = S_ISDIR( ssp.st_mode ) ? kXR_isDir : 0;
74 
75  std::ostringstream data;
76  data << ssp.st_dev << " " << ssp.st_size << " " << flags << " "
77  << ssp.st_mtime;
78  log->Debug( FileMsg, "%s", data.str().c_str() );
79 
80  StatInfo *statInfo = new StatInfo();
81  if( !statInfo->ParseServerResponse( data.str().c_str() ) )
82  {
83  log->Error( FileMsg, "Stat: ParseServerResponse failed." );
84  delete statInfo;
85  return QueueTask( new XRootDStatus( stError, errErrorResponse, kXR_FSError ),
86  0, handler );
87  }
88 
89  AnyObject *resp = new AnyObject();
90  resp->Set( statInfo );
91  return QueueTask( new XRootDStatus(), resp, handler );
92  }
93 
94  XrdCl::XRootDStatus Rm( const std::string &path,
95  XrdCl::ResponseHandler *handler,
96  uint16_t timeout )
97  {
98  using namespace XrdCl;
99 
100  Log *log = DefaultEnv::GetLog();
101  if( unlink( path.c_str() ) )
102  {
103  log->Error( FileMsg, "Rm: failed: %s", XrdSysE2T( errno ) );
105  XProtocol::mapError( errno ) );
106  return QueueTask( error, 0, handler );
107  }
108 
109  return QueueTask( new XRootDStatus(), 0, handler );
110  }
111 
112  static LocalFS& Instance()
113  {
114  static LocalFS instance;
115  return instance;
116  }
117 
118  private:
119 
120  //------------------------------------------------------------------------
121  // Private constructors
122  //------------------------------------------------------------------------
123  LocalFS() : jmngr( XrdCl::DefaultEnv::GetPostMaster()->GetJobManager() )
124  {
125 
126  }
127 
128  //------------------------------------------------------------------------
129  // Private copy constructors
130  //------------------------------------------------------------------------
131  LocalFS( const LocalFS& );
132 
133  //------------------------------------------------------------------------
134  // Private assignment operator
135  //------------------------------------------------------------------------
136  LocalFS& operator=( const LocalFS& );
137 
138  //------------------------------------------------------------------------
139  // QueueTask - queues error/success tasks for all operations.
140  // Must always return stOK.
141  // Is always creating the same HostList containing only localhost.
142  //------------------------------------------------------------------------
144  XrdCl::ResponseHandler *handler )
145  {
146  using namespace XrdCl;
147 
148  // if it is simply the sync handler we can release the semaphore
149  // and return there is no need to execute this in the thread-pool
150  SyncResponseHandler *syncHandler =
151  dynamic_cast<SyncResponseHandler*>( handler );
152  if( syncHandler )
153  {
154  syncHandler->HandleResponse( st, resp );
155  return XRootDStatus();
156  }
157 
158  LocalFileTask *task = new LocalFileTask( st, resp, 0, handler );
159  jmngr->QueueJob( task );
160  return XRootDStatus();
161  }
162 
163  XrdCl::JobManager *jmngr;
164 
165  };
166 
167  //----------------------------------------------------------------------------
168  // Get delimiter for the opaque info
169  //----------------------------------------------------------------------------
170  char GetCgiDelimiter( bool &hasCgi )
171  {
172  if( !hasCgi )
173  {
174  hasCgi = true;
175  return '?';
176  }
177 
178  return '&';
179  }
180  //----------------------------------------------------------------------------
181  // Filters out client specific CGI
182  //----------------------------------------------------------------------------
183  std::string FilterXrdClCgi( const std::string &path )
184  {
185  // first check if there's an opaque info at all
186  size_t pos = path.find( '?' );
187  if( pos == std::string::npos )
188  return path;
189 
190  std::string filteredPath = path.substr( 0 , pos );
191  std::string cgi = path.substr( pos + 1 );
192 
193  bool hasCgi = false;
194  pos = 0;
195  size_t xrdcl = std::string::npos;
196  do
197  {
198  xrdcl = cgi.find( "xrdcl.", pos );
199 
200  if( xrdcl == std::string:: npos )
201  {
202  filteredPath += GetCgiDelimiter( hasCgi );
203  filteredPath += cgi.substr( pos );
204  pos = cgi.size();
205  }
206  else
207  {
208  if( xrdcl != pos )
209  {
210  filteredPath += GetCgiDelimiter( hasCgi );
211  filteredPath += cgi.substr( pos, xrdcl - 1 - pos );
212  }
213 
214  pos = cgi.find( '&', xrdcl );
215  if( pos != std::string::npos )
216  ++pos;
217  }
218 
219  }
220  while( pos < cgi.size() && pos != std::string::npos );
221 
222  return filteredPath;
223  }
224 
225  //----------------------------------------------------------------------------
227  //----------------------------------------------------------------------------
228  class DeallocFSHandler: public XrdCl::ResponseHandler
229  {
230  public:
231  //------------------------------------------------------------------------
232  // Constructor and destructor
233  //------------------------------------------------------------------------
234  DeallocFSHandler( XrdCl::FileSystem *fs, ResponseHandler *userHandler ):
235  pFS(fs), pUserHandler(userHandler) {}
236 
237  virtual ~DeallocFSHandler()
238  {
239  delete pFS;
240  }
241 
242  //------------------------------------------------------------------------
243  // Handle the response
244  //------------------------------------------------------------------------
245  virtual void HandleResponse( XrdCl::XRootDStatus *status,
246  XrdCl::AnyObject *response )
247  {
248  pUserHandler->HandleResponse(status, response);
249  delete this;
250  }
251 
252  private:
253  XrdCl::FileSystem *pFS;
254  ResponseHandler *pUserHandler;
255  };
256 
257  //----------------------------------------------------------------------------
258  // Deep locate handler
259  //----------------------------------------------------------------------------
260  class DeepLocateHandler: public XrdCl::ResponseHandler
261  {
262  public:
263  //------------------------------------------------------------------------
264  // Constructor
265  //------------------------------------------------------------------------
266  DeepLocateHandler( XrdCl::ResponseHandler *handler,
267  const std::string &path,
269  time_t timeout ):
270  pFirstTime( true ),
271  pPartial( false ),
272  pOutstanding( 1 ),
273  pHandler( handler ),
274  pPath( path ),
275  pFlags( flags )
276  {
277  if (timeout == 0) {
279  XrdCl::DefaultEnv::GetEnv()->GetInt("RequestTimeout", val);
280  timeout = val;
281  }
282 
283  pExpires = ::time(nullptr) + timeout;
284  pLocations = new XrdCl::LocationInfo();
285  }
286 
287  //------------------------------------------------------------------------
288  // Destructor
289  //------------------------------------------------------------------------
290  ~DeepLocateHandler()
291  {
292  delete pLocations;
293  }
294 
295  //------------------------------------------------------------------------
296  // Handle the response
297  //------------------------------------------------------------------------
298  virtual void HandleResponse( XrdCl::XRootDStatus *status,
299  XrdCl::AnyObject *response )
300  {
301  XrdSysMutexHelper scopedLock( pMutex );
302  using namespace XrdCl;
303  Log *log = DefaultEnv::GetLog();
304  --pOutstanding;
305 
306  //----------------------------------------------------------------------
307  // We've got an error, react accordingly
308  //----------------------------------------------------------------------
309  if( !status->IsOK() )
310  {
311  log->Dump( FileSystemMsg, "[%p@DeepLocate(%s)] Got error "
312  "response: %s", this, pPath.c_str(),
313  status->ToStr().c_str() );
314 
315  //--------------------------------------------------------------------
316  // We have failed with the first request
317  //--------------------------------------------------------------------
318  if( pFirstTime )
319  {
320  log->Debug( FileSystemMsg, "[%p@DeepLocate(%s)] Failed to get "
321  "the initial location list: %s", this, pPath.c_str(),
322  status->ToStr().c_str() );
323  pHandler->HandleResponse( status, response );
324  scopedLock.UnLock();
325  delete this;
326  return;
327  }
328 
329  pPartial = true;
330 
331  //--------------------------------------------------------------------
332  // We have no more outstanding requests, so let give to the client
333  // what we have
334  //--------------------------------------------------------------------
335  if( !pOutstanding )
336  {
337  log->Debug( FileSystemMsg, "[%p@DeepLocate(%s)] No outstanding "
338  "requests, give out what we've got", this,
339  pPath.c_str() );
340  scopedLock.UnLock();
341  HandleFinalResponse();
342  }
343  delete status;
344  return;
345  }
346  pFirstTime = false;
347 
348  //----------------------------------------------------------------------
349  // Extract the answer
350  //----------------------------------------------------------------------
351  LocationInfo *info = 0;
352  response->Get( info );
354 
355  log->Dump( FileSystemMsg, "[%p@DeepLocate(%s)] Got %d locations",
356  this, pPath.c_str(), info->GetSize() );
357 
358  for( it = info->Begin(); it != info->End(); ++it )
359  {
360  //--------------------------------------------------------------------
361  // Add the location to the list
362  //--------------------------------------------------------------------
363  if( it->IsServer() )
364  {
365  pLocations->Add( *it );
366  continue;
367  }
368 
369  //--------------------------------------------------------------------
370  // Ask the manager for the location of servers
371  //--------------------------------------------------------------------
372  if( it->IsManager() )
373  {
374  ++pOutstanding;
375  FileSystem *fs = new FileSystem( it->GetAddress() );
376  if( pOutstanding == 0 || // protect against overflow, short circuiting
377  // will make sure the other part won't be executed
378  !fs->Locate( pPath, pFlags, new DeallocFSHandler(fs, this),
379  pExpires-::time(0)).IsOK() )
380  {
381  --pOutstanding;
382  pPartial = true;
383  delete fs;
384  }
385  }
386  }
387 
388  //----------------------------------------------------------------------
389  // Clean up and check if we have anything else to do
390  //----------------------------------------------------------------------
391  delete response;
392  delete status;
393  if( !pOutstanding )
394  {
395  scopedLock.UnLock();
396  HandleFinalResponse();
397  }
398  }
399 
400  //------------------------------------------------------------------------
401  // Build the response for the client
402  //------------------------------------------------------------------------
403  void HandleFinalResponse()
404  {
405  using namespace XrdCl;
406 
407  //----------------------------------------------------------------------
408  // Nothing found
409  //----------------------------------------------------------------------
410  if( !pLocations->GetSize() )
411  {
412  pHandler->HandleResponse( new XRootDStatus( stError, errErrorResponse,
413  kXR_NotFound,
414  "No valid location found" ),
415  0 );
416  }
417  //----------------------------------------------------------------------
418  // We return an answer
419  //----------------------------------------------------------------------
420  else
421  {
422  AnyObject *obj = new AnyObject();
423  obj->Set( pLocations );
424  pLocations = 0;
425  XRootDStatus *st = new XRootDStatus();
426  if( pPartial ) st->code = suPartial;
427  pHandler->HandleResponse( st, obj );
428  }
429  delete this;
430  }
431 
432  private:
433  bool pFirstTime;
434  bool pPartial;
435  uint16_t pOutstanding;
436  XrdCl::ResponseHandler *pHandler;
437  XrdCl::LocationInfo *pLocations;
438  std::string pPath;
440  time_t pExpires;
441  XrdSysMutex pMutex;
442  };
443 
444  //----------------------------------------------------------------------------
445  // Handle stat results for a dirlist request
446  //----------------------------------------------------------------------------
447  class DirListStatHandler: public XrdCl::ResponseHandler
448  {
449  public:
450  //------------------------------------------------------------------------
451  // Constructor
452  //------------------------------------------------------------------------
453  DirListStatHandler( XrdCl::DirectoryList *list,
454  uint32_t index,
455  XrdCl::RequestSync *sync ):
456  pList( list ),
457  pIndex( index ),
458  pSync( sync )
459  {
460  }
461 
462  //------------------------------------------------------------------------
463  // Check if we were successful and if so put the StatInfo object
464  // in the appropriate entry info
465  //------------------------------------------------------------------------
466  virtual void HandleResponse( XrdCl::XRootDStatus *status,
467  XrdCl::AnyObject *response )
468  {
469  if( !status->IsOK() )
470  {
471  delete status;
472  pSync->TaskDone( false );
473  delete this;
474  return;
475  }
476 
477  XrdCl::StatInfo *info = 0;
478  response->Get( info );
479  response->Set( (char*) 0 );
480  pList->At( pIndex )->SetStatInfo( info );
481  delete status;
482  delete response;
483  pSync->TaskDone();
484  delete this;
485  }
486 
487  private:
488  XrdCl::DirectoryList *pList;
489  uint32_t pIndex;
490  XrdCl::RequestSync *pSync;
491  };
492 
493  //----------------------------------------------------------------------------
494  // Recursive dirlist common context for all handlers
495  //----------------------------------------------------------------------------
496  struct RecursiveDirListCtx
497  {
498  RecursiveDirListCtx( const XrdCl::URL &url, const std::string &path,
500  XrdCl::ResponseHandler *handler, time_t expires ) :
501  finalst( 0 ), pending( 1 ),
502  dirList( new XrdCl::DirectoryList() ), expires( expires ),
503  handler( handler ), flags( flags ),
504  fs( new XrdCl::FileSystem( url ) )
505  {
506  dirList->SetParentName( path );
507  }
508 
509  ~RecursiveDirListCtx()
510  {
511  delete finalst;
512  delete dirList;
513  delete fs;
514  }
515 
516  void UpdateStatus( const XrdCl::XRootDStatus &st )
517  {
518  using namespace XrdCl;
519 
520  if( !finalst )
521  {
522  finalst = st.IsOK() ? new XRootDStatus() : new XRootDStatus( st );
523  return;
524  }
525 
526  // if they disagree set the status to partial
527  if( ( finalst->IsOK() && !st.IsOK() ) ||
528  ( !finalst->IsOK() && st.IsOK() ) )
529  *finalst = XRootDStatus( stOK, suPartial );
530  }
531 
532  XrdCl::XRootDStatus *finalst;
533  int pending;
534  XrdCl::DirectoryList *dirList;
535  time_t expires;
536  XrdCl::ResponseHandler *handler;
538  XrdCl::FileSystem *fs;
539  XrdSysMutex mtx;
540  };
541 
542  //----------------------------------------------------------------------------
543  // Handle results for a recursive dirlist request
544  //----------------------------------------------------------------------------
545  class RecursiveDirListHandler: public XrdCl::ResponseHandler
546  {
547  public:
548 
549  RecursiveDirListHandler( const XrdCl::URL &url,
550  const std::string &path,
552  XrdCl::ResponseHandler *handler,
553  time_t timeout )
554  {
555  time_t expires = 0;
556  if( timeout )
557  expires = ::time( 0 ) + timeout;
558  pCtx = new RecursiveDirListCtx( url, path, flags,
559  handler, expires );
560  }
561 
562  RecursiveDirListHandler( RecursiveDirListCtx *ctx ) : pCtx( ctx )
563  {
564 
565  }
566 
567  virtual void HandleResponse( XrdCl::XRootDStatus *status,
568  XrdCl::AnyObject *response )
569  {
570  using namespace XrdCl;
571 
572  Log *log = DefaultEnv::GetLog();
573  bool finalrsp = !( status->IsOK() && status->code == XrdCl::suContinue );
574  XrdSysMutexHelper scoped( pCtx->mtx );
575 
576  // check if we have to continue with the same handler (the response
577  // has been chunked), if not we can decrement the number of pending
578  // DieLists
579  if( finalrsp )
580  --pCtx->pending;
581 
582  pCtx->UpdateStatus( *status );
583 
584  if( status->IsOK() )
585  {
586  // get the response
587  DirectoryList *dirList = 0;
588  response->Get( dirList );
589 
590  std::string parent = pCtx->dirList->GetParentName();
591 
593  for( itr = dirList->Begin(); itr != dirList->End(); ++itr )
594  {
595  DirectoryList::ListEntry *entry = *itr;
596  StatInfo *info = entry->GetStatInfo();
597  if( !info )
598  {
599  log->Error( FileMsg, "Recursive directory list operation for %s failed: "
600  "kXR_dirlist with stat operation not supported.",
601  parent.c_str() );
602  pCtx->UpdateStatus( XRootDStatus( stError, errNotSupported ) );
603  continue;
604  }
605  std::string path = dirList->GetParentName() + entry->GetName();
606 
607  // add new entry to the result
608  path = path.substr( parent.size() );
609  entry->SetStatInfo( 0 ); // StatInfo is no longer owned by dirList
611  new DirectoryList::ListEntry( entry->GetHostAddress(), path, info );
612  pCtx->dirList->Add( e );
613 
614  // if it's a directory do a recursive call
615  if( info->TestFlags( StatInfo::IsDir ) )
616  {
617  // bump the pending counter
618  ++pCtx->pending;
619  // switch of the recursive flag, we will
620  // provide the respective handler ourself,
621  // make sure that stat is on
622  DirListFlags::Flags flags = ( pCtx->flags & (~DirListFlags::Recursive) )
624  // the recursive dir list handler
625  RecursiveDirListHandler *handler = new RecursiveDirListHandler( pCtx );
626  // timeout
627  time_t timeout = 0;
628  if( pCtx->expires )
629  {
630  timeout = pCtx->expires - ::time( 0 );
631  if( timeout <= 0 )
632  {
633  log->Error( FileMsg, "Recursive directory list operation for %s expired.",
634  parent.c_str() );
635  pCtx->UpdateStatus( XRootDStatus( stError, errOperationExpired ) );
636  break;
637  }
638  }
639  // send the request
640  std::string child = parent + path;
641  XRootDStatus st = pCtx->fs->DirList( child, flags, handler, timeout );
642  if( !st.IsOK() )
643  {
644  log->Error( FileMsg, "Recursive directory list operation for %s failed: %s",
645  child.c_str(), st.ToString().c_str() );
646  pCtx->UpdateStatus( st );
647  continue;
648  }
649  }
650  }
651  }
652 
653  // if there are no more outstanding dirlist queries we can finalize the request
654  if( pCtx->pending == 0 )
655  {
656  AnyObject *resp = new AnyObject();
657  resp->Set( pCtx->dirList );
658  pCtx->dirList = 0; // dirList is no longer owned by pCtx
659  pCtx->handler->HandleResponse( pCtx->finalst, resp );
660  pCtx->finalst = 0; // status is no longer owned by pCtx
661 
662  // finalize the common context
663  scoped.UnLock();
664  delete pCtx;
665  }
666  // if the user requested chunked response we give what we have to the user handler
667  else if( status->IsOK() && ( pCtx->flags & DirListFlags::Chunked ) )
668  {
669  std::string parent = pCtx->dirList->GetParentName();
670  AnyObject *resp = new AnyObject();
671  resp->Set( pCtx->dirList );
672  pCtx->dirList = new XrdCl::DirectoryList();
673  pCtx->dirList->SetParentName( parent );
674  pCtx->handler->HandleResponse( new XRootDStatus( stOK, suContinue ), resp );
675  }
676 
677  // clean up the arguments
678  delete status;
679  delete response;
680  // if we won't be continuing with the same handler, it can be deleted
681  if( finalrsp )
682  delete this;
683  }
684 
685  private:
686 
687  RecursiveDirListCtx *pCtx;
688  };
689 
690  //----------------------------------------------------------------------------
691  // Exception for a merge dirlist handler
692  //----------------------------------------------------------------------------
693  struct MergeDirLsErr
694  {
695  MergeDirLsErr( XrdCl::XRootDStatus *&status, XrdCl::AnyObject *&response ) :
696  status( status ), response( response )
697  {
698  status = 0; response = 0;
699  }
700 
701  MergeDirLsErr() :
702  status( new XrdCl::XRootDStatus( XrdCl::stError, XrdCl::errInternal ) ),
703  response( 0 )
704  {
705 
706  }
707 
708  XrdCl::XRootDStatus *status;
709  XrdCl::AnyObject *response;
710  };
711 
712 
713 
714  //----------------------------------------------------------------------------
715  // Handle results for a merge dirlist request
716  //----------------------------------------------------------------------------
717  class MergeDirListHandler: public XrdCl::ResponseHandler
718  {
719  public:
720 
721  MergeDirListHandler( bool allowChunked, XrdCl::ResponseHandler *handler ) :
722  allowChunked( allowChunked ), pHandler( handler )
723  {
724 
725  }
726 
727  virtual void HandleResponse( XrdCl::XRootDStatus *status,
728  XrdCl::AnyObject *response )
729  {
730  XrdSysMutexHelper lck( mtx );
731 
732  bool finalrsp = !( status->IsOK() && status->code == XrdCl::suContinue );
733 
734  try
735  {
736  if( !status->IsOK() )
737  throw MergeDirLsErr( status, response );
738 
739  if( !response )
740  throw MergeDirLsErr();
741 
742  XrdCl::DirectoryList *dirlist = 0;
743  response->Get( dirlist );
744 
745  if( !dirlist )
746  throw MergeDirLsErr();
747 
748  if( allowChunked )
749  MergeChunked( dirlist );
750  else
751  Merge( dirlist );
752 
753  response->Set( dirlist );
754  pHandler->HandleResponse( status, response );
755  }
756  catch( const MergeDirLsErr &err )
757  {
758  delete status; delete response;
759  pHandler->HandleResponse( err.status, err.response );
760  }
761 
762  if( finalrsp )
763  {
764  lck.UnLock();
765  delete this;
766  }
767  }
768 
769  void MergeChunked( XrdCl::DirectoryList *&response )
770  {
771  using namespace XrdCl;
772 
773  std::set<ListEntry*, less> unique;
774  // set of unique list entries from the response
775  std::set<ListEntry*, less> tmp( response->Begin(), response->End() );
776  // all the unique list entries that were not reported so far
777  std::set_difference( tmp.begin(), tmp.end(),
778  uniquesofar.begin(), uniquesofar.end(),
779  std::inserter( unique, unique.end() ) );
780 
781  // we update the set of unique list entries that were already
782  // reported to the user's handler
783  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
784  {
785  ListEntry *ent = *itr;
786  if( !uniquesofar.count( ent ) )
787  {
788  StatInfo *info = ent->GetStatInfo() ? new StatInfo( *ent->GetStatInfo() ) : 0;
789  ListEntry *newent = new ListEntry( ent->GetHostAddress(), ent->GetName(), info );
790  uniquesofar.insert( newent );
791  }
792  }
793 
794  DirectoryList *dirlist = new DirectoryList();
795  dirlist->SetParentName( response->GetParentName() );
796  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
797  {
798  ListEntry *entry = *itr;
799  dirlist->Add( new ListEntry( entry->GetHostAddress(),
800  entry->GetName(),
801  entry->GetStatInfo() ) );
802  entry->SetStatInfo( 0 );
803  }
804 
805  delete response;
806  response = dirlist;
807  }
808 
809  static void Merge( XrdCl::DirectoryList *&response )
810  {
811  std::set<ListEntry*, less> unique( response->Begin(), response->End() );
812 
814  dirlist->SetParentName( response->GetParentName() );
815  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
816  {
817  ListEntry *entry = *itr;
818  dirlist->Add( new ListEntry( entry->GetHostAddress(),
819  entry->GetName(),
820  entry->GetStatInfo() ) );
821  entry->SetStatInfo( 0 );
822  }
823 
824  delete response;
825  response = dirlist;
826 }
827 
828  private:
829 
830  typedef XrdCl::DirectoryList::ListEntry ListEntry;
831 
832  struct less
833  {
834  bool operator() (const ListEntry *x, const ListEntry *y) const
835  {
836  if( x->GetName() != y->GetName() )
837  return x->GetName() < y->GetName();
838 
839  const XrdCl::StatInfo *xStatInfo = x->GetStatInfo();
840  const XrdCl::StatInfo *yStatInfo = y->GetStatInfo();
841 
842  if( xStatInfo == yStatInfo )
843  return false;
844 
845  if( xStatInfo == 0 )
846  return true;
847 
848  if( yStatInfo == 0 )
849  return false;
850 
851  if( xStatInfo->GetSize() != yStatInfo->GetSize() )
852  return xStatInfo->GetSize() < yStatInfo->GetSize();
853 
854  if( xStatInfo->GetFlags() != yStatInfo->GetFlags() )
855  return xStatInfo->GetFlags() < yStatInfo->GetFlags();
856 
857  return false;
858  }
859  };
860 
861  bool allowChunked;
862  XrdSysMutex mtx;
863  std::set<ListEntry*, less> uniquesofar;
864  XrdCl::ResponseHandler *pHandler;
865  };
866 }
867 
868 namespace XrdCl
869 {
870  struct FileSystemData;
871 
872  //----------------------------------------------------------------------------
874  //----------------------------------------------------------------------------
876  {
877  public:
878  //------------------------------------------------------------------------
879  // Constructor and destructor
880  //------------------------------------------------------------------------
881  AssignLBHandler( std::shared_ptr<FileSystemData> &fs,
882  ResponseHandler *userHandler ):
883  pFS(fs), pUserHandler(userHandler) {}
884 
885  virtual ~AssignLBHandler() {}
886 
887  //------------------------------------------------------------------------
888  // Response callback
889  //------------------------------------------------------------------------
890  virtual void HandleResponseWithHosts( XRootDStatus *status,
891  AnyObject *response,
892  HostList *hostList );
893 
894  private:
895  std::shared_ptr<FileSystemData> pFS;
896  ResponseHandler *pUserHandler;
897  };
898 
899  //----------------------------------------------------------------------------
901  //----------------------------------------------------------------------------
903  {
904  public:
905  //------------------------------------------------------------------------
906  // Constructor and destructor
907  //------------------------------------------------------------------------
908  AssignLastURLHandler( std::shared_ptr<FileSystemData> &fs,
909  ResponseHandler *userHandler ):
910  pFS(fs), pUserHandler(userHandler) {}
911 
913 
914  //------------------------------------------------------------------------
915  // Response callback
916  //------------------------------------------------------------------------
917  virtual void HandleResponseWithHosts( XRootDStatus *status,
918  AnyObject *response,
919  HostList *hostList );
920 
921  private:
922  std::shared_ptr<FileSystemData> pFS;
923  ResponseHandler *pUserHandler;
924  };
925 
926 
928  {
929  FileSystemData( const URL &url ) :
930  pLoadBalancerLookupDone( false ),
931  pFollowRedirects( true ),
932  pUrl( new URL( url.GetURL() ) )
933  {
934  }
935 
936  //------------------------------------------------------------------------
937  // Send a message in a locked environment
938  //------------------------------------------------------------------------
939  static XRootDStatus Send( std::shared_ptr<FileSystemData> &fs,
940  Message *msg,
941  ResponseHandler *handler,
942  MessageSendParams &params )
943  {
944  Log *log = DefaultEnv::GetLog();
945  XrdSysMutexHelper scopedLock( fs->pMutex );
946 
947  log->Dump( FileSystemMsg, "[%p@%s] Sending %s", fs.get(),
948  fs->pUrl->GetHostId().c_str(), msg->GetObfuscatedDescription().c_str() );
949 
950  AssignLastURLHandler *lastUrlHandler = new AssignLastURLHandler( fs, handler );
951  handler = lastUrlHandler;
952 
953  AssignLBHandler *lbHandler = nullptr;
954  if( !fs->pLoadBalancerLookupDone && fs->pFollowRedirects )
955  {
956  lbHandler = new AssignLBHandler( fs, handler );
957  handler = lbHandler;
958  }
959 
960  params.followRedirects = fs->pFollowRedirects;
961 
962  auto st = MessageUtils::SendMessage( *fs->pUrl, msg, handler, params, 0 );
963  if( !st.IsOK() )
964  {
965  delete lastUrlHandler;
966  delete lbHandler;
967  }
968 
969  return st;
970  }
971 
972  //----------------------------------------------------------------------------
973  // Assign a load balancer if it has not already been assigned
974  //----------------------------------------------------------------------------
975  void AssignLoadBalancer( const URL &url )
976  {
977  Log *log = DefaultEnv::GetLog();
978  XrdSysMutexHelper scopedLock( pMutex );
979 
980  if( pLoadBalancerLookupDone )
981  return;
982 
983  log->Dump( FileSystemMsg, "[%p@%s] Assigning %s as load balancer", this,
984  pUrl->GetHostId().c_str(), url.GetHostId().c_str() );
985 
986  pUrl.reset( new URL( url ) );
987  pLoadBalancerLookupDone = true;
988  }
989 
990  //----------------------------------------------------------------------------
991  // Assign last URL
992  //----------------------------------------------------------------------------
993  void AssignLastURL( const URL &url )
994  {
995  Log *log = DefaultEnv::GetLog();
996  XrdSysMutexHelper scopedLock( pMutex );
997 
998  log->Dump( FileSystemMsg, "[%p@%s] Assigning %s as last URL", this,
999  pUrl->GetHostId().c_str(), url.GetHostId().c_str() );
1000 
1001  pLastUrl.reset( new URL( url ) );
1002  }
1003 
1007  std::unique_ptr<URL> pUrl;
1008  std::unique_ptr<URL> pLastUrl;
1009  };
1010 
1011  //----------------------------------------------------------------------------
1013  //----------------------------------------------------------------------------
1015  {
1016  FileSystemImpl( const URL &url ) :
1017  fsdata( std::make_shared<FileSystemData>( url ) )
1018  {
1019  }
1020 
1021  std::shared_ptr<FileSystemData> fsdata;
1022  };
1023 
1024  //------------------------------------------------------------------------
1025  // Response callback
1026  //------------------------------------------------------------------------
1027  void AssignLBHandler::HandleResponseWithHosts( XRootDStatus *status,
1028  AnyObject *response,
1029  HostList *hostList )
1030  {
1031  if( status->IsOK() )
1032  {
1033  HostList::reverse_iterator it;
1034  for( it = hostList->rbegin(); it != hostList->rend(); ++it )
1035  if( it->loadBalancer )
1036  {
1037  pFS->AssignLoadBalancer( it->url );
1038  break;
1039  }
1040  }
1041 
1042  bool finalrsp = !( status->IsOK() && status->code == suContinue );
1043 
1044  SyncResponseHandler * syncHandler = dynamic_cast<SyncResponseHandler*>( pUserHandler );
1045  if( !syncHandler )
1046  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1047 
1048  if( finalrsp )
1049  {
1050  if( syncHandler )
1051  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1052  delete this;
1053  }
1054  }
1055 
1056  //------------------------------------------------------------------------
1057  // Response callback
1058  //------------------------------------------------------------------------
1059  void AssignLastURLHandler::HandleResponseWithHosts( XRootDStatus *status,
1060  AnyObject *response,
1061  HostList *hostList )
1062  {
1063  if( status->IsOK() && hostList )
1064  pFS->AssignLastURL( hostList->front().url );
1065 
1066  bool finalrsp = !( status->IsOK() && status->code == suContinue );
1067 
1068  SyncResponseHandler *syncHandler = dynamic_cast<SyncResponseHandler*>( pUserHandler );
1069  if( !syncHandler )
1070  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1071 
1072  if( finalrsp )
1073  {
1074  if( syncHandler )
1075  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1076  delete this;
1077  }
1078  }
1079 
1080  //----------------------------------------------------------------------------
1081  // Constructor
1082  //----------------------------------------------------------------------------
1083  FileSystem::FileSystem( const URL &url, bool enablePlugIns ):
1084  pImpl( new FileSystemImpl( url ) ),
1085  pPlugIn(0)
1086  {
1087  //--------------------------------------------------------------------------
1088  // Check if we need to install a plug-in for this URL
1089  //--------------------------------------------------------------------------
1090  if( enablePlugIns )
1091  {
1092  Log *log = DefaultEnv::GetLog();
1093  std::string urlStr = url.GetURL();
1095  if( fact )
1096  {
1097  pPlugIn = fact->CreateFileSystem( urlStr );
1098  if( !pPlugIn )
1099  {
1100  log->Error( FileMsg, "Plug-in factory failed to produce a plug-in "
1101  "for %s, continuing without one", url.GetObfuscatedURL().c_str() );
1102  }
1103  }
1104  }
1105 
1106  if( !pPlugIn )
1108  }
1109 
1110  //----------------------------------------------------------------------------
1111  // Destructor
1112  //----------------------------------------------------------------------------
1114  {
1115  if( !pPlugIn )
1116  {
1119  }
1120 
1121  delete pPlugIn;
1122  delete pImpl;
1123  }
1124 
1125  //----------------------------------------------------------------------------
1126  // Locate a file - async
1127  //----------------------------------------------------------------------------
1128  XRootDStatus FileSystem::Locate( const std::string &path,
1129  OpenFlags::Flags flags,
1130  ResponseHandler *handler,
1131  uint16_t timeout )
1132  {
1133  if( pPlugIn )
1134  return pPlugIn->Locate( path, flags, handler, timeout );
1135 
1136  std::string fPath = FilterXrdClCgi( path );
1137 
1138  Message *msg;
1139  ClientLocateRequest *req;
1140  MessageUtils::CreateRequest( msg, req, fPath.length() );
1141 
1142  req->requestid = kXR_locate;
1143  req->options = flags;
1144  req->dlen = fPath.length();
1145  msg->Append( fPath.c_str(), fPath.length(), 24 );
1146  MessageSendParams params; params.timeout = timeout;
1148 
1150 
1151  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1152  }
1153 
1154  //----------------------------------------------------------------------------
1155  // Locate a file - sync
1156  //----------------------------------------------------------------------------
1157  XRootDStatus FileSystem::Locate( const std::string &path,
1158  OpenFlags::Flags flags,
1159  LocationInfo *&response,
1160  uint16_t timeout )
1161  {
1162  SyncResponseHandler handler;
1163  Status st = Locate( path, flags, &handler, timeout );
1164  if( !st.IsOK() )
1165  return st;
1166 
1167  return MessageUtils::WaitForResponse( &handler, response );
1168  }
1169 
1170  //----------------------------------------------------------------------------
1171  // Locate a file, recursively locate all disk servers - async
1172  //----------------------------------------------------------------------------
1173  XRootDStatus FileSystem::DeepLocate( const std::string &path,
1174  OpenFlags::Flags flags,
1175  ResponseHandler *handler,
1176  uint16_t timeout )
1177  {
1178  return Locate( path, flags,
1179  new DeepLocateHandler( handler, path, flags, timeout ), timeout );
1180  }
1181 
1182  //----------------------------------------------------------------------------
1183  // Locate a file, recursively locate all disk servers - sync
1184  //----------------------------------------------------------------------------
1185  XRootDStatus FileSystem::DeepLocate( const std::string &path,
1186  OpenFlags::Flags flags,
1187  LocationInfo *&response,
1188  uint16_t timeout )
1189  {
1190  SyncResponseHandler handler;
1191  Status st = DeepLocate( path, flags, &handler, timeout );
1192  if( !st.IsOK() )
1193  return st;
1194 
1195  return MessageUtils::WaitForResponse( &handler, response );
1196  }
1197 
1198  //----------------------------------------------------------------------------
1199  // Move a directory or a file - async
1200  //----------------------------------------------------------------------------
1201  XRootDStatus FileSystem::Mv( const std::string &source,
1202  const std::string &dest,
1203  ResponseHandler *handler,
1204  uint16_t timeout )
1205  {
1206  if( pPlugIn )
1207  return pPlugIn->Mv( source, dest, handler, timeout );
1208 
1209  std::string fSource = FilterXrdClCgi( source );
1210  std::string fDest = FilterXrdClCgi( dest );
1211 
1212  Message *msg;
1213  ClientMvRequest *req;
1214  MessageUtils::CreateRequest( msg, req, fSource.length() + fDest.length()+1 );
1215 
1216  req->requestid = kXR_mv;
1217  req->dlen = fSource.length() + fDest.length()+1;
1218  req->arg1len = fSource.length();
1219  msg->Append( fSource.c_str(), fSource.length(), 24 );
1220  *msg->GetBuffer(24 + fSource.length()) = ' ';
1221  msg->Append( fDest.c_str(), fDest.length(), 25 + fSource.length() );
1222  MessageSendParams params; params.timeout = timeout;
1224 
1226 
1227  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1228  }
1229 
1230  //----------------------------------------------------------------------------
1231  // Move a directory or a file - sync
1232  //----------------------------------------------------------------------------
1233  XRootDStatus FileSystem::Mv( const std::string &source,
1234  const std::string &dest,
1235  uint16_t timeout )
1236  {
1237  SyncResponseHandler handler;
1238  Status st = Mv( source, dest, &handler, timeout );
1239  if( !st.IsOK() )
1240  return st;
1241 
1242  return MessageUtils::WaitForStatus( &handler );
1243  }
1244 
1245  //----------------------------------------------------------------------------
1246  // Obtain server information - async
1247  //----------------------------------------------------------------------------
1249  const Buffer &arg,
1250  ResponseHandler *handler,
1251  uint16_t timeout )
1252  {
1253  if( pPlugIn )
1254  return pPlugIn->Query( queryCode, arg, handler, timeout );
1255 
1256  Message *msg;
1257  ClientQueryRequest *req;
1258  MessageUtils::CreateRequest( msg, req, arg.GetSize() );
1259 
1260  req->requestid = kXR_query;
1261  req->infotype = queryCode;
1262  req->dlen = arg.GetSize();
1263  msg->Append( arg.GetBuffer(), arg.GetSize(), 24 );
1264  MessageSendParams params; params.timeout = timeout;
1267 
1268  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1269  }
1270 
1271  //----------------------------------------------------------------------------
1272  // Obtain server information - sync
1273  //----------------------------------------------------------------------------
1275  const Buffer &arg,
1276  Buffer *&response,
1277  uint16_t timeout )
1278  {
1279  SyncResponseHandler handler;
1280  Status st = Query( queryCode, arg, &handler, timeout );
1281  if( !st.IsOK() )
1282  return st;
1283 
1284  return MessageUtils::WaitForResponse( &handler, response );
1285  }
1286 
1287  //----------------------------------------------------------------------------
1288  // Truncate a file - async
1289  //----------------------------------------------------------------------------
1290  XRootDStatus FileSystem::Truncate( const std::string &path,
1291  uint64_t size,
1292  ResponseHandler *handler,
1293  uint16_t timeout )
1294  {
1295  if( pPlugIn )
1296  return pPlugIn->Truncate( path, size, handler, timeout );
1297 
1298  std::string fPath = FilterXrdClCgi( path );
1299 
1300  Message *msg;
1301  ClientTruncateRequest *req;
1302  MessageUtils::CreateRequest( msg, req, fPath.length() );
1303 
1304  req->requestid = kXR_truncate;
1305  req->offset = size;
1306  req->dlen = fPath.length();
1307  msg->Append( fPath.c_str(), fPath.length(), 24 );
1308  MessageSendParams params; params.timeout = timeout;
1311 
1312  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1313  }
1314 
1315  //----------------------------------------------------------------------------
1316  // Truncate a file - sync
1317  //----------------------------------------------------------------------------
1318  XRootDStatus FileSystem::Truncate( const std::string &path,
1319  uint64_t size,
1320  uint16_t timeout )
1321  {
1322  SyncResponseHandler handler;
1323  Status st = Truncate( path, size, &handler, timeout );
1324  if( !st.IsOK() )
1325  return st;
1326 
1327  return MessageUtils::WaitForStatus( &handler );
1328  }
1329 
1330  //----------------------------------------------------------------------------
1331  // Remove a file - async
1332  //----------------------------------------------------------------------------
1333  XRootDStatus FileSystem::Rm( const std::string &path,
1334  ResponseHandler *handler,
1335  uint16_t timeout )
1336  {
1337  if( pPlugIn )
1338  return pPlugIn->Rm( path, handler, timeout );
1339 
1340  if( pImpl->fsdata->pUrl->IsLocalFile() )
1341  return LocalFS::Instance().Rm( path, handler, timeout );
1342 
1343  std::string fPath = FilterXrdClCgi( path );
1344 
1345  Message *msg;
1346  ClientRmRequest *req;
1347  MessageUtils::CreateRequest( msg, req, fPath.length() );
1348 
1349  req->requestid = kXR_rm;
1350  req->dlen = fPath.length();
1351  msg->Append( fPath.c_str(), fPath.length(), 24 );
1352  MessageSendParams params; params.timeout = timeout;
1355 
1356  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1357  }
1358 
1359  //----------------------------------------------------------------------------
1360  // Remove a file - sync
1361  //----------------------------------------------------------------------------
1362  XRootDStatus FileSystem::Rm( const std::string &path,
1363  uint16_t timeout )
1364  {
1365  SyncResponseHandler handler;
1366  Status st = Rm( path, &handler, timeout );
1367  if( !st.IsOK() )
1368  return st;
1369 
1370  return MessageUtils::WaitForStatus( &handler );
1371  }
1372 
1373  //----------------------------------------------------------------------------
1374  // Create a directory - async
1375  //----------------------------------------------------------------------------
1376  XRootDStatus FileSystem::MkDir( const std::string &path,
1377  MkDirFlags::Flags flags,
1378  Access::Mode mode,
1379  ResponseHandler *handler,
1380  uint16_t timeout )
1381  {
1382  if( pPlugIn )
1383  return pPlugIn->MkDir( path, flags, mode, handler, timeout );
1384 
1385  std::string fPath = FilterXrdClCgi( path );
1386 
1387  Message *msg;
1388  ClientMkdirRequest *req;
1389  MessageUtils::CreateRequest( msg, req, fPath.length() );
1390 
1391  req->requestid = kXR_mkdir;
1392  req->options[0] = flags;
1393  req->mode = mode;
1394  req->dlen = fPath.length();
1395  msg->Append( fPath.c_str(), fPath.length(), 24 );
1396  MessageSendParams params; params.timeout = timeout;
1399 
1400  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1401  }
1402 
1403  //----------------------------------------------------------------------------
1404  // Create a directory - sync
1405  //----------------------------------------------------------------------------
1406  XRootDStatus FileSystem::MkDir( const std::string &path,
1407  MkDirFlags::Flags flags,
1408  Access::Mode mode,
1409  uint16_t timeout )
1410  {
1411  SyncResponseHandler handler;
1412  Status st = MkDir( path, flags, mode, &handler, timeout );
1413  if( !st.IsOK() )
1414  return st;
1415 
1416  return MessageUtils::WaitForStatus( &handler );
1417  }
1418 
1419  //----------------------------------------------------------------------------
1420  // Remove a directory - async
1421  //----------------------------------------------------------------------------
1422  XRootDStatus FileSystem::RmDir( const std::string &path,
1423  ResponseHandler *handler,
1424  uint16_t timeout )
1425  {
1426  if( pPlugIn )
1427  return pPlugIn->RmDir( path, handler, timeout );
1428 
1429  std::string fPath = FilterXrdClCgi( path );
1430 
1431  Message *msg;
1432  ClientRmdirRequest *req;
1433  MessageUtils::CreateRequest( msg, req, fPath.length() );
1434 
1435  req->requestid = kXR_rmdir;
1436  req->dlen = fPath.length();
1437  msg->Append( fPath.c_str(), fPath.length(), 24 );
1438  MessageSendParams params; params.timeout = timeout;
1441 
1442  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1443  }
1444 
1445  //----------------------------------------------------------------------------
1446  // Remove a directory - sync
1447  //----------------------------------------------------------------------------
1448  XRootDStatus FileSystem::RmDir( const std::string &path,
1449  uint16_t timeout )
1450  {
1451  SyncResponseHandler handler;
1452  Status st = RmDir( path, &handler, timeout );
1453  if( !st.IsOK() )
1454  return st;
1455 
1456  return MessageUtils::WaitForStatus( &handler );
1457  }
1458 
1459  //----------------------------------------------------------------------------
1460  // Change access mode on a directory or a file - async
1461  //----------------------------------------------------------------------------
1462  XRootDStatus FileSystem::ChMod( const std::string &path,
1463  Access::Mode mode,
1464  ResponseHandler *handler,
1465  uint16_t timeout )
1466  {
1467  if( pPlugIn )
1468  return pPlugIn->ChMod( path, mode, handler, timeout );
1469 
1470  std::string fPath = FilterXrdClCgi( path );
1471 
1472  Message *msg;
1473  ClientChmodRequest *req;
1474  MessageUtils::CreateRequest( msg, req, fPath.length() );
1475 
1476  req->requestid = kXR_chmod;
1477  req->mode = mode;
1478  req->dlen = fPath.length();
1479  msg->Append( fPath.c_str(), fPath.length(), 24 );
1480  MessageSendParams params; params.timeout = timeout;
1483 
1484  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1485  }
1486 
1487  //----------------------------------------------------------------------------
1488  // Change access mode on a directory or a file - async
1489  //----------------------------------------------------------------------------
1490  XRootDStatus FileSystem::ChMod( const std::string &path,
1491  Access::Mode mode,
1492  uint16_t timeout )
1493  {
1494  SyncResponseHandler handler;
1495  Status st = ChMod( path, mode, &handler, timeout );
1496  if( !st.IsOK() )
1497  return st;
1498 
1499  return MessageUtils::WaitForStatus( &handler );
1500  }
1501 
1502  //----------------------------------------------------------------------------
1503  // Check if the server is alive - async
1504  //----------------------------------------------------------------------------
1506  uint16_t timeout )
1507  {
1508  if( pPlugIn )
1509  return pPlugIn->Ping( handler, timeout );
1510 
1511  Message *msg;
1512  ClientPingRequest *req;
1513  MessageUtils::CreateRequest( msg, req );
1514 
1515  req->requestid = kXR_ping;
1516  MessageSendParams params; params.timeout = timeout;
1519 
1520  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1521  }
1522 
1523  //----------------------------------------------------------------------------
1524  // Check if the server is alive - sync
1525  //----------------------------------------------------------------------------
1526  XRootDStatus FileSystem::Ping( uint16_t timeout )
1527  {
1528  SyncResponseHandler handler;
1529  Status st = Ping( &handler, timeout );
1530  if( !st.IsOK() )
1531  return st;
1532 
1533  return MessageUtils::WaitForStatus( &handler );
1534  }
1535 
1536  //----------------------------------------------------------------------------
1537  // Obtain status information for a path - async
1538  //----------------------------------------------------------------------------
1539  XRootDStatus FileSystem::Stat( const std::string &path,
1540  ResponseHandler *handler,
1541  uint16_t timeout )
1542  {
1543  if( pPlugIn )
1544  return pPlugIn->Stat( path, handler, timeout );
1545 
1546  if( pImpl->fsdata->pUrl->IsLocalFile() )
1547  return LocalFS::Instance().Stat( path, handler, timeout );
1548 
1549  std::string fPath = FilterXrdClCgi( path );
1550 
1551  Message *msg;
1552  ClientStatRequest *req;
1553  MessageUtils::CreateRequest( msg, req, fPath.length() );
1554 
1555  req->requestid = kXR_stat;
1556  req->options = 0;
1557  req->dlen = fPath.length();
1558  msg->Append( fPath.c_str(), fPath.length(), 24 );
1559  MessageSendParams params; params.timeout = timeout;
1562 
1563  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1564  }
1565 
1566  //----------------------------------------------------------------------------
1567  // Obtain status information for a path - sync
1568  //----------------------------------------------------------------------------
1569  XRootDStatus FileSystem::Stat( const std::string &path,
1570  StatInfo *&response,
1571  uint16_t timeout )
1572  {
1573  SyncResponseHandler handler;
1574  Status st = Stat( path, &handler, timeout );
1575  if( !st.IsOK() )
1576  return st;
1577 
1578  return MessageUtils::WaitForResponse( &handler, response );
1579  }
1580 
1581  //----------------------------------------------------------------------------
1582  // Obtain status information for a path - async
1583  //----------------------------------------------------------------------------
1584  XRootDStatus FileSystem::StatVFS( const std::string &path,
1585  ResponseHandler *handler,
1586  uint16_t timeout )
1587  {
1588  if( pPlugIn )
1589  return pPlugIn->StatVFS( path, handler, timeout );
1590 
1591  std::string fPath = FilterXrdClCgi( path );
1592 
1593  Message *msg;
1594  ClientStatRequest *req;
1595  MessageUtils::CreateRequest( msg, req, fPath.length() );
1596 
1597  req->requestid = kXR_stat;
1598  req->options = kXR_vfs;
1599  req->dlen = fPath.length();
1600  msg->Append( fPath.c_str(), fPath.length(), 24 );
1601  MessageSendParams params; params.timeout = timeout;
1604 
1605  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1606  }
1607 
1608  //----------------------------------------------------------------------------
1609  // Obtain status information for a path - sync
1610  //----------------------------------------------------------------------------
1611  XRootDStatus FileSystem::StatVFS( const std::string &path,
1612  StatInfoVFS *&response,
1613  uint16_t timeout )
1614  {
1615  SyncResponseHandler handler;
1616  Status st = StatVFS( path, &handler, timeout );
1617  if( !st.IsOK() )
1618  return st;
1619 
1620  return MessageUtils::WaitForResponse( &handler, response );
1621  }
1622 
1623  //----------------------------------------------------------------------------
1624  // Obtain server protocol information - async
1625  //----------------------------------------------------------------------------
1627  uint16_t timeout )
1628  {
1629  if( pPlugIn )
1630  return pPlugIn->Protocol( handler, timeout );
1631 
1632  Message *msg;
1633  ClientProtocolRequest *req;
1634  MessageUtils::CreateRequest( msg, req );
1635 
1636  req->requestid = kXR_protocol;
1638  MessageSendParams params; params.timeout = timeout;
1641 
1642  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1643  }
1644 
1645  //----------------------------------------------------------------------------
1646  // Obtain server protocol information - sync
1647  //----------------------------------------------------------------------------
1649  uint16_t timeout )
1650  {
1651  SyncResponseHandler handler;
1652  Status st = Protocol( &handler, timeout );
1653  if( !st.IsOK() )
1654  return st;
1655 
1656  return MessageUtils::WaitForResponse( &handler, response );
1657  }
1658 
1659  //----------------------------------------------------------------------------
1660  // List entries of a directory - async
1661  //----------------------------------------------------------------------------
1662  XRootDStatus FileSystem::DirList( const std::string &path,
1663  DirListFlags::Flags flags,
1664  ResponseHandler *handler,
1665  uint16_t timeout )
1666  {
1667  if( pPlugIn )
1668  return pPlugIn->DirList( path, flags, handler, timeout );
1669 
1670  URL url = URL( path );
1671  std::string fPath = FilterXrdClCgi( path );
1672 
1673  if( flags & DirListFlags::Zip )
1674  {
1675  // stat the file to check if it is a directory or a file
1676  // the ZIP handler will take care of the rest
1677  ZipListHandler *zipHandler = new ZipListHandler( *pImpl->fsdata->pUrl, path, flags, handler, timeout );
1678  XRootDStatus st = Stat( path, zipHandler, timeout );
1679  if( !st.IsOK() )
1680  delete zipHandler;
1681  return st;
1682  }
1683 
1684  Message *msg;
1685  ClientDirlistRequest *req;
1686  MessageUtils::CreateRequest( msg, req, fPath.length() );
1687 
1688  req->requestid = kXR_dirlist;
1689  req->dlen = fPath.length();
1690 
1691  if( ( flags & DirListFlags::Stat ) || ( flags & DirListFlags::Recursive ) )
1692  req->options[0] = kXR_dstat;
1693 
1694  if( ( flags & DirListFlags::Cksm ) )
1695  req->options[0] = kXR_dstat | kXR_dcksm;
1696 
1697  if( flags & DirListFlags::Recursive )
1698  handler = new RecursiveDirListHandler( *pImpl->fsdata->pUrl, url.GetPath(), flags, handler, timeout );
1699 
1700  if( flags & DirListFlags::Merge )
1701  handler = new MergeDirListHandler( flags & DirListFlags::Chunked, handler );
1702 
1703  msg->Append( fPath.c_str(), fPath.length(), 24 );
1704  MessageSendParams params; params.timeout = timeout;
1705  if( flags & DirListFlags::Chunked )
1706  params.chunkedResponse = true;
1709 
1710  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1711  }
1712 
1713  //----------------------------------------------------------------------------
1714  // List entries of a directory - sync
1715  //----------------------------------------------------------------------------
1716  XRootDStatus FileSystem::DirList( const std::string &path,
1717  DirListFlags::Flags flags,
1718  DirectoryList *&response,
1719  uint16_t timeout )
1720  {
1721  //--------------------------------------------------------------------------
1722  // Chunked response is only possible for async DirList call
1723  //--------------------------------------------------------------------------
1724  if( flags & DirListFlags::Chunked )
1726 
1727  //--------------------------------------------------------------------------
1728  // If the path ends with '.zip' extension add Zip flag
1729  //--------------------------------------------------------------------------
1730  static const std::string zip_sufix = ".zip";
1731  if( path.size() >= zip_sufix.size() &&
1732  std::equal( zip_sufix.rbegin(), zip_sufix.rend(), path.rbegin() ) )
1733  flags |= DirListFlags::Zip;
1734 
1735  //--------------------------------------------------------------------------
1736  // We do the deep locate and ask all the returned servers for the list
1737  //--------------------------------------------------------------------------
1738  if( flags & DirListFlags::Locate )
1739  {
1740  bool isserver = false;
1741  //------------------------------------------------------------------------
1742  // Check if destination is a data server
1743  //------------------------------------------------------------------------
1744  {
1745  AnyObject obj;
1747  *pImpl->fsdata->pUrl, XRootDQuery::ServerFlags, obj);
1748 
1749  if( st.IsOK() )
1750  {
1751  int *ptr = 0;
1752  obj.Get( ptr );
1753  isserver = ( *ptr & kXR_isServer );
1754  delete ptr;
1755  }
1756  }
1757 
1758  if (isserver) {
1759  // Just disable the locate flag if we are talking to a single server
1760  flags &= ~DirListFlags::Locate;
1761  } else {
1762  //------------------------------------------------------------------------
1763  // Locate all the disk servers holding the directory
1764  //------------------------------------------------------------------------
1765  LocationInfo *locations;
1766  std::string locatePath = "*"; locatePath += path;
1767 
1768  XRootDStatus st = DeepLocate(locatePath,
1772  locations);
1773 
1774  if( !st.IsOK() )
1775  return st;
1776 
1777  if( locations->GetSize() == 0 )
1778  {
1779  delete locations;
1780  return XRootDStatus( stError, errNotFound );
1781  }
1782 
1783  //------------------------------------------------------------------------
1784  // Ask each server for a directory list
1785  //------------------------------------------------------------------------
1786  flags &= ~DirListFlags::Locate;
1787  FileSystem *fs;
1788  DirectoryList *currentResp = 0;
1789  uint32_t errors = 0;
1790  uint32_t numLocations = locations->GetSize();
1791  bool partial = st.code == suPartial ? true : false;
1792 
1793  response = new DirectoryList();
1794  response->SetParentName( path );
1795 
1796  for( uint32_t i = 0; i < locations->GetSize(); ++i )
1797  {
1798  URL locationURL( locations->At(i).GetAddress() );
1799  // make sure the original protocol is preserved (root vs roots)
1800  locationURL.SetProtocol( pImpl->fsdata->pUrl->GetProtocol() );
1801  fs = new FileSystem( locationURL );
1802  st = fs->DirList( path, flags, currentResp, timeout );
1803  if( !st.IsOK() )
1804  {
1805  ++errors;
1806  delete fs;
1807  continue;
1808  }
1809 
1810  if( st.code == suPartial )
1811  partial = true;
1812 
1814 
1815  for( it = currentResp->Begin(); it != currentResp->End(); ++it )
1816  {
1817  response->Add( *it );
1818  *it = 0;
1819  }
1820 
1821  delete fs;
1822  delete currentResp;
1823  fs = 0;
1824  currentResp = 0;
1825  }
1826 
1827  delete locations;
1828 
1829  if( flags & DirListFlags::Merge )
1830  MergeDirListHandler::Merge( response );
1831 
1832  if( errors || partial )
1833  {
1834  if( errors == numLocations )
1835  return st;
1836  return XRootDStatus( stOK, suPartial );
1837  }
1838  return XRootDStatus();
1839  }
1840  }
1841 
1842  //--------------------------------------------------------------------------
1843  // We just ask the current server
1844  //--------------------------------------------------------------------------
1845  SyncResponseHandler handler;
1846  XRootDStatus st = DirList( path, flags, &handler, timeout );
1847  if( !st.IsOK() )
1848  return st;
1849 
1850  st = MessageUtils::WaitForResponse( &handler, response );
1851  if( !st.IsOK() )
1852  return st;
1853 
1854  //--------------------------------------------------------------------------
1855  // Do the stats on all the entries if necessary.
1856  // If we already have the stat objects it means that the bulk stat has
1857  // succeeded.
1858  //--------------------------------------------------------------------------
1859  if( !(flags & DirListFlags::Stat) )
1860  return st;
1861 
1862  if( response->GetSize() && response->At(0)->GetStatInfo() )
1863  return st;
1864 
1865  uint32_t quota = response->GetSize() <= 1024 ? response->GetSize() : 1024;
1866  RequestSync sync( response->GetSize(), quota );
1867  for( uint32_t i = 0; i < response->GetSize(); ++i )
1868  {
1869  std::string fullPath = response->GetParentName()+response->At(i)->GetName();
1870  ResponseHandler *handler = new DirListStatHandler( response, i, &sync );
1871  st = Stat( fullPath, handler, timeout );
1872  if( !st.IsOK() )
1873  {
1874  sync.TaskDone( false );
1875  delete handler;
1876  }
1877  sync.WaitForQuota();
1878  }
1879  sync.WaitForAll();
1880 
1881  if( sync.FailureCount() )
1882  return XRootDStatus( stOK, suPartial );
1883 
1884  return XRootDStatus();
1885  }
1886 
1887  //----------------------------------------------------------------------------
1888  // Send cache info to the server - async
1889  //----------------------------------------------------------------------------
1890  XRootDStatus FileSystem::SendCache( const std::string &info,
1891  ResponseHandler *handler,
1892  uint16_t timeout )
1893  {
1894  // Note: adding SendCache() to the FileSystemPlugin class breaks ABI!
1895  // So, the class is missing this until we do a major release. TODO
1896  //if( pPlugIn )
1897  // return pPlugIn->SendCache( info, handler, timeout );
1898  return SendSet("cache ", info, handler, timeout );
1899  }
1900 
1901  //----------------------------------------------------------------------------
1903  //----------------------------------------------------------------------------
1904  XRootDStatus FileSystem::SendCache( const std::string &info,
1905  Buffer *&response,
1906  uint16_t timeout )
1907  {
1908  SyncResponseHandler handler;
1909  Status st = SendCache( info, &handler, timeout );
1910  if( !st.IsOK() )
1911  return st;
1912 
1913  return MessageUtils::WaitForResponse( &handler, response );
1914  }
1915 
1916  //----------------------------------------------------------------------------
1917  // Send info to the server - async
1918  //----------------------------------------------------------------------------
1919  XRootDStatus FileSystem::SendInfo( const std::string &info,
1920  ResponseHandler *handler,
1921  uint16_t timeout )
1922  {
1923  if( pPlugIn )
1924  return pPlugIn->SendInfo( info, handler, timeout );
1925  return SendSet("monitor info ", info, handler, timeout );
1926  }
1927 
1928  //----------------------------------------------------------------------------
1930  //----------------------------------------------------------------------------
1931  XRootDStatus FileSystem::SendInfo( const std::string &info,
1932  Buffer *&response,
1933  uint16_t timeout )
1934  {
1935  SyncResponseHandler handler;
1936  Status st = SendInfo( info, &handler, timeout );
1937  if( !st.IsOK() )
1938  return st;
1939 
1940  return MessageUtils::WaitForResponse( &handler, response );
1941  }
1942 
1943  //----------------------------------------------------------------------------
1944  // Send set request to the server - async
1945  //----------------------------------------------------------------------------
1946  XRootDStatus FileSystem::SendSet( const char *prefix,
1947  const std::string &info,
1948  ResponseHandler *handler,
1949  uint16_t timeout )
1950  {
1951 
1952  Message *msg;
1953  ClientSetRequest *req;
1954  size_t prefixLen = strlen( prefix );
1955  MessageUtils::CreateRequest( msg, req, info.length()+prefixLen );
1956 
1957  req->requestid = kXR_set;
1958  req->dlen = info.length()+prefixLen;
1959  msg->Append( prefix, prefixLen, 24 );
1960  msg->Append( info.c_str(), info.length(), 24+prefixLen );
1961  MessageSendParams params; params.timeout = timeout;
1964 
1965  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1966  }
1967 
1968  //----------------------------------------------------------------------------
1969  // Prepare one or more files for access - async
1970  //----------------------------------------------------------------------------
1971  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
1972  PrepareFlags::Flags flags,
1973  uint8_t priority,
1974  ResponseHandler *handler,
1975  uint16_t timeout )
1976  {
1977  if( pPlugIn )
1978  return pPlugIn->Prepare( fileList, flags, priority, handler, timeout );
1979 
1980  std::vector<std::string>::const_iterator it;
1981  std::string list;
1982  for( it = fileList.begin(); it != fileList.end(); ++it )
1983  {
1984  list += *it;
1985  list += "\n";
1986  }
1987  list.erase( list.length()-1, 1 );
1988 
1989  Message *msg;
1990  ClientPrepareRequest *req;
1991  MessageUtils::CreateRequest( msg, req, list.length() );
1992 
1993  req->requestid = kXR_prepare;
1994  req->options = 0xff & flags;
1995  req->optionX = 0xffff & ( flags >> 8 );
1996  req->prty = priority;
1997  req->dlen = list.length();
1998 
1999  msg->Append( list.c_str(), list.length(), 24 );
2000 
2001  MessageSendParams params; params.timeout = timeout;
2004 
2005  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
2006  }
2007 
2008  //------------------------------------------------------------------------
2009  // Prepare one or more files for access - sync
2010  //------------------------------------------------------------------------
2011  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
2012  PrepareFlags::Flags flags,
2013  uint8_t priority,
2014  Buffer *&response,
2015  uint16_t timeout )
2016  {
2017  SyncResponseHandler handler;
2018  Status st = Prepare( fileList, flags, priority, &handler, timeout );
2019  if( !st.IsOK() )
2020  return st;
2021 
2022  return MessageUtils::WaitForResponse( &handler, response );
2023  }
2024 
2025  //------------------------------------------------------------------------
2026  // Set extended attributes - async
2027  //------------------------------------------------------------------------
2028  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2029  const std::vector<xattr_t> &attrs,
2030  ResponseHandler *handler,
2031  uint16_t timeout )
2032  {
2033  if( pPlugIn )
2035 
2036  return XAttrOperationImpl( kXR_fattrSet, 0, path, attrs, handler, timeout );
2037  }
2038 
2039  //------------------------------------------------------------------------
2040  // Set extended attributes - sync
2041  //------------------------------------------------------------------------
2042  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2043  const std::vector<xattr_t> &attrs,
2044  std::vector<XAttrStatus> &result,
2045  uint16_t timeout )
2046  {
2047  SyncResponseHandler handler;
2048  XRootDStatus st = SetXAttr( path, attrs, &handler, timeout );
2049  if( !st.IsOK() )
2050  return st;
2051 
2052  std::vector<XAttrStatus> *resp = 0;
2053  st = MessageUtils::WaitForResponse( &handler, resp );
2054  if( resp ) result.swap( *resp );
2055  delete resp;
2056 
2057  return st;
2058  }
2059 
2060  //------------------------------------------------------------------------
2061  // Get extended attributes - async
2062  //------------------------------------------------------------------------
2063  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2064  const std::vector<std::string> &attrs,
2065  ResponseHandler *handler,
2066  uint16_t timeout )
2067  {
2068  if( pPlugIn )
2070 
2071  return XAttrOperationImpl( kXR_fattrGet, 0, path, attrs, handler, timeout );
2072  }
2073 
2074  //------------------------------------------------------------------------
2075  // Get extended attributes - sync
2076  //------------------------------------------------------------------------
2077  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2078  const std::vector<std::string> &attrs,
2079  std::vector<XAttr> &result,
2080  uint16_t timeout )
2081  {
2082  SyncResponseHandler handler;
2083  XRootDStatus st = GetXAttr( path, attrs, &handler, timeout );
2084  if( !st.IsOK() )
2085  return st;
2086 
2087  std::vector<XAttr> *resp = 0;
2088  st = MessageUtils::WaitForResponse( &handler, resp );
2089  if( resp ) result.swap( *resp );
2090  delete resp;
2091 
2092  return st;
2093  }
2094 
2095  //------------------------------------------------------------------------
2096  // Delete extended attributes - async
2097  //------------------------------------------------------------------------
2098  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2099  const std::vector<std::string> &attrs,
2100  ResponseHandler *handler,
2101  uint16_t timeout )
2102  {
2103  if( pPlugIn )
2105 
2106  return XAttrOperationImpl( kXR_fattrDel, 0, path, attrs, handler, timeout );
2107  }
2108 
2109  //------------------------------------------------------------------------
2110  // Delete extended attributes - sync
2111  //------------------------------------------------------------------------
2112  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2113  const std::vector<std::string> &attrs,
2114  std::vector<XAttrStatus> &result,
2115  uint16_t timeout )
2116  {
2117  SyncResponseHandler handler;
2118  XRootDStatus st = DelXAttr( path, attrs, &handler, timeout );
2119  if( !st.IsOK() )
2120  return st;
2121 
2122  std::vector<XAttrStatus> *resp = 0;
2123  st = MessageUtils::WaitForResponse( &handler, resp );
2124  if( resp ) result.swap( *resp );
2125  delete resp;
2126 
2127  return st;
2128  }
2129 
2130  //------------------------------------------------------------------------
2131  // List extended attributes - async
2132  //------------------------------------------------------------------------
2133  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2134  ResponseHandler *handler,
2135  uint16_t timeout )
2136  {
2137  if( pPlugIn )
2139 
2140  static const std::vector<std::string> nothing;
2141  return XAttrOperationImpl( kXR_fattrList, ClientFattrRequest::aData,
2142  path, nothing, handler, timeout );
2143  }
2144 
2145  //------------------------------------------------------------------------
2146  // List extended attributes - sync
2147  //------------------------------------------------------------------------
2148  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2149  std::vector<XAttr> &result,
2150  uint16_t timeout )
2151  {
2152  SyncResponseHandler handler;
2153  XRootDStatus st = ListXAttr( path, &handler, timeout );
2154  if( !st.IsOK() )
2155  return st;
2156 
2157  std::vector<XAttr> *resp = 0;
2158  st = MessageUtils::WaitForResponse( &handler, resp );
2159  if( resp ) result.swap( *resp );
2160  delete resp;
2161 
2162  return st;
2163  }
2164 
2165  //----------------------------------------------------------------------------
2166  // Set file property
2167  //----------------------------------------------------------------------------
2168  bool FileSystem::SetProperty( const std::string &name,
2169  const std::string &value )
2170  {
2171  if( pPlugIn )
2172  return pPlugIn->SetProperty( name, value );
2173 
2174  if( name == "FollowRedirects" )
2175  {
2176  if( value == "true" ) pImpl->fsdata->pFollowRedirects = true;
2177  else pImpl->fsdata->pFollowRedirects = false;
2178  return true;
2179  }
2180  return false;
2181  }
2182 
2183  //----------------------------------------------------------------------------
2184  // Get file property
2185  //----------------------------------------------------------------------------
2186  bool FileSystem::GetProperty( const std::string &name,
2187  std::string &value ) const
2188  {
2189  if( pPlugIn )
2190  return pPlugIn->GetProperty( name, value );
2191 
2192  if( name == "FollowRedirects" )
2193  {
2194  if( pImpl->fsdata->pFollowRedirects ) value = "true";
2195  else value = "false";
2196  return true;
2197  }
2198  else if( name == "LastURL" )
2199  {
2200  if( pImpl->fsdata->pLastUrl )
2201  {
2202  value = pImpl->fsdata->pLastUrl->GetURL();
2203  return true;
2204  }
2205  else return false;
2206  }
2207 
2208  return false;
2209  }
2210 
2211  //------------------------------------------------------------------------
2212  // Generic implementation of xattr operation
2213  //------------------------------------------------------------------------
2214  template<typename T>
2215  Status FileSystem::XAttrOperationImpl( kXR_char subcode,
2216  kXR_char options,
2217  const std::string &path,
2218  const std::vector<T> &attrs,
2219  ResponseHandler *handler,
2220  uint16_t timeout )
2221  {
2222  Message *msg;
2223  ClientFattrRequest *req;
2224  MessageUtils::CreateRequest( msg, req );
2225 
2226  req->requestid = kXR_fattr;
2227  req->subcode = subcode;
2228  req->options = options;
2229  req->numattr = attrs.size();
2230  memset( req->fhandle, 0, 4 );
2231  XRootDStatus st = MessageUtils::CreateXAttrBody( msg, attrs, path );
2232  if( !st.IsOK() ) return st;
2233 
2234  MessageSendParams params; params.timeout = timeout;
2236 
2238 
2239  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
2240  }
2241 
2242  //------------------------------------------------------------------------
2243  // Lock the internal lock
2244  //------------------------------------------------------------------------
2245  void FileSystem::Lock()
2246  {
2247  pImpl->fsdata->pMutex.Lock();
2248  }
2249 
2250  //------------------------------------------------------------------------
2251  // Unlock the internal lock
2252  //------------------------------------------------------------------------
2253  void FileSystem::UnLock()
2254  {
2255  pImpl->fsdata->pMutex.UnLock();
2256  }
2257 }
kXR_char options[1]
Definition: XProtocol.hh:248
@ kXR_NotFound
Definition: XProtocol.hh:1001
@ kXR_FSError
Definition: XProtocol.hh:995
kXR_int16 arg1len
Definition: XProtocol.hh:430
kXR_unt16 requestid
Definition: XProtocol.hh:630
@ kXR_fattrDel
Definition: XProtocol.hh:270
@ kXR_fattrSet
Definition: XProtocol.hh:273
@ kXR_fattrList
Definition: XProtocol.hh:272
@ kXR_fattrGet
Definition: XProtocol.hh:271
kXR_unt16 requestid
Definition: XProtocol.hh:546
kXR_int32 dlen
Definition: XProtocol.hh:431
kXR_unt16 requestid
Definition: XProtocol.hh:345
@ kXR_dstat
Definition: XProtocol.hh:240
@ kXR_dcksm
Definition: XProtocol.hh:241
kXR_unt16 requestid
Definition: XProtocol.hh:428
kXR_unt16 infotype
Definition: XProtocol.hh:631
@ kXR_mkdir
Definition: XProtocol.hh:120
@ kXR_chmod
Definition: XProtocol.hh:114
@ kXR_dirlist
Definition: XProtocol.hh:116
@ kXR_fattr
Definition: XProtocol.hh:132
@ kXR_rm
Definition: XProtocol.hh:126
@ kXR_query
Definition: XProtocol.hh:113
@ kXR_set
Definition: XProtocol.hh:130
@ kXR_rmdir
Definition: XProtocol.hh:127
@ kXR_truncate
Definition: XProtocol.hh:140
@ kXR_protocol
Definition: XProtocol.hh:118
@ kXR_mv
Definition: XProtocol.hh:121
@ kXR_ping
Definition: XProtocol.hh:123
@ kXR_stat
Definition: XProtocol.hh:129
@ kXR_locate
Definition: XProtocol.hh:139
@ kXR_prepare
Definition: XProtocol.hh:133
kXR_int32 dlen
Definition: XProtocol.hh:699
kXR_unt16 requestid
Definition: XProtocol.hh:719
#define kXR_isServer
Definition: XProtocol.hh:1157
kXR_unt16 requestid
Definition: XProtocol.hh:768
kXR_unt16 requestid
Definition: XProtocol.hh:415
kXR_char options[1]
Definition: XProtocol.hh:416
kXR_unt16 requestid
Definition: XProtocol.hh:697
#define kXR_PROTOCOLVERSION
Definition: XProtocol.hh:70
@ kXR_vfs
Definition: XProtocol.hh:763
kXR_int32 dlen
Definition: XProtocol.hh:722
kXR_unt16 requestid
Definition: XProtocol.hh:191
kXR_int32 dlen
Definition: XProtocol.hh:772
kXR_char options
Definition: XProtocol.hh:769
@ kXR_isDir
Definition: XProtocol.hh:1221
kXR_unt16 requestid
Definition: XProtocol.hh:708
unsigned char kXR_char
Definition: XPtypes.hh:65
struct stat Stat
Definition: XrdCks.cc:49
static void child()
static void parent()
int stat(const char *path, struct stat *buf)
int unlink(const char *path)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
static int mapError(int rc)
Definition: XProtocol.hh:1361
void Set(Type object, bool own=true)
void Get(Type &object)
Retrieve the object being held.
Wrapper class used to assign a load balancer.
AssignLBHandler(std::shared_ptr< FileSystemData > &fs, ResponseHandler *userHandler)
Wrapper class used to assign last URL.
AssignLastURLHandler(std::shared_ptr< FileSystemData > &fs, ResponseHandler *userHandler)
Binary blob representation.
Definition: XrdClBuffer.hh:34
const char * GetBuffer(uint32_t offset=0) const
Get the message buffer.
Definition: XrdClBuffer.hh:72
void Append(const char *buffer, uint32_t size)
Append data at the position pointed to by the append cursor.
Definition: XrdClBuffer.hh:164
uint32_t GetSize() const
Get the size of the message.
Definition: XrdClBuffer.hh:132
static PlugInManager * GetPlugInManager()
Get plug-in manager.
static Log * GetLog()
Get default log.
static PostMaster * GetPostMaster()
Get default post master.
static ForkHandler * GetForkHandler()
Get the fork handler.
static Env * GetEnv()
Get default client environment.
void SetStatInfo(StatInfo *info)
Set the stat info object (and transfer the ownership)
const std::string & GetHostAddress() const
Get host address.
const std::string & GetName() const
Get file name.
StatInfo * GetStatInfo()
Get the stat info object.
ListEntry * At(uint32_t index)
Get an entry at given index.
void Add(ListEntry *entry)
Add an entry to the list - takes ownership.
uint32_t GetSize() const
Get the size of the listing.
DirList::iterator Iterator
Directory listing iterator.
Iterator End()
Get the end iterator.
Iterator Begin()
Get the begin iterator.
const std::string & GetParentName() const
Get parent directory name.
void SetParentName(const std::string &parent)
Set name of the parent directory.
bool GetInt(const std::string &key, int &value)
Definition: XrdClEnv.cc:89
virtual XRootDStatus Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Ping(ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus SendInfo(const std::string &info, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus DirList(const std::string &path, DirListFlags::Flags flags, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus ChMod(const std::string &path, Access::Mode mode, ResponseHandler *handler, uint16_t timeout)
virtual bool GetProperty(const std::string &name, std::string &value) const
virtual XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Locate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Protocol(ResponseHandler *handler, uint16_t timeout=0)
virtual XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, uint16_t timeout)
virtual bool SetProperty(const std::string &name, const std::string &value)
virtual XRootDStatus Query(QueryCode::Code queryCode, const Buffer &arg, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Prepare(const std::vector< std::string > &fileList, PrepareFlags::Flags flags, uint8_t priority, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Rm(const std::string &path, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Stat(const std::string &path, ResponseHandler *handler, uint16_t timeout)
virtual XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, uint16_t timeout)
Send file/filesystem queries to an XRootD cluster.
XRootDStatus SetXAttr(const std::string &path, const std::vector< xattr_t > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
bool SetProperty(const std::string &name, const std::string &value)
XRootDStatus Protocol(ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus DirList(const std::string &path, DirListFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Query(QueryCode::Code queryCode, const Buffer &arg, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Locate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus SendInfo(const std::string &info, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Stat(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Prepare(const std::vector< std::string > &fileList, PrepareFlags::Flags flags, uint8_t priority, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus ChMod(const std::string &path, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus DelXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus ListXAttr(const std::string &path, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Rm(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
FileSystem(const URL &url, bool enablePlugIns=true)
XRootDStatus DeepLocate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus SendCache(const std::string &info, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
~FileSystem()
Destructor.
XRootDStatus GetXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Ping(ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
bool GetProperty(const std::string &name, std::string &value) const
XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
void RegisterFileSystemObject(FileSystem *fs)
void UnRegisterFileSystemObject(FileSystem *fs)
Un-register a file system object.
A synchronized queue.
const std::string & GetAddress() const
Get address.
Path location info.
uint32_t GetSize() const
Get number of locations.
Iterator Begin()
Get the location begin iterator.
Location & At(uint32_t index)
Get the location at index.
LocationList::iterator Iterator
Iterator over locations.
Iterator End()
Get the location end iterator.
Handle diagnostics.
Definition: XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
Definition: XrdClLog.cc:299
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition: XrdClLog.cc:282
static void ProcessSendParams(MessageSendParams &sendParams)
Process sending params.
static Status CreateXAttrBody(Message *msg, const std::vector< T > &vec, const std::string &path="")
static XrdCl::XRootDStatus WaitForResponse(SyncResponseHandler *handler, Type *&response)
Wait for the response.
static void CreateRequest(Message *&msg, Request *&req, uint32_t payloadSize=0)
Create a message.
static XRootDStatus WaitForStatus(SyncResponseHandler *handler)
Wait and return the status of the query.
The message representation used throughout the system.
Definition: XrdClMessage.hh:32
const std::string & GetObfuscatedDescription() const
Get the description of the message with authz parameter obfuscated.
virtual FileSystemPlugIn * CreateFileSystem(const std::string &url)=0
Create a file system plug-in for the given URL.
PlugInFactory * GetFactory(const std::string url)
Status QueryTransport(const URL &url, uint16_t query, AnyObject &result)
A helper running a fixed number of requests at a given time.
void WaitForAll()
Wait for all the requests to be finished.
void TaskDone(bool success=true)
Report the request finish.
uint32_t FailureCount() const
Number of tasks finishing with an error.
void WaitForQuota()
Wait for the request quota.
Handle an async response.
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Object stat info.
bool TestFlags(uint32_t flags) const
Test flags.
uint64_t GetSize() const
Get size (in bytes)
bool ParseServerResponse(const char *data)
Parse server response and fill up the object.
uint32_t GetFlags() const
Get flags.
Synchronize the response.
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
Handle the response.
URL representation.
Definition: XrdClURL.hh:31
std::string GetHostId() const
Get the host part of the URL (user:password@host:port)
Definition: XrdClURL.hh:99
std::string GetURL() const
Get the URL.
Definition: XrdClURL.hh:86
std::string GetObfuscatedURL() const
Get the URL with authz information obfuscated.
Definition: XrdClURL.cc:491
void SetProtocol(const std::string &protocol)
Set protocol.
Definition: XrdClURL.hh:126
const std::string & GetPath() const
Get the path.
Definition: XrdClURL.hh:217
std::string ToStr() const
Convert to string.
static void SetDescription(Message *msg)
Get the description of a message.
const uint16_t suPartial
Definition: XrdClStatus.hh:41
const uint16_t errErrorResponse
Definition: XrdClStatus.hh:105
const uint16_t errOperationExpired
Definition: XrdClStatus.hh:90
RmImpl< false > Rm
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
const uint16_t errNotFound
Definition: XrdClStatus.hh:100
std::vector< HostInfo > HostList
const uint16_t errInternal
Internal error.
Definition: XrdClStatus.hh:56
const uint16_t stOK
Everything went OK.
Definition: XrdClStatus.hh:31
const uint64_t FileMsg
const int DefaultRequestTimeout
const uint16_t errNotSupported
Definition: XrdClStatus.hh:62
const uint16_t errLocalError
Definition: XrdClStatus.hh:107
const uint16_t suContinue
Definition: XrdClStatus.hh:39
const uint64_t FileSystemMsg
static const int aData
Definition: XProtocol.hh:298
kXR_char fhandle[4]
Definition: XProtocol.hh:288
kXR_unt16 requestid
Definition: XProtocol.hh:287
Mode
Access mode.
@ Stat
Stat each entry.
@ Merge
Merge duplicates.
@ Zip
List content of ZIP files.
@ Recursive
Do a recursive listing.
@ Cksm
Get checksum for every entry.
@ Chunked
Serve chunked results for better performance.
static XRootDStatus Send(std::shared_ptr< FileSystemData > &fs, Message *msg, ResponseHandler *handler, MessageSendParams &params)
FileSystemData(const URL &url)
void AssignLastURL(const URL &url)
std::unique_ptr< URL > pLastUrl
std::unique_ptr< URL > pUrl
void AssignLoadBalancer(const URL &url)
Implementation holding the data members.
FileSystemImpl(const URL &url)
std::shared_ptr< FileSystemData > fsdata
Flags
Open flags, may be or'd when appropriate.
Code
XRootD query request codes.
Procedure execution status.
Definition: XrdClStatus.hh:115
uint16_t code
Error type, or additional hints on what to do.
Definition: XrdClStatus.hh:147
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124
std::string ToString() const
Create a string representation.
Definition: XrdClStatus.cc:97
static const uint16_t ServerFlags
returns server flags