| // Copyright 2011 The Goma Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| |
| #ifndef DEVTOOLS_GOMA_CLIENT_MULTI_HTTP_RPC_H_ |
| #define DEVTOOLS_GOMA_CLIENT_MULTI_HTTP_RPC_H_ |
| |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "basictypes.h" |
| #include "http_rpc.h" |
| #include "lockhelper.h" |
| |
| using std::string; |
| |
| namespace google { |
| namespace protobuf { |
| class Message; |
| } // namespace protobuf |
| } // namespace google |
| |
| namespace devtools_goma { |
| |
| class ExecReq; |
| class ExecResp; |
| class OneshotClosure; |
| class StoreFileReq; |
| class StoreFileResp; |
| class WorkerThreadManager; |
| |
| // MultiExecClient is an ExecService.Exec API service implementation that |
| // is realized by ExecService.MultiExec stub on top of HttpRPC. |
| // Client can use Exec() as single Exec API call, but MultiExecClient packs |
| // at most max_req_in_call into single MultiExec call to path over http_rpc. |
| // It also checks pending requests in each check_interval_ms, and if any |
| // pending Exec requests, it issues MultiExec call. |
| class MultiHttpRPC { |
| public: |
| struct Options { |
| Options(); |
| size_t max_req_in_call; |
| size_t req_size_threshold_in_call; |
| int check_interval_ms; |
| }; |
| |
| virtual ~MultiHttpRPC(); |
| |
| virtual void Call(HttpRPC::Status* http_rpc_stat, |
| const google::protobuf::Message* req, |
| google::protobuf::Message* resp, |
| OneshotClosure* callback); |
| |
| void Wait(); |
| |
| const Options& options() { return options_; } |
| bool available(); |
| |
| string DebugString() const; |
| |
| protected: |
| class MultiJob; |
| friend class MultiJob; |
| |
| MultiHttpRPC(HttpRPC* http_rpc, |
| string path, |
| string multi_path, |
| const Options& options, |
| WorkerThreadManager* wm); |
| |
| // Returns a key for pending multi job for the given req. |
| // req will be batched in same multi job if the key is the same. |
| // Returns "" by default (so no affinity). |
| virtual string MultiJobKey(const google::protobuf::Message* req); |
| |
| virtual void Setup(MultiJob* job) = 0; |
| virtual void Done(MultiJob* job, int i, HttpRPC::Status* stat, |
| google::protobuf::Message* resp) = 0; |
| |
| void CheckPending(); |
| void UnregisterCheckPending(PeriodicClosureId id); |
| void Disable(); |
| |
| void JobDone(); |
| |
| WorkerThreadManager* wm_; |
| HttpRPC* http_rpc_; |
| const string path_; |
| const string multi_path_; |
| const Options options_; |
| |
| PeriodicClosureId periodic_callback_id_; |
| |
| mutable Lock mu_; |
| // Condition to check num_multi_job_ becomes 0. |
| ConditionVariable cond_; |
| int num_multi_job_; // number of jobs on-the-fly. |
| |
| std::unordered_map<string, MultiJob*> pending_multi_jobs_; |
| bool available_; |
| std::vector<int> num_call_by_multi_; |
| int num_call_by_req_num_; |
| int num_call_by_req_size_; |
| int num_call_by_latency_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MultiHttpRPC); |
| }; |
| |
| class MultiFileStore : public MultiHttpRPC { |
| public: |
| MultiFileStore(HttpRPC* http_rpc, |
| const string& path, |
| const MultiHttpRPC::Options& options, |
| WorkerThreadManager* wm); |
| ~MultiFileStore() override; |
| |
| void StoreFile(HttpRPC::Status* http_rpc_stat, |
| const StoreFileReq* req, StoreFileResp* resp, |
| OneshotClosure* callback); |
| |
| void Setup(MultiHttpRPC::MultiJob* job) override; |
| void Done(MultiHttpRPC::MultiJob* job, |
| int i, HttpRPC::Status* stat, |
| google::protobuf::Message* resp) override; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MultiFileStore); |
| }; |
| |
| } // namespace devtools_goma |
| |
| #endif // DEVTOOLS_GOMA_CLIENT_MULTI_HTTP_RPC_H_ |