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 namespace XrdCl 00032 { 00033 //---------------------------------------------------------------------------- 00038 //---------------------------------------------------------------------------- 00039 template<typename Hdlr> 00040 struct IsResponseHandler 00041 { 00042 //------------------------------------------------------------------------ 00045 //------------------------------------------------------------------------ 00046 static constexpr bool value = std::is_base_of<XrdCl::ResponseHandler, Hdlr>::value; 00047 }; 00048 00049 //---------------------------------------------------------------------------- 00054 //---------------------------------------------------------------------------- 00055 template<typename Hdlr> 00056 struct IsResponseHandler<Hdlr*> 00057 { 00058 //------------------------------------------------------------------------ 00061 //------------------------------------------------------------------------ 00062 static constexpr bool value = std::is_base_of<XrdCl::ResponseHandler, Hdlr>::value; 00063 }; 00064 00065 //---------------------------------------------------------------------------- 00067 //---------------------------------------------------------------------------- 00068 class SimpleFunctionWrapper: public ResponseHandler 00069 { 00070 public: 00071 00072 //------------------------------------------------------------------------ 00074 // 00076 //------------------------------------------------------------------------ 00077 SimpleFunctionWrapper( 00078 std::function<void( XRootDStatus& )> handleFunction ) : 00079 fun( handleFunction ) 00080 { 00081 } 00082 00083 //------------------------------------------------------------------------ 00085 //------------------------------------------------------------------------ 00086 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00087 { 00088 fun( *status ); 00089 delete status; 00090 delete response; 00091 delete this; 00092 } 00093 00094 private: 00095 //------------------------------------------------------------------------ 00097 //------------------------------------------------------------------------ 00098 std::function<void( XRootDStatus& )> fun; 00099 }; 00100 00101 //---------------------------------------------------------------------------- 00105 //---------------------------------------------------------------------------- 00106 template<typename ResponseType> 00107 class FunctionWrapper: public ResponseHandler 00108 { 00109 public: 00110 00111 //------------------------------------------------------------------------ 00113 // 00115 //------------------------------------------------------------------------ 00116 FunctionWrapper( 00117 std::function<void( XRootDStatus&, ResponseType& )> handleFunction ) : 00118 fun( handleFunction ) 00119 { 00120 } 00121 00122 //------------------------------------------------------------------------ 00124 //------------------------------------------------------------------------ 00125 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00126 { 00127 ResponseType *res = nullptr; 00128 if( status->IsOK() ) 00129 response->Get( res ); 00130 else 00131 res = &nullref; 00132 fun( *status, *res ); 00133 delete status; 00134 delete response; 00135 delete this; 00136 } 00137 00138 private: 00139 //------------------------------------------------------------------------ 00141 //------------------------------------------------------------------------ 00142 std::function<void( XRootDStatus&, ResponseType& )> fun; 00143 00144 //------------------------------------------------------------------------ 00146 //------------------------------------------------------------------------ 00147 static ResponseType nullref; 00148 }; 00149 00150 //---------------------------------------------------------------------------- 00151 // Initialize the 'null-reference' 00152 //---------------------------------------------------------------------------- 00153 template<typename ResponseType> 00154 ResponseType FunctionWrapper<ResponseType>::nullref; 00155 00156 00157 //---------------------------------------------------------------------------- 00162 //---------------------------------------------------------------------------- 00163 template<typename Response, typename Return> 00164 class TaskWrapper: public ResponseHandler 00165 { 00166 public: 00167 00168 //------------------------------------------------------------------------ 00170 // 00172 //------------------------------------------------------------------------ 00173 TaskWrapper( std::packaged_task<Return( XRootDStatus&, Response& )> && task ) : 00174 task( std::move( task ) ) 00175 { 00176 } 00177 00178 //------------------------------------------------------------------------ 00180 //------------------------------------------------------------------------ 00181 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00182 { 00183 Response *resp = nullptr; 00184 if( status->IsOK() ) 00185 response->Get( resp ); 00186 else 00187 resp = &nullref; 00188 task( *status, *resp ); 00189 delete status; 00190 delete response; 00191 delete this; 00192 } 00193 00194 private: 00195 00196 //------------------------------------------------------------------------ 00198 //------------------------------------------------------------------------ 00199 std::packaged_task<Return( XRootDStatus&, Response& )> task; 00200 00201 //------------------------------------------------------------------------ 00203 //------------------------------------------------------------------------ 00204 static Response nullref; 00205 }; 00206 00207 //---------------------------------------------------------------------------- 00208 // Initialize the 'null-reference' 00209 //---------------------------------------------------------------------------- 00210 template<typename Response, typename Return> 00211 Response TaskWrapper<Response, Return>::nullref; 00212 00213 //---------------------------------------------------------------------------- 00219 //---------------------------------------------------------------------------- 00220 template<typename Return> 00221 class TaskWrapper<void, Return> 00222 { 00223 public: 00224 00225 //------------------------------------------------------------------------ 00227 // 00229 //------------------------------------------------------------------------ 00230 TaskWrapper( std::packaged_task<Return( XRootDStatus& )> && task ) : 00231 task( std::move( task ) ) 00232 { 00233 } 00234 00235 //------------------------------------------------------------------------ 00237 //------------------------------------------------------------------------ 00238 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00239 { 00240 task( *status ); 00241 delete status; 00242 delete response; 00243 delete this; 00244 } 00245 00246 private: 00247 00248 //------------------------------------------------------------------------ 00250 //------------------------------------------------------------------------ 00251 std::packaged_task<Return( XRootDStatus& )> task; 00252 }; 00253 00254 00255 //---------------------------------------------------------------------------- 00257 //---------------------------------------------------------------------------- 00258 class ExOpenFuncWrapper: public ResponseHandler 00259 { 00260 public: 00261 00262 //------------------------------------------------------------------------ 00264 // 00266 //------------------------------------------------------------------------ 00267 ExOpenFuncWrapper( File &f, 00268 std::function<void( XRootDStatus&, StatInfo& )> handleFunction ) : 00269 f( f ), fun( handleFunction ) 00270 { 00271 } 00272 00273 //------------------------------------------------------------------------ 00275 //------------------------------------------------------------------------ 00276 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00277 { 00278 StatInfo *info = nullptr; 00279 if( status->IsOK() ) 00280 XRootDStatus st = f.Stat( false, info ); 00281 else 00282 info = &nullref; 00283 fun( *status, *info ); 00284 if( info != &nullref ) delete info; 00285 delete status; 00286 delete response; 00287 delete this; 00288 } 00289 00290 private: 00291 File &f; 00292 //------------------------------------------------------------------------ 00294 //------------------------------------------------------------------------ 00295 std::function<void( XRootDStatus&, StatInfo& )> fun; 00296 00297 //------------------------------------------------------------------------ 00299 //------------------------------------------------------------------------ 00300 static StatInfo nullref; 00301 }; 00302 00303 //---------------------------------------------------------------------------- 00304 // Initialize the 'null-reference' 00305 //---------------------------------------------------------------------------- 00306 StatInfo ExOpenFuncWrapper::nullref; 00307 00308 //---------------------------------------------------------------------------- 00310 //---------------------------------------------------------------------------- 00311 class PipelineException : public std::exception 00312 { 00313 public: 00314 00315 //------------------------------------------------------------------------ 00317 //------------------------------------------------------------------------ 00318 PipelineException( const XRootDStatus &error ) : error( error ) 00319 { 00320 00321 } 00322 00323 //------------------------------------------------------------------------ 00325 //------------------------------------------------------------------------ 00326 PipelineException( const PipelineException &ex ) : error( ex.error ) 00327 { 00328 00329 } 00330 00331 //------------------------------------------------------------------------ 00333 //------------------------------------------------------------------------ 00334 PipelineException& operator=( const PipelineException &ex ) 00335 { 00336 error = ex.error; 00337 return *this; 00338 } 00339 00340 //------------------------------------------------------------------------ 00342 //------------------------------------------------------------------------ 00343 const char* what() const noexcept 00344 { 00345 return error.ToString().c_str(); 00346 } 00347 00348 //------------------------------------------------------------------------ 00350 //------------------------------------------------------------------------ 00351 const XRootDStatus& GetError() const 00352 { 00353 return error; 00354 } 00355 00356 private: 00357 00358 //------------------------------------------------------------------------ 00360 //------------------------------------------------------------------------ 00361 XRootDStatus error; 00362 }; 00363 00364 //---------------------------------------------------------------------------- 00368 //---------------------------------------------------------------------------- 00369 template<typename Response> 00370 class FutureWrapperBase : public ResponseHandler 00371 { 00372 public: 00373 00374 //------------------------------------------------------------------------ 00379 //------------------------------------------------------------------------ 00380 FutureWrapperBase( std::future<Response> &ftr ) : called( false ) 00381 { 00382 ftr = prms.get_future(); 00383 } 00384 00385 //------------------------------------------------------------------------ 00389 //------------------------------------------------------------------------ 00390 ~FutureWrapperBase() 00391 { 00392 if( !called ) 00393 this->SetException( XRootDStatus( stError, errPipelineFailed ) ); 00394 } 00395 00396 protected: 00397 00398 //------------------------------------------------------------------------ 00402 //------------------------------------------------------------------------ 00403 void SetException( const XRootDStatus &err ) 00404 { 00405 std::exception_ptr ex = std::make_exception_ptr( PipelineException( err ) ); 00406 prms.set_exception( ex ); 00407 } 00408 00409 //------------------------------------------------------------------------ 00411 //------------------------------------------------------------------------ 00412 std::promise<Response> prms; 00413 00414 //------------------------------------------------------------------------ 00416 //------------------------------------------------------------------------ 00417 bool called; 00418 00419 }; 00420 00421 //---------------------------------------------------------------------------- 00425 //---------------------------------------------------------------------------- 00426 template<typename Response> 00427 class FutureWrapper : public FutureWrapperBase<Response> 00428 { 00429 public: 00430 00431 //------------------------------------------------------------------------ 00435 //------------------------------------------------------------------------ 00436 FutureWrapper( std::future<Response> &ftr ) : FutureWrapperBase<Response>( ftr ) 00437 { 00438 00439 } 00440 00441 //------------------------------------------------------------------------ 00443 //------------------------------------------------------------------------ 00444 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00445 { 00446 this->called = true; 00447 00448 if( status->IsOK() ) 00449 { 00450 Response *resp = 0; 00451 response->Get( resp ); 00452 this->prms.set_value( std::move( *resp ) ); 00453 } 00454 else 00455 this->SetException( *status ); 00456 00457 delete status; 00458 delete response; 00459 delete this; 00460 } 00461 }; 00462 00463 //---------------------------------------------------------------------------- 00465 //---------------------------------------------------------------------------- 00466 template<> 00467 class FutureWrapper<void> : public FutureWrapperBase<void> 00468 { 00469 public: 00470 00471 //------------------------------------------------------------------------ 00475 //------------------------------------------------------------------------ 00476 FutureWrapper( std::future<void> &ftr ) : FutureWrapperBase<void>( ftr ) 00477 { 00478 00479 } 00480 00481 //------------------------------------------------------------------------ 00483 //------------------------------------------------------------------------ 00484 void HandleResponse( XRootDStatus *status, AnyObject *response ) 00485 { 00486 this->called = true; 00487 00488 00489 if( status->IsOK() ) 00490 { 00491 prms.set_value(); 00492 } 00493 else 00494 SetException( *status ); 00495 00496 delete status; 00497 delete response; 00498 delete this; 00499 } 00500 }; 00501 00502 00503 //---------------------------------------------------------------------------- 00508 //---------------------------------------------------------------------------- 00509 template<typename Response> 00510 struct RespBase 00511 { 00512 //------------------------------------------------------------------------ 00517 //------------------------------------------------------------------------ 00518 inline static ResponseHandler* Create( ResponseHandler *hdlr ) 00519 { 00520 return hdlr; 00521 } 00522 00523 //------------------------------------------------------------------------ 00528 //------------------------------------------------------------------------ 00529 inline static ResponseHandler* Create( ResponseHandler &hdlr ) 00530 { 00531 return &hdlr; 00532 } 00533 00534 //------------------------------------------------------------------------ 00539 //------------------------------------------------------------------------ 00540 inline static ResponseHandler* Create( std::future<Response> &ftr ) 00541 { 00542 return new FutureWrapper<Response>( ftr ); 00543 } 00544 }; 00545 00546 //---------------------------------------------------------------------------- 00551 //---------------------------------------------------------------------------- 00552 template<typename Response> 00553 struct Resp: RespBase<Response> 00554 { 00555 //------------------------------------------------------------------------ 00560 //------------------------------------------------------------------------ 00561 inline static ResponseHandler* Create( std::function<void( XRootDStatus&, 00562 Response& )> func ) 00563 { 00564 return new FunctionWrapper<Response>( func ); 00565 } 00566 00567 //------------------------------------------------------------------------ 00572 //------------------------------------------------------------------------ 00573 template<typename Return> 00574 inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus&, 00575 Response& )> &task ) 00576 { 00577 return new TaskWrapper<Response, Return>( std::move( task ) ); 00578 } 00579 00580 //------------------------------------------------------------------------ 00582 //------------------------------------------------------------------------ 00583 using RespBase<Response>::Create; 00584 }; 00585 00586 //---------------------------------------------------------------------------- 00590 //---------------------------------------------------------------------------- 00591 template<> 00592 struct Resp<void>: RespBase<void> 00593 { 00594 //------------------------------------------------------------------------ 00599 //------------------------------------------------------------------------ 00600 inline static ResponseHandler* Create( std::function<void( XRootDStatus& )> func ) 00601 { 00602 return new SimpleFunctionWrapper( func ); 00603 } 00604 00605 //------------------------------------------------------------------------ 00610 //------------------------------------------------------------------------ 00611 template<typename Return> 00612 inline static ResponseHandler* Create( std::packaged_task<Return( XRootDStatus& )> &task ) 00613 { 00614 return new TaskWrapper<void, Return>( std::move( task ) ); 00615 } 00616 00617 //------------------------------------------------------------------------ 00619 //------------------------------------------------------------------------ 00620 using RespBase<void>::Create; 00621 }; 00622 } 00623 00624 #endif // __XRD_CL_OPERATIONS_HANDLERS_HH__