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 //----------------------------------------------------------------------------
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>
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
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 //------------------------------------------------------------------------
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;
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 //------------------------------------------------------------------------
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 //------------------------------------------------------------------------
711 using RespBase<Response>::Create;
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 //------------------------------------------------------------------------
759 using RespBase<void>::Create;
760 };
761}
762
763#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.
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)
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)
uint16_t status
Status of the execution.
bool IsOK() const
We're fine.