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 
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 
71  };
72 
73  //----------------------------------------------------------------------------
75  //----------------------------------------------------------------------------
77  {
78  public:
79 
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 
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 )
168  {
169  }
170 
171  //------------------------------------------------------------------------
173  //------------------------------------------------------------------------
174  void HandleResponse( XRootDStatus *status, AnyObject *response )
175  {
176  std::unique_ptr<XRootDStatus> delst( status );
177  std::unique_ptr<AnyObject> delrsp( response );
178  Response *res = GetResponse<Response>( status, response );
179  fun( *status, *res );
180  }
181 
182  private:
183  //------------------------------------------------------------------------
185  //------------------------------------------------------------------------
186  std::function<void( XRootDStatus&, Response& )> fun;
187  };
188 
189  //----------------------------------------------------------------------------
193  //----------------------------------------------------------------------------
194  template<>
195  class FunctionWrapper<void> : public ResponseHandler
196  {
197  public:
198 
199  //------------------------------------------------------------------------
201  //
203  //------------------------------------------------------------------------
205  std::function<void( XRootDStatus& )> handleFunction ) :
206  fun( handleFunction )
207  {
208  }
209 
210  //------------------------------------------------------------------------
212  //------------------------------------------------------------------------
213  void HandleResponse( XRootDStatus *status, AnyObject *response )
214  {
215  std::unique_ptr<XRootDStatus> delst( status );
216  std::unique_ptr<AnyObject> delrsp( response );
217  fun( *status );
218  }
219 
220  private:
221  //------------------------------------------------------------------------
223  //------------------------------------------------------------------------
224  std::function<void( XRootDStatus& )> fun;
225  };
226 
227  //----------------------------------------------------------------------------
232  //----------------------------------------------------------------------------
233  template<typename Response, typename Return>
235  {
236  public:
237 
238  //------------------------------------------------------------------------
240  //
242  //------------------------------------------------------------------------
243  TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) :
244  task( std::move( task ) )
245  {
246  }
247 
248  //------------------------------------------------------------------------
250  //------------------------------------------------------------------------
251  void HandleResponse( XRootDStatus *status, AnyObject *response )
252  {
253  std::unique_ptr<XRootDStatus> delst( status );
254  std::unique_ptr<AnyObject> delrsp( response );
255  Response *resp = GetResponse<Response>( status, response );
256  task( *status, *resp );
257  }
258 
259  private:
260 
261  //------------------------------------------------------------------------
263  //------------------------------------------------------------------------
264  std::packaged_task<Return( XRootDStatus&, Response& )> task;
265  };
266 
267  //----------------------------------------------------------------------------
273  //----------------------------------------------------------------------------
274  template<typename Return>
275  class TaskWrapper<void, Return>: public ResponseHandler
276  {
277  public:
278 
279  //------------------------------------------------------------------------
281  //
283  //------------------------------------------------------------------------
284  TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) :
285  task( std::move( task ) )
286  {
287  }
288 
289  //------------------------------------------------------------------------
291  //------------------------------------------------------------------------
292  void HandleResponse( XRootDStatus *status, AnyObject *response )
293  {
294  std::unique_ptr<XRootDStatus> delst( status );
295  std::unique_ptr<AnyObject> delrsp( response );
296  task( *status );
297  }
298 
299  private:
300 
301  //------------------------------------------------------------------------
303  //------------------------------------------------------------------------
304  std::packaged_task<Return( XRootDStatus& )> task;
305  };
306 
307 
308  //----------------------------------------------------------------------------
310  //----------------------------------------------------------------------------
312  {
313  public:
314 
315  //------------------------------------------------------------------------
317  //
319  //------------------------------------------------------------------------
321  std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) :
322  f( f ), fun( handleFunction )
323  {
324  }
325 
326  //------------------------------------------------------------------------
328  //------------------------------------------------------------------------
329  void HandleResponse( XRootDStatus *status, AnyObject *response )
330  {
331  delete response;
332  std::unique_ptr<XRootDStatus> delst( status );
333  std::unique_ptr<StatInfo> delrsp;
334  StatInfo *info = nullptr;
335  if( status->IsOK() )
336  {
337  XRootDStatus st = f->Stat( false, info );
338  delrsp.reset( info );
339  }
340  else
341  info = &NullRef<StatInfo>::value;
342  fun( *status, *info );
343  }
344 
345  private:
347  //------------------------------------------------------------------------
349  //------------------------------------------------------------------------
350  std::function<void( XRootDStatus&, StatInfo& )> fun;
351  };
352 
353  //----------------------------------------------------------------------------
355  //----------------------------------------------------------------------------
356  class PipelineException : public std::exception
357  {
358  public:
359 
360  //------------------------------------------------------------------------
362  //------------------------------------------------------------------------
364  {
365 
366  }
367 
368  //------------------------------------------------------------------------
370  //------------------------------------------------------------------------
372  {
373 
374  }
375 
376  //------------------------------------------------------------------------
378  //------------------------------------------------------------------------
380  {
381  error = ex.error;
382  return *this;
383  }
384 
385  //------------------------------------------------------------------------
387  //------------------------------------------------------------------------
388  const char* what() const noexcept
389  {
390  return error.ToString().c_str();
391  }
392 
393  //------------------------------------------------------------------------
395  //------------------------------------------------------------------------
396  const XRootDStatus& GetError() const
397  {
398  return error;
399  }
400 
401  private:
402 
403  //------------------------------------------------------------------------
405  //------------------------------------------------------------------------
407  };
408 
409  //----------------------------------------------------------------------------
413  //----------------------------------------------------------------------------
414  template<typename Response>
416  {
417  public:
418 
419  //------------------------------------------------------------------------
424  //------------------------------------------------------------------------
425  FutureWrapperBase( std::future<Response> &ftr ) : fulfilled( false )
426  {
427  ftr = prms.get_future();
428  }
429 
430  //------------------------------------------------------------------------
432  //------------------------------------------------------------------------
434  {
436  }
437 
438  protected:
439 
440  //------------------------------------------------------------------------
444  //------------------------------------------------------------------------
445  inline void SetException( const XRootDStatus &err )
446  {
447  std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) );
448  prms.set_exception( ex );
449  fulfilled = true;
450  }
451 
452  //------------------------------------------------------------------------
454  //------------------------------------------------------------------------
455  std::promise<Response> prms;
456  bool fulfilled;
457  };
458 
459  //----------------------------------------------------------------------------
463  //----------------------------------------------------------------------------
464  template<typename Response>
465  class FutureWrapper : public FutureWrapperBase<Response>
466  {
467  public:
468 
469  //------------------------------------------------------------------------
473  //------------------------------------------------------------------------
474  FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr )
475  {
476  }
477 
478  //------------------------------------------------------------------------
480  //------------------------------------------------------------------------
481  void HandleResponse( XRootDStatus *status, AnyObject *response )
482  {
483  std::unique_ptr<XRootDStatus> delst( status );
484  std::unique_ptr<AnyObject> delrsp( response );
485  if( status->IsOK() )
486  {
487  Response *resp = GetResponse<Response>( response );
488  if( resp == &NullRef<Response>::value )
490  else
491  {
492  this->prms.set_value( std::move( *resp ) );
493  this->fulfilled = true;
494  }
495  }
496  else
497  this->SetException( *status );
498  }
499  };
500 
501  //----------------------------------------------------------------------------
503  //----------------------------------------------------------------------------
504  template<>
505  class FutureWrapper<void> : public FutureWrapperBase<void>
506  {
507  public:
508 
509  //------------------------------------------------------------------------
513  //------------------------------------------------------------------------
514  FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr )
515  {
516  }
517 
518  //------------------------------------------------------------------------
520  //------------------------------------------------------------------------
521  void HandleResponse( XRootDStatus *status, AnyObject *response )
522  {
523  std::unique_ptr<XRootDStatus> delst( status );
524  std::unique_ptr<AnyObject> delrsp( response );
525  if( status->IsOK() )
526  {
527  prms.set_value();
528  fulfilled = true;
529  }
530  else
531  SetException( *status );
532  }
533  };
534 
535 
536  //----------------------------------------------------------------------------
538  //----------------------------------------------------------------------------
540  {
541  public:
542 
543  //------------------------------------------------------------------------
547  //------------------------------------------------------------------------
549  {
550  }
551 
552  //------------------------------------------------------------------------
557  //------------------------------------------------------------------------
558  virtual void HandleResponseWithHosts( XRootDStatus *status,
559  AnyObject *response,
560  HostList *hostList )
561  {
562  handler->HandleResponseWithHosts( status, response, hostList );
563  }
564 
565  private:
566  //------------------------------------------------------------------------
568  //------------------------------------------------------------------------
570  };
571 
572 
573  //----------------------------------------------------------------------------
578  //----------------------------------------------------------------------------
579  template<typename Response>
580  struct RespBase
581  {
582  //------------------------------------------------------------------------
587  //------------------------------------------------------------------------
588  inline static ResponseHandler* Create( ResponseHandler *hdlr )
589  {
590  return new RawWrapper( hdlr );
591  }
592 
593  //------------------------------------------------------------------------
598  //------------------------------------------------------------------------
599  inline static ResponseHandler* Create( ResponseHandler &hdlr )
600  {
601  return new RawWrapper( &hdlr );
602  }
603 
604  //------------------------------------------------------------------------
609  //------------------------------------------------------------------------
610  inline static ResponseHandler* Create( std::future<Response> &ftr )
611  {
612  return new FutureWrapper<Response>( ftr );
613  }
614  };
615 
616  //----------------------------------------------------------------------------
621  //----------------------------------------------------------------------------
622  template<typename Response>
623  struct Resp: RespBase<Response>
624  {
625  //------------------------------------------------------------------------
630  //------------------------------------------------------------------------
631  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
632  Response& )> func )
633  {
634  return new FunctionWrapper<Response>( func );
635  }
636 
637  //------------------------------------------------------------------------
642  //------------------------------------------------------------------------
643  template<typename Return>
644  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&,
645  Response& )> &task )
646  {
647  return new TaskWrapper<Response, Return>( std::move( task ) );
648  }
649 
650  //------------------------------------------------------------------------
652  //------------------------------------------------------------------------
654  };
655 
656  //----------------------------------------------------------------------------
660  //----------------------------------------------------------------------------
661  template<>
662  struct Resp<void>: RespBase<void>
663  {
664  //------------------------------------------------------------------------
669  //------------------------------------------------------------------------
670  inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func )
671  {
672  return new FunctionWrapper<void>( func );
673  }
674 
675  //------------------------------------------------------------------------
680  //------------------------------------------------------------------------
681  template<typename Return>
682  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task )
683  {
684  return new TaskWrapper<void, Return>( std::move( task ) );
685  }
686 
687  //------------------------------------------------------------------------
689  //------------------------------------------------------------------------
691  };
692 }
693 
694 #endif // __XRD_CL_OPERATIONS_HANDLERS_HH__
ExOpenFuncWrapper(const Ctx< File > &f, std::function< void(XRootDStatus &, StatInfo &)> handleFunction)
Constructor.
Definition: XrdClOperationHandlers.hh:320
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:292
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:213
TaskWrapper(std::packaged_task< Return(XRootDStatus &, Response &)> &&task)
Constructor.
Definition: XrdClOperationHandlers.hh:243
Definition: XrdClAnyObject.hh:32
static ResponseHandler * Create(ResponseHandler &hdlr)
Definition: XrdClOperationHandlers.hh:599
Utility class for storing a pointer to operation context.
Definition: XrdClCtx.hh:37
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Definition: XrdClOperationHandlers.hh:558
const char * what() const noexcept
inherited from std::exception
Definition: XrdClOperationHandlers.hh:388
void Get(Type &object)
Retrieve the object being held.
Definition: XrdClAnyObject.hh:78
std::string ToString() const
Create a string representation.
Object stat info.
Definition: XrdClXRootDResponses.hh:399
Definition: XrdClOperationHandlers.hh:415
static ResponseHandler * Create(std::future< Response > &ftr)
Definition: XrdClOperationHandlers.hh:610
std::promise< Response > prms
promise that corresponds to the future
Definition: XrdClOperationHandlers.hh:455
Definition: XrdClOperationHandlers.hh:111
std::function< void(XRootDStatus &, StatInfo &)> fun
user defined function, functor or lambda
Definition: XrdClOperationHandlers.hh:350
static ResponseHandler * Create(std::packaged_task< Return(XRootDStatus &, Response &)> &task)
Definition: XrdClOperationHandlers.hh:644
bool IsOK() const
We&#39;re fine.
Definition: XrdClStatus.hh:122
static Response value
Definition: XrdClOperationHandlers.hh:113
Definition: XrdClOperationHandlers.hh:195
RawWrapper(ResponseHandler *handler)
Definition: XrdClOperationHandlers.hh:548
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:52
PipelineException(const PipelineException &ex)
Copy constructor.
Definition: XrdClOperationHandlers.hh:371
uint16_t status
Status of the execution.
Definition: XrdClStatus.hh:139
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:251
Definition: XrdClOperationHandlers.hh:234
FunctionWrapper(std::function< void(XRootDStatus &)> handleFunction)
Constructor.
Definition: XrdClOperationHandlers.hh:204
Definition: XrdClOperationHandlers.hh:623
std::function< void(XRootDStatus &, Response &)> fun
user defined function, functor or lambda
Definition: XrdClOperationHandlers.hh:186
Definition: XrdClOperationHandlers.hh:275
TaskWrapper(std::packaged_task< Return(XRootDStatus &)> &&task)
Constructor.
Definition: XrdClOperationHandlers.hh:284
FutureWrapper(std::future< Response > &ftr)
Definition: XrdClOperationHandlers.hh:474
void SetException(const XRootDStatus &err)
Definition: XrdClOperationHandlers.hh:445
Pipeline exception, wrapps an XRootDStatus.
Definition: XrdClOperationHandlers.hh:356
std::vector< HostInfo > HostList
Definition: XrdClXRootDResponses.hh:1035
Helper class for unpacking single XAttr from bulk response.
Definition: XrdClOperationHandlers.hh:76
Definition: XrdClOperationHandlers.hh:465
void Set(Type object, bool own=true)
Definition: XrdClAnyObject.hh:59
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
PipelineException & operator=(const PipelineException &ex)
Assigment operator.
Definition: XrdClOperationHandlers.hh:379
Request status.
Definition: XrdClXRootDResponses.hh:218
Definition: XrdClAnyObject.hh:25
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:174
static ResponseHandler * Create(std::function< void(XRootDStatus &, Response &)> func)
Definition: XrdClOperationHandlers.hh:631
std::packaged_task< Return(XRootDStatus &, Response &)> task
user defined task
Definition: XrdClOperationHandlers.hh:264
const uint16_t errPipelineFailed
Pipeline failed and operation couldn&#39;t be executed.
Definition: XrdClStatus.hh:66
std::packaged_task< Return(XRootDStatus &)> task
user defined task
Definition: XrdClOperationHandlers.hh:304
const XRootDStatus & GetError() const
Definition: XrdClOperationHandlers.hh:396
Definition: XrdClOperationHandlers.hh:580
Lambda wrapper.
Definition: XrdClOperationHandlers.hh:311
static ResponseHandler * Create(std::packaged_task< Return(XRootDStatus &)> &task)
Definition: XrdClOperationHandlers.hh:682
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:87
UnpackXAttrStatus(ResponseHandler *handler)
Definition: XrdClOperationHandlers.hh:45
Handle an async response.
Definition: XrdClXRootDResponses.hh:1040
Helper class for unpacking single XAttrStatus from bulk response.
Definition: XrdClOperationHandlers.hh:41
ResponseHandler * handler
The actual operation handler (we don&#39;t own the pointer)
Definition: XrdClOperationHandlers.hh:569
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
Definition: XrdClXRootDResponses.hh:1070
Wrapper class for raw response handler (ResponseHandler).
Definition: XrdClOperationHandlers.hh:539
ResponseHandler * handler
Definition: XrdClOperationHandlers.hh:102
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
Definition: XrdClXRootDResponses.hh:1054
Response * GetResponse(AnyObject *rsp)
Definition: XrdClOperationHandlers.hh:129
static ResponseHandler * Create(ResponseHandler *hdlr)
Definition: XrdClOperationHandlers.hh:588
const uint16_t errInternal
Internal error.
Definition: XrdClStatus.hh:56
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:521
XRootDStatus error
the XRootDStatus associated with this exception
Definition: XrdClOperationHandlers.hh:406
ResponseHandler * handler
Definition: XrdClOperationHandlers.hh:70
std::function< void(XRootDStatus &)> fun
user defined function, functor or lambda
Definition: XrdClOperationHandlers.hh:224
FunctionWrapper(std::function< void(XRootDStatus &, Response &)> handleFunction)
Constructor.
Definition: XrdClOperationHandlers.hh:165
FutureWrapperBase(std::future< Response > &ftr)
Definition: XrdClOperationHandlers.hh:425
Definition: XrdClOperationHandlers.hh:156
PipelineException(const XRootDStatus &error)
Constructor from XRootDStatus.
Definition: XrdClOperationHandlers.hh:363
Ctx< File > f
Definition: XrdClOperationHandlers.hh:346
UnpackXAttr(ResponseHandler *handler)
Definition: XrdClOperationHandlers.hh:80
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:329
FutureWrapper(std::future< void > &ftr)
Definition: XrdClOperationHandlers.hh:514
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
Definition: XrdClOperationHandlers.hh:481
bool fulfilled
Definition: XrdClOperationHandlers.hh:456
virtual ~FutureWrapperBase()
Destructor.
Definition: XrdClOperationHandlers.hh:433
static ResponseHandler * Create(std::function< void(XRootDStatus &)> func)
Definition: XrdClOperationHandlers.hh:670