00001 //------------------------------------------------------------------------------ 00002 // Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN) 00003 // Author: Krzysztof Jamrog <krzysztof.piotr.jamrog@cern.ch>, 00004 // Michal Simon <michal.simon@cern.ch> 00005 //------------------------------------------------------------------------------ 00006 // This file is part of the XRootD software suite. 00007 // 00008 // XRootD is free software: you can redistribute it and/or modify 00009 // it under the terms of the GNU Lesser General Public License as published by 00010 // the Free Software Foundation, either version 3 of the License, or 00011 // (at your option) any later version. 00012 // 00013 // XRootD is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Lesser General Public License 00019 // along with XRootD. If not, see <http://www.gnu.org/licenses/>. 00020 // 00021 // In applying this licence, CERN does not waive the privileges and immunities 00022 // granted to it by virtue of its status as an Intergovernmental Organization 00023 // or submit itself to any jurisdiction. 00024 //------------------------------------------------------------------------------ 00025 00026 #ifndef __XRD_CL_OPERATION_HANDLERS_HH__ 00027 #define __XRD_CL_OPERATION_HANDLERS_HH__ 00028 00029 #include "XrdCl/XrdClFile.hh" 00030 00031 #include<functional> 00032 #include<future> 00033 #include <atomic> 00034 00035 namespace XrdCl 00036 { 00037 //---------------------------------------------------------------------------- 00039 //---------------------------------------------------------------------------- 00040 class UnpackXAttrStatus : public ResponseHandler 00041 { 00042 public: 00043 00044 UnpackXAttrStatus( ResponseHandler *handler ) : handler( handler ) 00045 { 00046 } 00047 00048 //------------------------------------------------------------------------ 00050 //------------------------------------------------------------------------ 00051 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00052 { 00053 // status maybe error for old servers not supporting xattrs 00054 if( !status->IsOK() ) 00055 { 00056 handler->HandleResponse( status, nullptr ); 00057 return; 00058 } 00059 00060 std::vector<XAttrStatus> *bulk = nullptr; 00061 response->Get( bulk ); 00062 *status = bulk->front().status; 00063 handler->HandleResponse( status, nullptr ); 00064 delete response; 00065 delete this; 00066 } 00067 00068 private: 00069 00070 ResponseHandler *handler; 00071 }; 00072 00073 //---------------------------------------------------------------------------- 00075 //---------------------------------------------------------------------------- 00076 class UnpackXAttr : public ResponseHandler 00077 { 00078 public: 00079 00080 UnpackXAttr( ResponseHandler *handler ) : handler( handler ) 00081 { 00082 } 00083 00084 //------------------------------------------------------------------------ 00086 //------------------------------------------------------------------------ 00087 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00088 { 00089 // status is always OK for bulk response 00090 00091 std::vector<XAttr> *bulk = nullptr; 00092 response->Get( bulk ); 00093 *status = bulk->front().status; 00094 std::string *rsp = new std::string( std::move( bulk->front().value ) ); 00095 delete bulk; 00096 response->Set( rsp ); 00097 handler->HandleResponse( status, response ); 00098 delete this; 00099 } 00100 00101 private: 00102 00103 ResponseHandler *handler; 00104 }; 00105 00106 //---------------------------------------------------------------------------- 00107 // Helper class for creating null references for particular types 00108 // 00109 // @arg Response : type for which we need a null reference 00110 //---------------------------------------------------------------------------- 00111 template<typename Response> 00112 struct NullRef 00113 { 00114 static Response value; 00115 }; 00116 00117 //---------------------------------------------------------------------------- 00118 // Initialize the 'null-reference' 00119 //---------------------------------------------------------------------------- 00120 template<typename Response> 00121 Response NullRef<Response>::value; 00122 00123 //---------------------------------------------------------------------------- 00128 //---------------------------------------------------------------------------- 00129 template<typename Response> 00130 inline Response* GetResponse( AnyObject *rsp ) 00131 { 00132 Response *ret = nullptr; 00133 rsp->Get( ret ); 00134 return ret; 00135 } 00136 00137 //---------------------------------------------------------------------------- 00143 //---------------------------------------------------------------------------- 00144 template<typename Response> 00145 inline Response* GetResponse( XRootDStatus *status, AnyObject *rsp ) 00146 { 00147 if( !status->IsOK() ) return &NullRef<Response>::value; 00148 return GetResponse<Response>( rsp ); 00149 } 00150 00151 //---------------------------------------------------------------------------- 00155 //---------------------------------------------------------------------------- 00156 template<typename Response> 00157 class FunctionWrapper: public ResponseHandler 00158 { 00159 public: 00160 00161 //------------------------------------------------------------------------ 00163 // 00165 //------------------------------------------------------------------------ 00166 FunctionWrapper( 00167 std::function<void( XRootDStatus&, Response& )> handleFunction ) : 00168 fun( handleFunction ) 00169 { 00170 } 00171 00172 //------------------------------------------------------------------------ 00174 //------------------------------------------------------------------------ 00175 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00176 { 00177 Response *res = GetResponse<Response>( status, response ); 00178 fun( *status, *res ); 00179 delete status; 00180 delete response; 00181 delete this; 00182 } 00183 00184 private: 00185 //------------------------------------------------------------------------ 00187 //------------------------------------------------------------------------ 00188 std::function<void( XRootDStatus&, Response& )> fun; 00189 }; 00190 00191 //---------------------------------------------------------------------------- 00195 //---------------------------------------------------------------------------- 00196 template<> 00197 class FunctionWrapper<void> : public ResponseHandler 00198 { 00199 public: 00200 00201 //------------------------------------------------------------------------ 00203 // 00205 //------------------------------------------------------------------------ 00206 FunctionWrapper( 00207 std::function<void( XRootDStatus& )> handleFunction ) : 00208 fun( handleFunction ) 00209 { 00210 } 00211 00212 //------------------------------------------------------------------------ 00214 //------------------------------------------------------------------------ 00215 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00216 { 00217 fun( *status ); 00218 delete status; 00219 delete response; 00220 delete this; 00221 } 00222 00223 private: 00224 //------------------------------------------------------------------------ 00226 //------------------------------------------------------------------------ 00227 std::function<void( XRootDStatus& )> fun; 00228 }; 00229 00230 //---------------------------------------------------------------------------- 00235 //---------------------------------------------------------------------------- 00236 template<typename Response, typename Return> 00237 class TaskWrapper: public ResponseHandler 00238 { 00239 public: 00240 00241 //------------------------------------------------------------------------ 00243 // 00245 //------------------------------------------------------------------------ 00246 TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) : 00247 task( std::move( task ) ) 00248 { 00249 } 00250 00251 //------------------------------------------------------------------------ 00253 //------------------------------------------------------------------------ 00254 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00255 { 00256 Response *resp = GetResponse<Response>( status, response ); 00257 task( *status, *resp ); 00258 delete status; 00259 delete response; 00260 delete this; 00261 } 00262 00263 private: 00264 00265 //------------------------------------------------------------------------ 00267 //------------------------------------------------------------------------ 00268 std::packaged_task<Return( XRootDStatus&, Response& )> task; 00269 }; 00270 00271 //---------------------------------------------------------------------------- 00277 //---------------------------------------------------------------------------- 00278 template<typename Return> 00279 class TaskWrapper<void, Return>: public ResponseHandler 00280 { 00281 public: 00282 00283 //------------------------------------------------------------------------ 00285 // 00287 //------------------------------------------------------------------------ 00288 TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) : 00289 task( std::move( task ) ) 00290 { 00291 } 00292 00293 //------------------------------------------------------------------------ 00295 //------------------------------------------------------------------------ 00296 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00297 { 00298 task( *status ); 00299 delete status; 00300 delete response; 00301 delete this; 00302 } 00303 00304 private: 00305 00306 //------------------------------------------------------------------------ 00308 //------------------------------------------------------------------------ 00309 std::packaged_task<Return( XRootDStatus& )> task; 00310 }; 00311 00312 00313 //---------------------------------------------------------------------------- 00315 //---------------------------------------------------------------------------- 00316 class ExOpenFuncWrapper: public ResponseHandler 00317 { 00318 public: 00319 00320 //------------------------------------------------------------------------ 00322 // 00324 //------------------------------------------------------------------------ 00325 ExOpenFuncWrapper( File &f, 00326 std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) : 00327 f( f ), fun( handleFunction ) 00328 { 00329 } 00330 00331 //------------------------------------------------------------------------ 00333 //------------------------------------------------------------------------ 00334 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00335 { 00336 StatInfo *info = nullptr; 00337 if( status->IsOK() ) 00338 XRootDStatus st = f.Stat( false, info ); 00339 else 00340 info = &NullRef<StatInfo>::value; 00341 fun( *status, *info ); 00342 if( info != &NullRef<StatInfo>::value ) delete info; 00343 delete status; 00344 delete response; 00345 delete this; 00346 } 00347 00348 private: 00349 File &f; 00350 //------------------------------------------------------------------------ 00352 //------------------------------------------------------------------------ 00353 std::function<void( XRootDStatus&, StatInfo& )> fun; 00354 }; 00355 00356 //---------------------------------------------------------------------------- 00358 //---------------------------------------------------------------------------- 00359 class PipelineException : public std::exception 00360 { 00361 public: 00362 00363 //------------------------------------------------------------------------ 00365 //------------------------------------------------------------------------ 00366 PipelineException( const XRootDStatus &error ) : error( error ) 00367 { 00368 00369 } 00370 00371 //------------------------------------------------------------------------ 00373 //------------------------------------------------------------------------ 00374 PipelineException( const PipelineException &ex ) : error( ex.error ) 00375 { 00376 00377 } 00378 00379 //------------------------------------------------------------------------ 00381 //------------------------------------------------------------------------ 00382 PipelineException& operator=( const PipelineException &ex ) 00383 { 00384 error = ex.error; 00385 return *this; 00386 } 00387 00388 //------------------------------------------------------------------------ 00390 //------------------------------------------------------------------------ 00391 const char* what() const noexcept 00392 { 00393 return error.ToString().c_str(); 00394 } 00395 00396 //------------------------------------------------------------------------ 00398 //------------------------------------------------------------------------ 00399 const XRootDStatus& GetError() const 00400 { 00401 return error; 00402 } 00403 00404 private: 00405 00406 //------------------------------------------------------------------------ 00408 //------------------------------------------------------------------------ 00409 XRootDStatus error; 00410 }; 00411 00412 //---------------------------------------------------------------------------- 00416 //---------------------------------------------------------------------------- 00417 template<typename Response> 00418 class FutureWrapperBase : public ResponseHandler 00419 { 00420 public: 00421 00422 //------------------------------------------------------------------------ 00427 //------------------------------------------------------------------------ 00428 FutureWrapperBase( std::future<Response> &ftr ) 00429 { 00430 ftr = prms.get_future(); 00431 } 00432 00433 protected: 00434 00435 //------------------------------------------------------------------------ 00439 //------------------------------------------------------------------------ 00440 void SetException( const XRootDStatus &err ) 00441 { 00442 std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) ); 00443 prms.set_exception( ex ); 00444 } 00445 00446 //------------------------------------------------------------------------ 00448 //------------------------------------------------------------------------ 00449 std::promise<Response> prms; 00450 }; 00451 00452 //---------------------------------------------------------------------------- 00456 //---------------------------------------------------------------------------- 00457 template<typename Response> 00458 class FutureWrapper : public FutureWrapperBase<Response> 00459 { 00460 public: 00461 00462 //------------------------------------------------------------------------ 00466 //------------------------------------------------------------------------ 00467 FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr ) 00468 { 00469 00470 } 00471 00472 //------------------------------------------------------------------------ 00474 //------------------------------------------------------------------------ 00475 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00476 { 00477 if( status->IsOK() ) 00478 { 00479 Response *resp = GetResponse<Response>( response ); 00480 if( resp == &NullRef<Response>::value ) 00481 this->SetException( XRootDStatus( stError, errInternal ) ); 00482 else 00483 this->prms.set_value( std::move( *resp ) ); 00484 } 00485 else 00486 this->SetException( *status ); 00487 00488 delete status; 00489 delete response; 00490 delete this; 00491 } 00492 }; 00493 00494 //---------------------------------------------------------------------------- 00496 //---------------------------------------------------------------------------- 00497 template<> 00498 class FutureWrapper<void> : public FutureWrapperBase<void> 00499 { 00500 public: 00501 00502 //------------------------------------------------------------------------ 00506 //------------------------------------------------------------------------ 00507 FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr ) 00508 { 00509 00510 } 00511 00512 //------------------------------------------------------------------------ 00514 //------------------------------------------------------------------------ 00515 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00516 { 00517 if( status->IsOK() ) 00518 { 00519 prms.set_value(); 00520 } 00521 else 00522 SetException( *status ); 00523 00524 delete status; 00525 delete response; 00526 delete this; 00527 } 00528 }; 00529 00530 00531 //---------------------------------------------------------------------------- 00536 //---------------------------------------------------------------------------- 00537 class FinalizeHandler : public ResponseHandler 00538 { 00539 public: 00540 00541 //------------------------------------------------------------------------ 00545 //------------------------------------------------------------------------ 00546 FinalizeHandler( ResponseHandler *handler ) : handler( handler ) 00547 { 00548 00549 } 00550 00551 //------------------------------------------------------------------------ 00553 //------------------------------------------------------------------------ 00554 virtual ~FinalizeHandler() 00555 { 00556 ResponseHandler* hdlr = handler.exchange( nullptr ); 00557 if( hdlr ) 00558 hdlr->HandleResponseWithHosts( new XRootDStatus( stError, errPipelineFailed), nullptr, nullptr ); 00559 } 00560 00561 //------------------------------------------------------------------------ 00566 //------------------------------------------------------------------------ 00567 virtual void HandleResponseWithHosts( XRootDStatus *status, 00568 AnyObject *response, 00569 HostList *hostList ) 00570 { 00571 ResponseHandler* hdlr = handler.exchange( nullptr ); 00572 if( hdlr ) 00573 hdlr->HandleResponseWithHosts( status, response, hostList ); 00574 } 00575 00576 private: 00577 00578 //------------------------------------------------------------------------ 00580 //------------------------------------------------------------------------ 00581 std::atomic<ResponseHandler*> handler; 00582 }; 00583 00584 //---------------------------------------------------------------------------- 00590 //---------------------------------------------------------------------------- 00591 inline FinalizeHandler* make_finalized( ResponseHandler *handler ) 00592 { 00593 return new FinalizeHandler( handler ); 00594 } 00595 00596 00597 //---------------------------------------------------------------------------- 00602 //---------------------------------------------------------------------------- 00603 template<typename Response> 00604 struct RespBase 00605 { 00606 //------------------------------------------------------------------------ 00611 //------------------------------------------------------------------------ 00612 inline static ResponseHandler* Create( ResponseHandler *hdlr ) 00613 { 00614 return make_finalized( hdlr ); 00615 } 00616 00617 //------------------------------------------------------------------------ 00622 //------------------------------------------------------------------------ 00623 inline static ResponseHandler* Create( ResponseHandler &hdlr ) 00624 { 00625 return make_finalized( &hdlr ); 00626 } 00627 00628 //------------------------------------------------------------------------ 00633 //------------------------------------------------------------------------ 00634 inline static ResponseHandler* Create( std::future<Response> &ftr ) 00635 { 00636 return make_finalized( new FutureWrapper<Response>( ftr ) ); 00637 } 00638 }; 00639 00640 //---------------------------------------------------------------------------- 00645 //---------------------------------------------------------------------------- 00646 template<typename Response> 00647 struct Resp: RespBase<Response> 00648 { 00649 //------------------------------------------------------------------------ 00654 //------------------------------------------------------------------------ 00655 inline static ResponseHandler* Create( std::function<void( XRootDStatus&, 00656 Response& )> func ) 00657 { 00658 return make_finalized( new FunctionWrapper<Response>( func ) ); 00659 } 00660 00661 //------------------------------------------------------------------------ 00666 //------------------------------------------------------------------------ 00667 template<typename Return> 00668 inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&, 00669 Response& )> &task ) 00670 { 00671 return make_finalized( new TaskWrapper<Response, Return>( std::move( task ) ) ); 00672 } 00673 00674 //------------------------------------------------------------------------ 00676 //------------------------------------------------------------------------ 00677 using RespBase<Response>::Create; 00678 }; 00679 00680 //---------------------------------------------------------------------------- 00684 //---------------------------------------------------------------------------- 00685 template<> 00686 struct Resp<void>: RespBase<void> 00687 { 00688 //------------------------------------------------------------------------ 00693 //------------------------------------------------------------------------ 00694 inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func ) 00695 { 00696 return make_finalized( new FunctionWrapper<void>( func ) ); 00697 } 00698 00699 //------------------------------------------------------------------------ 00704 //------------------------------------------------------------------------ 00705 template<typename Return> 00706 inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task ) 00707 { 00708 return make_finalized( new TaskWrapper<void, Return>( std::move( task ) ) ); 00709 } 00710 00711 //------------------------------------------------------------------------ 00713 //------------------------------------------------------------------------ 00714 using RespBase<void>::Create; 00715 }; 00716 } 00717 00718 #endif // __XRD_CL_OPERATIONS_HANDLERS_HH__