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  if(!info) {
356  log->Error(FileSystemMsg,
357  "[%p@DeepLocate(%s)] No locations received in response",
358  this, pPath.c_str());
359  return;
360  }
361 
362  log->Dump( FileSystemMsg, "[%p@DeepLocate(%s)] Got %d locations",
363  this, pPath.c_str(), info->GetSize() );
364 
365  for( it = info->Begin(); it != info->End(); ++it )
366  {
367  //--------------------------------------------------------------------
368  // Add the location to the list
369  //--------------------------------------------------------------------
370  if( it->IsServer() )
371  {
372  pLocations->Add( *it );
373  continue;
374  }
375 
376  //--------------------------------------------------------------------
377  // Ask the manager for the location of servers
378  //--------------------------------------------------------------------
379  if( it->IsManager() )
380  {
381  ++pOutstanding;
382  FileSystem *fs = new FileSystem( it->GetAddress() );
383  if( pOutstanding == 0 || // protect against overflow, short circuiting
384  // will make sure the other part won't be executed
385  !fs->Locate( pPath, pFlags, new DeallocFSHandler(fs, this),
386  pExpires-::time(0)).IsOK() )
387  {
388  --pOutstanding;
389  pPartial = true;
390  delete fs;
391  }
392  }
393  }
394 
395  //----------------------------------------------------------------------
396  // Clean up and check if we have anything else to do
397  //----------------------------------------------------------------------
398  delete response;
399  delete status;
400  if( !pOutstanding )
401  {
402  scopedLock.UnLock();
403  HandleFinalResponse();
404  }
405  }
406 
407  //------------------------------------------------------------------------
408  // Build the response for the client
409  //------------------------------------------------------------------------
410  void HandleFinalResponse()
411  {
412  using namespace XrdCl;
413 
414  //----------------------------------------------------------------------
415  // Nothing found
416  //----------------------------------------------------------------------
417  if( !pLocations->GetSize() )
418  {
419  pHandler->HandleResponse( new XRootDStatus( stError, errErrorResponse,
420  kXR_NotFound,
421  "No valid location found" ),
422  0 );
423  }
424  //----------------------------------------------------------------------
425  // We return an answer
426  //----------------------------------------------------------------------
427  else
428  {
429  AnyObject *obj = new AnyObject();
430  obj->Set( pLocations );
431  pLocations = 0;
432  XRootDStatus *st = new XRootDStatus();
433  if( pPartial ) st->code = suPartial;
434  pHandler->HandleResponse( st, obj );
435  }
436  delete this;
437  }
438 
439  private:
440  bool pFirstTime;
441  bool pPartial;
442  uint16_t pOutstanding;
443  XrdCl::ResponseHandler *pHandler;
444  XrdCl::LocationInfo *pLocations;
445  std::string pPath;
447  time_t pExpires;
448  XrdSysMutex pMutex;
449  };
450 
451  //----------------------------------------------------------------------------
452  // Handle stat results for a dirlist request
453  //----------------------------------------------------------------------------
454  class DirListStatHandler: public XrdCl::ResponseHandler
455  {
456  public:
457  //------------------------------------------------------------------------
458  // Constructor
459  //------------------------------------------------------------------------
460  DirListStatHandler( XrdCl::DirectoryList *list,
461  uint32_t index,
462  XrdCl::RequestSync *sync ):
463  pList( list ),
464  pIndex( index ),
465  pSync( sync )
466  {
467  }
468 
469  //------------------------------------------------------------------------
470  // Check if we were successful and if so put the StatInfo object
471  // in the appropriate entry info
472  //------------------------------------------------------------------------
473  virtual void HandleResponse( XrdCl::XRootDStatus *status,
474  XrdCl::AnyObject *response )
475  {
476  if( !status->IsOK() )
477  {
478  delete status;
479  pSync->TaskDone( false );
480  delete this;
481  return;
482  }
483 
484  XrdCl::StatInfo *info = 0;
485  response->Get( info );
486  response->Set( (char*) 0 );
487  pList->At( pIndex )->SetStatInfo( info );
488  delete status;
489  delete response;
490  pSync->TaskDone();
491  delete this;
492  }
493 
494  private:
495  XrdCl::DirectoryList *pList;
496  uint32_t pIndex;
497  XrdCl::RequestSync *pSync;
498  };
499 
500  //----------------------------------------------------------------------------
501  // Recursive dirlist common context for all handlers
502  //----------------------------------------------------------------------------
503  struct RecursiveDirListCtx
504  {
505  RecursiveDirListCtx( const XrdCl::URL &url, const std::string &path,
507  XrdCl::ResponseHandler *handler, time_t expires ) :
508  finalst( 0 ), pending( 1 ),
509  dirList( new XrdCl::DirectoryList() ), expires( expires ),
510  handler( handler ), flags( flags ),
511  fs( new XrdCl::FileSystem( url ) )
512  {
513  dirList->SetParentName( path );
514  }
515 
516  ~RecursiveDirListCtx()
517  {
518  delete finalst;
519  delete dirList;
520  delete fs;
521  }
522 
523  void UpdateStatus( const XrdCl::XRootDStatus &st )
524  {
525  using namespace XrdCl;
526 
527  if( !finalst )
528  {
529  finalst = st.IsOK() ? new XRootDStatus() : new XRootDStatus( st );
530  return;
531  }
532 
533  // if they disagree set the status to partial
534  if( ( finalst->IsOK() && !st.IsOK() ) ||
535  ( !finalst->IsOK() && st.IsOK() ) )
536  *finalst = XRootDStatus( stOK, suPartial );
537  }
538 
539  XrdCl::XRootDStatus *finalst;
540  int pending;
541  XrdCl::DirectoryList *dirList;
542  time_t expires;
543  XrdCl::ResponseHandler *handler;
545  XrdCl::FileSystem *fs;
546  XrdSysMutex mtx;
547  };
548 
549  //----------------------------------------------------------------------------
550  // Handle results for a recursive dirlist request
551  //----------------------------------------------------------------------------
552  class RecursiveDirListHandler: public XrdCl::ResponseHandler
553  {
554  public:
555 
556  RecursiveDirListHandler( const XrdCl::URL &url,
557  const std::string &path,
559  XrdCl::ResponseHandler *handler,
560  time_t timeout )
561  {
562  time_t expires = 0;
563  if( timeout )
564  expires = ::time( 0 ) + timeout;
565  pCtx = new RecursiveDirListCtx( url, path, flags,
566  handler, expires );
567  }
568 
569  RecursiveDirListHandler( RecursiveDirListCtx *ctx ) : pCtx( ctx )
570  {
571 
572  }
573 
574  virtual void HandleResponse( XrdCl::XRootDStatus *status,
575  XrdCl::AnyObject *response )
576  {
577  using namespace XrdCl;
578 
579  Log *log = DefaultEnv::GetLog();
580  bool finalrsp = !( status->IsOK() && status->code == XrdCl::suContinue );
581  XrdSysMutexHelper scoped( pCtx->mtx );
582 
583  // check if we have to continue with the same handler (the response
584  // has been chunked), if not we can decrement the number of pending
585  // DieLists
586  if( finalrsp )
587  --pCtx->pending;
588 
589  pCtx->UpdateStatus( *status );
590 
591  if( status->IsOK() )
592  {
593  // get the response
594  DirectoryList *dirList = 0;
595  response->Get( dirList );
596 
597  std::string parent = pCtx->dirList->GetParentName();
598 
600  for( itr = dirList->Begin(); itr != dirList->End(); ++itr )
601  {
602  DirectoryList::ListEntry *entry = *itr;
603  StatInfo *info = entry->GetStatInfo();
604  if( !info )
605  {
606  log->Error( FileMsg, "Recursive directory list operation for %s failed: "
607  "kXR_dirlist with stat operation not supported.",
608  parent.c_str() );
609  pCtx->UpdateStatus( XRootDStatus( stError, errNotSupported ) );
610  continue;
611  }
612  std::string path = dirList->GetParentName() + entry->GetName();
613 
614  // add new entry to the result
615  path = path.substr( parent.size() );
616  entry->SetStatInfo( 0 ); // StatInfo is no longer owned by dirList
618  new DirectoryList::ListEntry( entry->GetHostAddress(), path, info );
619  pCtx->dirList->Add( e );
620 
621  // if it's a directory do a recursive call
622  if( info->TestFlags( StatInfo::IsDir ) )
623  {
624  // bump the pending counter
625  ++pCtx->pending;
626  // switch of the recursive flag, we will
627  // provide the respective handler ourself,
628  // make sure that stat is on
629  DirListFlags::Flags flags = ( pCtx->flags & (~DirListFlags::Recursive) )
631  // the recursive dir list handler
632  RecursiveDirListHandler *handler = new RecursiveDirListHandler( pCtx );
633  // timeout
634  time_t timeout = 0;
635  if( pCtx->expires )
636  {
637  timeout = pCtx->expires - ::time( 0 );
638  if( timeout <= 0 )
639  {
640  log->Error( FileMsg, "Recursive directory list operation for %s expired.",
641  parent.c_str() );
642  pCtx->UpdateStatus( XRootDStatus( stError, errOperationExpired ) );
643  break;
644  }
645  }
646  // send the request
647  std::string child = parent + path;
648  XRootDStatus st = pCtx->fs->DirList( child, flags, handler, timeout );
649  if( !st.IsOK() )
650  {
651  log->Error( FileMsg, "Recursive directory list operation for %s failed: %s",
652  child.c_str(), st.ToString().c_str() );
653  pCtx->UpdateStatus( st );
654  continue;
655  }
656  }
657  }
658  }
659 
660  // if there are no more outstanding dirlist queries we can finalize the request
661  if( pCtx->pending == 0 )
662  {
663  AnyObject *resp = new AnyObject();
664  resp->Set( pCtx->dirList );
665  pCtx->dirList = 0; // dirList is no longer owned by pCtx
666  pCtx->handler->HandleResponse( pCtx->finalst, resp );
667  pCtx->finalst = 0; // status is no longer owned by pCtx
668 
669  // finalize the common context
670  scoped.UnLock();
671  delete pCtx;
672  }
673  // if the user requested chunked response we give what we have to the user handler
674  else if( status->IsOK() && ( pCtx->flags & DirListFlags::Chunked ) )
675  {
676  std::string parent = pCtx->dirList->GetParentName();
677  AnyObject *resp = new AnyObject();
678  resp->Set( pCtx->dirList );
679  pCtx->dirList = new XrdCl::DirectoryList();
680  pCtx->dirList->SetParentName( parent );
681  pCtx->handler->HandleResponse( new XRootDStatus( stOK, suContinue ), resp );
682  }
683 
684  // clean up the arguments
685  delete status;
686  delete response;
687  // if we won't be continuing with the same handler, it can be deleted
688  if( finalrsp )
689  delete this;
690  }
691 
692  private:
693 
694  RecursiveDirListCtx *pCtx;
695  };
696 
697  //----------------------------------------------------------------------------
698  // Exception for a merge dirlist handler
699  //----------------------------------------------------------------------------
700  struct MergeDirLsErr
701  {
702  MergeDirLsErr( XrdCl::XRootDStatus *&status, XrdCl::AnyObject *&response ) :
703  status( status ), response( response )
704  {
705  status = 0; response = 0;
706  }
707 
708  MergeDirLsErr() :
709  status( new XrdCl::XRootDStatus( XrdCl::stError, XrdCl::errInternal ) ),
710  response( 0 )
711  {
712 
713  }
714 
715  XrdCl::XRootDStatus *status;
716  XrdCl::AnyObject *response;
717  };
718 
719 
720 
721  //----------------------------------------------------------------------------
722  // Handle results for a merge dirlist request
723  //----------------------------------------------------------------------------
724  class MergeDirListHandler: public XrdCl::ResponseHandler
725  {
726  public:
727 
728  MergeDirListHandler( bool allowChunked, XrdCl::ResponseHandler *handler ) :
729  allowChunked( allowChunked ), pHandler( handler )
730  {
731 
732  }
733 
734  virtual void HandleResponse( XrdCl::XRootDStatus *status,
735  XrdCl::AnyObject *response )
736  {
737  XrdSysMutexHelper lck( mtx );
738 
739  bool finalrsp = !( status->IsOK() && status->code == XrdCl::suContinue );
740 
741  try
742  {
743  if( !status->IsOK() )
744  throw MergeDirLsErr( status, response );
745 
746  if( !response )
747  throw MergeDirLsErr();
748 
749  XrdCl::DirectoryList *dirlist = 0;
750  response->Get( dirlist );
751 
752  if( !dirlist )
753  throw MergeDirLsErr();
754 
755  if( allowChunked )
756  MergeChunked( dirlist );
757  else
758  Merge( dirlist );
759 
760  response->Set( dirlist );
761  pHandler->HandleResponse( status, response );
762  }
763  catch( const MergeDirLsErr &err )
764  {
765  delete status; delete response;
766  pHandler->HandleResponse( err.status, err.response );
767  }
768 
769  if( finalrsp )
770  {
771  lck.UnLock();
772  delete this;
773  }
774  }
775 
776  void MergeChunked( XrdCl::DirectoryList *&response )
777  {
778  using namespace XrdCl;
779 
780  std::set<ListEntry*, less> unique;
781  // set of unique list entries from the response
782  std::set<ListEntry*, less> tmp( response->Begin(), response->End() );
783  // all the unique list entries that were not reported so far
784  std::set_difference( tmp.begin(), tmp.end(),
785  uniquesofar.begin(), uniquesofar.end(),
786  std::inserter( unique, unique.end() ) );
787 
788  // we update the set of unique list entries that were already
789  // reported to the user's handler
790  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
791  {
792  ListEntry *ent = *itr;
793  if( !uniquesofar.count( ent ) )
794  {
795  StatInfo *info = ent->GetStatInfo() ? new StatInfo( *ent->GetStatInfo() ) : 0;
796  ListEntry *newent = new ListEntry( ent->GetHostAddress(), ent->GetName(), info );
797  uniquesofar.insert( newent );
798  }
799  }
800 
801  DirectoryList *dirlist = new DirectoryList();
802  dirlist->SetParentName( response->GetParentName() );
803  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
804  {
805  ListEntry *entry = *itr;
806  dirlist->Add( new ListEntry( entry->GetHostAddress(),
807  entry->GetName(),
808  entry->GetStatInfo() ) );
809  entry->SetStatInfo( 0 );
810  }
811 
812  delete response;
813  response = dirlist;
814  }
815 
816  static void Merge( XrdCl::DirectoryList *&response )
817  {
818  std::set<ListEntry*, less> unique( response->Begin(), response->End() );
819 
821  dirlist->SetParentName( response->GetParentName() );
822  for( auto itr = unique.begin(); itr != unique.end(); ++itr )
823  {
824  ListEntry *entry = *itr;
825  dirlist->Add( new ListEntry( entry->GetHostAddress(),
826  entry->GetName(),
827  entry->GetStatInfo() ) );
828  entry->SetStatInfo( 0 );
829  }
830 
831  delete response;
832  response = dirlist;
833 }
834 
835  private:
836 
837  typedef XrdCl::DirectoryList::ListEntry ListEntry;
838 
839  struct less
840  {
841  bool operator() (const ListEntry *x, const ListEntry *y) const
842  {
843  if( x->GetName() != y->GetName() )
844  return x->GetName() < y->GetName();
845 
846  const XrdCl::StatInfo *xStatInfo = x->GetStatInfo();
847  const XrdCl::StatInfo *yStatInfo = y->GetStatInfo();
848 
849  if( xStatInfo == yStatInfo )
850  return false;
851 
852  if( xStatInfo == 0 )
853  return true;
854 
855  if( yStatInfo == 0 )
856  return false;
857 
858  if( xStatInfo->GetSize() != yStatInfo->GetSize() )
859  return xStatInfo->GetSize() < yStatInfo->GetSize();
860 
861  if( xStatInfo->GetFlags() != yStatInfo->GetFlags() )
862  return xStatInfo->GetFlags() < yStatInfo->GetFlags();
863 
864  return false;
865  }
866  };
867 
868  bool allowChunked;
869  XrdSysMutex mtx;
870  std::set<ListEntry*, less> uniquesofar;
871  XrdCl::ResponseHandler *pHandler;
872  };
873 }
874 
875 namespace XrdCl
876 {
877  struct FileSystemData;
878 
879  //----------------------------------------------------------------------------
881  //----------------------------------------------------------------------------
883  {
884  public:
885  //------------------------------------------------------------------------
886  // Constructor and destructor
887  //------------------------------------------------------------------------
888  AssignLBHandler( std::shared_ptr<FileSystemData> &fs,
889  ResponseHandler *userHandler ):
890  pFS(fs), pUserHandler(userHandler) {}
891 
892  virtual ~AssignLBHandler() {}
893 
894  //------------------------------------------------------------------------
895  // Response callback
896  //------------------------------------------------------------------------
897  virtual void HandleResponseWithHosts( XRootDStatus *status,
898  AnyObject *response,
899  HostList *hostList );
900 
901  private:
902  std::shared_ptr<FileSystemData> pFS;
903  ResponseHandler *pUserHandler;
904  };
905 
906  //----------------------------------------------------------------------------
908  //----------------------------------------------------------------------------
910  {
911  public:
912  //------------------------------------------------------------------------
913  // Constructor and destructor
914  //------------------------------------------------------------------------
915  AssignLastURLHandler( std::shared_ptr<FileSystemData> &fs,
916  ResponseHandler *userHandler ):
917  pFS(fs), pUserHandler(userHandler) {}
918 
920 
921  //------------------------------------------------------------------------
922  // Response callback
923  //------------------------------------------------------------------------
924  virtual void HandleResponseWithHosts( XRootDStatus *status,
925  AnyObject *response,
926  HostList *hostList );
927 
928  private:
929  std::shared_ptr<FileSystemData> pFS;
930  ResponseHandler *pUserHandler;
931  };
932 
933 
935  {
936  FileSystemData( const URL &url ) :
937  pLoadBalancerLookupDone( false ),
938  pFollowRedirects( true ),
939  pUrl( new URL( url.GetURL() ) )
940  {
941  }
942 
943  //------------------------------------------------------------------------
944  // Send a message in a locked environment
945  //------------------------------------------------------------------------
946  static XRootDStatus Send( std::shared_ptr<FileSystemData> &fs,
947  Message *msg,
948  ResponseHandler *handler,
949  MessageSendParams &params )
950  {
951  Log *log = DefaultEnv::GetLog();
952  XrdSysMutexHelper scopedLock( fs->pMutex );
953 
954  log->Dump( FileSystemMsg, "[%p@%s] Sending %s", fs.get(),
955  fs->pUrl->GetHostId().c_str(), msg->GetObfuscatedDescription().c_str() );
956 
957  AssignLastURLHandler *lastUrlHandler = new AssignLastURLHandler( fs, handler );
958  handler = lastUrlHandler;
959 
960  AssignLBHandler *lbHandler = nullptr;
961  if( !fs->pLoadBalancerLookupDone && fs->pFollowRedirects )
962  {
963  lbHandler = new AssignLBHandler( fs, handler );
964  handler = lbHandler;
965  }
966 
967  params.followRedirects = fs->pFollowRedirects;
968 
969  auto st = MessageUtils::SendMessage( *fs->pUrl, msg, handler, params, 0 );
970  if( !st.IsOK() )
971  {
972  delete lastUrlHandler;
973  delete lbHandler;
974  }
975 
976  return st;
977  }
978 
979  //----------------------------------------------------------------------------
980  // Assign a load balancer if it has not already been assigned
981  //----------------------------------------------------------------------------
982  void AssignLoadBalancer( const URL &url )
983  {
984  Log *log = DefaultEnv::GetLog();
985  XrdSysMutexHelper scopedLock( pMutex );
986 
987  if( pLoadBalancerLookupDone )
988  return;
989 
990  log->Dump( FileSystemMsg, "[%p@%s] Assigning %s as load balancer", this,
991  pUrl->GetHostId().c_str(), url.GetHostId().c_str() );
992 
993  pUrl.reset( new URL( url ) );
994  pLoadBalancerLookupDone = true;
995  }
996 
997  //----------------------------------------------------------------------------
998  // Assign last URL
999  //----------------------------------------------------------------------------
1000  void AssignLastURL( const URL &url )
1001  {
1002  Log *log = DefaultEnv::GetLog();
1003  XrdSysMutexHelper scopedLock( pMutex );
1004 
1005  log->Dump( FileSystemMsg, "[%p@%s] Assigning %s as last URL", this,
1006  pUrl->GetHostId().c_str(), url.GetHostId().c_str() );
1007 
1008  pLastUrl.reset( new URL( url ) );
1009  }
1010 
1014  std::unique_ptr<URL> pUrl;
1015  std::unique_ptr<URL> pLastUrl;
1016  };
1017 
1018  //----------------------------------------------------------------------------
1020  //----------------------------------------------------------------------------
1022  {
1023  FileSystemImpl( const URL &url ) :
1024  fsdata( std::make_shared<FileSystemData>( url ) )
1025  {
1026  }
1027 
1028  std::shared_ptr<FileSystemData> fsdata;
1029  };
1030 
1031  //------------------------------------------------------------------------
1032  // Response callback
1033  //------------------------------------------------------------------------
1034  void AssignLBHandler::HandleResponseWithHosts( XRootDStatus *status,
1035  AnyObject *response,
1036  HostList *hostList )
1037  {
1038  if( status->IsOK() )
1039  {
1040  HostList::reverse_iterator it;
1041  for( it = hostList->rbegin(); it != hostList->rend(); ++it )
1042  if( it->loadBalancer )
1043  {
1044  pFS->AssignLoadBalancer( it->url );
1045  break;
1046  }
1047  }
1048 
1049  bool finalrsp = !( status->IsOK() && status->code == suContinue );
1050 
1051  SyncResponseHandler * syncHandler = dynamic_cast<SyncResponseHandler*>( pUserHandler );
1052  if( !syncHandler )
1053  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1054 
1055  if( finalrsp )
1056  {
1057  if( syncHandler )
1058  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1059  delete this;
1060  }
1061  }
1062 
1063  //------------------------------------------------------------------------
1064  // Response callback
1065  //------------------------------------------------------------------------
1066  void AssignLastURLHandler::HandleResponseWithHosts( XRootDStatus *status,
1067  AnyObject *response,
1068  HostList *hostList )
1069  {
1070  if( status->IsOK() && hostList )
1071  pFS->AssignLastURL( hostList->front().url );
1072 
1073  bool finalrsp = !( status->IsOK() && status->code == suContinue );
1074 
1075  SyncResponseHandler *syncHandler = dynamic_cast<SyncResponseHandler*>( pUserHandler );
1076  if( !syncHandler )
1077  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1078 
1079  if( finalrsp )
1080  {
1081  if( syncHandler )
1082  pUserHandler->HandleResponseWithHosts( status, response, hostList );
1083  delete this;
1084  }
1085  }
1086 
1087  //----------------------------------------------------------------------------
1088  // Constructor
1089  //----------------------------------------------------------------------------
1090  FileSystem::FileSystem( const URL &url, bool enablePlugIns ):
1091  pImpl( new FileSystemImpl( url ) ),
1092  pPlugIn(0)
1093  {
1094  //--------------------------------------------------------------------------
1095  // Check if we need to install a plug-in for this URL
1096  //--------------------------------------------------------------------------
1097  if( enablePlugIns )
1098  {
1099  Log *log = DefaultEnv::GetLog();
1100  std::string urlStr = url.GetURL();
1102  if( fact )
1103  {
1104  pPlugIn = fact->CreateFileSystem( urlStr );
1105  if( !pPlugIn )
1106  {
1107  log->Error( FileMsg, "Plug-in factory failed to produce a plug-in "
1108  "for %s, continuing without one", url.GetObfuscatedURL().c_str() );
1109  }
1110  }
1111  }
1112 
1113  if( !pPlugIn )
1115  }
1116 
1117  //----------------------------------------------------------------------------
1118  // Destructor
1119  //----------------------------------------------------------------------------
1121  {
1122  if( !pPlugIn )
1123  {
1126  }
1127 
1128  delete pPlugIn;
1129  delete pImpl;
1130  }
1131 
1132  //----------------------------------------------------------------------------
1133  // Locate a file - async
1134  //----------------------------------------------------------------------------
1135  XRootDStatus FileSystem::Locate( const std::string &path,
1136  OpenFlags::Flags flags,
1137  ResponseHandler *handler,
1138  uint16_t timeout )
1139  {
1140  if( pPlugIn )
1141  return pPlugIn->Locate( path, flags, handler, timeout );
1142 
1143  std::string fPath = FilterXrdClCgi( path );
1144 
1145  Message *msg;
1146  ClientLocateRequest *req;
1147  MessageUtils::CreateRequest( msg, req, fPath.length() );
1148 
1149  req->requestid = kXR_locate;
1150  req->options = flags;
1151  req->dlen = fPath.length();
1152  msg->Append( fPath.c_str(), fPath.length(), 24 );
1153  MessageSendParams params; params.timeout = timeout;
1155 
1157 
1158  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1159  }
1160 
1161  //----------------------------------------------------------------------------
1162  // Locate a file - sync
1163  //----------------------------------------------------------------------------
1164  XRootDStatus FileSystem::Locate( const std::string &path,
1165  OpenFlags::Flags flags,
1166  LocationInfo *&response,
1167  uint16_t timeout )
1168  {
1169  SyncResponseHandler handler;
1170  Status st = Locate( path, flags, &handler, timeout );
1171  if( !st.IsOK() )
1172  return st;
1173 
1174  return MessageUtils::WaitForResponse( &handler, response );
1175  }
1176 
1177  //----------------------------------------------------------------------------
1178  // Locate a file, recursively locate all disk servers - async
1179  //----------------------------------------------------------------------------
1180  XRootDStatus FileSystem::DeepLocate( const std::string &path,
1181  OpenFlags::Flags flags,
1182  ResponseHandler *handler,
1183  uint16_t timeout )
1184  {
1185  return Locate( path, flags,
1186  new DeepLocateHandler( handler, path, flags, timeout ), timeout );
1187  }
1188 
1189  //----------------------------------------------------------------------------
1190  // Locate a file, recursively locate all disk servers - sync
1191  //----------------------------------------------------------------------------
1192  XRootDStatus FileSystem::DeepLocate( const std::string &path,
1193  OpenFlags::Flags flags,
1194  LocationInfo *&response,
1195  uint16_t timeout )
1196  {
1197  SyncResponseHandler handler;
1198  Status st = DeepLocate( path, flags, &handler, timeout );
1199  if( !st.IsOK() )
1200  return st;
1201 
1202  return MessageUtils::WaitForResponse( &handler, response );
1203  }
1204 
1205  //----------------------------------------------------------------------------
1206  // Move a directory or a file - async
1207  //----------------------------------------------------------------------------
1208  XRootDStatus FileSystem::Mv( const std::string &source,
1209  const std::string &dest,
1210  ResponseHandler *handler,
1211  uint16_t timeout )
1212  {
1213  if( pPlugIn )
1214  return pPlugIn->Mv( source, dest, handler, timeout );
1215 
1216  std::string fSource = FilterXrdClCgi( source );
1217  std::string fDest = FilterXrdClCgi( dest );
1218 
1219  Message *msg;
1220  ClientMvRequest *req;
1221  MessageUtils::CreateRequest( msg, req, fSource.length() + fDest.length()+1 );
1222 
1223  req->requestid = kXR_mv;
1224  req->dlen = fSource.length() + fDest.length()+1;
1225  req->arg1len = fSource.length();
1226  msg->Append( fSource.c_str(), fSource.length(), 24 );
1227  *msg->GetBuffer(24 + fSource.length()) = ' ';
1228  msg->Append( fDest.c_str(), fDest.length(), 25 + fSource.length() );
1229  MessageSendParams params; params.timeout = timeout;
1231 
1233 
1234  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1235  }
1236 
1237  //----------------------------------------------------------------------------
1238  // Move a directory or a file - sync
1239  //----------------------------------------------------------------------------
1240  XRootDStatus FileSystem::Mv( const std::string &source,
1241  const std::string &dest,
1242  uint16_t timeout )
1243  {
1244  SyncResponseHandler handler;
1245  Status st = Mv( source, dest, &handler, timeout );
1246  if( !st.IsOK() )
1247  return st;
1248 
1249  return MessageUtils::WaitForStatus( &handler );
1250  }
1251 
1252  //----------------------------------------------------------------------------
1253  // Obtain server information - async
1254  //----------------------------------------------------------------------------
1256  const Buffer &arg,
1257  ResponseHandler *handler,
1258  uint16_t timeout )
1259  {
1260  if( pPlugIn )
1261  return pPlugIn->Query( queryCode, arg, handler, timeout );
1262 
1263  Message *msg;
1264  ClientQueryRequest *req;
1265  MessageUtils::CreateRequest( msg, req, arg.GetSize() );
1266 
1267  req->requestid = kXR_query;
1268  req->infotype = queryCode;
1269  req->dlen = arg.GetSize();
1270  msg->Append( arg.GetBuffer(), arg.GetSize(), 24 );
1271  MessageSendParams params; params.timeout = timeout;
1274 
1275  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1276  }
1277 
1278  //----------------------------------------------------------------------------
1279  // Obtain server information - sync
1280  //----------------------------------------------------------------------------
1282  const Buffer &arg,
1283  Buffer *&response,
1284  uint16_t timeout )
1285  {
1286  SyncResponseHandler handler;
1287  Status st = Query( queryCode, arg, &handler, timeout );
1288  if( !st.IsOK() )
1289  return st;
1290 
1291  return MessageUtils::WaitForResponse( &handler, response );
1292  }
1293 
1294  //----------------------------------------------------------------------------
1295  // Truncate a file - async
1296  //----------------------------------------------------------------------------
1297  XRootDStatus FileSystem::Truncate( const std::string &path,
1298  uint64_t size,
1299  ResponseHandler *handler,
1300  uint16_t timeout )
1301  {
1302  if( pPlugIn )
1303  return pPlugIn->Truncate( path, size, handler, timeout );
1304 
1305  std::string fPath = FilterXrdClCgi( path );
1306 
1307  Message *msg;
1308  ClientTruncateRequest *req;
1309  MessageUtils::CreateRequest( msg, req, fPath.length() );
1310 
1311  req->requestid = kXR_truncate;
1312  req->offset = size;
1313  req->dlen = fPath.length();
1314  msg->Append( fPath.c_str(), fPath.length(), 24 );
1315  MessageSendParams params; params.timeout = timeout;
1318 
1319  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1320  }
1321 
1322  //----------------------------------------------------------------------------
1323  // Truncate a file - sync
1324  //----------------------------------------------------------------------------
1325  XRootDStatus FileSystem::Truncate( const std::string &path,
1326  uint64_t size,
1327  uint16_t timeout )
1328  {
1329  SyncResponseHandler handler;
1330  Status st = Truncate( path, size, &handler, timeout );
1331  if( !st.IsOK() )
1332  return st;
1333 
1334  return MessageUtils::WaitForStatus( &handler );
1335  }
1336 
1337  //----------------------------------------------------------------------------
1338  // Remove a file - async
1339  //----------------------------------------------------------------------------
1340  XRootDStatus FileSystem::Rm( const std::string &path,
1341  ResponseHandler *handler,
1342  uint16_t timeout )
1343  {
1344  if( pPlugIn )
1345  return pPlugIn->Rm( path, handler, timeout );
1346 
1347  if( pImpl->fsdata->pUrl->IsLocalFile() )
1348  return LocalFS::Instance().Rm( path, handler, timeout );
1349 
1350  std::string fPath = FilterXrdClCgi( path );
1351 
1352  Message *msg;
1353  ClientRmRequest *req;
1354  MessageUtils::CreateRequest( msg, req, fPath.length() );
1355 
1356  req->requestid = kXR_rm;
1357  req->dlen = fPath.length();
1358  msg->Append( fPath.c_str(), fPath.length(), 24 );
1359  MessageSendParams params; params.timeout = timeout;
1362 
1363  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1364  }
1365 
1366  //----------------------------------------------------------------------------
1367  // Remove a file - sync
1368  //----------------------------------------------------------------------------
1369  XRootDStatus FileSystem::Rm( const std::string &path,
1370  uint16_t timeout )
1371  {
1372  SyncResponseHandler handler;
1373  Status st = Rm( path, &handler, timeout );
1374  if( !st.IsOK() )
1375  return st;
1376 
1377  return MessageUtils::WaitForStatus( &handler );
1378  }
1379 
1380  //----------------------------------------------------------------------------
1381  // Create a directory - async
1382  //----------------------------------------------------------------------------
1383  XRootDStatus FileSystem::MkDir( const std::string &path,
1384  MkDirFlags::Flags flags,
1385  Access::Mode mode,
1386  ResponseHandler *handler,
1387  uint16_t timeout )
1388  {
1389  if( pPlugIn )
1390  return pPlugIn->MkDir( path, flags, mode, handler, timeout );
1391 
1392  std::string fPath = FilterXrdClCgi( path );
1393 
1394  Message *msg;
1395  ClientMkdirRequest *req;
1396  MessageUtils::CreateRequest( msg, req, fPath.length() );
1397 
1398  req->requestid = kXR_mkdir;
1399  req->options[0] = flags;
1400  req->mode = mode;
1401  req->dlen = fPath.length();
1402  msg->Append( fPath.c_str(), fPath.length(), 24 );
1403  MessageSendParams params; params.timeout = timeout;
1406 
1407  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1408  }
1409 
1410  //----------------------------------------------------------------------------
1411  // Create a directory - sync
1412  //----------------------------------------------------------------------------
1413  XRootDStatus FileSystem::MkDir( const std::string &path,
1414  MkDirFlags::Flags flags,
1415  Access::Mode mode,
1416  uint16_t timeout )
1417  {
1418  SyncResponseHandler handler;
1419  Status st = MkDir( path, flags, mode, &handler, timeout );
1420  if( !st.IsOK() )
1421  return st;
1422 
1423  return MessageUtils::WaitForStatus( &handler );
1424  }
1425 
1426  //----------------------------------------------------------------------------
1427  // Remove a directory - async
1428  //----------------------------------------------------------------------------
1429  XRootDStatus FileSystem::RmDir( const std::string &path,
1430  ResponseHandler *handler,
1431  uint16_t timeout )
1432  {
1433  if( pPlugIn )
1434  return pPlugIn->RmDir( path, handler, timeout );
1435 
1436  std::string fPath = FilterXrdClCgi( path );
1437 
1438  Message *msg;
1439  ClientRmdirRequest *req;
1440  MessageUtils::CreateRequest( msg, req, fPath.length() );
1441 
1442  req->requestid = kXR_rmdir;
1443  req->dlen = fPath.length();
1444  msg->Append( fPath.c_str(), fPath.length(), 24 );
1445  MessageSendParams params; params.timeout = timeout;
1448 
1449  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1450  }
1451 
1452  //----------------------------------------------------------------------------
1453  // Remove a directory - sync
1454  //----------------------------------------------------------------------------
1455  XRootDStatus FileSystem::RmDir( const std::string &path,
1456  uint16_t timeout )
1457  {
1458  SyncResponseHandler handler;
1459  Status st = RmDir( path, &handler, timeout );
1460  if( !st.IsOK() )
1461  return st;
1462 
1463  return MessageUtils::WaitForStatus( &handler );
1464  }
1465 
1466  //----------------------------------------------------------------------------
1467  // Change access mode on a directory or a file - async
1468  //----------------------------------------------------------------------------
1469  XRootDStatus FileSystem::ChMod( const std::string &path,
1470  Access::Mode mode,
1471  ResponseHandler *handler,
1472  uint16_t timeout )
1473  {
1474  if( pPlugIn )
1475  return pPlugIn->ChMod( path, mode, handler, timeout );
1476 
1477  std::string fPath = FilterXrdClCgi( path );
1478 
1479  Message *msg;
1480  ClientChmodRequest *req;
1481  MessageUtils::CreateRequest( msg, req, fPath.length() );
1482 
1483  req->requestid = kXR_chmod;
1484  req->mode = mode;
1485  req->dlen = fPath.length();
1486  msg->Append( fPath.c_str(), fPath.length(), 24 );
1487  MessageSendParams params; params.timeout = timeout;
1490 
1491  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1492  }
1493 
1494  //----------------------------------------------------------------------------
1495  // Change access mode on a directory or a file - async
1496  //----------------------------------------------------------------------------
1497  XRootDStatus FileSystem::ChMod( const std::string &path,
1498  Access::Mode mode,
1499  uint16_t timeout )
1500  {
1501  SyncResponseHandler handler;
1502  Status st = ChMod( path, mode, &handler, timeout );
1503  if( !st.IsOK() )
1504  return st;
1505 
1506  return MessageUtils::WaitForStatus( &handler );
1507  }
1508 
1509  //----------------------------------------------------------------------------
1510  // Check if the server is alive - async
1511  //----------------------------------------------------------------------------
1513  uint16_t timeout )
1514  {
1515  if( pPlugIn )
1516  return pPlugIn->Ping( handler, timeout );
1517 
1518  Message *msg;
1519  ClientPingRequest *req;
1520  MessageUtils::CreateRequest( msg, req );
1521 
1522  req->requestid = kXR_ping;
1523  MessageSendParams params; params.timeout = timeout;
1526 
1527  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1528  }
1529 
1530  //----------------------------------------------------------------------------
1531  // Check if the server is alive - sync
1532  //----------------------------------------------------------------------------
1533  XRootDStatus FileSystem::Ping( uint16_t timeout )
1534  {
1535  SyncResponseHandler handler;
1536  Status st = Ping( &handler, timeout );
1537  if( !st.IsOK() )
1538  return st;
1539 
1540  return MessageUtils::WaitForStatus( &handler );
1541  }
1542 
1543  //----------------------------------------------------------------------------
1544  // Obtain status information for a path - async
1545  //----------------------------------------------------------------------------
1546  XRootDStatus FileSystem::Stat( const std::string &path,
1547  ResponseHandler *handler,
1548  uint16_t timeout )
1549  {
1550  if( pPlugIn )
1551  return pPlugIn->Stat( path, handler, timeout );
1552 
1553  if( pImpl->fsdata->pUrl->IsLocalFile() )
1554  return LocalFS::Instance().Stat( path, handler, timeout );
1555 
1556  std::string fPath = FilterXrdClCgi( path );
1557 
1558  Message *msg;
1559  ClientStatRequest *req;
1560  MessageUtils::CreateRequest( msg, req, fPath.length() );
1561 
1562  req->requestid = kXR_stat;
1563  req->options = 0;
1564  req->dlen = fPath.length();
1565  msg->Append( fPath.c_str(), fPath.length(), 24 );
1566  MessageSendParams params; params.timeout = timeout;
1569 
1570  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1571  }
1572 
1573  //----------------------------------------------------------------------------
1574  // Obtain status information for a path - sync
1575  //----------------------------------------------------------------------------
1576  XRootDStatus FileSystem::Stat( const std::string &path,
1577  StatInfo *&response,
1578  uint16_t timeout )
1579  {
1580  SyncResponseHandler handler;
1581  Status st = Stat( path, &handler, timeout );
1582  if( !st.IsOK() )
1583  return st;
1584 
1585  return MessageUtils::WaitForResponse( &handler, response );
1586  }
1587 
1588  //----------------------------------------------------------------------------
1589  // Obtain status information for a path - async
1590  //----------------------------------------------------------------------------
1591  XRootDStatus FileSystem::StatVFS( const std::string &path,
1592  ResponseHandler *handler,
1593  uint16_t timeout )
1594  {
1595  if( pPlugIn )
1596  return pPlugIn->StatVFS( path, handler, timeout );
1597 
1598  std::string fPath = FilterXrdClCgi( path );
1599 
1600  Message *msg;
1601  ClientStatRequest *req;
1602  MessageUtils::CreateRequest( msg, req, fPath.length() );
1603 
1604  req->requestid = kXR_stat;
1605  req->options = kXR_vfs;
1606  req->dlen = fPath.length();
1607  msg->Append( fPath.c_str(), fPath.length(), 24 );
1608  MessageSendParams params; params.timeout = timeout;
1611 
1612  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1613  }
1614 
1615  //----------------------------------------------------------------------------
1616  // Obtain status information for a path - sync
1617  //----------------------------------------------------------------------------
1618  XRootDStatus FileSystem::StatVFS( const std::string &path,
1619  StatInfoVFS *&response,
1620  uint16_t timeout )
1621  {
1622  SyncResponseHandler handler;
1623  Status st = StatVFS( path, &handler, timeout );
1624  if( !st.IsOK() )
1625  return st;
1626 
1627  return MessageUtils::WaitForResponse( &handler, response );
1628  }
1629 
1630  //----------------------------------------------------------------------------
1631  // Obtain server protocol information - async
1632  //----------------------------------------------------------------------------
1634  uint16_t timeout )
1635  {
1636  if( pPlugIn )
1637  return pPlugIn->Protocol( handler, timeout );
1638 
1639  Message *msg;
1640  ClientProtocolRequest *req;
1641  MessageUtils::CreateRequest( msg, req );
1642 
1643  req->requestid = kXR_protocol;
1645  MessageSendParams params; params.timeout = timeout;
1648 
1649  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1650  }
1651 
1652  //----------------------------------------------------------------------------
1653  // Obtain server protocol information - sync
1654  //----------------------------------------------------------------------------
1656  uint16_t timeout )
1657  {
1658  SyncResponseHandler handler;
1659  Status st = Protocol( &handler, timeout );
1660  if( !st.IsOK() )
1661  return st;
1662 
1663  return MessageUtils::WaitForResponse( &handler, response );
1664  }
1665 
1666  //----------------------------------------------------------------------------
1667  // List entries of a directory - async
1668  //----------------------------------------------------------------------------
1669  XRootDStatus FileSystem::DirList( const std::string &path,
1670  DirListFlags::Flags flags,
1671  ResponseHandler *handler,
1672  uint16_t timeout )
1673  {
1674  if( pPlugIn )
1675  return pPlugIn->DirList( path, flags, handler, timeout );
1676 
1677  URL url = URL( path );
1678  std::string fPath = FilterXrdClCgi( path );
1679 
1680  if( flags & DirListFlags::Zip )
1681  {
1682  // stat the file to check if it is a directory or a file
1683  // the ZIP handler will take care of the rest
1684  ZipListHandler *zipHandler = new ZipListHandler( *pImpl->fsdata->pUrl, path, flags, handler, timeout );
1685  XRootDStatus st = Stat( path, zipHandler, timeout );
1686  if( !st.IsOK() )
1687  delete zipHandler;
1688  return st;
1689  }
1690 
1691  Message *msg;
1692  ClientDirlistRequest *req;
1693  MessageUtils::CreateRequest( msg, req, fPath.length() );
1694 
1695  req->requestid = kXR_dirlist;
1696  req->dlen = fPath.length();
1697 
1698  if( ( flags & DirListFlags::Stat ) || ( flags & DirListFlags::Recursive ) )
1699  req->options[0] = kXR_dstat;
1700 
1701  if( ( flags & DirListFlags::Cksm ) )
1702  req->options[0] = kXR_dstat | kXR_dcksm;
1703 
1704  if( flags & DirListFlags::Recursive )
1705  handler = new RecursiveDirListHandler( *pImpl->fsdata->pUrl, url.GetPath(), flags, handler, timeout );
1706 
1707  if( flags & DirListFlags::Merge )
1708  handler = new MergeDirListHandler( flags & DirListFlags::Chunked, handler );
1709 
1710  msg->Append( fPath.c_str(), fPath.length(), 24 );
1711  MessageSendParams params; params.timeout = timeout;
1712  if( flags & DirListFlags::Chunked )
1713  params.chunkedResponse = true;
1716 
1717  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1718  }
1719 
1720  //----------------------------------------------------------------------------
1721  // List entries of a directory - sync
1722  //----------------------------------------------------------------------------
1723  XRootDStatus FileSystem::DirList( const std::string &path,
1724  DirListFlags::Flags flags,
1725  DirectoryList *&response,
1726  uint16_t timeout )
1727  {
1728  //--------------------------------------------------------------------------
1729  // Chunked response is only possible for async DirList call
1730  //--------------------------------------------------------------------------
1731  if( flags & DirListFlags::Chunked )
1733 
1734  //--------------------------------------------------------------------------
1735  // If the path ends with '.zip' extension add Zip flag
1736  //--------------------------------------------------------------------------
1737  static const std::string zip_sufix = ".zip";
1738  if( path.size() >= zip_sufix.size() &&
1739  std::equal( zip_sufix.rbegin(), zip_sufix.rend(), path.rbegin() ) )
1740  flags |= DirListFlags::Zip;
1741 
1742  //--------------------------------------------------------------------------
1743  // We do the deep locate and ask all the returned servers for the list
1744  //--------------------------------------------------------------------------
1745  if( flags & DirListFlags::Locate )
1746  {
1747  bool isserver = false;
1748  //------------------------------------------------------------------------
1749  // Check if destination is a data server
1750  //------------------------------------------------------------------------
1751  {
1752  AnyObject obj;
1754  *pImpl->fsdata->pUrl, XRootDQuery::ServerFlags, obj);
1755 
1756  if( st.IsOK() )
1757  {
1758  int *ptr = 0;
1759  obj.Get( ptr );
1760  isserver = ( ptr && (*ptr & kXR_isServer) );
1761  delete ptr;
1762  }
1763  }
1764 
1765  if (isserver) {
1766  // Just disable the locate flag if we are talking to a single server
1767  flags &= ~DirListFlags::Locate;
1768  } else {
1769  //------------------------------------------------------------------------
1770  // Locate all the disk servers holding the directory
1771  //------------------------------------------------------------------------
1772  LocationInfo *locations;
1773  std::string locatePath = "*"; locatePath += path;
1774 
1775  XRootDStatus st = DeepLocate(locatePath,
1779  locations);
1780 
1781  if( !st.IsOK() )
1782  return st;
1783 
1784  if( locations->GetSize() == 0 )
1785  {
1786  delete locations;
1787  return XRootDStatus( stError, errNotFound );
1788  }
1789 
1790  //------------------------------------------------------------------------
1791  // Ask each server for a directory list
1792  //------------------------------------------------------------------------
1793  flags &= ~DirListFlags::Locate;
1794  FileSystem *fs;
1795  DirectoryList *currentResp = 0;
1796  uint32_t errors = 0;
1797  uint32_t numLocations = locations->GetSize();
1798  bool partial = st.code == suPartial ? true : false;
1799 
1800  response = new DirectoryList();
1801  response->SetParentName( path );
1802 
1803  for( uint32_t i = 0; i < locations->GetSize(); ++i )
1804  {
1805  URL locationURL( locations->At(i).GetAddress() );
1806  // make sure the original protocol is preserved (root vs roots)
1807  locationURL.SetProtocol( pImpl->fsdata->pUrl->GetProtocol() );
1808  fs = new FileSystem( locationURL );
1809  st = fs->DirList( path, flags, currentResp, timeout );
1810  if( !st.IsOK() )
1811  {
1812  ++errors;
1813  delete fs;
1814  continue;
1815  }
1816 
1817  if( st.code == suPartial )
1818  partial = true;
1819 
1821 
1822  for( it = currentResp->Begin(); it != currentResp->End(); ++it )
1823  {
1824  response->Add( *it );
1825  *it = 0;
1826  }
1827 
1828  delete fs;
1829  delete currentResp;
1830  fs = 0;
1831  currentResp = 0;
1832  }
1833 
1834  delete locations;
1835 
1836  if( flags & DirListFlags::Merge )
1837  MergeDirListHandler::Merge( response );
1838 
1839  if( errors || partial )
1840  {
1841  if( errors == numLocations )
1842  return st;
1843  return XRootDStatus( stOK, suPartial );
1844  }
1845  return XRootDStatus();
1846  }
1847  }
1848 
1849  //--------------------------------------------------------------------------
1850  // We just ask the current server
1851  //--------------------------------------------------------------------------
1852  SyncResponseHandler handler;
1853  XRootDStatus st = DirList( path, flags, &handler, timeout );
1854  if( !st.IsOK() )
1855  return st;
1856 
1857  st = MessageUtils::WaitForResponse( &handler, response );
1858  if( !st.IsOK() )
1859  return st;
1860 
1861  //--------------------------------------------------------------------------
1862  // Do the stats on all the entries if necessary.
1863  // If we already have the stat objects it means that the bulk stat has
1864  // succeeded.
1865  //--------------------------------------------------------------------------
1866  if( !(flags & DirListFlags::Stat) )
1867  return st;
1868 
1869  if( response->GetSize() && response->At(0)->GetStatInfo() )
1870  return st;
1871 
1872  uint32_t quota = response->GetSize() <= 1024 ? response->GetSize() : 1024;
1873  RequestSync sync( response->GetSize(), quota );
1874  for( uint32_t i = 0; i < response->GetSize(); ++i )
1875  {
1876  std::string fullPath = response->GetParentName()+response->At(i)->GetName();
1877  ResponseHandler *handler = new DirListStatHandler( response, i, &sync );
1878  st = Stat( fullPath, handler, timeout );
1879  if( !st.IsOK() )
1880  {
1881  sync.TaskDone( false );
1882  delete handler;
1883  }
1884  sync.WaitForQuota();
1885  }
1886  sync.WaitForAll();
1887 
1888  if( sync.FailureCount() )
1889  return XRootDStatus( stOK, suPartial );
1890 
1891  return XRootDStatus();
1892  }
1893 
1894  //----------------------------------------------------------------------------
1895  // Send cache info to the server - async
1896  //----------------------------------------------------------------------------
1897  XRootDStatus FileSystem::SendCache( const std::string &info,
1898  ResponseHandler *handler,
1899  uint16_t timeout )
1900  {
1901  // Note: adding SendCache() to the FileSystemPlugin class breaks ABI!
1902  // So, the class is missing this until we do a major release. TODO
1903  //if( pPlugIn )
1904  // return pPlugIn->SendCache( info, handler, timeout );
1905  return SendSet("cache ", info, handler, timeout );
1906  }
1907 
1908  //----------------------------------------------------------------------------
1910  //----------------------------------------------------------------------------
1911  XRootDStatus FileSystem::SendCache( const std::string &info,
1912  Buffer *&response,
1913  uint16_t timeout )
1914  {
1915  SyncResponseHandler handler;
1916  Status st = SendCache( info, &handler, timeout );
1917  if( !st.IsOK() )
1918  return st;
1919 
1920  return MessageUtils::WaitForResponse( &handler, response );
1921  }
1922 
1923  //----------------------------------------------------------------------------
1924  // Send info to the server - async
1925  //----------------------------------------------------------------------------
1926  XRootDStatus FileSystem::SendInfo( const std::string &info,
1927  ResponseHandler *handler,
1928  uint16_t timeout )
1929  {
1930  if( pPlugIn )
1931  return pPlugIn->SendInfo( info, handler, timeout );
1932  return SendSet("monitor info ", info, handler, timeout );
1933  }
1934 
1935  //----------------------------------------------------------------------------
1937  //----------------------------------------------------------------------------
1938  XRootDStatus FileSystem::SendInfo( const std::string &info,
1939  Buffer *&response,
1940  uint16_t timeout )
1941  {
1942  SyncResponseHandler handler;
1943  Status st = SendInfo( info, &handler, timeout );
1944  if( !st.IsOK() )
1945  return st;
1946 
1947  return MessageUtils::WaitForResponse( &handler, response );
1948  }
1949 
1950  //----------------------------------------------------------------------------
1951  // Send set request to the server - async
1952  //----------------------------------------------------------------------------
1953  XRootDStatus FileSystem::SendSet( const char *prefix,
1954  const std::string &info,
1955  ResponseHandler *handler,
1956  uint16_t timeout )
1957  {
1958 
1959  Message *msg;
1960  ClientSetRequest *req;
1961  size_t prefixLen = strlen( prefix );
1962  MessageUtils::CreateRequest( msg, req, info.length()+prefixLen );
1963 
1964  req->requestid = kXR_set;
1965  req->dlen = info.length()+prefixLen;
1966  msg->Append( prefix, prefixLen, 24 );
1967  msg->Append( info.c_str(), info.length(), 24+prefixLen );
1968  MessageSendParams params; params.timeout = timeout;
1971 
1972  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
1973  }
1974 
1975  //----------------------------------------------------------------------------
1976  // Prepare one or more files for access - async
1977  //----------------------------------------------------------------------------
1978  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
1979  PrepareFlags::Flags flags,
1980  uint8_t priority,
1981  ResponseHandler *handler,
1982  uint16_t timeout )
1983  {
1984  if( pPlugIn )
1985  return pPlugIn->Prepare( fileList, flags, priority, handler, timeout );
1986 
1987  std::vector<std::string>::const_iterator it;
1988  std::string list;
1989  for( it = fileList.begin(); it != fileList.end(); ++it )
1990  {
1991  list += *it;
1992  list += "\n";
1993  }
1994  list.erase( list.length()-1, 1 );
1995 
1996  Message *msg;
1997  ClientPrepareRequest *req;
1998  MessageUtils::CreateRequest( msg, req, list.length() );
1999 
2000  req->requestid = kXR_prepare;
2001  req->options = 0xff & flags;
2002  req->optionX = 0xffff & ( flags >> 8 );
2003  req->prty = priority;
2004  req->dlen = list.length();
2005 
2006  msg->Append( list.c_str(), list.length(), 24 );
2007 
2008  MessageSendParams params; params.timeout = timeout;
2011 
2012  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
2013  }
2014 
2015  //------------------------------------------------------------------------
2016  // Prepare one or more files for access - sync
2017  //------------------------------------------------------------------------
2018  XRootDStatus FileSystem::Prepare( const std::vector<std::string> &fileList,
2019  PrepareFlags::Flags flags,
2020  uint8_t priority,
2021  Buffer *&response,
2022  uint16_t timeout )
2023  {
2024  SyncResponseHandler handler;
2025  Status st = Prepare( fileList, flags, priority, &handler, timeout );
2026  if( !st.IsOK() )
2027  return st;
2028 
2029  return MessageUtils::WaitForResponse( &handler, response );
2030  }
2031 
2032  //------------------------------------------------------------------------
2033  // Set extended attributes - async
2034  //------------------------------------------------------------------------
2035  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2036  const std::vector<xattr_t> &attrs,
2037  ResponseHandler *handler,
2038  uint16_t timeout )
2039  {
2040  if( pPlugIn )
2042 
2043  return XAttrOperationImpl( kXR_fattrSet, 0, path, attrs, handler, timeout );
2044  }
2045 
2046  //------------------------------------------------------------------------
2047  // Set extended attributes - sync
2048  //------------------------------------------------------------------------
2049  XRootDStatus FileSystem::SetXAttr( const std::string &path,
2050  const std::vector<xattr_t> &attrs,
2051  std::vector<XAttrStatus> &result,
2052  uint16_t timeout )
2053  {
2054  SyncResponseHandler handler;
2055  XRootDStatus st = SetXAttr( path, attrs, &handler, timeout );
2056  if( !st.IsOK() )
2057  return st;
2058 
2059  std::vector<XAttrStatus> *resp = 0;
2060  st = MessageUtils::WaitForResponse( &handler, resp );
2061  if( resp ) result.swap( *resp );
2062  delete resp;
2063 
2064  return st;
2065  }
2066 
2067  //------------------------------------------------------------------------
2068  // Get extended attributes - async
2069  //------------------------------------------------------------------------
2070  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2071  const std::vector<std::string> &attrs,
2072  ResponseHandler *handler,
2073  uint16_t timeout )
2074  {
2075  if( pPlugIn )
2077 
2078  return XAttrOperationImpl( kXR_fattrGet, 0, path, attrs, handler, timeout );
2079  }
2080 
2081  //------------------------------------------------------------------------
2082  // Get extended attributes - sync
2083  //------------------------------------------------------------------------
2084  XRootDStatus FileSystem::GetXAttr( const std::string &path,
2085  const std::vector<std::string> &attrs,
2086  std::vector<XAttr> &result,
2087  uint16_t timeout )
2088  {
2089  SyncResponseHandler handler;
2090  XRootDStatus st = GetXAttr( path, attrs, &handler, timeout );
2091  if( !st.IsOK() )
2092  return st;
2093 
2094  std::vector<XAttr> *resp = 0;
2095  st = MessageUtils::WaitForResponse( &handler, resp );
2096  if( resp ) result.swap( *resp );
2097  delete resp;
2098 
2099  return st;
2100  }
2101 
2102  //------------------------------------------------------------------------
2103  // Delete extended attributes - async
2104  //------------------------------------------------------------------------
2105  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2106  const std::vector<std::string> &attrs,
2107  ResponseHandler *handler,
2108  uint16_t timeout )
2109  {
2110  if( pPlugIn )
2112 
2113  return XAttrOperationImpl( kXR_fattrDel, 0, path, attrs, handler, timeout );
2114  }
2115 
2116  //------------------------------------------------------------------------
2117  // Delete extended attributes - sync
2118  //------------------------------------------------------------------------
2119  XRootDStatus FileSystem::DelXAttr( const std::string &path,
2120  const std::vector<std::string> &attrs,
2121  std::vector<XAttrStatus> &result,
2122  uint16_t timeout )
2123  {
2124  SyncResponseHandler handler;
2125  XRootDStatus st = DelXAttr( path, attrs, &handler, timeout );
2126  if( !st.IsOK() )
2127  return st;
2128 
2129  std::vector<XAttrStatus> *resp = 0;
2130  st = MessageUtils::WaitForResponse( &handler, resp );
2131  if( resp ) result.swap( *resp );
2132  delete resp;
2133 
2134  return st;
2135  }
2136 
2137  //------------------------------------------------------------------------
2138  // List extended attributes - async
2139  //------------------------------------------------------------------------
2140  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2141  ResponseHandler *handler,
2142  uint16_t timeout )
2143  {
2144  if( pPlugIn )
2146 
2147  static const std::vector<std::string> nothing;
2148  return XAttrOperationImpl( kXR_fattrList, ClientFattrRequest::aData,
2149  path, nothing, handler, timeout );
2150  }
2151 
2152  //------------------------------------------------------------------------
2153  // List extended attributes - sync
2154  //------------------------------------------------------------------------
2155  XRootDStatus FileSystem::ListXAttr( const std::string &path,
2156  std::vector<XAttr> &result,
2157  uint16_t timeout )
2158  {
2159  SyncResponseHandler handler;
2160  XRootDStatus st = ListXAttr( path, &handler, timeout );
2161  if( !st.IsOK() )
2162  return st;
2163 
2164  std::vector<XAttr> *resp = 0;
2165  st = MessageUtils::WaitForResponse( &handler, resp );
2166  if( resp ) result.swap( *resp );
2167  delete resp;
2168 
2169  return st;
2170  }
2171 
2172  //----------------------------------------------------------------------------
2173  // Set file property
2174  //----------------------------------------------------------------------------
2175  bool FileSystem::SetProperty( const std::string &name,
2176  const std::string &value )
2177  {
2178  if( pPlugIn )
2179  return pPlugIn->SetProperty( name, value );
2180 
2181  if( name == "FollowRedirects" )
2182  {
2183  if( value == "true" ) pImpl->fsdata->pFollowRedirects = true;
2184  else pImpl->fsdata->pFollowRedirects = false;
2185  return true;
2186  }
2187  return false;
2188  }
2189 
2190  //----------------------------------------------------------------------------
2191  // Get file property
2192  //----------------------------------------------------------------------------
2193  bool FileSystem::GetProperty( const std::string &name,
2194  std::string &value ) const
2195  {
2196  if( pPlugIn )
2197  return pPlugIn->GetProperty( name, value );
2198 
2199  if( name == "FollowRedirects" )
2200  {
2201  if( pImpl->fsdata->pFollowRedirects ) value = "true";
2202  else value = "false";
2203  return true;
2204  }
2205  else if( name == "LastURL" )
2206  {
2207  if( pImpl->fsdata->pLastUrl )
2208  {
2209  value = pImpl->fsdata->pLastUrl->GetURL();
2210  return true;
2211  }
2212  else return false;
2213  }
2214 
2215  return false;
2216  }
2217 
2218  //------------------------------------------------------------------------
2219  // Generic implementation of xattr operation
2220  //------------------------------------------------------------------------
2221  template<typename T>
2222  Status FileSystem::XAttrOperationImpl( kXR_char subcode,
2223  kXR_char options,
2224  const std::string &path,
2225  const std::vector<T> &attrs,
2226  ResponseHandler *handler,
2227  uint16_t timeout )
2228  {
2229  Message *msg;
2230  ClientFattrRequest *req;
2231  MessageUtils::CreateRequest( msg, req );
2232 
2233  req->requestid = kXR_fattr;
2234  req->subcode = subcode;
2235  req->options = options;
2236  req->numattr = attrs.size();
2237  memset( req->fhandle, 0, 4 );
2238  XRootDStatus st = MessageUtils::CreateXAttrBody( msg, attrs, path );
2239  if( !st.IsOK() ) return st;
2240 
2241  MessageSendParams params; params.timeout = timeout;
2243 
2245 
2246  return FileSystemData::Send( pImpl->fsdata, msg, handler, params );
2247  }
2248 
2249  //------------------------------------------------------------------------
2250  // Lock the internal lock
2251  //------------------------------------------------------------------------
2252  void FileSystem::Lock()
2253  {
2254  pImpl->fsdata->pMutex.Lock();
2255  }
2256 
2257  //------------------------------------------------------------------------
2258  // Unlock the internal lock
2259  //------------------------------------------------------------------------
2260  void FileSystem::UnLock()
2261  {
2262  pImpl->fsdata->pMutex.UnLock();
2263  }
2264 }
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:1362
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:498
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