|
|
|||
File indexing completed on 2026-09-09 09:28:46
0001 //------------------------------------------------------------------------------ 0002 // Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN) 0003 // Author: Krzysztof Jamrog <krzysztof.piotr.jamrog@cern.ch>, 0004 // Michal Simon <michal.simon@cern.ch> 0005 //------------------------------------------------------------------------------ 0006 // This file is part of the XRootD software suite. 0007 // 0008 // XRootD is free software: you can redistribute it and/or modify 0009 // it under the terms of the GNU Lesser General Public License as published by 0010 // the Free Software Foundation, either version 3 of the License, or 0011 // (at your option) any later version. 0012 // 0013 // XRootD is distributed in the hope that it will be useful, 0014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0016 // GNU General Public License for more details. 0017 // 0018 // You should have received a copy of the GNU Lesser General Public License 0019 // along with XRootD. If not, see <http://www.gnu.org/licenses/>. 0020 // 0021 // In applying this licence, CERN does not waive the privileges and immunities 0022 // granted to it by virtue of its status as an Intergovernmental Organization 0023 // or submit itself to any jurisdiction. 0024 //------------------------------------------------------------------------------ 0025 0026 #ifndef __XRD_CL_OPERATIONS_HH__ 0027 #define __XRD_CL_OPERATIONS_HH__ 0028 0029 #include <memory> 0030 #include <stdexcept> 0031 #include <sstream> 0032 #include <tuple> 0033 #include <future> 0034 #include "XrdCl/XrdClXRootDResponses.hh" 0035 #include "XrdCl/XrdClOperationHandlers.hh" 0036 #include "XrdCl/XrdClArg.hh" 0037 #include "XrdCl/XrdClOperationTimeout.hh" 0038 #include "XrdCl/XrdClFinalOperation.hh" 0039 #include "XrdSys/XrdSysPthread.hh" 0040 0041 #include "XrdCl/XrdClResponseJob.hh" 0042 #include "XrdCl/XrdClJobManager.hh" 0043 #include "XrdCl/XrdClPostMaster.hh" 0044 #include "XrdCl/XrdClDefaultEnv.hh" 0045 0046 namespace XrdCl 0047 { 0048 0049 class Pipeline; 0050 class PipelineHandler; 0051 0052 //---------------------------------------------------------------------------- 0053 //! Operation template. An Operation is a once-use-only object - once executed 0054 //! by a Workflow engine it is invalidated. Also if used as an argument for 0055 //! >> or | the original object gets invalidated. 0056 //! 0057 //! @arg HasHndl : true if operation has a handler, false otherwise 0058 //---------------------------------------------------------------------------- 0059 template<bool HasHndl> 0060 class Operation 0061 { 0062 // Declare friendship between templates 0063 template<bool> 0064 friend class Operation; 0065 0066 friend std::future<XRootDStatus> Async( Pipeline, uint16_t ); 0067 0068 friend class Pipeline; 0069 friend class PipelineHandler; 0070 0071 public: 0072 0073 //------------------------------------------------------------------------ 0074 //! Constructor 0075 //------------------------------------------------------------------------ 0076 Operation() : valid( true ) 0077 { 0078 } 0079 0080 //------------------------------------------------------------------------ 0081 //! Move constructor between template instances. 0082 //------------------------------------------------------------------------ 0083 template<bool from> 0084 Operation( Operation<from> && op ) : 0085 handler( std::move( op.handler ) ), valid( true ) 0086 { 0087 if( !op.valid ) throw std::invalid_argument( "Cannot construct " 0088 "Operation from an invalid Operation!" ); 0089 op.valid = false; 0090 } 0091 0092 //------------------------------------------------------------------------ 0093 //! Destructor 0094 //------------------------------------------------------------------------ 0095 virtual ~Operation() 0096 { 0097 } 0098 0099 //------------------------------------------------------------------------ 0100 //! Name of the operation. 0101 //------------------------------------------------------------------------ 0102 virtual std::string ToString() = 0; 0103 0104 //------------------------------------------------------------------------ 0105 //! Move current object into newly allocated instance 0106 //! 0107 //! @return : the new instance 0108 //------------------------------------------------------------------------ 0109 virtual Operation<HasHndl>* Move() = 0; 0110 0111 //------------------------------------------------------------------------ 0112 //! Move current object into newly allocated instance, and convert 0113 //! it into 'handled' operation. 0114 //! 0115 //! @return : the new instance 0116 //------------------------------------------------------------------------ 0117 virtual Operation<true>* ToHandled() = 0; 0118 0119 protected: 0120 0121 //------------------------------------------------------------------------ 0122 //! Run operation 0123 //! 0124 //! @param prms : the promise that we will have a result 0125 //! @param final : the object to call at the end of pipeline 0126 //------------------------------------------------------------------------ 0127 void Run( Timeout timeout, 0128 std::promise<XRootDStatus> prms, 0129 std::function<void(const XRootDStatus&)> final ); 0130 0131 //------------------------------------------------------------------------ 0132 //! Run the actual operation 0133 //! 0134 //! @param params : container with parameters forwarded from 0135 //! previous operation 0136 //! @return : status of the operation 0137 //------------------------------------------------------------------------ 0138 virtual XRootDStatus RunImpl( PipelineHandler *handler, uint16_t timeout ) = 0; 0139 0140 //------------------------------------------------------------------------ 0141 //! Add next operation in the pipeline 0142 //! 0143 //! @param op : operation to add 0144 //------------------------------------------------------------------------ 0145 void AddOperation( Operation<true> *op ); 0146 0147 //------------------------------------------------------------------------ 0148 //! Operation handler 0149 //------------------------------------------------------------------------ 0150 std::unique_ptr<PipelineHandler> handler; 0151 0152 //------------------------------------------------------------------------ 0153 //! Flag indicating if it is a valid object 0154 //------------------------------------------------------------------------ 0155 bool valid; 0156 }; 0157 0158 //---------------------------------------------------------------------------- 0159 //! Type of the recovery function to be provided by the user 0160 //---------------------------------------------------------------------------- 0161 typedef std::function<Operation<true>*(const XRootDStatus&)> rcvry_func; 0162 0163 //---------------------------------------------------------------------------- 0164 //! Wrapper for ResponseHandler, used only internally to run next operation 0165 //! after previous one is finished 0166 //---------------------------------------------------------------------------- 0167 class PipelineHandler: public ResponseHandler 0168 { 0169 template<bool> friend class Operation; 0170 0171 public: 0172 0173 //------------------------------------------------------------------------ 0174 //! Constructor. 0175 //! 0176 //! @param handler : the handler of our operation 0177 //------------------------------------------------------------------------ 0178 PipelineHandler( ResponseHandler *handler ); 0179 0180 //------------------------------------------------------------------------ 0181 //! Default Constructor. 0182 //------------------------------------------------------------------------ 0183 PipelineHandler() 0184 { 0185 } 0186 0187 //------------------------------------------------------------------------ 0188 //! Callback function. 0189 //------------------------------------------------------------------------ 0190 void HandleResponseWithHosts( XRootDStatus *status, AnyObject *response, 0191 HostList *hostList ); 0192 0193 //------------------------------------------------------------------------ 0194 //! Callback function. 0195 //------------------------------------------------------------------------ 0196 void HandleResponse( XRootDStatus *status, AnyObject *response ); 0197 0198 //------------------------------------------------------------------------ 0199 //! Destructor. 0200 //------------------------------------------------------------------------ 0201 ~PipelineHandler() 0202 { 0203 } 0204 0205 //------------------------------------------------------------------------ 0206 //! Add new operation to the pipeline 0207 //! 0208 //! @param operation : operation to add 0209 //------------------------------------------------------------------------ 0210 void AddOperation( Operation<true> *operation ); 0211 0212 //------------------------------------------------------------------------ 0213 //! Set workflow to this and all next handlers. In the last handler 0214 //! it is used to finish workflow execution 0215 //! 0216 //! @param prms : a promis that the pipeline will have a result 0217 //! @param final : a callable that should be called at the end of 0218 //! pipeline 0219 //------------------------------------------------------------------------ 0220 void Assign( const Timeout &timeout, 0221 std::promise<XRootDStatus> prms, 0222 std::function<void(const XRootDStatus&)> final, 0223 Operation<true> *opr ); 0224 0225 //------------------------------------------------------------------------ 0226 //! Assign the finalization routine 0227 //------------------------------------------------------------------------ 0228 void Assign( std::function<void(const XRootDStatus&)> final ); 0229 0230 //------------------------------------------------------------------------ 0231 //! Called by a pipeline on the handler of its first operation before Run 0232 //------------------------------------------------------------------------ 0233 void PreparePipelineStart(); 0234 0235 private: 0236 0237 //------------------------------------------------------------------------ 0238 //! Callback function implementation; 0239 //------------------------------------------------------------------------ 0240 void HandleResponseImpl( XRootDStatus *status, AnyObject *response, HostList *hostList ); 0241 0242 inline void dealloc( XRootDStatus *status, AnyObject *response, 0243 HostList *hostList ) 0244 { 0245 delete status; 0246 delete response; 0247 delete hostList; 0248 } 0249 0250 //------------------------------------------------------------------------ 0251 //! The handler of our operation 0252 //------------------------------------------------------------------------ 0253 std::unique_ptr<ResponseHandler> responseHandler; 0254 0255 //------------------------------------------------------------------------ 0256 //! The operation the handler is assigned to 0257 //------------------------------------------------------------------------ 0258 std::unique_ptr<Operation<true>> currentOperation; 0259 0260 //------------------------------------------------------------------------ 0261 //! Next operation in the pipeline 0262 //------------------------------------------------------------------------ 0263 std::unique_ptr<Operation<true>> nextOperation; 0264 0265 //------------------------------------------------------------------------ 0266 //! Pipeline timeout 0267 //------------------------------------------------------------------------ 0268 Timeout timeout; 0269 0270 //------------------------------------------------------------------------ 0271 //! The promise that there will be a result (traveling along the pipeline) 0272 //------------------------------------------------------------------------ 0273 std::promise<XRootDStatus> prms; 0274 0275 //------------------------------------------------------------------------ 0276 //! The lambda/function/functor that should be called at the end of the 0277 //! pipeline (traveling along the pipeline) 0278 //------------------------------------------------------------------------ 0279 std::function<void(const XRootDStatus&)> final; 0280 }; 0281 0282 //---------------------------------------------------------------------------- 0283 //! A wrapper around operation pipeline. A Pipeline is a once-use-only 0284 //! object - once executed by a Workflow engine it is invalidated. 0285 //! 0286 //! Takes ownership of given operation pipeline (which is in most would 0287 //! be a temporary object) 0288 //---------------------------------------------------------------------------- 0289 class Pipeline 0290 { 0291 template<bool> friend class ParallelOperation; 0292 friend std::future<XRootDStatus> Async( Pipeline, uint16_t ); 0293 friend class PipelineHandler; 0294 0295 public: 0296 0297 //------------------------------------------------------------------------ 0298 //! Default constructor 0299 //------------------------------------------------------------------------ 0300 Pipeline() 0301 { 0302 } 0303 0304 //------------------------------------------------------------------------ 0305 //! Constructor 0306 //------------------------------------------------------------------------ 0307 Pipeline( Operation<true> *op ) : 0308 operation( op->Move() ) 0309 { 0310 } 0311 0312 //------------------------------------------------------------------------ 0313 //! Constructor 0314 //------------------------------------------------------------------------ 0315 Pipeline( Operation<true> &op ) : 0316 operation( op.Move() ) 0317 { 0318 } 0319 0320 //------------------------------------------------------------------------ 0321 //! Constructor 0322 //------------------------------------------------------------------------ 0323 Pipeline( Operation<true> &&op ) : 0324 operation( op.Move() ) 0325 { 0326 } 0327 0328 Pipeline( Operation<false> *op ) : 0329 operation( op->ToHandled() ) 0330 { 0331 } 0332 0333 //------------------------------------------------------------------------ 0334 //! Constructor 0335 //------------------------------------------------------------------------ 0336 Pipeline( Operation<false> &op ) : 0337 operation( op.ToHandled() ) 0338 { 0339 } 0340 0341 //------------------------------------------------------------------------ 0342 //! Constructor 0343 //------------------------------------------------------------------------ 0344 Pipeline( Operation<false> &&op ) : 0345 operation( op.ToHandled() ) 0346 { 0347 } 0348 0349 Pipeline( Pipeline &&pipe ) : 0350 operation( std::move( pipe.operation ) ) 0351 { 0352 } 0353 0354 //------------------------------------------------------------------------ 0355 //! Constructor 0356 //------------------------------------------------------------------------ 0357 Pipeline& operator=( Pipeline &&pipe ) 0358 { 0359 operation = std::move( pipe.operation ); 0360 return *this; 0361 } 0362 0363 //------------------------------------------------------------------------ 0364 //! Extend pipeline 0365 //------------------------------------------------------------------------ 0366 Pipeline& operator|=( Operation<true>&& op ) 0367 { 0368 operation->AddOperation( op.Move() ); 0369 return *this; 0370 } 0371 0372 //------------------------------------------------------------------------ 0373 //! Extend pipeline 0374 //------------------------------------------------------------------------ 0375 Pipeline& operator|=( Operation<false>&& op ) 0376 { 0377 operation->AddOperation( op.ToHandled() ); 0378 return *this; 0379 } 0380 0381 //------------------------------------------------------------------------ 0382 //! Conversion to Operation<true> 0383 //! 0384 //! @throws : std::logic_error if pipeline is invalid 0385 //------------------------------------------------------------------------ 0386 operator Operation<true>&() 0387 { 0388 if( !bool( operation ) ) throw std::logic_error( "Invalid pipeline." ); 0389 return *operation.get(); 0390 } 0391 0392 //------------------------------------------------------------------------ 0393 //! Conversion to boolean 0394 //! 0395 //! @return : true if it's a valid pipeline, false otherwise 0396 //------------------------------------------------------------------------ 0397 operator bool() 0398 { 0399 return bool( operation ); 0400 } 0401 0402 //------------------------------------------------------------------------ 0403 //! Stop the current pipeline 0404 //! 0405 //! @param status : the final status for the pipeline 0406 //------------------------------------------------------------------------ 0407 static void Stop( const XRootDStatus &status = XrdCl::XRootDStatus() ); 0408 0409 //------------------------------------------------------------------------ 0410 //! Repeat current operation 0411 //------------------------------------------------------------------------ 0412 static void Repeat(); 0413 0414 //------------------------------------------------------------------------ 0415 //! Replace current operation 0416 //------------------------------------------------------------------------ 0417 static void Replace( Operation<false> &&opr ); 0418 0419 //------------------------------------------------------------------------ 0420 //! Replace with pipeline 0421 //------------------------------------------------------------------------ 0422 static void Replace( Pipeline p ); 0423 0424 //------------------------------------------------------------------------ 0425 //! Ignore error and proceed with the pipeline 0426 //------------------------------------------------------------------------ 0427 static void Ignore(); 0428 0429 private: 0430 0431 //------------------------------------------------------------------------ 0432 //! Member access declaration, provides access to the underlying 0433 //! operation. 0434 //! 0435 //! @return : pointer to the underlying 0436 //------------------------------------------------------------------------ 0437 Operation<true>* operator->() 0438 { 0439 return operation.get(); 0440 } 0441 0442 //------------------------------------------------------------------------ 0443 //! Schedules the underlying pipeline for execution. 0444 //! 0445 //! @param timeout : pipeline timeout value 0446 //! @param final : to be called at the end of the pipeline 0447 //------------------------------------------------------------------------ 0448 void Run( Timeout timeout, std::function<void(const XRootDStatus&)> final = nullptr ) 0449 { 0450 if( ftr.valid() ) 0451 throw std::logic_error( "Pipeline is already running!" ); 0452 0453 // a promise that the pipe will have a result 0454 std::promise<XRootDStatus> prms; 0455 ftr = prms.get_future(); 0456 0457 if( !operation ) std::logic_error( "Empty pipeline!" ); 0458 0459 Operation<true> *opr = operation.release(); 0460 PipelineHandler *h = opr->handler.get(); 0461 if( h ) 0462 h->PreparePipelineStart(); 0463 0464 opr->Run( timeout, std::move( prms ), std::move( final ) ); 0465 } 0466 0467 //------------------------------------------------------------------------ 0468 //! First operation in the pipeline 0469 //------------------------------------------------------------------------ 0470 std::unique_ptr<Operation<true>> operation; 0471 0472 //------------------------------------------------------------------------ 0473 //! The future result of the pipeline 0474 //------------------------------------------------------------------------ 0475 std::future<XRootDStatus> ftr; 0476 0477 }; 0478 0479 //---------------------------------------------------------------------------- 0480 //! Helper function, schedules execution of given pipeline 0481 //! 0482 //! @param pipeline : the pipeline to be executed 0483 //! @param timeout : the pipeline timeout 0484 //! 0485 //! @return : future status of the operation 0486 //---------------------------------------------------------------------------- 0487 inline std::future<XRootDStatus> Async( Pipeline pipeline, uint16_t timeout = 0 ) 0488 { 0489 pipeline.Run( timeout ); 0490 return std::move( pipeline.ftr ); 0491 } 0492 0493 //---------------------------------------------------------------------------- 0494 //! Helper function, schedules execution of given pipeline and waits for 0495 //! the status 0496 //! 0497 //! @param pipeline : the pipeline to be executed 0498 //! @param timeout : the pipeline timeout 0499 //! 0500 //! @return : status of the operation 0501 //---------------------------------------------------------------------------- 0502 inline XRootDStatus WaitFor( Pipeline pipeline, uint16_t timeout = 0 ) 0503 { 0504 return Async( std::move( pipeline ), timeout ).get(); 0505 } 0506 0507 //---------------------------------------------------------------------------- 0508 //! Concrete Operation template 0509 //! Defines | and >> operator as well as operation arguments. 0510 //! 0511 //! @arg Derived : the class that derives from this template (CRTP) 0512 //! @arg HasHndl : true if operation has a handler, false otherwise 0513 //! @arg Args : operation arguments 0514 //---------------------------------------------------------------------------- 0515 template<template<bool> class Derived, bool HasHndl, typename HdlrFactory, typename ... Args> 0516 class ConcreteOperation: public Operation<HasHndl> 0517 { 0518 template<template<bool> class, bool, typename, typename ...> 0519 friend class ConcreteOperation; 0520 0521 public: 0522 0523 //------------------------------------------------------------------------ 0524 //! Constructor 0525 //! 0526 //! @param args : operation arguments 0527 //------------------------------------------------------------------------ 0528 ConcreteOperation( Args&&... args ) : args( std::tuple<Args...>( std::move( args )... ) ), 0529 timeout( 0 ) 0530 { 0531 static_assert( !HasHndl, "It is only possible to construct operation without handler" ); 0532 } 0533 0534 //------------------------------------------------------------------------ 0535 //! Move constructor from other states 0536 //! 0537 //! @arg from : state from which the object is being converted 0538 //! 0539 //! @param op : the object that is being converted 0540 //------------------------------------------------------------------------ 0541 template<bool from> 0542 ConcreteOperation( ConcreteOperation<Derived, from, HdlrFactory, Args...> && op ) : 0543 Operation<HasHndl>( std::move( op ) ), args( std::move( op.args ) ), timeout( 0 ) 0544 { 0545 } 0546 0547 //------------------------------------------------------------------------ 0548 //! Adds ResponseHandler/function/functor/lambda/future handler for 0549 //! the operation. 0550 //! 0551 //! Note: due to reference collapsing this covers both l-value and 0552 //! r-value references. 0553 //! 0554 //! @param hdlr : function/functor/lambda 0555 //------------------------------------------------------------------------ 0556 template<typename Hdlr> 0557 Derived<true> operator>>( Hdlr &&hdlr ) 0558 { 0559 return this->StreamImpl( HdlrFactory::Create( hdlr ) ); 0560 } 0561 0562 //------------------------------------------------------------------------ 0563 //! Creates a pipeline of 2 or more operations 0564 //! 0565 //! @param op : operation to add 0566 //! 0567 //! @return : handled operation 0568 //------------------------------------------------------------------------ 0569 Derived<true> operator|( Operation<true> &op ) 0570 { 0571 return PipeImpl( *this, op ); 0572 } 0573 0574 //------------------------------------------------------------------------ 0575 //! Creates a pipeline of 2 or more operations 0576 //! 0577 //! @param op : operation to add 0578 //! 0579 //! @return : handled operation 0580 //------------------------------------------------------------------------ 0581 Derived<true> operator|( Operation<true> &&op ) 0582 { 0583 return PipeImpl( *this, op ); 0584 } 0585 0586 //------------------------------------------------------------------------ 0587 //! Creates a pipeline of 2 or more operations 0588 //! 0589 //! @param op operation to add 0590 //! 0591 //! @return handled operation 0592 //------------------------------------------------------------------------ 0593 Derived<true> operator|( Operation<false> &op ) 0594 { 0595 return PipeImpl( *this, op ); 0596 } 0597 0598 //------------------------------------------------------------------------ 0599 //! Creates a pipeline of 2 or more operations 0600 //! 0601 //! @param op : operation to add 0602 //! 0603 //! @return : handled operation 0604 //------------------------------------------------------------------------ 0605 Derived<true> operator|( Operation<false> &&op ) 0606 { 0607 return PipeImpl( *this, op ); 0608 } 0609 0610 //------------------------------------------------------------------------ 0611 //! Adds a final operation to the pipeline 0612 //------------------------------------------------------------------------ 0613 Derived<true> operator|( FinalOperation &&fo ) 0614 { 0615 AllocHandler( *this ); 0616 this->handler->Assign( fo.final ); 0617 return this->template Transform<true>(); 0618 } 0619 0620 //------------------------------------------------------------------------ 0621 //! Move current object into newly allocated instance 0622 //! 0623 //! @return : the new instance 0624 //------------------------------------------------------------------------ 0625 inline Operation<HasHndl>* Move() 0626 { 0627 Derived<HasHndl> *me = static_cast<Derived<HasHndl>*>( this ); 0628 return new Derived<HasHndl>( std::move( *me ) ); 0629 } 0630 0631 //------------------------------------------------------------------------ 0632 //! Transform operation to handled 0633 //! 0634 //! @return Operation<true>& 0635 //------------------------------------------------------------------------ 0636 inline Operation<true>* ToHandled() 0637 { 0638 this->handler.reset( new PipelineHandler() ); 0639 Derived<HasHndl> *me = static_cast<Derived<HasHndl>*>( this ); 0640 return new Derived<true>( std::move( *me ) ); 0641 } 0642 0643 //------------------------------------------------------------------------ 0644 //! Set operation timeout 0645 //------------------------------------------------------------------------ 0646 Derived<HasHndl> Timeout( uint16_t timeout ) 0647 { 0648 this->timeout = timeout; 0649 Derived<HasHndl> *me = static_cast<Derived<HasHndl>*>( this ); 0650 return std::move( *me ); 0651 } 0652 0653 protected: 0654 0655 //------------------------------------------------------------------------ 0656 //! Transform into a new instance with desired state 0657 //! 0658 //! @return : new instance in the desired state 0659 //------------------------------------------------------------------------ 0660 template<bool to> 0661 inline Derived<to> Transform() 0662 { 0663 Derived<HasHndl> *me = static_cast<Derived<HasHndl>*>( this ); 0664 return Derived<to>( std::move( *me ) ); 0665 } 0666 0667 //------------------------------------------------------------------------ 0668 //! Implements operator>> functionality 0669 //! 0670 //! @param handler : handler to be added 0671 //! 0672 //! @return : return an instance of Derived<true> 0673 //------------------------------------------------------------------------ 0674 inline Derived<true> StreamImpl( ResponseHandler *handler ) 0675 { 0676 static_assert( !HasHndl, "Operator >> is available only for operation without handler" ); 0677 this->handler.reset( new PipelineHandler( handler ) ); 0678 return Transform<true>(); 0679 } 0680 0681 //------------------------------------------------------------------------ 0682 // Allocate handler if necessary 0683 //------------------------------------------------------------------------ 0684 inline static 0685 void AllocHandler( ConcreteOperation<Derived, true, HdlrFactory, Args...> &me ) 0686 { 0687 // nothing to do 0688 } 0689 0690 //------------------------------------------------------------------------ 0691 // Allocate handler if necessary 0692 //------------------------------------------------------------------------ 0693 inline static 0694 void AllocHandler( ConcreteOperation<Derived, false, HdlrFactory, Args...> &me ) 0695 { 0696 me.handler.reset( new PipelineHandler() ); 0697 } 0698 0699 //------------------------------------------------------------------------ 0700 //! Implements operator| functionality 0701 //! 0702 //! @param me : reference to myself (*this) 0703 //! @param op : reference to the other operation 0704 //! 0705 //! @return : move-copy of myself 0706 //------------------------------------------------------------------------ 0707 inline static 0708 Derived<true> PipeImpl( ConcreteOperation<Derived, HasHndl, HdlrFactory, 0709 Args...> &me, Operation<true> &op ) 0710 { 0711 AllocHandler( me ); // if HasHndl is false allocate handler 0712 me.AddOperation( op.Move() ); 0713 return me.template Transform<true>(); 0714 } 0715 0716 //------------------------------------------------------------------------ 0717 //! Implements operator| functionality 0718 //! 0719 //! @param me : reference to myself (*this) 0720 //! @param op : reference to the other operation 0721 //! 0722 //! @return : move-copy of myself 0723 //------------------------------------------------------------------------ 0724 inline static 0725 Derived<true> PipeImpl( ConcreteOperation<Derived, HasHndl, HdlrFactory, 0726 Args...> &me, Operation<false> &op ) 0727 { 0728 AllocHandler( me ); // if HasHndl is false allocate handler 0729 me.AddOperation( op.ToHandled() ); 0730 return me.template Transform<true>(); 0731 } 0732 0733 //------------------------------------------------------------------------ 0734 //! Operation arguments 0735 //------------------------------------------------------------------------ 0736 std::tuple<Args...> args; 0737 0738 //------------------------------------------------------------------------ 0739 //! Operation timeout 0740 //------------------------------------------------------------------------ 0741 uint16_t timeout; 0742 }; 0743 0744 // Out-of-line methods for class Operation 0745 0746 template <bool HasHndl> 0747 void Operation<HasHndl>::Run(Timeout timeout, std::promise<XRootDStatus> prms, 0748 std::function<void(const XRootDStatus &)> f) 0749 { 0750 static_assert(HasHndl, "Only an operation that has a handler can be assigned to workflow"); 0751 0752 XRootDStatus st; 0753 handler->Assign(timeout, std::move(prms), std::move(f), this); 0754 PipelineHandler *h = handler.release(); 0755 0756 try { 0757 st = RunImpl(h, timeout); 0758 } catch (const operation_expired &ex) { 0759 st = XRootDStatus(stError, errOperationExpired); 0760 } catch (const PipelineException &ex) { // probably not needed 0761 st = ex.GetError(); 0762 } catch (const std::exception &ex) { 0763 st = XRootDStatus(stError, errInternal, 0, ex.what()); 0764 } 0765 0766 if (!st.IsOK()) { 0767 ResponseJob *job = new ResponseJob(h, new XRootDStatus(st), 0, nullptr); 0768 DefaultEnv::GetPostMaster()->GetJobManager()->QueueJob(job); 0769 } 0770 } 0771 0772 template <bool HasHndl> 0773 void Operation<HasHndl>::AddOperation(Operation<true> *op) 0774 { 0775 if (handler) 0776 handler->AddOperation(op); 0777 } 0778 } 0779 0780 #endif // __XRD_CL_OPERATIONS_HH__
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|