XRootD
Loading...
Searching...
No Matches
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
36namespace 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 //------------------------------------------------------------------------
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;
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 //------------------------------------------------------------------------
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 //------------------------------------------------------------------------
699 using RespBase<Response>::Create;
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 //------------------------------------------------------------------------
747 using RespBase<void>::Create;
748 };
749}
750
751#endif // __XRD_CL_OPERATIONS_HANDLERS_HH__
bool Create
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.
const XRootDStatus & GetError() const
PipelineException(const XRootDStatus &error)
Constructor from XRootDStatus.
PipelineException(const PipelineException &ex)
Copy constructor.
PipelineException & operator=(const PipelineException &ex)
Assigment operator.
const char * what() const noexcept
inherited from std::exception
Wrapper class for raw response handler (ResponseHandler).
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
RawWrapper(ResponseHandler *handler)
Handle an async 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.
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
UnpackXAttrStatus(ResponseHandler *handler)
void HandleResponse(XRootDStatus *status, AnyObject *response)
Callback method.
UnpackXAttr(ResponseHandler *handler)
Response * GetResponse(AnyObject *rsp)
const uint16_t stError
An error occurred that could potentially be retried.
std::vector< HostInfo > HostList
const uint16_t errInternal
Internal error.
const uint16_t errPipelineFailed
Pipeline failed and operation couldn't be executed.
Utility class for storing a pointer to operation context.
Definition XrdClCtx.hh:39
static ResponseHandler * Create(ResponseHandler *hdlr)
static ResponseHandler * Create(ResponseHandler &hdlr)
static ResponseHandler * Create(std::future< Response > &ftr)
static ResponseHandler * Create(std::packaged_task< Return(XRootDStatus &)> &task)
static ResponseHandler * Create(std::function< void(XRootDStatus &, HostList &)> func)
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)
bool IsOK() const
We're fine.