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, 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, "[0x%x@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, "[0x%x@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, "[0x%x@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, "[0x%x@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: ",
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, "[0x%x@%s] Sending %s", fs.get(),
948  fs->pUrl->GetHostId().c_str(), msg->GetDescription().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, "[0x%x@%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, "[0x%x@%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", urlStr.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  //------------------------------------------------------------------------
1741  // Locate all the disk servers holding the directory
1742  //------------------------------------------------------------------------
1743  LocationInfo *locations;
1744  std::string locatePath = "*"; locatePath += path;
1745  XRootDStatus st = DeepLocate( locatePath,
1747 
1748  if( !st.IsOK() )
1749  return st;
1750 
1751  if( locations->GetSize() == 0 )
1752  {
1753  delete locations;
1754  return XRootDStatus( stError, errNotFound );
1755  }
1756 
1757  // Check if destination is a data server
1758  bool isserver = false;
1759  AnyObject obj;
1761  if( st.IsOK() )
1762  {
1763  int *ptr = 0;
1764  obj.Get( ptr );
1765  isserver = ( *ptr & kXR_isServer );
1766  delete ptr;
1767  }
1768 
1769  if( !isserver )
1770  {
1771  //------------------------------------------------------------------------
1772  // Ask each server for a directory list
1773  //------------------------------------------------------------------------
1774  flags &= ~DirListFlags::Locate;
1775  FileSystem *fs;
1776  DirectoryList *currentResp = 0;
1777  uint32_t errors = 0;
1778  uint32_t numLocations = locations->GetSize();
1779  bool partial = st.code == suPartial ? true : false;
1780 
1781  response = new DirectoryList();
1782  response->SetParentName( path );
1783 
1784  for( uint32_t i = 0; i < locations->GetSize(); ++i )
1785  {
1786  URL locationURL( locations->At(i).GetAddress() );
1787  // make sure the original protocol is preserved (root vs roots)
1788  locationURL.SetProtocol( pImpl->fsdata->pUrl->GetProtocol() );
1789  fs = new FileSystem( locationURL );
1790  st = fs->DirList( path, flags, currentResp, timeout );
1791  if( !st.IsOK() )
1792  {
1793  ++errors;
1794  delete fs;
1795  continue;
1796  }
1797 
1798  if( st.code == suPartial )
1799  partial = true;
1800 
1802 
1803  for( it = currentResp->Begin(); it != currentResp->End(); ++it )
1804  {
1805  response->Add( *it );
1806  *it = 0;
1807  }
1808 
1809  delete fs;
1810  delete currentResp;
1811  fs = 0;
1812  currentResp = 0;
1813  }
1814  delete locations;
1815 
1816  if( flags & DirListFlags::Merge )
1817  MergeDirListHandler::Merge( response );
1818 
1819  if( errors || partial )
1820  {
1821  if( errors == numLocations )
1822  return st;
1823  return XRootDStatus( stOK, suPartial );
1824  }
1825  return XRootDStatus();
1826  }
1827  else
1828  delete locations;
1829  }
1830 
1831  //--------------------------------------------------------------------------
1832  // We just ask the current server
1833  //--------------------------------------------------------------------------
1834  SyncResponseHandler handler;
1835  XRootDStatus st = DirList( path, flags, &handler, timeout );
1836  if( !st.IsOK() )
1837  return st;
1838 
1839  st = MessageUtils::WaitForResponse( &handler, response );
1840  if( !st.IsOK() )
1841  return st;
1842 
1843  //--------------------------------------------------------------------------
1844  // Do the stats on all the entries if necessary.
1845  // If we already have the stat objects it means that the bulk stat has
1846  // succeeded.
1847  //--------------------------------------------------------------------------
1848  if( !(flags & DirListFlags::Stat) )
1849  return st;
1850 
1851  if( response->GetSize() && response->At(0)->GetStatInfo() )
1852  return st;
1853 
1854  uint32_t quota = response->GetSize() <= 1024 ? response->GetSize() : 1024;
1855  RequestSync sync( response->GetSize(), quota );
1856  for( uint32_t i = 0; i < response->GetSize(); ++i )
1857  {
1858  std::string fullPath = response->GetParentName()+response->At(i)->GetName();
1859  ResponseHandler *handler = new DirListStatHandler( response, i, &sync );
1860  st = Stat( fullPath, handler, timeout );
1861  if( !st.IsOK() )
1862  {
1863  sync.TaskDone( false );
1864  delete handler;
1865  }
1866  sync.WaitForQuota();
1867  }
1868  sync.WaitForAll();
1869 
1870  if( sync.FailureCount() )
1871  return XRootDStatus( stOK, suPartial );
1872 
1873  return XRootDStatus();
1874  }
1875 
1876  //----------------------------------------------------------------------------
1877  // Send cache info to the server - async
1878  //----------------------------------------------------------------------------
1879  XRootDStatus FileSystem::SendCache( const std::string &info,
1880  ResponseHandler *handler,
1881  uint16_t timeout )
1882  {
1883  // Note: adding SendCache() to the FileSystemPlugin class breaks ABI!
1884  // So, the class is missing this until we do a major release. TODO
1885  //if( pPlugIn )
1886  // return pPlugIn->SendCache( info, handler, timeout );
1887  return SendSet("cache ", info, handler, timeout );
1888  }
1889 
1890  //----------------------------------------------------------------------------
1892  //----------------------------------------------------------------------------
1893  XRootDStatus FileSystem::SendCache( const std::string &info,
1894  Buffer *&response,
1895  uint16_t timeout )
1896  {
1897  SyncResponseHandler handler;
1898  Status st = SendCache( info, &handler, timeout );
1899  if( !st.IsOK() )
1900  return st;
1901 
1902  return MessageUtils::WaitForResponse( &handler, response );
1903  }
1904 
1905  //----------------------------------------------------------------------------
1906  // Send info to the server - async
1907  //----------------------------------------------------------------------------
1908  XRootDStatus FileSystem::SendInfo( const std::string &info,
1909  ResponseHandler *handler,
1910  uint16_t timeout )
1911  {
1912  if( pPlugIn )
1913  return pPlugIn->SendInfo( info, handler, timeout );
1914  return SendSet("monitor info ", info, handler, timeout );
1915  }
1916 
1917  //----------------------------------------------------------------------------
1919  //----------------------------------------------------------------------------
1920  XRootDStatus FileSystem::SendInfo( const std::string &info,
1921  Buffer *&response,
1922  uint16_t timeout )
1923  {
1924  SyncResponseHandler handler;
1925  Status st = SendInfo( info, &handler, timeout );
1926  if( !st.IsOK() )
1927  return st;
1928 
1929  return MessageUtils::WaitForResponse( &handler, response );
1930  }
1931 
1932  //----------------------------------------------------------------------------
1933  // Send set request to the server - async
1934  //----------------------------------------------------------------------------
1935  XRootDStatus FileSystem::SendSet( const char *prefix,
1936  const std::string &info,
1937  ResponseHandler *handler,
1938  uint16_t timeout )
1939  {
1940 
1941  Message *msg;
1942  ClientSetRequest *req;
1943  size_t prefixLen = strlen( prefix );
1944  MessageUtils::CreateRequest( msg, req, info.length()+prefixLen );
1945 
1946  req->requestid = kXR_set;
1947  req->dlen = info.length()+prefixLen;
1948  msg->Append( prefix, prefixLen, 24 );
1949  msg->Append( info.c_str(), info.length(), 24+prefixLen );
1950  MessageSendParams params; params.timeout = timeout;
1953 
1954  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1955  }
1956 
1957  //----------------------------------------------------------------------------
1958  // Prepare one or more files for access - async
1959  //----------------------------------------------------------------------------
1960  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
1961  PrepareFlags::Flags flags,
1962  uint8_t priority,
1963  ResponseHandler *handler,
1964  uint16_t timeout )
1965  {
1966  if( pPlugIn )
1967  return pPlugIn->Prepare( fileList, flags, priority, handler, timeout );
1968 
1969  std::vector<std::string>::const_iterator it;
1970  std::string list;
1971  for( it = fileList.begin(); it != fileList.end(); ++it )
1972  {
1973  list += *it;
1974  list += "\n";
1975  }
1976  list.erase( list.length()-1, 1 );
1977 
1978  Message *msg;
1979  ClientPrepareRequest *req;
1980  MessageUtils::CreateRequest( msg, req, list.length() );
1981 
1982  req->requestid = kXR_prepare;
1983  req->options = 0xff & flags;
1984  req->optionX = 0xffff & ( flags >> 8 );
1985  req->prty = priority;
1986  req->dlen = list.length();
1987 
1988  msg->Append( list.c_str(), list.length(), 24 );
1989 
1990  MessageSendParams params; params.timeout = timeout;
1993 
1994  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1995  }
1996 
1997  //------------------------------------------------------------------------
1998  // Prepare one or more files for access - sync
1999  //------------------------------------------------------------------------
2000  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
2001  PrepareFlags::Flags flags,
2002  uint8_t priority,
2003  Buffer *&response,
2004  uint16_t timeout )
2005  {
2006  SyncResponseHandler handler;
2007  Status st = Prepare( fileList, flags, priority, &handler, timeout );
2008  if( !st.IsOK() )
2009  return st;
2010 
2011  return MessageUtils::WaitForResponse( &handler, response );
2012  }
2013 
2014  //------------------------------------------------------------------------
2015  // Set extended attributes - async
2016  //------------------------------------------------------------------------
2017  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2018  const std::vector<xattr_t> &attrs,
2019  ResponseHandler *handler,
2020  uint16_t timeout )
2021  {
2022  if( pPlugIn )
2024 
2025  return XAttrOperationImpl( kXR_fattrSet, 0, path, attrs, handler, timeout );
2026  }
2027 
2028  //------------------------------------------------------------------------
2029  // Set extended attributes - sync
2030  //------------------------------------------------------------------------
2031  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2032  const std::vector<xattr_t> &attrs,
2033  std::vector<XAttrStatus> &result,
2034  uint16_t timeout )
2035  {
2036  SyncResponseHandler handler;
2037  XRootDStatus st = SetXAttr( path, attrs, &handler, timeout );
2038  if( !st.IsOK() )
2039  return st;
2040 
2041  std::vector<XAttrStatus> *resp = 0;
2042  st = MessageUtils::WaitForResponse( &handler, resp );
2043  if( resp ) result.swap( *resp );
2044  delete resp;
2045 
2046  return st;
2047  }
2048 
2049  //------------------------------------------------------------------------
2050  // Get extended attributes - async
2051  //------------------------------------------------------------------------
2052  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2053  const std::vector<std::string> &attrs,
2054  ResponseHandler *handler,
2055  uint16_t timeout )
2056  {
2057  if( pPlugIn )
2059 
2060  return XAttrOperationImpl( kXR_fattrGet, 0, path, attrs, handler, timeout );
2061  }
2062 
2063  //------------------------------------------------------------------------
2064  // Get extended attributes - sync
2065  //------------------------------------------------------------------------
2066  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2067  const std::vector<std::string> &attrs,
2068  std::vector<XAttr> &result,
2069  uint16_t timeout )
2070  {
2071  SyncResponseHandler handler;
2072  XRootDStatus st = GetXAttr( path, attrs, &handler, timeout );
2073  if( !st.IsOK() )
2074  return st;
2075 
2076  std::vector<XAttr> *resp = 0;
2077  st = MessageUtils::WaitForResponse( &handler, resp );
2078  if( resp ) result.swap( *resp );
2079  delete resp;
2080 
2081  return st;
2082  }
2083 
2084  //------------------------------------------------------------------------
2085  // Delete extended attributes - async
2086  //------------------------------------------------------------------------
2087  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2088  const std::vector<std::string> &attrs,
2089  ResponseHandler *handler,
2090  uint16_t timeout )
2091  {
2092  if( pPlugIn )
2094 
2095  return XAttrOperationImpl( kXR_fattrDel, 0, path, attrs, handler, timeout );
2096  }
2097 
2098  //------------------------------------------------------------------------
2099  // Delete extended attributes - sync
2100  //------------------------------------------------------------------------
2101  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2102  const std::vector<std::string> &attrs,
2103  std::vector<XAttrStatus> &result,
2104  uint16_t timeout )
2105  {
2106  SyncResponseHandler handler;
2107  XRootDStatus st = DelXAttr( path, attrs, &handler, timeout );
2108  if( !st.IsOK() )
2109  return st;
2110 
2111  std::vector<XAttrStatus> *resp = 0;
2112  st = MessageUtils::WaitForResponse( &handler, resp );
2113  if( resp ) result.swap( *resp );
2114  delete resp;
2115 
2116  return st;
2117  }
2118 
2119  //------------------------------------------------------------------------
2120  // List extended attributes - async
2121  //------------------------------------------------------------------------
2122  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2123  ResponseHandler *handler,
2124  uint16_t timeout )
2125  {
2126  if( pPlugIn )
2128 
2129  static const std::vector<std::string> nothing;
2130  return XAttrOperationImpl( kXR_fattrList, ClientFattrRequest::aData,
2131  path, nothing, handler, timeout );
2132  }
2133 
2134  //------------------------------------------------------------------------
2135  // List extended attributes - sync
2136  //------------------------------------------------------------------------
2137  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2138  std::vector<XAttr> &result,
2139  uint16_t timeout )
2140  {
2141  SyncResponseHandler handler;
2142  XRootDStatus st = ListXAttr( path, &handler, timeout );
2143  if( !st.IsOK() )
2144  return st;
2145 
2146  std::vector<XAttr> *resp = 0;
2147  st = MessageUtils::WaitForResponse( &handler, resp );
2148  if( resp ) result.swap( *resp );
2149  delete resp;
2150 
2151  return st;
2152  }
2153 
2154  //----------------------------------------------------------------------------
2155  // Set file property
2156  //----------------------------------------------------------------------------
2157  bool FileSystem::SetProperty( const std::string &name,
2158  const std::string &value )
2159  {
2160  if( pPlugIn )
2161  return pPlugIn->SetProperty( name, value );
2162 
2163  if( name == "FollowRedirects" )
2164  {
2165  if( value == "true" ) pImpl->fsdata->pFollowRedirects = true;
2166  else pImpl->fsdata->pFollowRedirects = false;
2167  return true;
2168  }
2169  return false;
2170  }
2171 
2172  //----------------------------------------------------------------------------
2173  // Get file property
2174  //----------------------------------------------------------------------------
2175  bool FileSystem::GetProperty( const std::string &name,
2176  std::string &value ) const
2177  {
2178  if( pPlugIn )
2179  return pPlugIn->GetProperty( name, value );
2180 
2181  if( name == "FollowRedirects" )
2182  {
2183  if( pImpl->fsdata->pFollowRedirects ) value = "true";
2184  else value = "false";
2185  return true;
2186  }
2187  else if( name == "LastURL" )
2188  {
2189  if( pImpl->fsdata->pLastUrl )
2190  {
2191  value = pImpl->fsdata->pLastUrl->GetURL();
2192  return true;
2193  }
2194  else return false;
2195  }
2196 
2197  return false;
2198  }
2199 
2200  //------------------------------------------------------------------------
2201  // Generic implementation of xattr operation
2202  //------------------------------------------------------------------------
2203  template<typename T>
2204  Status FileSystem::XAttrOperationImpl( kXR_char subcode,
2205  kXR_char options,
2206  const std::string &path,
2207  const std::vector<T> &attrs,
2208  ResponseHandler *handler,
2209  uint16_t timeout )
2210  {
2211  Message *msg;
2212  ClientFattrRequest *req;
2213  MessageUtils::CreateRequest( msg, req );
2214 
2215  req->requestid = kXR_fattr;
2216  req->subcode = subcode;
2217  req->options = options;
2218  req->numattr = attrs.size();
2219  memset( req->fhandle, 0, 4 );
2220  XRootDStatus st = MessageUtils::CreateXAttrBody( msg, attrs, path );
2221  if( !st.IsOK() ) return st;
2222 
2223  MessageSendParams params; params.timeout = timeout;
2225 
2227 
2228  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
2229  }
2230 
2231  //------------------------------------------------------------------------
2232  // Lock the internal lock
2233  //------------------------------------------------------------------------
2234  void FileSystem::Lock()
2235  {
2236  pImpl->fsdata->pMutex.Lock();
2237  }
2238 
2239  //------------------------------------------------------------------------
2240  // Unlock the internal lock
2241  //------------------------------------------------------------------------
2242  void FileSystem::UnLock()
2243  {
2244  pImpl->fsdata->pMutex.UnLock();
2245  }
2246 }
kXR_char options[1]
Definition: XProtocol.hh:248
@ kXR_NotFound
Definition: XProtocol.hh:999
@ kXR_FSError
Definition: XProtocol.hh:993
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:697
kXR_unt16 requestid
Definition: XProtocol.hh:717
#define kXR_isServer
Definition: XProtocol.hh:1155
kXR_unt16 requestid
Definition: XProtocol.hh:766
kXR_unt16 requestid
Definition: XProtocol.hh:415
kXR_char options[1]
Definition: XProtocol.hh:416
kXR_unt16 requestid
Definition: XProtocol.hh:695
#define kXR_PROTOCOLVERSION
Definition: XProtocol.hh:70
@ kXR_vfs
Definition: XProtocol.hh:761
kXR_int32 dlen
Definition: XProtocol.hh:720
kXR_unt16 requestid
Definition: XProtocol.hh:191
kXR_int32 dlen
Definition: XProtocol.hh:770
kXR_char options
Definition: XProtocol.hh:767
@ kXR_isDir
Definition: XProtocol.hh:1218
kXR_unt16 requestid
Definition: XProtocol.hh:706
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:99
static int mapError(int rc)
Definition: XProtocol.hh:1358
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:30
const std::string & GetDescription() const
Get the description of the message.
Definition: XrdClMessage.hh:95
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:94
std::string GetURL() const
Get the URL.
Definition: XrdClURL.hh:86
void SetProtocol(const std::string &protocol)
Set protocol.
Definition: XrdClURL.hh:121
const std::string & GetPath() const
Get the path.
Definition: XrdClURL.hh:212
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