GRPC C++  1.18.0
call_op_set.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
20 #define GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
21 
22 #include <assert.h>
23 #include <array>
24 #include <cstring>
25 #include <functional>
26 #include <map>
27 #include <memory>
28 #include <vector>
29 
43 
44 #include <grpc/impl/codegen/atm.h>
47 
48 namespace grpc {
49 
52 
53 namespace internal {
54 class Call;
55 class CallHook;
56 
57 // TODO(yangg) if the map is changed before we send, the pointers will be a
58 // mess. Make sure it does not happen.
60  const std::multimap<grpc::string, grpc::string>& metadata,
61  size_t* metadata_count, const grpc::string& optional_error_details) {
62  *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1);
63  if (*metadata_count == 0) {
64  return nullptr;
65  }
66  grpc_metadata* metadata_array =
67  (grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
68  (*metadata_count) * sizeof(grpc_metadata)));
69  size_t i = 0;
70  for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
71  metadata_array[i].key = SliceReferencingString(iter->first);
72  metadata_array[i].value = SliceReferencingString(iter->second);
73  }
74  if (!optional_error_details.empty()) {
75  metadata_array[i].key =
76  g_core_codegen_interface->grpc_slice_from_static_buffer(
78  metadata_array[i].value = SliceReferencingString(optional_error_details);
79  }
80  return metadata_array;
81 }
82 } // namespace internal
83 
85 class WriteOptions {
86  public:
87  WriteOptions() : flags_(0), last_message_(false) {}
88  WriteOptions(const WriteOptions& other)
89  : flags_(other.flags_), last_message_(other.last_message_) {}
90 
92  inline void Clear() { flags_ = 0; }
93 
95  inline uint32_t flags() const { return flags_; }
96 
101  SetBit(GRPC_WRITE_NO_COMPRESS);
102  return *this;
103  }
104 
109  ClearBit(GRPC_WRITE_NO_COMPRESS);
110  return *this;
111  }
112 
117  inline bool get_no_compression() const {
118  return GetBit(GRPC_WRITE_NO_COMPRESS);
119  }
120 
126  SetBit(GRPC_WRITE_BUFFER_HINT);
127  return *this;
128  }
129 
135  ClearBit(GRPC_WRITE_BUFFER_HINT);
136  return *this;
137  }
138 
143  inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
144 
148  SetBit(GRPC_WRITE_BUFFER_HINT);
149  return *this;
150  }
151 
153  ClearBit(GRPC_WRITE_BUFFER_HINT);
154  return *this;
155  }
156 
157  inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
158 
165  last_message_ = true;
166  return *this;
167  }
168 
172  last_message_ = false;
173  return *this;
174  }
175 
179  SetBit(GRPC_WRITE_THROUGH);
180  return *this;
181  }
182 
183  inline bool is_write_through() const { return GetBit(GRPC_WRITE_THROUGH); }
184 
189  bool is_last_message() const { return last_message_; }
190 
192  flags_ = rhs.flags_;
193  return *this;
194  }
195 
196  private:
197  void SetBit(const uint32_t mask) { flags_ |= mask; }
198 
199  void ClearBit(const uint32_t mask) { flags_ &= ~mask; }
200 
201  bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; }
202 
203  uint32_t flags_;
204  bool last_message_;
205 };
206 
207 namespace internal {
208 
211 template <int I>
212 class CallNoOp {
213  protected:
214  void AddOp(grpc_op* ops, size_t* nops) {}
215  void FinishOp(bool* status) {}
217  InterceptorBatchMethodsImpl* interceptor_methods) {}
219  InterceptorBatchMethodsImpl* interceptor_methods) {}
220  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {}
221 };
222 
224  public:
225  CallOpSendInitialMetadata() : send_(false) {
226  maybe_compression_level_.is_set = false;
227  }
228 
229  void SendInitialMetadata(std::multimap<grpc::string, grpc::string>* metadata,
230  uint32_t flags) {
231  maybe_compression_level_.is_set = false;
232  send_ = true;
233  flags_ = flags;
234  metadata_map_ = metadata;
235  }
236 
238  maybe_compression_level_.is_set = true;
239  maybe_compression_level_.level = level;
240  }
241 
242  protected:
243  void AddOp(grpc_op* ops, size_t* nops) {
244  if (!send_ || hijacked_) return;
245  grpc_op* op = &ops[(*nops)++];
247  op->flags = flags_;
248  op->reserved = NULL;
249  initial_metadata_ =
250  FillMetadataArray(*metadata_map_, &initial_metadata_count_, "");
251  op->data.send_initial_metadata.count = initial_metadata_count_;
252  op->data.send_initial_metadata.metadata = initial_metadata_;
254  maybe_compression_level_.is_set;
255  if (maybe_compression_level_.is_set) {
257  maybe_compression_level_.level;
258  }
259  }
260  void FinishOp(bool* status) {
261  if (!send_ || hijacked_) return;
262  g_core_codegen_interface->gpr_free(initial_metadata_);
263  send_ = false;
264  }
265 
267  InterceptorBatchMethodsImpl* interceptor_methods) {
268  if (!send_) return;
269  interceptor_methods->AddInterceptionHookPoint(
271  interceptor_methods->SetSendInitialMetadata(metadata_map_);
272  }
273 
275  InterceptorBatchMethodsImpl* interceptor_methods) {}
276 
277  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
278  hijacked_ = true;
279  }
280 
281  bool hijacked_ = false;
282  bool send_;
283  uint32_t flags_;
285  std::multimap<grpc::string, grpc::string>* metadata_map_;
287  struct {
288  bool is_set;
290  } maybe_compression_level_;
291 };
292 
294  public:
295  CallOpSendMessage() : send_buf_() {}
296 
299  template <class M>
300  Status SendMessage(const M& message,
302 
303  template <class M>
304  Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
305 
306  protected:
307  void AddOp(grpc_op* ops, size_t* nops) {
308  if (!send_buf_.Valid() || hijacked_) return;
309  grpc_op* op = &ops[(*nops)++];
310  op->op = GRPC_OP_SEND_MESSAGE;
311  op->flags = write_options_.flags();
312  op->reserved = NULL;
313  op->data.send_message.send_message = send_buf_.c_buffer();
314  // Flags are per-message: clear them after use.
315  write_options_.Clear();
316  }
317  void FinishOp(bool* status) { send_buf_.Clear(); }
318 
320  InterceptorBatchMethodsImpl* interceptor_methods) {
321  if (!send_buf_.Valid()) return;
322  interceptor_methods->AddInterceptionHookPoint(
324  interceptor_methods->SetSendMessage(&send_buf_);
325  }
326 
328  InterceptorBatchMethodsImpl* interceptor_methods) {
329  // The contents of the SendMessage value that was previously set
330  // has had its references stolen by core's operations
331  interceptor_methods->SetSendMessage(nullptr);
332  }
333 
334  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
335  hijacked_ = true;
336  }
337 
338  private:
339  bool hijacked_ = false;
340  ByteBuffer send_buf_;
341  WriteOptions write_options_;
342 };
343 
344 template <class M>
346  write_options_ = options;
347  bool own_buf;
348  // TODO(vjpai): Remove the void below when possible
349  // The void in the template parameter below should not be needed
350  // (since it should be implicit) but is needed due to an observed
351  // difference in behavior between clang and gcc for certain internal users
353  message, send_buf_.bbuf_ptr(), &own_buf);
354  if (!own_buf) {
355  send_buf_.Duplicate();
356  }
357  return result;
358 }
359 
360 template <class M>
362  return SendMessage(message, WriteOptions());
363 }
364 
365 template <class R>
366 class CallOpRecvMessage {
367  public:
369  : got_message(false),
370  message_(nullptr),
371  allow_not_getting_message_(false) {}
372 
373  void RecvMessage(R* message) { message_ = message; }
374 
375  // Do not change status if no message is received.
376  void AllowNoMessage() { allow_not_getting_message_ = true; }
377 
379 
380  protected:
381  void AddOp(grpc_op* ops, size_t* nops) {
382  if (message_ == nullptr || hijacked_) return;
383  grpc_op* op = &ops[(*nops)++];
384  op->op = GRPC_OP_RECV_MESSAGE;
385  op->flags = 0;
386  op->reserved = NULL;
387  op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
388  }
389 
390  void FinishOp(bool* status) {
391  if (message_ == nullptr || hijacked_) return;
392  if (recv_buf_.Valid()) {
393  if (*status) {
394  got_message = *status =
395  SerializationTraits<R>::Deserialize(recv_buf_.bbuf_ptr(), message_)
396  .ok();
397  recv_buf_.Release();
398  } else {
399  got_message = false;
400  recv_buf_.Clear();
401  }
402  } else {
403  got_message = false;
404  if (!allow_not_getting_message_) {
405  *status = false;
406  }
407  }
408  message_ = nullptr;
409  }
410 
412  InterceptorBatchMethodsImpl* interceptor_methods) {
413  interceptor_methods->SetRecvMessage(message_);
414  }
415 
417  InterceptorBatchMethodsImpl* interceptor_methods) {
418  if (!got_message) return;
419  interceptor_methods->AddInterceptionHookPoint(
421  }
422  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
423  hijacked_ = true;
424  if (message_ == nullptr) return;
425  interceptor_methods->AddInterceptionHookPoint(
427  got_message = true;
428  }
429 
430  private:
431  R* message_;
432  ByteBuffer recv_buf_;
433  bool allow_not_getting_message_;
434  bool hijacked_ = false;
435 };
436 
438  public:
439  virtual Status Deserialize(ByteBuffer* buf) = 0;
440  virtual ~DeserializeFunc() {}
441 };
442 
443 template <class R>
444 class DeserializeFuncType final : public DeserializeFunc {
445  public:
446  DeserializeFuncType(R* message) : message_(message) {}
447  Status Deserialize(ByteBuffer* buf) override {
448  return SerializationTraits<R>::Deserialize(buf->bbuf_ptr(), message_);
449  }
450 
451  ~DeserializeFuncType() override {}
452 
453  private:
454  R* message_; // Not a managed pointer because management is external to this
455 };
456 
458  public:
460  : got_message(false), allow_not_getting_message_(false) {}
461 
462  template <class R>
463  void RecvMessage(R* message) {
464  // Use an explicit base class pointer to avoid resolution error in the
465  // following unique_ptr::reset for some old implementations.
466  DeserializeFunc* func = new DeserializeFuncType<R>(message);
467  deserialize_.reset(func);
468  message_ = message;
469  }
470 
471  // Do not change status if no message is received.
472  void AllowNoMessage() { allow_not_getting_message_ = true; }
473 
475 
476  protected:
477  void AddOp(grpc_op* ops, size_t* nops) {
478  if (!deserialize_ || hijacked_) return;
479  grpc_op* op = &ops[(*nops)++];
480  op->op = GRPC_OP_RECV_MESSAGE;
481  op->flags = 0;
482  op->reserved = NULL;
483  op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
484  }
485 
486  void FinishOp(bool* status) {
487  if (!deserialize_ || hijacked_) return;
488  if (recv_buf_.Valid()) {
489  if (*status) {
490  got_message = true;
491  *status = deserialize_->Deserialize(&recv_buf_).ok();
492  recv_buf_.Release();
493  } else {
494  got_message = false;
495  recv_buf_.Clear();
496  }
497  } else {
498  got_message = false;
499  if (!allow_not_getting_message_) {
500  *status = false;
501  }
502  }
503  deserialize_.reset();
504  }
505 
507  InterceptorBatchMethodsImpl* interceptor_methods) {
508  interceptor_methods->SetRecvMessage(message_);
509  }
510 
512  InterceptorBatchMethodsImpl* interceptor_methods) {
513  if (!got_message) return;
514  interceptor_methods->AddInterceptionHookPoint(
516  }
517  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
518  hijacked_ = true;
519  if (!deserialize_) return;
520  interceptor_methods->AddInterceptionHookPoint(
522  }
523 
524  private:
525  void* message_;
526  bool hijacked_ = false;
527  std::unique_ptr<DeserializeFunc> deserialize_;
528  ByteBuffer recv_buf_;
529  bool allow_not_getting_message_;
530 };
531 
533  public:
534  CallOpClientSendClose() : send_(false) {}
535 
536  void ClientSendClose() { send_ = true; }
537 
538  protected:
539  void AddOp(grpc_op* ops, size_t* nops) {
540  if (!send_ || hijacked_) return;
541  grpc_op* op = &ops[(*nops)++];
543  op->flags = 0;
544  op->reserved = NULL;
545  }
546  void FinishOp(bool* status) { send_ = false; }
547 
549  InterceptorBatchMethodsImpl* interceptor_methods) {
550  if (!send_) return;
551  interceptor_methods->AddInterceptionHookPoint(
553  }
554 
556  InterceptorBatchMethodsImpl* interceptor_methods) {}
557 
558  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
559  hijacked_ = true;
560  }
561 
562  private:
563  bool hijacked_ = false;
564  bool send_;
565 };
566 
568  public:
569  CallOpServerSendStatus() : send_status_available_(false) {}
570 
572  std::multimap<grpc::string, grpc::string>* trailing_metadata,
573  const Status& status) {
574  send_error_details_ = status.error_details();
575  metadata_map_ = trailing_metadata;
576  send_status_available_ = true;
577  send_status_code_ = static_cast<grpc_status_code>(status.error_code());
578  send_error_message_ = status.error_message();
579  }
580 
581  protected:
582  void AddOp(grpc_op* ops, size_t* nops) {
583  if (!send_status_available_ || hijacked_) return;
584  trailing_metadata_ = FillMetadataArray(
585  *metadata_map_, &trailing_metadata_count_, send_error_details_);
586  grpc_op* op = &ops[(*nops)++];
589  trailing_metadata_count_;
590  op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
591  op->data.send_status_from_server.status = send_status_code_;
592  error_message_slice_ = SliceReferencingString(send_error_message_);
594  send_error_message_.empty() ? nullptr : &error_message_slice_;
595  op->flags = 0;
596  op->reserved = NULL;
597  }
598 
599  void FinishOp(bool* status) {
600  if (!send_status_available_ || hijacked_) return;
601  g_core_codegen_interface->gpr_free(trailing_metadata_);
602  send_status_available_ = false;
603  }
604 
606  InterceptorBatchMethodsImpl* interceptor_methods) {
607  if (!send_status_available_) return;
608  interceptor_methods->AddInterceptionHookPoint(
610  interceptor_methods->SetSendTrailingMetadata(metadata_map_);
611  interceptor_methods->SetSendStatus(&send_status_code_, &send_error_details_,
612  &send_error_message_);
613  }
614 
616  InterceptorBatchMethodsImpl* interceptor_methods) {}
617 
618  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
619  hijacked_ = true;
620  }
621 
622  private:
623  bool hijacked_ = false;
624  bool send_status_available_;
625  grpc_status_code send_status_code_;
626  grpc::string send_error_details_;
627  grpc::string send_error_message_;
628  size_t trailing_metadata_count_;
629  std::multimap<grpc::string, grpc::string>* metadata_map_;
630  grpc_metadata* trailing_metadata_;
631  grpc_slice error_message_slice_;
632 };
633 
635  public:
636  CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
637 
639  context->initial_metadata_received_ = true;
640  metadata_map_ = &context->recv_initial_metadata_;
641  }
642 
643  protected:
644  void AddOp(grpc_op* ops, size_t* nops) {
645  if (metadata_map_ == nullptr || hijacked_) return;
646  grpc_op* op = &ops[(*nops)++];
648  op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
649  op->flags = 0;
650  op->reserved = NULL;
651  }
652 
653  void FinishOp(bool* status) {
654  if (metadata_map_ == nullptr || hijacked_) return;
655  }
656 
658  InterceptorBatchMethodsImpl* interceptor_methods) {
659  interceptor_methods->SetRecvInitialMetadata(metadata_map_);
660  }
661 
663  InterceptorBatchMethodsImpl* interceptor_methods) {
664  if (metadata_map_ == nullptr) return;
665  interceptor_methods->AddInterceptionHookPoint(
667  metadata_map_ = nullptr;
668  }
669 
670  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
671  hijacked_ = true;
672  if (metadata_map_ == nullptr) return;
673  interceptor_methods->AddInterceptionHookPoint(
675  }
676 
677  private:
678  bool hijacked_ = false;
679  MetadataMap* metadata_map_;
680 };
681 
683  public:
685  : recv_status_(nullptr), debug_error_string_(nullptr) {}
686 
687  void ClientRecvStatus(ClientContext* context, Status* status) {
688  client_context_ = context;
689  metadata_map_ = &client_context_->trailing_metadata_;
690  recv_status_ = status;
691  error_message_ = g_core_codegen_interface->grpc_empty_slice();
692  }
693 
694  protected:
695  void AddOp(grpc_op* ops, size_t* nops) {
696  if (recv_status_ == nullptr || hijacked_) return;
697  grpc_op* op = &ops[(*nops)++];
699  op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
700  op->data.recv_status_on_client.status = &status_code_;
701  op->data.recv_status_on_client.status_details = &error_message_;
702  op->data.recv_status_on_client.error_string = &debug_error_string_;
703  op->flags = 0;
704  op->reserved = NULL;
705  }
706 
707  void FinishOp(bool* status) {
708  if (recv_status_ == nullptr || hijacked_) return;
709  grpc::string binary_error_details = metadata_map_->GetBinaryErrorDetails();
710  *recv_status_ =
711  Status(static_cast<StatusCode>(status_code_),
712  GRPC_SLICE_IS_EMPTY(error_message_)
713  ? grpc::string()
714  : grpc::string(GRPC_SLICE_START_PTR(error_message_),
715  GRPC_SLICE_END_PTR(error_message_)),
716  binary_error_details);
717  client_context_->set_debug_error_string(
718  debug_error_string_ != nullptr ? debug_error_string_ : "");
719  g_core_codegen_interface->grpc_slice_unref(error_message_);
720  if (debug_error_string_ != nullptr) {
721  g_core_codegen_interface->gpr_free((void*)debug_error_string_);
722  }
723  }
724 
726  InterceptorBatchMethodsImpl* interceptor_methods) {
727  interceptor_methods->SetRecvStatus(recv_status_);
728  interceptor_methods->SetRecvTrailingMetadata(metadata_map_);
729  }
730 
732  InterceptorBatchMethodsImpl* interceptor_methods) {
733  if (recv_status_ == nullptr) return;
734  interceptor_methods->AddInterceptionHookPoint(
736  recv_status_ = nullptr;
737  }
738 
739  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
740  hijacked_ = true;
741  if (recv_status_ == nullptr) return;
742  interceptor_methods->AddInterceptionHookPoint(
744  }
745 
746  private:
747  bool hijacked_ = false;
748  ClientContext* client_context_;
749  MetadataMap* metadata_map_;
750  Status* recv_status_;
751  const char* debug_error_string_;
752  grpc_status_code status_code_;
753  grpc_slice error_message_;
754 };
755 
756 template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
757  class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
758  class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
759 class CallOpSet;
760 
767 template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
768 class CallOpSet : public CallOpSetInterface,
769  public Op1,
770  public Op2,
771  public Op3,
772  public Op4,
773  public Op5,
774  public Op6 {
775  public:
776  CallOpSet() : core_cq_tag_(this), return_tag_(this) {}
777  // The copy constructor and assignment operator reset the value of
778  // core_cq_tag_, return_tag_, done_intercepting_ and interceptor_methods_
779  // since those are only meaningful on a specific object, not across objects.
780  CallOpSet(const CallOpSet& other)
781  : core_cq_tag_(this),
782  return_tag_(this),
783  call_(other.call_),
784  done_intercepting_(false),
785  interceptor_methods_(InterceptorBatchMethodsImpl()) {}
786 
787  CallOpSet& operator=(const CallOpSet& other) {
788  core_cq_tag_ = this;
789  return_tag_ = this;
790  call_ = other.call_;
791  done_intercepting_ = false;
792  interceptor_methods_ = InterceptorBatchMethodsImpl();
793  return *this;
794  }
795 
796  void FillOps(Call* call) override {
797  done_intercepting_ = false;
798  g_core_codegen_interface->grpc_call_ref(call->call());
799  call_ =
800  *call; // It's fine to create a copy of call since it's just pointers
801 
802  if (RunInterceptors()) {
803  ContinueFillOpsAfterInterception();
804  } else {
805  // After the interceptors are run, ContinueFillOpsAfterInterception will
806  // be run
807  }
808  }
809 
810  bool FinalizeResult(void** tag, bool* status) override {
811  if (done_intercepting_) {
812  // We have already finished intercepting and filling in the results. This
813  // round trip from the core needed to be made because interceptors were
814  // run
815  *tag = return_tag_;
816  *status = saved_status_;
817  g_core_codegen_interface->grpc_call_unref(call_.call());
818  return true;
819  }
820 
821  this->Op1::FinishOp(status);
822  this->Op2::FinishOp(status);
823  this->Op3::FinishOp(status);
824  this->Op4::FinishOp(status);
825  this->Op5::FinishOp(status);
826  this->Op6::FinishOp(status);
827  saved_status_ = *status;
828  if (RunInterceptorsPostRecv()) {
829  *tag = return_tag_;
830  g_core_codegen_interface->grpc_call_unref(call_.call());
831  return true;
832  }
833  // Interceptors are going to be run, so we can't return the tag just yet.
834  // After the interceptors are run, ContinueFinalizeResultAfterInterception
835  return false;
836  }
837 
838  void set_output_tag(void* return_tag) { return_tag_ = return_tag; }
839 
840  void* core_cq_tag() override { return core_cq_tag_; }
841 
846  void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
847 
848  // This will be called while interceptors are run if the RPC is a hijacked
849  // RPC. This should set hijacking state for each of the ops.
850  void SetHijackingState() override {
851  this->Op1::SetHijackingState(&interceptor_methods_);
852  this->Op2::SetHijackingState(&interceptor_methods_);
853  this->Op3::SetHijackingState(&interceptor_methods_);
854  this->Op4::SetHijackingState(&interceptor_methods_);
855  this->Op5::SetHijackingState(&interceptor_methods_);
856  this->Op6::SetHijackingState(&interceptor_methods_);
857  }
858 
859  // Should be called after interceptors are done running
861  static const size_t MAX_OPS = 6;
862  grpc_op ops[MAX_OPS];
863  size_t nops = 0;
864  this->Op1::AddOp(ops, &nops);
865  this->Op2::AddOp(ops, &nops);
866  this->Op3::AddOp(ops, &nops);
867  this->Op4::AddOp(ops, &nops);
868  this->Op5::AddOp(ops, &nops);
869  this->Op6::AddOp(ops, &nops);
871  g_core_codegen_interface->grpc_call_start_batch(
872  call_.call(), ops, nops, core_cq_tag(), nullptr));
873  }
874 
875  // Should be called after interceptors are done running on the finalize result
876  // path
878  done_intercepting_ = true;
880  g_core_codegen_interface->grpc_call_start_batch(
881  call_.call(), nullptr, 0, core_cq_tag(), nullptr));
882  }
883 
884  private:
885  // Returns true if no interceptors need to be run
886  bool RunInterceptors() {
887  interceptor_methods_.ClearState();
888  interceptor_methods_.SetCallOpSetInterface(this);
889  interceptor_methods_.SetCall(&call_);
890  this->Op1::SetInterceptionHookPoint(&interceptor_methods_);
891  this->Op2::SetInterceptionHookPoint(&interceptor_methods_);
892  this->Op3::SetInterceptionHookPoint(&interceptor_methods_);
893  this->Op4::SetInterceptionHookPoint(&interceptor_methods_);
894  this->Op5::SetInterceptionHookPoint(&interceptor_methods_);
895  this->Op6::SetInterceptionHookPoint(&interceptor_methods_);
896  return interceptor_methods_.RunInterceptors();
897  }
898  // Returns true if no interceptors need to be run
899  bool RunInterceptorsPostRecv() {
900  // Call and OpSet had already been set on the set state.
901  // SetReverse also clears previously set hook points
902  interceptor_methods_.SetReverse();
903  this->Op1::SetFinishInterceptionHookPoint(&interceptor_methods_);
904  this->Op2::SetFinishInterceptionHookPoint(&interceptor_methods_);
905  this->Op3::SetFinishInterceptionHookPoint(&interceptor_methods_);
906  this->Op4::SetFinishInterceptionHookPoint(&interceptor_methods_);
907  this->Op5::SetFinishInterceptionHookPoint(&interceptor_methods_);
908  this->Op6::SetFinishInterceptionHookPoint(&interceptor_methods_);
909  return interceptor_methods_.RunInterceptors();
910  }
911 
912  void* core_cq_tag_;
913  void* return_tag_;
914  Call call_;
915  bool done_intercepting_ = false;
916  InterceptorBatchMethodsImpl interceptor_methods_;
917  bool saved_status_;
918 };
919 
920 } // namespace internal
921 } // namespace grpc
922 
923 #endif // GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
void ContinueFillOpsAfterInterception() override
Definition: call_op_set.h:860
everything went ok
Definition: grpc_types.h:366
grpc_op_type op
Operation type, as defined by grpc_op_type.
Definition: grpc_types.h:548
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:555
grpc_metadata_array * recv_initial_metadata
Definition: grpc_types.h:591
union grpc_op::grpc_op_data data
bool get_no_compression() const
Get value for the flag indicating whether compression for the next message write is forcefully disabl...
Definition: call_op_set.h:117
void * reserved
Reserved for future usage.
Definition: grpc_types.h:552
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:216
WriteOptions & clear_buffer_hint()
Clears flag indicating that the write may be buffered and need not go out on the wire immediately...
Definition: call_op_set.h:134
void SetRecvMessage(void *message)
Definition: interceptor_common.h:137
grpc_status_code
Definition: status.h:26
WriteOptions & set_buffer_hint()
Sets flag indicating that the write may be buffered and need not go out on the wire immediately...
Definition: call_op_set.h:125
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:141
void FinishOp(bool *status)
Definition: call_op_set.h:599
void SetHijackingState() override
Definition: call_op_set.h:850
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:644
void ClientSendClose()
Definition: call_op_set.h:536
virtual void grpc_call_ref(grpc_call *call)=0
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:558
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:739
CallOpRecvMessage()
Definition: call_op_set.h:368
std::string string
Definition: config.h:35
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:277
bool get_buffer_hint() const
Get value for the flag indicating that the write may be buffered and need not go out on the wire imme...
Definition: call_op_set.h:143
WriteOptions & clear_no_compression()
Clears flag for the disabling of compression for the next message write.
Definition: call_op_set.h:108
struct grpc_byte_buffer ** recv_message
Definition: grpc_types.h:599
void FinishOp(bool *status)
Definition: call_op_set.h:653
void SetSendMessage(ByteBuffer *buf)
Definition: interceptor_common.h:118
struct grpc_byte_buffer * send_message
This op takes ownership of the slices in send_message.
Definition: grpc_types.h:574
Send a close from the client: one and only one instance MUST be sent from the client, unless the call was cancelled - in which case this can be skipped.
Definition: grpc_types.h:513
CallOpSet(const CallOpSet &other)
Definition: call_op_set.h:780
Send status from the server: one and only one instance MUST be sent from the server unless the call w...
Definition: grpc_types.h:518
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:307
void AllowNoMessage()
Definition: call_op_set.h:472
Definition: metadata_map.h:33
WriteOptions & set_last_message()
last-message bit: indicates this is the last message in a stream client-side: makes Write the equival...
Definition: call_op_set.h:164
#define GRPC_WRITE_NO_COMPRESS
Force compression to be disabled for a particular write (start_write/add_metadata).
Definition: grpc_types.h:413
grpc_slice key
the key, value values are expected to line up with grpc_mdelem: if changing them, update metadata...
Definition: grpc_types.h:445
Status Deserialize(ByteBuffer *buf) override
Definition: call_op_set.h:447
CallOpRecvInitialMetadata()
Definition: call_op_set.h:636
struct grpc_op::grpc_op_data::grpc_op_recv_message recv_message
void SetRecvStatus(Status *status)
Definition: interceptor_common.h:143
Primary implementation of CallOpSetInterface.
Definition: call_op_set.h:759
#define GRPC_SLICE_IS_EMPTY(slice)
Definition: slice.h:127
grpc_slice value
Definition: grpc_types.h:446
#define GRPC_WRITE_THROUGH
Force this message to be written to the socket before completing it.
Definition: grpc_types.h:415
const char ** error_string
If this is not nullptr, it will be populated with the full fidelity error string for debugging purpos...
Definition: grpc_types.h:613
grpc_slice * status_details
Definition: grpc_types.h:609
void Clear()
Clear all flags.
Definition: call_op_set.h:92
virtual grpc_slice grpc_empty_slice()=0
WriteOptions & set_write_through()
Guarantee that all bytes have been written to the socket before completing this write (usually writes...
Definition: call_op_set.h:178
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:506
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. ...
Definition: slice.h:80
bool send_
Definition: call_op_set.h:282
#define GRPC_WRITE_BUFFER_HINT
Write Flags:
Definition: grpc_types.h:410
void RecvInitialMetadata(ClientContext *context)
Definition: call_op_set.h:638
Send a message: 0 or more of these operations can occur for each call.
Definition: grpc_types.h:508
bool got_message
Definition: call_op_set.h:378
virtual void grpc_call_unref(grpc_call *call)=0
The first two in this list are for clients and servers.
bool is_write_through() const
Definition: call_op_set.h:183
WriteOptions()
Definition: call_op_set.h:87
WriteOptions & clear_last_message()
Clears flag indicating that this is the last message in a stream, disabling coalescing.
Definition: call_op_set.h:171
grpc_slice SliceReferencingString(const grpc::string &str)
Definition: slice.h:131
struct grpc_op::grpc_op_data::grpc_op_send_initial_metadata::grpc_op_send_initial_metadata_maybe_compression_level maybe_compression_level
void ClientRecvStatus(ClientContext *context, Status *status)
Definition: call_op_set.h:687
grpc_compression_level
Compression levels allow a party with knowledge of its peer&#39;s accepted encodings to request compressi...
Definition: compression_types.h:71
grpc_call * call() const
Definition: call.h:70
#define GRPC_SLICE_START_PTR(slice)
Definition: slice.h:116
void ContinueFinalizeResultAfterInterception() override
Definition: call_op_set.h:877
bool is_set
Definition: call_op_set.h:288
grpc_metadata_array * trailing_metadata
ownership of the array is with the caller, but ownership of the elements stays with the call object (...
Definition: grpc_types.h:607
WriteOptions & clear_corked()
Definition: call_op_set.h:152
WriteOptions & set_no_compression()
Sets flag for the disabling of compression for the next message write.
Definition: call_op_set.h:100
#define GRPC_SLICE_END_PTR(slice)
Definition: slice.h:125
CallOpClientSendClose()
Definition: call_op_set.h:534
void FinishOp(bool *status)
Definition: call_op_set.h:260
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:174
WriteOptions & operator=(const WriteOptions &rhs)
Definition: call_op_set.h:191
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:695
Definition: byte_buffer.h:55
::google::protobuf::util::Status Status
Definition: config_protobuf.h:93
uint32_t flags_
Definition: call_op_set.h:283
Default argument for CallOpSet.
Definition: call_op_set.h:212
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:511
void FinishOp(bool *status)
Definition: call_op_set.h:707
grpc_compression_level level
Definition: call_op_set.h:289
bool got_message
Definition: call_op_set.h:474
grpc::string error_message() const
Return the instance&#39;s error message.
Definition: status.h:112
Definition: call_op_set.h:437
Defines how to serialize and deserialize some type.
Definition: serialization_traits.h:58
The following three are for hijacked clients only and can only be registered by the global intercepto...
StatusCode error_code() const
Return the instance&#39;s error code.
Definition: status.h:110
CallOpServerSendStatus()
Definition: call_op_set.h:569
bool FinalizeResult(void **tag, bool *status) override
FinalizeResult must be called before informing user code that the operation bound to the underlying c...
Definition: call_op_set.h:810
Definition: call_op_set.h:567
void set_compression_level(grpc_compression_level level)
Definition: call_op_set.h:237
Definition: call_op_set.h:223
bool is_corked() const
Definition: call_op_set.h:157
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:477
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:670
Definition: call_op_set.h:634
Status SendMessage(const M &message, WriteOptions options) GRPC_MUST_USE_RESULT
Send message using options for the write.
Definition: call_op_set.h:345
std::multimap< grpc::string, grpc::string > * metadata_map_
Definition: call_op_set.h:285
uint32_t flags() const
Returns raw flags bitset.
Definition: call_op_set.h:95
grpc_metadata * FillMetadataArray(const std::multimap< grpc::string, grpc::string > &metadata, size_t *metadata_count, const grpc::string &optional_error_details)
Definition: call_op_set.h:59
struct grpc_op::grpc_op_data::grpc_op_recv_initial_metadata recv_initial_metadata
A single metadata element.
Definition: grpc_types.h:442
Definition: call_op_set.h:293
struct grpc_op::grpc_op_data::grpc_op_send_initial_metadata send_initial_metadata
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:243
void FinishOp(bool *status)
Definition: call_op_set.h:486
Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT which has no arguments) ...
Definition: grpc_types.h:546
virtual grpc_slice grpc_slice_from_static_buffer(const void *buffer, size_t length)=0
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:548
This header provides an object that reads bytes directly from a grpc::ByteBuffer, via the ZeroCopyInp...
Definition: alarm.h:24
Receive initial metadata: one and only one MUST be made on the client, must not be made on the server...
Definition: grpc_types.h:523
void RecvMessage(R *message)
Definition: call_op_set.h:463
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:218
void FillOps(Call *call) override
Fills in grpc_op, starting from ops[*nops] and moving upwards.
Definition: call_op_set.h:796
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:327
struct grpc_op::grpc_op_data::grpc_op_send_message send_message
void SendInitialMetadata(std::multimap< grpc::string, grpc::string > *metadata, uint32_t flags)
Definition: call_op_set.h:229
CoreCodegenInterface * g_core_codegen_interface
Definition: call_op_set.h:50
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:582
void * core_cq_tag() override
Get the tag to be used at the core completion queue.
Definition: call_op_set.h:840
#define GRPC_MUST_USE_RESULT
Definition: port_platform.h:473
Send initial metadata: one and only one instance MUST be sent for each call, unless the call was canc...
Definition: grpc_types.h:504
WriteOptions(const WriteOptions &other)
Definition: call_op_set.h:88
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:539
CallOpClientRecvStatus()
Definition: call_op_set.h:684
Definition: interceptor_common.h:36
Definition: byte_buffer.h:41
void ServerSendStatus(std::multimap< grpc::string, grpc::string > *trailing_metadata, const Status &status)
Definition: call_op_set.h:571
void FinishOp(bool *status)
Definition: call_op_set.h:546
Per-message write options.
Definition: call_op_set.h:85
grpc_slice * status_details
optional: set to NULL if no details need sending, non-NULL if they do pointer will not be retained pa...
Definition: grpc_types.h:583
CallOpSet & operator=(const CallOpSet &other)
Definition: call_op_set.h:787
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:274
void AllowNoMessage()
Definition: call_op_set.h:376
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:615
size_t trailing_metadata_count
Definition: grpc_types.h:577
CallOpSendMessage()
Definition: call_op_set.h:295
grpc_metadata * metadata
Definition: grpc_types.h:560
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:319
void FinishOp(bool *status)
Definition: call_op_set.h:215
virtual grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved)=0
void FinishOp(bool *status)
Definition: call_op_set.h:390
A thin wrapper around grpc_completion_queue (see src/core/lib/surface/completion_queue.h).
Definition: completion_queue.h:95
Definition: call_op_set.h:532
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:416
An abstract collection of call ops, used to generate the grpc_call_op structure to pass down to the l...
Definition: call_op_set_interface.h:34
virtual void grpc_slice_unref(grpc_slice slice)=0
void SetSendStatus(grpc_status_code *code, grpc::string *error_details, grpc::string *error_message)
Definition: interceptor_common.h:125
void SetSendTrailingMetadata(std::multimap< grpc::string, grpc::string > *metadata)
Definition: interceptor_common.h:132
virtual ~DeserializeFunc()
Definition: call_op_set.h:440
void SetRecvInitialMetadata(MetadataMap *map)
Definition: interceptor_common.h:139
void RecvMessage(R *message)
Definition: call_op_set.h:373
struct grpc_op::grpc_op_data::grpc_op_send_status_from_server send_status_from_server
Interface between the codegen library and the minimal subset of core features required by the generat...
Definition: core_codegen_interface.h:37
void set_output_tag(void *return_tag)
Definition: call_op_set.h:838
CallOpSendInitialMetadata()
Definition: call_op_set.h:225
void SetSendInitialMetadata(std::multimap< grpc::string, grpc::string > *metadata)
Definition: interceptor_common.h:120
WriteOptions & set_corked()
corked bit: aliases set_buffer_hint currently, with the intent that set_buffer_hint will be removed i...
Definition: call_op_set.h:147
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:220
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:214
Did it work? If it didn&#39;t, why?
Definition: status.h:31
void FinishOp(bool *status)
Definition: call_op_set.h:317
Receive status on the client: one and only one must be made on the client.
Definition: grpc_types.h:533
grpc_metadata * initial_metadata_
Definition: call_op_set.h:286
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:618
void AddInterceptionHookPoint(experimental::InterceptionHookPoints type)
Definition: interceptor_common.h:78
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:517
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:662
DeserializeFuncType(R *message)
Definition: call_op_set.h:446
size_t initial_metadata_count_
Definition: call_op_set.h:284
void SetFinishInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:731
void SetRecvTrailingMetadata(MetadataMap *map)
Definition: interceptor_common.h:145
grpc_status_code status
Definition: grpc_types.h:579
grpc_status_code * status
Definition: grpc_types.h:608
size_t count
Definition: grpc_types.h:559
Definition: call_op_set.h:457
uint32_t flags
Write flags bitset for grpc_begin_messages.
Definition: grpc_types.h:550
bool is_last_message() const
Get value for the flag indicating that this is the last message, and should be coalesced with trailin...
Definition: call_op_set.h:189
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:657
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:725
Definition: call_op_set.h:682
virtual void gpr_free(void *p)=0
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:605
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:422
Receive a message: 0 or more of these operations can occur for each call.
Definition: grpc_types.h:527
A sequence of bytes.
Definition: byte_buffer.h:64
CallOpGenericRecvMessage()
Definition: call_op_set.h:459
void AddOp(grpc_op *ops, size_t *nops)
Definition: call_op_set.h:381
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:411
CallOpSet()
Definition: call_op_set.h:776
const char kBinaryErrorDetailsKey[]
Definition: metadata_map.h:31
The following two are for all clients and servers.
void SetInterceptionHookPoint(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:266
void set_core_cq_tag(void *core_cq_tag)
set_core_cq_tag is used to provide a different core CQ tag than "this".
Definition: call_op_set.h:846
grpc::string error_details() const
Return the (binary) error details.
Definition: status.h:115
Straightforward wrapping of the C call object.
Definition: call.h:36
grpc_metadata * trailing_metadata
Definition: grpc_types.h:578
void SetHijackingState(InterceptorBatchMethodsImpl *interceptor_methods)
Definition: call_op_set.h:334
struct grpc_op::grpc_op_data::grpc_op_recv_status_on_client recv_status_on_client
virtual void * gpr_malloc(size_t size)=0
~DeserializeFuncType() override
Definition: call_op_set.h:451