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  if (status && bulk && !bulk->empty()) {
64  *status = bulk->front().status;
65  }
66  handler->HandleResponse( status, nullptr );
67  delete response;
68  }
69 
70  private:
71 
72  ResponseHandler *handler;
73  };
74 
75  //----------------------------------------------------------------------------
77  //----------------------------------------------------------------------------
79  {
80  public:
81 
82  UnpackXAttr( ResponseHandler *handler ) : handler( handler )
83  {
84  }
85 
86  //------------------------------------------------------------------------
88  //------------------------------------------------------------------------
89  void HandleResponse( XRootDStatus *status, AnyObject *response )
90  {
91  // status is always OK for bulk response
92 
93  std::vector<XAttr> *bulk = nullptr;
94  response->Get( bulk );
95 
96  if (bulk && !bulk->empty()) {
97  if (status)
98  *status = bulk->front().status;
99 
100  std::string *rsp = new std::string(std::move(bulk->front().value));
101  response->Set( rsp );
102  }
103 
104  delete bulk;
105  handler->HandleResponse( status, response );
106  }
107 
108  private:
109 
110  ResponseHandler *handler;
111  };
112 
113  //----------------------------------------------------------------------------
114  // Helper class for creating null references for particular types
115  //
116  // @arg Response : type for which we need a null reference
117  //----------------------------------------------------------------------------
118  template<typename Response>
119  struct NullRef
120  {
121  static Response value;
122  };
123 
124  //----------------------------------------------------------------------------
125  // Initialize the 'null-reference'
126  //----------------------------------------------------------------------------
127  template<typename Response>
128  Response NullRef<Response>::value;
129 
130  //----------------------------------------------------------------------------
135  //----------------------------------------------------------------------------
136  template<typename Response>
137  inline Response* GetResponse( AnyObject *rsp )
138  {
139  Response *ret = nullptr;
140  rsp->Get( ret );
141  return ret;
142  }
143 
144  //----------------------------------------------------------------------------
150  //----------------------------------------------------------------------------
151  template<typename Response>
152  inline Response* GetResponse( XRootDStatus *status, AnyObject *rsp )
153  {
154  if( !status->IsOK() ) return &NullRef<Response>::value;
155  return GetResponse<Response>( rsp );
156  }
157 
158  //----------------------------------------------------------------------------
162  //----------------------------------------------------------------------------
163  template<typename Response>
165  {
166  public:
167 
168  //------------------------------------------------------------------------
170  //
172  //------------------------------------------------------------------------
174  std::function<void( XRootDStatus&, Response& )> handleFunction ) :
175  fun( [handleFunction]( XRootDStatus &s, Response &r, HostList& ){ handleFunction( s, r ); } )
176  {
177  }
178 
179  //------------------------------------------------------------------------
181  //
183  //------------------------------------------------------------------------
185  std::function<void( XRootDStatus&, Response&, HostList& )> handleFunction ) :
186  fun( handleFunction )
187  {
188  }
189 
190  //------------------------------------------------------------------------
192  //------------------------------------------------------------------------
193  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
194  {
195  std::unique_ptr<XRootDStatus> delst( status );
196  std::unique_ptr<AnyObject> delrsp( response );
197  std::unique_ptr<HostList> delhl( hostList );
198  Response *res = GetResponse<Response>( status, response );
199  fun( *status, *res, *hostList );
200  }
201 
202  private:
203  //------------------------------------------------------------------------
205  //------------------------------------------------------------------------
206  std::function<void( XRootDStatus&, Response&, HostList& )> fun;
207  };
208 
209  //----------------------------------------------------------------------------
213  //----------------------------------------------------------------------------
214  template<>
215  class FunctionWrapper<void> : public ResponseHandler
216  {
217  public:
218 
219  //------------------------------------------------------------------------
221  //
223  //------------------------------------------------------------------------
225  std::function<void( XRootDStatus& )> handleFunction ) :
226  fun( [handleFunction]( XRootDStatus& s, HostList& ){ handleFunction( s ); } )
227  {
228  }
229 
230  //------------------------------------------------------------------------
232  //
234  //------------------------------------------------------------------------
236  std::function<void( XRootDStatus&, HostList& )> handleFunction ) :
237  fun( handleFunction )
238  {
239  }
240 
241  //------------------------------------------------------------------------
243  //------------------------------------------------------------------------
244  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
245  {
246  std::unique_ptr<XRootDStatus> delst( status );
247  std::unique_ptr<AnyObject> delrsp( response );
248  std::unique_ptr<HostList> delhl( hostList );
249  fun( *status, *hostList );
250  }
251 
252  private:
253  //------------------------------------------------------------------------
255  //------------------------------------------------------------------------
256  std::function<void( XRootDStatus&, HostList& )> fun;
257  };
258 
259  //----------------------------------------------------------------------------
264  //----------------------------------------------------------------------------
265  template<typename Response, typename Return>
267  {
268  public:
269 
270  //------------------------------------------------------------------------
272  //
274  //------------------------------------------------------------------------
275  TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) :
276  task( std::move( task ) )
277  {
278  }
279 
280  //------------------------------------------------------------------------
282  //------------------------------------------------------------------------
283  void HandleResponse( XRootDStatus *status, AnyObject *response )
284  {
285  std::unique_ptr<XRootDStatus> delst( status );
286  std::unique_ptr<AnyObject> delrsp( response );
287  Response *resp = GetResponse<Response>( status, response );
288  task( *status, *resp );
289  }
290 
291  private:
292 
293  //------------------------------------------------------------------------
295  //------------------------------------------------------------------------
296  std::packaged_task<Return( XRootDStatus&, Response& )> task;
297  };
298 
299  //----------------------------------------------------------------------------
305  //----------------------------------------------------------------------------
306  template<typename Return>
307  class TaskWrapper<void, Return>: public ResponseHandler
308  {
309  public:
310 
311  //------------------------------------------------------------------------
313  //
315  //------------------------------------------------------------------------
316  TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) :
317  task( std::move( task ) )
318  {
319  }
320 
321  //------------------------------------------------------------------------
323  //------------------------------------------------------------------------
324  void HandleResponse( XRootDStatus *status, AnyObject *response )
325  {
326  std::unique_ptr<XRootDStatus> delst( status );
327  std::unique_ptr<AnyObject> delrsp( response );
328  task( *status );
329  }
330 
331  private:
332 
333  //------------------------------------------------------------------------
335  //------------------------------------------------------------------------
336  std::packaged_task<Return( XRootDStatus& )> task;
337  };
338 
339 
340  //----------------------------------------------------------------------------
342  //----------------------------------------------------------------------------
344  {
345  public:
346 
347  //------------------------------------------------------------------------
349  //
351  //------------------------------------------------------------------------
353  std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) :
354  f( f ), fun( [handleFunction]( XRootDStatus &s, StatInfo &i, HostList& ){ handleFunction( s, i ); } )
355  {
356  }
357 
358  //------------------------------------------------------------------------
360  //
362  //------------------------------------------------------------------------
364  std::function<void( XRootDStatus&, StatInfo&, HostList& )> handleFunction ) :
365  f( f ), fun( handleFunction )
366  {
367  }
368 
369  //------------------------------------------------------------------------
371  //------------------------------------------------------------------------
372  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
373  {
374  delete response;
375  std::unique_ptr<XRootDStatus> delst( status );
376  std::unique_ptr<StatInfo> delrsp;
377  std::unique_ptr<HostList> delhl;
378  StatInfo *info = nullptr;
379  if( status->IsOK() )
380  {
381  XRootDStatus st = f->Stat( false, info );
382  delrsp.reset( info );
383  }
384  else
385  info = &NullRef<StatInfo>::value;
386  fun( *status, *info, *hostList );
387  }
388 
389  private:
390  Ctx<File> f;
391  //------------------------------------------------------------------------
393  //------------------------------------------------------------------------
394  std::function<void( XRootDStatus&, StatInfo&, HostList& )> fun;
395  };
396 
397  //----------------------------------------------------------------------------
399  //----------------------------------------------------------------------------
400  class PipelineException : public std::exception
401  {
402  public:
403 
404  //------------------------------------------------------------------------
406  //------------------------------------------------------------------------
407  PipelineException( const XRootDStatus &error ) : error( error ), strerr( error.ToString() )
408  {
409 
410  }
411 
412  //------------------------------------------------------------------------
414  //------------------------------------------------------------------------
415  PipelineException( const PipelineException &ex ) : error( ex.error ), strerr( ex.error.ToString() )
416  {
417 
418  }
419 
420  //------------------------------------------------------------------------
422  //------------------------------------------------------------------------
424  {
425  error = ex.error;
426  strerr = ex.strerr;
427  return *this;
428  }
429 
430  //------------------------------------------------------------------------
432  //------------------------------------------------------------------------
433  const char* what() const noexcept
434  {
435  return strerr.c_str();
436  }
437 
438  //------------------------------------------------------------------------
440  //------------------------------------------------------------------------
441  const XRootDStatus& GetError() const
442  {
443  return error;
444  }
445 
446  private:
447 
448  //------------------------------------------------------------------------
450  //------------------------------------------------------------------------
451  XRootDStatus error;
452  std::string strerr;
453  };
454 
455  //----------------------------------------------------------------------------
459  //----------------------------------------------------------------------------
460  template<typename Response>
462  {
463  public:
464 
465  //------------------------------------------------------------------------
470  //------------------------------------------------------------------------
471  FutureWrapperBase( std::future<Response> &ftr ) : fulfilled( false )
472  {
473  ftr = prms.get_future();
474  }
475 
476  //------------------------------------------------------------------------
478  //------------------------------------------------------------------------
480  {
482  }
483 
484  protected:
485 
486  //------------------------------------------------------------------------
490  //------------------------------------------------------------------------
491  inline void SetException( const XRootDStatus &err )
492  {
493  std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) );
494  prms.set_exception( ex );
495  fulfilled = true;
496  }
497 
498  //------------------------------------------------------------------------
500  //------------------------------------------------------------------------
501  std::promise<Response> prms;
502  bool fulfilled;
503  };
504 
505  //----------------------------------------------------------------------------
509  //----------------------------------------------------------------------------
510  template<typename Response>
511  class FutureWrapper : public FutureWrapperBase<Response>
512  {
513  public:
514 
515  //------------------------------------------------------------------------
519  //------------------------------------------------------------------------
520  FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr )
521  {
522  }
523 
524  //------------------------------------------------------------------------
526  //------------------------------------------------------------------------
527  void HandleResponse( XRootDStatus *status, AnyObject *response )
528  {
529  std::unique_ptr<XRootDStatus> delst( status );
530  std::unique_ptr<AnyObject> delrsp( response );
531  if( status->IsOK() )
532  {
533  Response *resp = GetResponse<Response>( response );
534  if( resp == &NullRef<Response>::value )
536  else
537  {
538  this->prms.set_value( std::move( *resp ) );
539  this->fulfilled = true;
540  }
541  }
542  else
543  this->SetException( *status );
544  }
545  };
546 
547  //----------------------------------------------------------------------------
549  //----------------------------------------------------------------------------
550  template<>
551  class FutureWrapper<void> : public FutureWrapperBase<void>
552  {
553  public:
554 
555  //------------------------------------------------------------------------
559  //------------------------------------------------------------------------
560  FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr )
561  {
562  }
563 
564  //------------------------------------------------------------------------
566  //------------------------------------------------------------------------
567  void HandleResponse( XRootDStatus *status, AnyObject *response )
568  {
569  std::unique_ptr<XRootDStatus> delst( status );
570  std::unique_ptr<AnyObject> delrsp( response );
571  if( status->IsOK() )
572  {
573  prms.set_value();
574  fulfilled = true;
575  }
576  else
577  SetException( *status );
578  }
579  };
580 
581 
582  //----------------------------------------------------------------------------
584  //----------------------------------------------------------------------------
586  {
587  public:
588 
589  //------------------------------------------------------------------------
593  //------------------------------------------------------------------------
594  RawWrapper( ResponseHandler *handler ) : handler( handler )
595  {
596  }
597 
598  //------------------------------------------------------------------------
603  //------------------------------------------------------------------------
604  virtual void HandleResponseWithHosts( XRootDStatus *status,
605  AnyObject *response,
606  HostList *hostList )
607  {
608  handler->HandleResponseWithHosts( status, response, hostList );
609  }
610 
611  private:
612  //------------------------------------------------------------------------
614  //------------------------------------------------------------------------
615  ResponseHandler *handler;
616  };
617 
618 
619  //----------------------------------------------------------------------------
624  //----------------------------------------------------------------------------
625  template<typename Response>
626  struct RespBase
627  {
628  //------------------------------------------------------------------------
633  //------------------------------------------------------------------------
634  inline static ResponseHandler* Create( ResponseHandler *hdlr )
635  {
636  return new RawWrapper( hdlr );
637  }
638 
639  //------------------------------------------------------------------------
644  //------------------------------------------------------------------------
645  inline static ResponseHandler* Create( ResponseHandler &hdlr )
646  {
647  return new RawWrapper( &hdlr );
648  }
649 
650  //------------------------------------------------------------------------
655  //------------------------------------------------------------------------
656  inline static ResponseHandler* Create( std::future<Response> &ftr )
657  {
658  return new FutureWrapper<Response>( ftr );
659  }
660  };
661 
662  //----------------------------------------------------------------------------
667  //----------------------------------------------------------------------------
668  template<typename Response>
669  struct Resp: RespBase<Response>
670  {
671  //------------------------------------------------------------------------
676  //------------------------------------------------------------------------
677  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
678  Response& )> func )
679  {
680  return new FunctionWrapper<Response>( func );
681  }
682 
683  //------------------------------------------------------------------------
688  //------------------------------------------------------------------------
689  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
690  Response&, HostList& )> func )
691  {
692  return new FunctionWrapper<Response>( func );
693  }
694 
695  //------------------------------------------------------------------------
700  //------------------------------------------------------------------------
701  template<typename Return>
702  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&,
703  Response& )> &task )
704  {
705  return new TaskWrapper<Response, Return>( std::move( task ) );
706  }
707 
708  //------------------------------------------------------------------------
710  //------------------------------------------------------------------------
712  };
713 
714  //----------------------------------------------------------------------------
718  //----------------------------------------------------------------------------
719  template<>
720  struct Resp<void>: RespBase<void>
721  {
722  //------------------------------------------------------------------------
727  //------------------------------------------------------------------------
728  inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func )
729  {
730  return new FunctionWrapper<void>( func );
731  }
732 
733  //------------------------------------------------------------------------
738  //------------------------------------------------------------------------
739  inline static ResponseHandler* Create( std::function<void( XRootDStatus&, HostList& )> func )
740  {
741  return new FunctionWrapper<void>( func );
742  }
743 
744  //------------------------------------------------------------------------
749  //------------------------------------------------------------------------
750  template<typename Return>
751  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task )
752  {
753  return new TaskWrapper<void, Return>( std::move( task ) );
754  }
755 
756  //------------------------------------------------------------------------
758  //------------------------------------------------------------------------
760  };
761 }
762 
763 #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