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  //----------------------------------------------------------------------------
118  //----------------------------------------------------------------------------
119  template<typename Response>
120  inline Response* GetResponse( AnyObject *rsp )
121  {
122  Response *ret = nullptr;
123  rsp->Get( ret );
124  return ret;
125  }
126 
127  //----------------------------------------------------------------------------
133  //----------------------------------------------------------------------------
134  template<typename Response>
135  inline Response* GetResponse( XRootDStatus *status, AnyObject *rsp )
136  {
137  return status->IsOK() ? GetResponse<Response>( rsp ) : nullptr;
138  }
139 
140  //----------------------------------------------------------------------------
144  //----------------------------------------------------------------------------
145  template<typename Response>
147  {
148  public:
149 
150  //------------------------------------------------------------------------
152  //
154  //------------------------------------------------------------------------
156  std::function<void( XRootDStatus&, Response& )> handleFunction ) :
157  fun( [handleFunction]( XRootDStatus &s, Response &r, HostList& ){ handleFunction( s, r ); } )
158  {
159  }
160 
161  //------------------------------------------------------------------------
163  //
165  //------------------------------------------------------------------------
167  std::function<void( XRootDStatus&, Response&, HostList& )> handleFunction ) :
168  fun( handleFunction )
169  {
170  }
171 
172  //------------------------------------------------------------------------
174  //------------------------------------------------------------------------
175  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
176  {
177  std::unique_ptr<XRootDStatus> delst( status );
178  std::unique_ptr<AnyObject> delrsp( response );
179  std::unique_ptr<HostList> delhl( hostList );
180  if (Response *res = GetResponse<Response>( status, response ))
181  fun( *status, *res, *hostList );
182  else {
183  Response dummy;
184  fun( *status, dummy, *hostList );
185  }
186  }
187 
188  private:
189  //------------------------------------------------------------------------
191  //------------------------------------------------------------------------
192  std::function<void( XRootDStatus&, Response&, HostList& )> fun;
193  };
194 
195  //----------------------------------------------------------------------------
199  //----------------------------------------------------------------------------
200  template<>
201  class FunctionWrapper<void> : public ResponseHandler
202  {
203  public:
204 
205  //------------------------------------------------------------------------
207  //
209  //------------------------------------------------------------------------
211  std::function<void( XRootDStatus& )> handleFunction ) :
212  fun( [handleFunction]( XRootDStatus& s, HostList& ){ handleFunction( s ); } )
213  {
214  }
215 
216  //------------------------------------------------------------------------
218  //
220  //------------------------------------------------------------------------
222  std::function<void( XRootDStatus&, HostList& )> handleFunction ) :
223  fun( handleFunction )
224  {
225  }
226 
227  //------------------------------------------------------------------------
229  //------------------------------------------------------------------------
230  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
231  {
232  std::unique_ptr<XRootDStatus> delst( status );
233  std::unique_ptr<AnyObject> delrsp( response );
234  std::unique_ptr<HostList> delhl( hostList );
235  fun( *status, *hostList );
236  }
237 
238  private:
239  //------------------------------------------------------------------------
241  //------------------------------------------------------------------------
242  std::function<void( XRootDStatus&, HostList& )> fun;
243  };
244 
245  //----------------------------------------------------------------------------
250  //----------------------------------------------------------------------------
251  template<typename Response, typename Return>
253  {
254  public:
255 
256  //------------------------------------------------------------------------
258  //
260  //------------------------------------------------------------------------
261  TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) :
262  task( std::move( task ) )
263  {
264  }
265 
266  //------------------------------------------------------------------------
268  //------------------------------------------------------------------------
269  void HandleResponse( XRootDStatus *status, AnyObject *response )
270  {
271  std::unique_ptr<XRootDStatus> delst( status );
272  std::unique_ptr<AnyObject> delrsp( response );
273  if (Response *resp = GetResponse<Response>( status, response )) {
274  task( *status, *resp );
275  } else {
276  Response dummy;
277  task( *status, dummy );
278  }
279  }
280 
281  private:
282 
283  //------------------------------------------------------------------------
285  //------------------------------------------------------------------------
286  std::packaged_task<Return( XRootDStatus&, Response& )> task;
287  };
288 
289  //----------------------------------------------------------------------------
295  //----------------------------------------------------------------------------
296  template<typename Return>
297  class TaskWrapper<void, Return>: public ResponseHandler
298  {
299  public:
300 
301  //------------------------------------------------------------------------
303  //
305  //------------------------------------------------------------------------
306  TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) :
307  task( std::move( task ) )
308  {
309  }
310 
311  //------------------------------------------------------------------------
313  //------------------------------------------------------------------------
314  void HandleResponse( XRootDStatus *status, AnyObject *response )
315  {
316  std::unique_ptr<XRootDStatus> delst( status );
317  std::unique_ptr<AnyObject> delrsp( response );
318  task( *status );
319  }
320 
321  private:
322 
323  //------------------------------------------------------------------------
325  //------------------------------------------------------------------------
326  std::packaged_task<Return( XRootDStatus& )> task;
327  };
328 
329 
330  //----------------------------------------------------------------------------
332  //----------------------------------------------------------------------------
334  {
335  public:
336 
337  //------------------------------------------------------------------------
339  //
341  //------------------------------------------------------------------------
343  std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) :
344  f( f ), fun( [handleFunction]( XRootDStatus &s, StatInfo &i, HostList& ){ handleFunction( s, i ); } )
345  {
346  }
347 
348  //------------------------------------------------------------------------
350  //
352  //------------------------------------------------------------------------
354  std::function<void( XRootDStatus&, StatInfo&, HostList& )> handleFunction ) :
355  f( f ), fun( handleFunction )
356  {
357  }
358 
359  //------------------------------------------------------------------------
361  //------------------------------------------------------------------------
362  void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, HostList *hostList )
363  {
364  std::unique_ptr<XRootDStatus> delst( status );
365  std::unique_ptr<AnyObject> delrsp( response );
366  std::unique_ptr<HostList> delhl( hostList );
367 
368  if( !status->IsOK() ) {
369  StatInfo dummy{};
370  fun( *status, dummy, *hostList );
371  return;
372  }
373 
374  StatInfo *info = nullptr;
375  XRootDStatus st = f->Stat( false, info );
376  fun( *status, *info, *hostList );
377  delete info;
378  }
379 
380  private:
381  Ctx<File> f;
382  //------------------------------------------------------------------------
384  //------------------------------------------------------------------------
385  std::function<void( XRootDStatus&, StatInfo&, HostList& )> fun;
386  };
387 
388  //----------------------------------------------------------------------------
390  //----------------------------------------------------------------------------
391  class PipelineException : public std::exception
392  {
393  public:
394 
395  //------------------------------------------------------------------------
397  //------------------------------------------------------------------------
398  PipelineException( const XRootDStatus &error ) : error( error ), strerr( error.ToString() )
399  {
400 
401  }
402 
403  //------------------------------------------------------------------------
405  //------------------------------------------------------------------------
406  PipelineException( const PipelineException &ex ) : error( ex.error ), strerr( ex.error.ToString() )
407  {
408 
409  }
410 
411  //------------------------------------------------------------------------
413  //------------------------------------------------------------------------
415  {
416  error = ex.error;
417  strerr = ex.strerr;
418  return *this;
419  }
420 
421  //------------------------------------------------------------------------
423  //------------------------------------------------------------------------
424  const char* what() const noexcept
425  {
426  return strerr.c_str();
427  }
428 
429  //------------------------------------------------------------------------
431  //------------------------------------------------------------------------
432  const XRootDStatus& GetError() const
433  {
434  return error;
435  }
436 
437  private:
438 
439  //------------------------------------------------------------------------
441  //------------------------------------------------------------------------
442  XRootDStatus error;
443  std::string strerr;
444  };
445 
446  //----------------------------------------------------------------------------
450  //----------------------------------------------------------------------------
451  template<typename Response>
453  {
454  public:
455 
456  //------------------------------------------------------------------------
461  //------------------------------------------------------------------------
462  FutureWrapperBase( std::future<Response> &ftr ) : fulfilled( false )
463  {
464  ftr = prms.get_future();
465  }
466 
467  //------------------------------------------------------------------------
469  //------------------------------------------------------------------------
471  {
473  }
474 
475  protected:
476 
477  //------------------------------------------------------------------------
481  //------------------------------------------------------------------------
482  inline void SetException( const XRootDStatus &err )
483  {
484  std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) );
485  prms.set_exception( ex );
486  fulfilled = true;
487  }
488 
489  //------------------------------------------------------------------------
491  //------------------------------------------------------------------------
492  std::promise<Response> prms;
493  bool fulfilled;
494  };
495 
496  //----------------------------------------------------------------------------
500  //----------------------------------------------------------------------------
501  template<typename Response>
502  class FutureWrapper : public FutureWrapperBase<Response>
503  {
504  public:
505 
506  //------------------------------------------------------------------------
510  //------------------------------------------------------------------------
511  FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr )
512  {
513  }
514 
515  //------------------------------------------------------------------------
517  //------------------------------------------------------------------------
518  void HandleResponse( XRootDStatus *status, AnyObject *response )
519  {
520  std::unique_ptr<XRootDStatus> delst( status );
521  std::unique_ptr<AnyObject> delrsp( response );
522  if( status->IsOK() ) {
523  if(Response *resp = GetResponse<Response>( response )) {
524  this->prms.set_value( std::move( *resp ) );
525  this->fulfilled = true;
526  } else {
528  }
529  } else {
530  this->SetException( *status );
531  }
532  }
533  };
534 
535  //----------------------------------------------------------------------------
537  //----------------------------------------------------------------------------
538  template<>
539  class FutureWrapper<void> : public FutureWrapperBase<void>
540  {
541  public:
542 
543  //------------------------------------------------------------------------
547  //------------------------------------------------------------------------
548  FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr )
549  {
550  }
551 
552  //------------------------------------------------------------------------
554  //------------------------------------------------------------------------
555  void HandleResponse( XRootDStatus *status, AnyObject *response )
556  {
557  std::unique_ptr<XRootDStatus> delst( status );
558  std::unique_ptr<AnyObject> delrsp( response );
559  if( status->IsOK() )
560  {
561  prms.set_value();
562  fulfilled = true;
563  }
564  else
565  SetException( *status );
566  }
567  };
568 
569 
570  //----------------------------------------------------------------------------
572  //----------------------------------------------------------------------------
574  {
575  public:
576 
577  //------------------------------------------------------------------------
581  //------------------------------------------------------------------------
582  RawWrapper( ResponseHandler *handler ) : handler( handler )
583  {
584  }
585 
586  //------------------------------------------------------------------------
591  //------------------------------------------------------------------------
592  virtual void HandleResponseWithHosts( XRootDStatus *status,
593  AnyObject *response,
594  HostList *hostList )
595  {
596  handler->HandleResponseWithHosts( status, response, hostList );
597  }
598 
599  private:
600  //------------------------------------------------------------------------
602  //------------------------------------------------------------------------
603  ResponseHandler *handler;
604  };
605 
606 
607  //----------------------------------------------------------------------------
612  //----------------------------------------------------------------------------
613  template<typename Response>
614  struct RespBase
615  {
616  //------------------------------------------------------------------------
621  //------------------------------------------------------------------------
622  inline static ResponseHandler* Create( ResponseHandler *hdlr )
623  {
624  return new RawWrapper( hdlr );
625  }
626 
627  //------------------------------------------------------------------------
632  //------------------------------------------------------------------------
633  inline static ResponseHandler* Create( ResponseHandler &hdlr )
634  {
635  return new RawWrapper( &hdlr );
636  }
637 
638  //------------------------------------------------------------------------
643  //------------------------------------------------------------------------
644  inline static ResponseHandler* Create( std::future<Response> &ftr )
645  {
646  return new FutureWrapper<Response>( ftr );
647  }
648  };
649 
650  //----------------------------------------------------------------------------
655  //----------------------------------------------------------------------------
656  template<typename Response>
657  struct Resp: RespBase<Response>
658  {
659  //------------------------------------------------------------------------
664  //------------------------------------------------------------------------
665  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
666  Response& )> func )
667  {
668  return new FunctionWrapper<Response>( func );
669  }
670 
671  //------------------------------------------------------------------------
676  //------------------------------------------------------------------------
677  inline static ResponseHandler* Create( std::function<void( XRootDStatus&,
678  Response&, HostList& )> func )
679  {
680  return new FunctionWrapper<Response>( func );
681  }
682 
683  //------------------------------------------------------------------------
688  //------------------------------------------------------------------------
689  template<typename Return>
690  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&,
691  Response& )> &task )
692  {
693  return new TaskWrapper<Response, Return>( std::move( task ) );
694  }
695 
696  //------------------------------------------------------------------------
698  //------------------------------------------------------------------------
700  };
701 
702  //----------------------------------------------------------------------------
706  //----------------------------------------------------------------------------
707  template<>
708  struct Resp<void>: RespBase<void>
709  {
710  //------------------------------------------------------------------------
715  //------------------------------------------------------------------------
716  inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func )
717  {
718  return new FunctionWrapper<void>( func );
719  }
720 
721  //------------------------------------------------------------------------
726  //------------------------------------------------------------------------
727  inline static ResponseHandler* Create( std::function<void( XRootDStatus&, HostList& )> func )
728  {
729  return new FunctionWrapper<void>( func );
730  }
731 
732  //------------------------------------------------------------------------
737  //------------------------------------------------------------------------
738  template<typename Return>
739  inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task )
740  {
741  return new TaskWrapper<void, Return>( std::move( task ) );
742  }
743 
744  //------------------------------------------------------------------------
746  //------------------------------------------------------------------------
748  };
749 }
750 
751 #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