XRootD
XrdClOperationHandlers.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN)
3 // Author: Krzysztof Jamrog <krzysztof.piotr.jamrog@cern.ch>,
4 // Michal Simon <michal.simon@cern.ch>
5 //------------------------------------------------------------------------------
6 // This file is part of the XRootD software suite.
7 //
8 // XRootD is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Lesser General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // XRootD is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public License
19 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
20 //
21 // In applying this licence, CERN does not waive the privileges and immunities
22 // granted to it by virtue of its status as an Intergovernmental Organization
23 // or submit itself to any jurisdiction.
24 //------------------------------------------------------------------------------
25 
26 #ifndef __XRD_CL_OPERATION_HANDLERS_HH__
27 #define __XRD_CL_OPERATION_HANDLERS_HH__
28 
29 #include "XrdCl/XrdClFile.hh"
30 #include "XrdCl/XrdClCtx.hh"
31 
32 #include<functional>
33 #include<future>
34 #include <memory>
35 
36 namespace XrdCl
37 {
38  //----------------------------------------------------------------------------
40  //----------------------------------------------------------------------------
42  {
43  public:
44 
45  UnpackXAttrStatus( ResponseHandler *handler ) : handler( handler )
46  {
47  }
48 
49  //------------------------------------------------------------------------
51  //------------------------------------------------------------------------
52  void HandleResponse( XRootDStatus *status, AnyObject *response )
53  {
54  // status maybe error for old servers not supporting xattrs
55  if( !status->IsOK() )
56  {
57  handler->HandleResponse( status, nullptr );
58  return;
59  }
60 
61  std::vector<XAttrStatus> *bulk = nullptr;
62  response->Get( bulk );
63  *status = bulk->front().status;
64  handler->HandleResponse( status, nullptr );
65  delete response;
66  }
67 
68  private:
69 
70  ResponseHandler *handler;
71  };
72 
73  //----------------------------------------------------------------------------
75  //----------------------------------------------------------------------------
77  {
78  public:
79 
80  UnpackXAttr( ResponseHandler *handler ) : handler( handler )
81  {
82  }
83 
84  //------------------------------------------------------------------------
86  //------------------------------------------------------------------------
87  void HandleResponse( XRootDStatus *status, AnyObject *response )
88  {
89  // status is always OK for bulk response
90 
91  std::vector<XAttr> *bulk = nullptr;
92  response->Get( bulk );
93  *status = bulk->front().status;
94  std::string *rsp = new std::string( std::move( bulk->front().value ) );
95  delete bulk;
96  response->Set( rsp );
97  handler->HandleResponse( status, response );
98  }
99 
100  private:
101 
102  ResponseHandler *handler;
103  };
104 
105  //----------------------------------------------------------------------------
106  // Helper class for creating null references for particular types
107  //
108  // @arg Response : type for which we need a null reference
109  //----------------------------------------------------------------------------
110  template<typename Response>
111  struct NullRef
112  {
113  static Response value;
114  };
115 
116  //----------------------------------------------------------------------------
117  // Initialize the 'null-reference'
118  //----------------------------------------------------------------------------
119  template<typename Response>
120  Response NullRef<Response>::value;
121 
122  //----------------------------------------------------------------------------
127  //----------------------------------------------------------------------------
128  template<typename Response>
129  inline Response* GetResponse( AnyObject *rsp )
130  {
131  Response *ret = nullptr;
132  rsp->Get( ret );
133  return ret;
134  }
135 
136  //----------------------------------------------------------------------------
142  //----------------------------------------------------------------------------
143  template<typename Response>
144  inline Response* GetResponse( XRootDStatus *status, AnyObject *rsp )
145  {
146  if( !status->IsOK() ) return &NullRef<Response>::value;
147  return GetResponse<Response>( rsp );
148  }
149 
150  //----------------------------------------------------------------------------
154  //----------------------------------------------------------------------------
155  template<typename Response>
157  {
158  public:
159 
160  //------------------------------------------------------------------------
162  //
164  //------------------------------------------------------------------------
166  std::function<void( XRootDStatus&, Response& )> handleFunction ) :
167  fun( [handleFunction]( XRootDStatus &s, Response &r, HostList& ){ handleFunction( s, r ); } )
168  {
169  }
170 
171  //------------------------------------------------------------------------
173  //
175  //------------------------------------------------------------------------
177  std::function<void( XRootDStatus&, Response&, HostList& )> handleFunction ) :
178  fun( handleFunction )
179  {
180  }
181 
182  //------------------------------------------------------------------------
184  //------------------------------------------------------------------------
185  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
186  {
187  std::unique_ptr<XRootDStatus> delst( status );
188  std::unique_ptr<AnyObject> delrsp( response );
189  std::unique_ptr<HostList> delhl( hostList );
190  Response *res = GetResponse<Response>( status, response );
191  fun( *status, *res, *hostList );
192  }
193 
194  private:
195  //------------------------------------------------------------------------
197  //------------------------------------------------------------------------
198  std::function<void( XRootDStatus&, Response&, HostList& )> fun;
199  };
200 
201  //----------------------------------------------------------------------------
205  //----------------------------------------------------------------------------
206  template<>
207  class FunctionWrapper<void> : public ResponseHandler
208  {
209  public:
210 
211  //------------------------------------------------------------------------
213  //
215  //------------------------------------------------------------------------
217  std::function<void( XRootDStatus& )> handleFunction ) :
218  fun( [handleFunction]( XRootDStatus& s, HostList& ){ handleFunction( s ); } )
219  {
220  }
221 
222  //------------------------------------------------------------------------
224  //
226  //------------------------------------------------------------------------
228  std::function<void( XRootDStatus&, HostList& )> handleFunction ) :
229  fun( handleFunction )
230  {
231  }
232 
233  //------------------------------------------------------------------------
235  //------------------------------------------------------------------------
236  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
237  {
238  std::unique_ptr<XRootDStatus> delst( status );
239  std::unique_ptr<AnyObject> delrsp( response );
240  std::unique_ptr<HostList> delhl( hostList );
241  fun( *status, *hostList );
242  }
243 
244  private:
245  //------------------------------------------------------------------------
247  //------------------------------------------------------------------------
248  std::function<void( XRootDStatus&, HostList& )> fun;
249  };
250 
251  //----------------------------------------------------------------------------
256  //----------------------------------------------------------------------------
257  template<typename Response, typename Return>
259  {
260  public:
261 
262  //------------------------------------------------------------------------
264  //
266  //------------------------------------------------------------------------
267  TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) :
268  task( std::move( task ) )
269  {
270  }
271 
272  //------------------------------------------------------------------------
274  //------------------------------------------------------------------------
275  void HandleResponse( XRootDStatus *status, AnyObject *response )
276  {
277  std::unique_ptr<XRootDStatus> delst( status );
278  std::unique_ptr<AnyObject> delrsp( response );
279  Response *resp = GetResponse<Response>( status, response );
280  task( *status, *resp );
281  }
282 
283  private:
284 
285  //------------------------------------------------------------------------
287  //------------------------------------------------------------------------
288  std::packaged_task<Return( XRootDStatus&, Response& )> task;
289  };
290 
291  //----------------------------------------------------------------------------
297  //----------------------------------------------------------------------------
298  template<typename Return>
299  class TaskWrapper<void, Return>: public ResponseHandler
300  {
301  public:
302 
303  //------------------------------------------------------------------------
305  //
307  //------------------------------------------------------------------------
308  TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) :
309  task( std::move( task ) )
310  {
311  }
312 
313  //------------------------------------------------------------------------
315  //------------------------------------------------------------------------
316  void HandleResponse( XRootDStatus *status, AnyObject *response )
317  {
318  std::unique_ptr<XRootDStatus> delst( status );
319  std::unique_ptr<AnyObject> delrsp( response );
320  task( *status );
321  }
322 
323  private:
324 
325  //------------------------------------------------------------------------
327  //------------------------------------------------------------------------
328  std::packaged_task<Return( XRootDStatus& )> task;
329  };
330 
331 
332  //----------------------------------------------------------------------------
334  //----------------------------------------------------------------------------
336  {
337  public:
338 
339  //------------------------------------------------------------------------
341  //
343  //------------------------------------------------------------------------
345  std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) :
346  f( f ), fun( [handleFunction]( XRootDStatus &s, StatInfo &i, HostList& ){ handleFunction( s, i ); } )
347  {
348  }
349 
350  //------------------------------------------------------------------------
352  //
354  //------------------------------------------------------------------------
356  std::function<void( XRootDStatus&, StatInfo&, HostList& )> handleFunction ) :
357  f( f ), fun( handleFunction )
358  {
359  }
360 
361  //------------------------------------------------------------------------
363  //------------------------------------------------------------------------
364  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
365  {
366  delete response;
367  std::unique_ptr<XRootDStatus> delst( status );
368  std::unique_ptr<StatInfo> delrsp;
369  std::unique_ptr<HostList> delhl;
370  StatInfo *info = nullptr;
371  if( status->IsOK() )
372  {
373  XRootDStatus st = f->Stat( false, info );
374  delrsp.reset( info );
375  }
376  else
377  info = &NullRef<StatInfo>::value;
378  fun( *status, *info, *hostList );
379  }
380 
381  private:
382  Ctx<File> f;
383  //------------------------------------------------------------------------
385  //------------------------------------------------------------------------
386  std::function<void( XRootDStatus&, StatInfo&, HostList& )> fun;
387  };
388 
389  //----------------------------------------------------------------------------
391  //----------------------------------------------------------------------------
392  class PipelineException : public std::exception
393  {
394  public:
395 
396  //------------------------------------------------------------------------
398  //------------------------------------------------------------------------
399  PipelineException( const XRootDStatus &error ) : error( error ), strerr( error.ToString() )
400  {
401 
402  }
403 
404  //------------------------------------------------------------------------
406  //------------------------------------------------------------------------
407  PipelineException( const PipelineException &ex ) : error( ex.error ), strerr( ex.error.ToString() )
408  {
409 
410  }
411 
412  //------------------------------------------------------------------------
414  //------------------------------------------------------------------------
416  {
417  error = ex.error;
418  strerr = ex.strerr;
419  return *this;
420  }
421 
422  //------------------------------------------------------------------------
424  //------------------------------------------------------------------------
425  const char* what() const noexcept
426  {
427  return strerr.c_str();
428  }
429 
430  //------------------------------------------------------------------------
432  //------------------------------------------------------------------------
433  const XRootDStatus& GetError() const
434  {
435  return error;
436  }
437 
438  private:
439 
440  //------------------------------------------------------------------------
442  //------------------------------------------------------------------------
443  XRootDStatus error;
444  std::string strerr;
445  };
446 
447  //----------------------------------------------------------------------------
451  //----------------------------------------------------------------------------
452  template<typename Response>
454  {
455  public:
456 
457  //------------------------------------------------------------------------
462  //------------------------------------------------------------------------
463  FutureWrapperBase( std::future<Response> &ftr ) : fulfilled( false )
464  {
465  ftr = prms.get_future();
466  }
467 
468  //------------------------------------------------------------------------
470  //------------------------------------------------------------------------
472  {
474  }
475 
476  protected:
477 
478  //------------------------------------------------------------------------
482  //------------------------------------------------------------------------
483  inline void SetException( const XRootDStatus &err )
484  {
485  std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) );
486  prms.set_exception( ex );
487  fulfilled = true;
488  }
489 
490  //------------------------------------------------------------------------
492  //------------------------------------------------------------------------
493  std::promise<Response> prms;
494  bool fulfilled;
495  };
496 
497  //----------------------------------------------------------------------------
501  //----------------------------------------------------------------------------
502  template<typename Response>
503  class FutureWrapper : public FutureWrapperBase<Response>
504  {
505  public:
506 
507  //------------------------------------------------------------------------
511  //------------------------------------------------------------------------
512  FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr )
513  {
514  }
515 
516  //------------------------------------------------------------------------
518  //------------------------------------------------------------------------
519  void HandleResponse( XRootDStatus *status, AnyObject *response )
520  {
521  std::unique_ptr<XRootDStatus> delst( status );
522  std::unique_ptr<AnyObject> delrsp( response );
523  if( status->IsOK() )
524  {
525  Response *resp = GetResponse<Response>( response );
526  if( resp == &NullRef<Response>::value )
528  else
529  {
530  this->prms.set_value( std::move( *resp ) );
531  this->fulfilled = true;
532  }
533  }
534  else
535  this->SetException( *status );
536  }
537  };
538 
539  //----------------------------------------------------------------------------
541  //----------------------------------------------------------------------------
542  template<>
543  class FutureWrapper<void> : public FutureWrapperBase<void>
544  {
545  public:
546 
547  //------------------------------------------------------------------------
551  //------------------------------------------------------------------------
552  FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr )
553  {
554  }
555 
556  //------------------------------------------------------------------------
558  //------------------------------------------------------------------------
559  void HandleResponse( XRootDStatus *status, AnyObject *response )
560  {
561  std::unique_ptr<XRootDStatus> delst( status );
562  std::unique_ptr<AnyObject> delrsp( response );
563  if( status->IsOK() )
564  {
565  prms.set_value();
566  fulfilled = true;
567  }
568  else
569  SetException( *status );
570  }
571  };
572 
573 
574  //----------------------------------------------------------------------------
576  //----------------------------------------------------------------------------
578  {
579  public:
580 
581  //------------------------------------------------------------------------
585  //------------------------------------------------------------------------
586  RawWrapper( ResponseHandler *handler ) : handler( handler )
587  {
588  }
589 
590  //------------------------------------------------------------------------
595  //------------------------------------------------------------------------
596  virtual void HandleResponseWithHosts( XRootDStatus *status,
597  AnyObject *response,
598  HostList *hostList )
599  {
600  handler->HandleResponseWithHosts( status, response, hostList );
601  }
602 
603  private:
604  //------------------------------------------------------------------------
606  //------------------------------------------------------------------------
607  ResponseHandler *handler;
608  };
609 
610 
611  //----------------------------------------------------------------------------
616  //----------------------------------------------------------------------------
617  template<typename Response>
618  struct RespBase
619  {
620  //------------------------------------------------------------------------
625  //------------------------------------------------------------------------
626  inline static ResponseHandler* Create( ResponseHandler *hdlr )
627  {
628  return new RawWrapper( hdlr );
629  }
630 
631  //------------------------------------------------------------------------
636  //------------------------------------------------------------------------
637  inline static ResponseHandler* Create( ResponseHandler &hdlr )
638  {
639  return new RawWrapper( &hdlr );
640  }
641 
642  //------------------------------------------------------------------------
647  //------------------------------------------------------------------------
648  inline static ResponseHandler* Create( std::future<Response> &ftr )
649  {
650  return new FutureWrapper<Response>( ftr );
651  }
652  };
653 
654  //----------------------------------------------------------------------------
659  //----------------------------------------------------------------------------
660  template<typename Response>
661  struct Resp: RespBase<Response>
662  {
663  //------------------------------------------------------------------------
668  //------------------------------------------------------------------------
669  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
670  Response& )> func )
671  {
672  return new FunctionWrapper<Response>( func );
673  }
674 
675  //------------------------------------------------------------------------
680  //------------------------------------------------------------------------
681  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
682  Response&, HostList& )> func )
683  {
684  return new FunctionWrapper<Response>( func );
685  }
686 
687  //------------------------------------------------------------------------
692  //------------------------------------------------------------------------
693  template<typename Return>
694  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&,
695  Response& )> &task )
696  {
697  return new TaskWrapper<Response, Return>( std::move( task ) );
698  }
699 
700  //------------------------------------------------------------------------
702  //------------------------------------------------------------------------
704  };
705 
706  //----------------------------------------------------------------------------
710  //----------------------------------------------------------------------------
711  template<>
712  struct Resp<void>: RespBase<void>
713  {
714  //------------------------------------------------------------------------
719  //------------------------------------------------------------------------
720  inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func )
721  {
722  return new FunctionWrapper<void>( func );
723  }
724 
725  //------------------------------------------------------------------------
730  //------------------------------------------------------------------------
731  inline static ResponseHandler* Create( std::function<void( XRootDStatus&, HostList& )> func )
732  {
733  return new FunctionWrapper<void>( func );
734  }
735 
736  //------------------------------------------------------------------------
741  //------------------------------------------------------------------------
742  template<typename Return>
743  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task )
744  {
745  return new TaskWrapper<void, Return>( std::move( task ) );
746  }
747 
748  //------------------------------------------------------------------------
750  //------------------------------------------------------------------------
752  };
753 }
754 
755 #endif // __XRD_CL_OPERATIONS_HANDLERS_HH__
void Set(Type object, bool own=true)
void Get(Type &object)
Retrieve the object being held.
void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Callback method.
ExOpenFuncWrapper(const Ctx< File > &f, std::function< void(XRootDStatus &, StatInfo &, HostList &)> handleFunction)
Constructor.
ExOpenFuncWrapper(const Ctx< File > &f, std::function< void(XRootDStatus &, StatInfo &)> handleFunction)
Constructor.
FunctionWrapper(std::function< void(XRootDStatus &, HostList &)> handleFunction)
Constructor.
void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Callback method.
FunctionWrapper(std::function< void(XRootDStatus &)> handleFunction)
Constructor.
FunctionWrapper(std::function< void(XRootDStatus &, Response &, HostList &)> handleFunction)
Constructor.
FunctionWrapper(std::function< void(XRootDStatus &, Response &)> handleFunction)
Constructor.
void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Callback method.
void SetException(const XRootDStatus &err)
std::promise< Response > prms
promise that corresponds to the future
virtual ~FutureWrapperBase()
Destructor.
FutureWrapperBase(std::future< Response > &ftr)
FutureWrapper(std::future< void > &ftr)
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
FutureWrapper(std::future< Response > &ftr)
Pipeline exception, wrapps an XRootDStatus.
PipelineException & operator=(const PipelineException &ex)
Assigment operator.
PipelineException(const XRootDStatus &error)
Constructor from XRootDStatus.
PipelineException(const PipelineException &ex)
Copy constructor.
const char * what() const noexcept
inherited from std::exception
const XRootDStatus & GetError() const
Wrapper class for raw response handler (ResponseHandler).
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
RawWrapper(ResponseHandler *handler)
Handle an async response.
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
Object stat info.
TaskWrapper(std::packaged_task< Return(XRootDStatus &)> &&task)
Constructor.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
TaskWrapper(std::packaged_task< Return(XRootDStatus &, Response &)> &&task)
Constructor.
Helper class for unpacking single XAttrStatus from bulk response.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
UnpackXAttrStatus(ResponseHandler *handler)
Helper class for unpacking single XAttr from bulk response.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
UnpackXAttr(ResponseHandler *handler)
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
std::vector< HostInfo > HostList
const uint16_t errInternal
Internal error.
Definition: XrdClStatus.hh:56
const uint16_t errPipelineFailed
Pipeline failed and operation couldn't be executed.
Definition: XrdClStatus.hh:66
Response * GetResponse(AnyObject *rsp)
Utility class for storing a pointer to operation context.
Definition: XrdClCtx.hh:39
static ResponseHandler * Create(std::future< Response > &ftr)
static ResponseHandler * Create(ResponseHandler *hdlr)
static ResponseHandler * Create(ResponseHandler &hdlr)
static ResponseHandler * Create(std::function< void(XRootDStatus &, HostList &)> func)
static ResponseHandler * Create(std::packaged_task< Return(XRootDStatus &)> &task)
static ResponseHandler * Create(std::function< void(XRootDStatus &)> func)
static ResponseHandler * Create(std::packaged_task< Return(XRootDStatus &, Response &)> &task)
static ResponseHandler * Create(std::function< void(XRootDStatus &, Response &)> func)
static ResponseHandler * Create(std::function< void(XRootDStatus &, Response &, HostList &)> func)
uint16_t status
Status of the execution.
Definition: XrdClStatus.hh:146
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124