diff --git a/services/backup/docker-server/contents/server/src/Reactors/server/base-reactors/ServerWriteReactorBase.h b/services/backup/docker-server/contents/server/src/Reactors/server/base-reactors/ServerWriteReactorBase.h index e7ff9d291..92d855773 100644 --- a/services/backup/docker-server/contents/server/src/Reactors/server/base-reactors/ServerWriteReactorBase.h +++ b/services/backup/docker-server/contents/server/src/Reactors/server/base-reactors/ServerWriteReactorBase.h @@ -1,106 +1,108 @@ #pragma once #include #include #include #include #include namespace comm { namespace network { namespace reactor { template class ServerWriteReactorBase : public grpc::ServerWriteReactor { Response response; bool initialized = false; std::atomic finished = false; void terminate(grpc::Status status); protected: // this is a const ref since it's not meant to be modified const Request &request; grpc::Status status; public: ServerWriteReactorBase(const Request *request); virtual void NextWrite(); void OnDone() override; void OnWriteDone(bool ok) override; virtual std::unique_ptr writeResponse(Response *response) = 0; virtual void initialize(){}; + virtual void validate(){}; virtual void doneCallback(){}; virtual void terminateCallback(){}; }; template void ServerWriteReactorBase::terminate(grpc::Status status) { this->status = status; try { this->terminateCallback(); + this->validate(); } catch (std::runtime_error &e) { this->status = grpc::Status(grpc::StatusCode::INTERNAL, e.what()); } if (!this->status.ok()) { std::cout << "error: " << this->status.error_message() << std::endl; } if (this->finished) { return; } this->Finish(status); this->finished = true; } template ServerWriteReactorBase::ServerWriteReactorBase( const Request *request) : request(*request) { // we cannot call this->NextWrite() here because it's going to call it on // the base class, not derived leading to the runtime error of calling // a pure virtual function // NextWrite has to be exposed as a public function and called explicitly // to initialize writing } template void ServerWriteReactorBase::NextWrite() { try { if (!this->initialized) { this->initialize(); this->initialized = true; } this->response = Response(); std::unique_ptr status = this->writeResponse(&this->response); if (status != nullptr) { this->terminate(*status); return; } this->StartWrite(&this->response); } catch (std::runtime_error &e) { std::cout << "error: " << e.what() << std::endl; this->terminate(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); } } template void ServerWriteReactorBase::OnDone() { this->doneCallback(); delete this; } template void ServerWriteReactorBase::OnWriteDone(bool ok) { if (!ok) { this->terminate(grpc::Status(grpc::StatusCode::INTERNAL, "writing error")); return; } this->NextWrite(); } } // namespace reactor } // namespace network } // namespace comm diff --git a/services/blob/src/Reactors/server/base-reactors/ServerWriteReactorBase.h b/services/blob/src/Reactors/server/base-reactors/ServerWriteReactorBase.h index e7ff9d291..92d855773 100644 --- a/services/blob/src/Reactors/server/base-reactors/ServerWriteReactorBase.h +++ b/services/blob/src/Reactors/server/base-reactors/ServerWriteReactorBase.h @@ -1,106 +1,108 @@ #pragma once #include #include #include #include #include namespace comm { namespace network { namespace reactor { template class ServerWriteReactorBase : public grpc::ServerWriteReactor { Response response; bool initialized = false; std::atomic finished = false; void terminate(grpc::Status status); protected: // this is a const ref since it's not meant to be modified const Request &request; grpc::Status status; public: ServerWriteReactorBase(const Request *request); virtual void NextWrite(); void OnDone() override; void OnWriteDone(bool ok) override; virtual std::unique_ptr writeResponse(Response *response) = 0; virtual void initialize(){}; + virtual void validate(){}; virtual void doneCallback(){}; virtual void terminateCallback(){}; }; template void ServerWriteReactorBase::terminate(grpc::Status status) { this->status = status; try { this->terminateCallback(); + this->validate(); } catch (std::runtime_error &e) { this->status = grpc::Status(grpc::StatusCode::INTERNAL, e.what()); } if (!this->status.ok()) { std::cout << "error: " << this->status.error_message() << std::endl; } if (this->finished) { return; } this->Finish(status); this->finished = true; } template ServerWriteReactorBase::ServerWriteReactorBase( const Request *request) : request(*request) { // we cannot call this->NextWrite() here because it's going to call it on // the base class, not derived leading to the runtime error of calling // a pure virtual function // NextWrite has to be exposed as a public function and called explicitly // to initialize writing } template void ServerWriteReactorBase::NextWrite() { try { if (!this->initialized) { this->initialize(); this->initialized = true; } this->response = Response(); std::unique_ptr status = this->writeResponse(&this->response); if (status != nullptr) { this->terminate(*status); return; } this->StartWrite(&this->response); } catch (std::runtime_error &e) { std::cout << "error: " << e.what() << std::endl; this->terminate(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); } } template void ServerWriteReactorBase::OnDone() { this->doneCallback(); delete this; } template void ServerWriteReactorBase::OnWriteDone(bool ok) { if (!ok) { this->terminate(grpc::Status(grpc::StatusCode::INTERNAL, "writing error")); return; } this->NextWrite(); } } // namespace reactor } // namespace network } // namespace comm