NCBI C++ ToolKit
grpc_integration.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: grpc_integration.cpp 99891 2023-05-18 18:14:23Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Aaron Ucko
27 *
28 * File Description:
29 * Glue for integrating gRPC into the C++ toolkit, to ensure logging
30 * and metadata propagation (sid, phid, auth tokens etc) are all
31 * handled uniformly and appropriately.
32 *
33 * ===========================================================================
34 */
35 
36 #include <ncbi_pch.hpp>
38 #include <corelib/ncbiapp.hpp>
39 #include <util/static_map.hpp>
40 #include <serial/error_codes.hpp>
41 #ifdef HAVE_LIBGRPC
42 # include <grpc++/server_context.h>
43 # include <grpc/support/alloc.h>
44 # include <grpc/support/log.h>
45 #endif
46 #ifdef NCBI_OS_UNIX
47 # include <connect/ext/ncbi_ifconf.h>
48 #endif
49 
50 #define NCBI_USE_ERRCODE_X Serial_GRPCIntegration
51 
53 
54 #ifdef HAVE_LIBGRPC
55 
56 static string s_EncodeMetadataName(const string& name)
57 {
58  static const CTempString kLegalPunct("-_.");
59  if (NStr::StartsWith(name, "ncbi_")) {
60  if (name == "ncbi_dtab") {
61  return "l5d-dtab";
62  } else if (name == "ncbi_phid") {
63  return "ncbi-phid";
64  } else if (name == "ncbi_sid") {
65  return "ncbi-sid";
66  }
67  }
68  string result = name;
70  for (char& c : result) {
71  if ( !isalnum((unsigned char) c) && kLegalPunct.find(c) == NPOS) {
72  c = '_';
73  }
74  }
75  return result;
76 }
77 
78 static string s_DecodeMetadataName(const CTempString& name)
79 {
80  if (name == "l5d-dtab") {
81  return "ncbi_dtab";
82  } else if (name == "ncbi-phid") {
83  return "ncbi_phid";
84  } else if (name == "ncbi-sid") {
85  return "ncbi_sid";
86  } else {
87  // NStr::ToUpper(name);
88  return name;
89  }
90 }
91 
92 inline
93 static string s_EncodeMetadataValue(const string& value)
94 {
96 }
97 
98 inline
100 {
102 }
103 
105 {
106 public:
107  CGRPCInitializer(void);
108 
109 private:
110  static grpc::Server::GlobalCallbacks* volatile sm_ServerCallbacks;
111 };
112 
113 grpc::Server::GlobalCallbacks* volatile CGRPCInitializer::sm_ServerCallbacks;
115 
116 extern "C" {
117  static void s_NCBI_GPR_Log_Function(gpr_log_func_args *args) {
118  static const char* unk_func = g_DiagUnknownFunction();
119  CDiagCompileInfo diag_info(args->file, args->line, unk_func, "GRPC");
120  EDiagSev sev = eDiag_Error;
121  switch (args->severity) {
122  case GPR_LOG_SEVERITY_DEBUG: sev = eDiag_Trace; break;
123  case GPR_LOG_SEVERITY_INFO: sev = eDiag_Info; break;
124  case GPR_LOG_SEVERITY_ERROR: sev = eDiag_Error; break;
125  }
126  CNcbiDiag(diag_info) << Severity(sev) << args->message << Endm;
127  }
128 }
129 
131 {
132  gpr_set_log_function(s_NCBI_GPR_Log_Function);
134  grpc::Server::SetGlobalCallbacks(sm_ServerCallbacks);
135  // NB: on the client side, we encourage the use of
136  // CGRPCClientContext rather than setting global callbacks, to
137  // avoid sending inappropriate metadata to non-NCBI services.
138 }
139 
140 #endif
141 
142 
143 unique_ptr<TGRPCBaseClientContext>
145  TGRPCPropagationOptions options)
146 {
147 #ifdef HAVE_LIBGRPC
148  unique_ptr<TGRPCBaseClientContext> result
149  (TGRPCBaseClientContext::FromServerContext(sctx, options));
150  if (result.get() != NULL) {
152  }
153  return result;
154 #else
155  return make_unique<CGRPCClientContext>();
156 #endif
157 }
158 
160 {
161 #ifdef HAVE_LIBGRPC
162  CDiagContext& dctx = GetDiagContext();
163  CRequestContext& rctx = dctx.GetRequestContext();
164  cctx.set_initial_metadata_corked(true);
165 #if 1
166  // Respectively redundant with ncbi_sid, ncbi_phid, and ncbi_dtab,
167  // but kept for now for the sake of servers that only recognize
168  // these legacy names.
169  if (rctx.IsSetSessionID()) {
170  cctx.AddMetadata("sessionid", rctx.GetSessionID());
171  }
172  cctx.AddMetadata("ncbiphid", rctx.GetNextSubHitID());
173  cctx.AddMetadata("dtab", rctx.GetDtab());
174 #endif
175  cctx.AddMetadata("client", dctx.GetAppName());
176 
177  CRequestContext_PassThrough pass_through;
178  bool need_filter = pass_through.IsSet("PATH");
179  if (need_filter) {
181  << "No NCBI_CONTEXT_FIELDS or [Context] Fields"
182  " setting; performing ad-hoc filtering.");
183  }
184  pass_through.Enumerate
185  ([&](const string& name, const string& value) {
186  if ( !need_filter || name == "http_proxy"
187  || NStr::StartsWith(name, "ncbi", NStr::eNocase)
188  || NStr::StartsWith(name, "l5d", NStr::eNocase)) {
189  cctx.AddMetadata(s_EncodeMetadataName(name),
191  }
192  return true;
193  });
194 # ifdef NCBI_OS_UNIX
195  if ( !rctx.IsSetClientIP() ) {
196  char buf[64];
197  if (NcbiGetHostIP(buf, sizeof(buf)) != nullptr) {
198  cctx.AddMetadata("ncbi_client_ip", buf);
199  }
200  }
201 # endif
202 #endif
203 }
204 
206 {
207 #ifdef HAVE_LIBGRPC
208  return true;
209 #else
210  return false;
211 #endif
212 }
213 
214 
215 #ifdef HAVE_LIBGRPC
216 
218 #define TSCP(x, y) { CRequestStatus::x, grpc::y }
219 static const TStatusCodePair sc_ErrorCodes[] = {
220  TSCP(e400_BadRequest, INVALID_ARGUMENT),
221  TSCP(e401_Unauthorized, PERMISSION_DENIED), // UNAUTHENTICATED?
222  TSCP(e402_PaymentRequired, PERMISSION_DENIED),
223  TSCP(e403_Forbidden, PERMISSION_DENIED),
224  TSCP(e404_NotFound, NOT_FOUND),
225  TSCP(e405_MethodNotAllowed, UNIMPLEMENTED), // INVALID_ARGUMENT?
226  TSCP(e406_NotAcceptable, UNIMPLEMENTED), // INVALID_ARGUMENT?
227  TSCP(e407_ProxyAuthRequired, PERMISSION_DENIED), // UNAUTHENTICATED?
228  TSCP(e408_RequestTimeout, DEADLINE_EXCEEDED),
229  TSCP(e409_Conflict, ABORTED),
230  TSCP(e410_Gone, NOT_FOUND),
231  TSCP(e411_LengthRequired, UNIMPLEMENTED), // INVALID_ARGUMENT?
232  TSCP(e412_PreconditionFailed, FAILED_PRECONDITION),
233  TSCP(e413_RequestEntityTooLarge, RESOURCE_EXHAUSTED), // ?
234  TSCP(e414_RequestURITooLong, RESOURCE_EXHAUSTED), // ?
235  TSCP(e415_UnsupportedMediaType, UNIMPLEMENTED), // INVALID_ARGUMENT?
236  TSCP(e416_RangeNotSatisfiable, OUT_OF_RANGE),
237  TSCP(e417_ExpectationFailed, FAILED_PRECONDITION),
238  TSCP(e422_UnprocessableEntity, UNIMPLEMENTED), // INVALID_ARGUMENT?
239  TSCP(e499_BrokenConnection, CANCELLED),
240  TSCP(e500_InternalServerError, INTERNAL),
241  TSCP(e501_NotImplemented, UNIMPLEMENTED),
242  TSCP(e502_BadGateway, INTERNAL),
243  TSCP(e503_ServiceUnavailable, UNAVAILABLE),
244  TSCP(e504_GatewayTimeout, DEADLINE_EXCEEDED),
245  TSCP(e505_HTTPVerNotSupported, UNIMPLEMENTED) // INVALID_ARGUMENT?
246 };
249 
250 #endif
251 
252 grpc::StatusCode g_AsGRPCStatusCode(CRequestStatus::ECode status_code)
253 {
254 #ifdef HAVE_LIBGRPC
255  TStatusCodeMap::const_iterator it = sc_ErrorCodeMap.find(status_code);
256  if (it != sc_ErrorCodeMap.end()) {
257  return it->second;
258  } else if (status_code >= CRequestStatus::e100_Continue
259  && status_code < CRequestStatus::e400_BadRequest) {
260  return grpc::OK;
261  } else {
262  return grpc::UNKNOWN;
263  }
264 #else
265  return status_code;
266 #endif
267 }
268 
269 #ifdef HAVE_LIBGRPC
270 
271 // Work around inability to compare pointers to members.
272 static void s_SetDtab(CRequestContext& r, const string& s)
273 {
274  r.SetDtab(s);
275 }
276 static void s_SetClientIP(CRequestContext& r, const string& s)
277 {
278  r.SetClientIP(s);
279 }
280 static void s_SetHitID(CRequestContext& r, const string& s)
281 {
282  r.SetHitID(s);
283 }
284 static void s_SetSessionID(CRequestContext& r, const string& s)
285 {
286  r.SetSessionID(s);
287 }
288 
289 typedef void (*FRCSetter)(CRequestContext&, const string&);
291 // Explicitly handle all four standard fields, since some may come in via
292 // legacy names and AddPassThroughProperty doesn't trigger interpretation
293 // and may well filter some or all of these fields out altogether.
294 static const TRCSetterPair sc_RCSetters[] = {
295  { "dtab", &s_SetDtab }, // legacy name
296  { "ncbi_client_ip", &s_SetClientIP },
297  { "ncbi_dtab", &s_SetDtab },
298  { "ncbi_phid", &s_SetHitID },
299  { "ncbi_sid", &s_SetSessionID },
300  { "ncbiphid", &s_SetHitID }, // legacy name
301  { "sessionid", &s_SetSessionID } // legacy name
302 };
305 
306 #endif
307 
308 // TODO - can either of these log any more information, such as the
309 // service name, the status code, or the number of bytes in and/or out?
310 // (Byte counts appear to be tracked internally but not exposed. :-/)
311 
313  EInvocationType invocation_type)
314 {
315  if (invocation_type == eImplicit && !x_IsRealRequest(sctx)) {
316  return;
317  }
318 
319  CDiagContext& dctx = GetDiagContext();
320  CRequestContext& rctx = dctx.GetRequestContext();
321  string client_name, peer_ip, port;
322  map<string, string> grpc_fields, env_fields;
323  rctx.SetRequestID();
324 #ifdef HAVE_LIBGRPC
325  if (sctx != NULL) {
326  SIZE_TYPE pos = sctx->peer().find(':');
327  if (pos != NPOS) {
328  string peer = sctx->peer().substr(pos + 1);
329  CTempString host;
330  pos = peer.rfind(':');
331  if (pos == NPOS || peer[peer.size() - 1] == ']') {
332  host = peer;
333  } else {
334  port = peer.substr(pos + 1);
335  host.assign(peer, 0, pos);
336  if (host[0] == '[' && host[pos - 1] == ']') {
337  host = host.substr(1, pos - 2);
338  }
339  }
340  if ( !host.empty() ) {
341  rctx.SetClientIP(host);
342  }
343  }
345  for (const auto& metadata : sctx->client_metadata()) {
346  CTempString nm(metadata.first .data(), metadata.first .size());
347  CTempString vl(metadata.second.data(), metadata.second.size());
348  string name = s_DecodeMetadataName (nm);
349  string value = s_DecodeMetadataValue(vl);
350  rctx.AddPassThroughProperty(name, value);
351 
352  string name2 = name;
353  NStr::ToLower(name2);
354  NStr::ReplaceInPlace(name2, "_", "-");
355  grpc_fields[name2] = value;
356 
358  = sc_RCSetterMap.find(name.c_str());
359  if (it != sc_RCSetterMap.end()) {
360  if (it->second == &s_SetClientIP
361  && peer_ip.empty() && rctx.GetClientIP() != value) {
362  peer_ip = rctx.GetClientIP();
363  }
364  rcsettings[it->second][name] = value;
365  } else if (metadata.first == "client") {
366  client_name = value;
367  }
368  }
369  for (const auto& it : rcsettings) {
370  const string* value = nullptr;
371  if (it.second.size() == 1) {
372  value = &it.second.begin()->second;
373  } else {
374  _ASSERT(it.second.size() == 2);
375  const string *old_name = nullptr, *new_name = nullptr;
376  for (const auto& it2 : it.second) {
377  if (NStr::StartsWith(it2.first, "ncbi_")) {
378  new_name = &it2.first;
379  value = &it2.second;
380  } else {
381  old_name = &it2.first;
382  }
383  }
384  _ASSERT(old_name != nullptr);
385  _ASSERT(new_name != nullptr && value != nullptr);
387  << "Ignoring deprecated metadata field "
388  << *old_name << " in favor of " << *new_name);
389  }
390  (*(it.first))(rctx, *value);
391  }
392  }
393 #endif
394  CDiagContext_Extra extra = dctx.PrintRequestStart();
395  if ( !client_name.empty() ) {
396  extra.Print("client_name", client_name);
397  }
398  if ( !peer_ip.empty() ) {
399  extra.Print("peer_ip", peer_ip);
400  }
401  if ( !port.empty() ) {
402  extra.Print("client_port", port);
403  }
404  extra.Flush();
405 
408  if (app == nullptr) {
409  env.reset(new CNcbiEnvironment);
410  } else {
411  env.reset(const_cast<CNcbiEnvironment*>(&app->GetEnvironment()),
412  eNoOwnership);
413  }
414  list<string> env_names;
415  env->Enumerate(env_names);
416  for (const auto & it : env_names) {
417  string name = it;
418  NStr::ToLower(name);
419  NStr::ReplaceInPlace(name, "_", "-");
420  env_fields[name] = env->Get(it);
421  }
422  CNcbiLogFields("env").LogFields(env_fields);
423  CNcbiLogFields("grpc").LogFields(grpc_fields);
424 }
425 
426 
428  EInvocationType invocation_type)
429 {
430  if (invocation_type == eImplicit && !x_IsRealRequest(sctx)) {
431  return;
432  }
434 }
435 
436 
438 {
439 #ifdef HAVE_LIBGRPC
440  auto peer = sctx->peer();
441  if ( !NStr::StartsWith(peer, "ipv4:127.")
442  && !NStr::StartsWith(peer, "ipv6:[::1]") ) {
443  return true;
444  }
445  for (const auto& it : sctx->client_metadata()) {
446  CTempString name(it.first.data(), it.first.size());
447  if (NStr::StartsWith(name, "ncbi") || name == "sessionid") {
448  // l5d-*? dtab?
449  return true;
450  }
451  }
452 #endif
453  return false;
454 }
455 
456 
457 /// Get "hostport" for the likes of "grpc::CreateChannel(hostport, ...)" trying
458 /// (in order of priority):
459 /// - Config file entry "[section] variable"
460 /// - Environment variables: env_var_name (if not empty/NULL);
461 /// then "NCBI_CONFIG__<section>__<name>"; then "GRPC_PROXY"
462 /// - The hard-coded NCBI default "linkerd:4142"
463 string g_NCBI_GRPC_GetAddress(const char* section,
464  const char* variable,
465  const char* env_var_name,
466  CParamBase::EParamSource* value_source)
467 {
468  auto addr = g_GetConfigString(section, variable, env_var_name, nullptr, value_source);
469  if ( addr.empty() ) {
470  addr = g_GetConfigString(nullptr, nullptr, "GRPC_PROXY", "linkerd:4142", value_source);
471  }
472  return addr;
473 }
474 
475 
@ UNKNOWN
Definition: aln_formats.hpp:38
Incapsulate compile time information such as __FILE__, __LINE__, NCBI_MODULE, current function.
Definition: ncbidiag.hpp:65
Temporary object for holding extra message arguments.
Definition: ncbidiag.hpp:1828
static grpc::Server::GlobalCallbacks *volatile sm_ServerCallbacks
static CNcbiApplication * Instance(void)
Singleton method.
Definition: ncbiapp.cpp:264
CNcbiDiag –.
Definition: ncbidiag.hpp:924
CNcbiEnvironment –.
Definition: ncbienv.hpp:110
CNcbiLogFields –.
Definition: ncbidiag.hpp:2397
Request context properties passed between tasks.
class CStaticArrayMap<> provides access to a static array in much the same way as CStaticArraySet<>,...
Definition: static_map.hpp:175
TBase::const_iterator const_iterator
Definition: static_map.hpp:179
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
Severity –.
Definition: ncbidiag.hpp:833
static HENV env
Definition: transaction2.c:38
const CNcbiEnvironment & GetEnvironment(void) const
Get the application's cached environment.
@ eNoOwnership
No ownership is assumed.
Definition: ncbi_types.h:135
#define NULL
Definition: ncbistd.hpp:225
void PrintRequestStop(void)
Print request stop message (for request-driven applications)
Definition: ncbidiag.cpp:2778
CDiagContext_Extra & Print(const string &name, const string &value)
The method does not print the argument, but adds it to the string.
Definition: ncbidiag.cpp:2622
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
void PrintRequestStart(const string &message)
Print request start message (for request-driven applications)
Definition: ncbidiag.cpp:2762
string GetSessionID(void) const
Session ID.
void SetRequestID(TCount rid)
Set request ID.
const string & GetNextSubHitID(CTempString prefix=CTempString())
Get current hit id appended with auto-incremented sub-hit id.
#define ERR_POST_X_ONCE(err_subcode, message)
Error posting only once during program execution with default error code and given error subcode.
Definition: ncbidiag.hpp:621
void SetClientIP(const string &client)
bool IsSetSessionID(void) const
static CRequestContext & GetRequestContext(void)
Shortcut to CDiagContextThreadData::GetThreadData().GetRequestContext()
Definition: ncbidiag.cpp:1901
string GetClientIP(void) const
Client IP/hostname.
void Enumerate(TCallback callback)
Enumerate all properties.
bool IsSet(CTempString name) const
Check if the property is set.
const string & GetDtab(void) const
void Flush(void)
Print the message and reset object.
Definition: ncbidiag.cpp:2332
bool IsSetClientIP(void) const
void AddPassThroughProperty(const string &name, const string &value)
Add pass-through value if it matches a pattern from NCBI_CONTEXT_FIELDS.
void LogFields(const TEntries &entries) const
Log (as an extra) all names/values matching fields in NCBI_LOG_FIELDS.
Definition: ncbidiag.hpp:2408
const string & GetAppName(void) const
Get application name.
Definition: ncbidiag.cpp:1857
EDiagSev
Severity level for the posted diagnostics.
Definition: ncbidiag.hpp:650
const char * g_DiagUnknownFunction(void)
Definition: ncbidiag.cpp:8344
@ eDiag_Trace
Trace message.
Definition: ncbidiag.hpp:657
@ eDiag_Info
Informational message.
Definition: ncbidiag.hpp:651
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
static void AddStandardNCBIMetadata(TParent &cctx)
grpc::ClientContext TGRPCBaseClientContext
grpc::StatusCode g_AsGRPCStatusCode(CRequestStatus::ECode status_code)
static bool x_IsRealRequest(const TGRPCServerContext *sctx)
grpc::PropagationOptions TGRPCPropagationOptions
static void EndRequest(grpc::ServerContext *sctx)
grpc::ServerContext TGRPCServerContext
static unique_ptr< TParent > FromServerContext(const TGRPCServerContext &sc, TGRPCPropagationOptions opts=TGRPCPropagationOptions())
EInvocationType
How was BeginRequest or EndRequest called?
static bool IsImplemented(void)
string g_NCBI_GRPC_GetAddress(const char *section, const char *variable, const char *env_var_name, CParamBase::EParamSource *value_source)
Get "hostport" for the likes of "grpc::CreateChannel(hostport, ...)" trying (in order of priority):
static void BeginRequest(grpc::ServerContext *sctx)
@ eImplicit
From {Pre,Post}SynchronousRequest.
string g_GetConfigString(const char *section, const char *variable, const char *env_var_name, const char *default_value, CParamBase::EParamSource *src=nullptr)
Helper functions for getting values from registry/environment.
Definition: ncbi_param.cpp:397
EParamSource
Source of the value returned by CParam::GetDefault().
Definition: ncbi_param.hpp:395
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
size_type rfind(const CTempString match, size_type pos=npos) const
Find the first instance of the entire matching string within the current string in a backward directi...
Definition: tempstr.hpp:705
#define NPOS
Definition: ncbistr.hpp:133
CTempString & assign(const char *src_str, size_type len)
Assign new values to the content of the a string.
Definition: tempstr.hpp:733
bool empty(void) const
Return true if the represented string is empty (i.e., the length is zero)
Definition: tempstr.hpp:334
static string CParse(const CTempString str, EQuoted quoted=eQuoted)
Discard C-style backslash escapes.
Definition: ncbistr.cpp:3972
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5414
CTempString substr(size_type pos) const
Obtain a substring from this string, beginning at a given offset.
Definition: tempstr.hpp:776
size_type find(const CTempString match, size_type pos=0) const
Find the first instance of the entire matching string within the current string, beginning at an opti...
Definition: tempstr.hpp:655
static string CEncode(const CTempString str, EQuoted quoted=eQuoted)
Encode a string for C/C++.
Definition: ncbistr.cpp:3958
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3396
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
@ eNotQuoted
String is not quoted.
Definition: ncbistr.hpp:2991
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
static void s_SetHitID(CRequestContext &r, const string &s)
static void s_SetSessionID(CRequestContext &r, const string &s)
SStaticPair< CRequestStatus::ECode, grpc::StatusCode > TStatusCodePair
SStaticPair< const char *, FRCSetter > TRCSetterPair
static void s_SetClientIP(CRequestContext &r, const string &s)
void(* FRCSetter)(CRequestContext &, const string &)
static string s_EncodeMetadataName(const string &name)
static string s_DecodeMetadataValue(const CTempString &value)
static CGRPCInitializer s_GRPCInitializer
static const TRCSetterPair sc_RCSetters[]
static void s_SetDtab(CRequestContext &r, const string &s)
CStaticArrayMap< CRequestStatus::ECode, grpc::StatusCode > TStatusCodeMap
static string s_EncodeMetadataValue(const string &value)
CStaticArrayMap< const char *, FRCSetter, PCase_CStr > TRCSetterMap
DEFINE_STATIC_ARRAY_MAP(TStatusCodeMap, sc_ErrorCodeMap, sc_ErrorCodes)
#define TSCP(x, y)
static const TStatusCodePair sc_ErrorCodes[]
static void s_NCBI_GPR_Log_Function(gpr_log_func_args *args)
static string s_DecodeMetadataName(const CTempString &name)
Definition of all error codes used in serial libraries (xser.lib, xcser.lib).
char * buf
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
char * NcbiGetHostIP(char *buf, size_t bufsize)
Definition: ncbi_ifconf.c:201
Defines the CNcbiApplication and CAppException classes for creating NCBI applications.
int isalnum(Uchar c)
Definition: ncbictype.hpp:62
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
Glue for integrating gRPC into the C++ toolkit, to ensure logging and metadata propagation (sid,...
Template structure SStaticPair is simlified replacement of STL pair<> Main reason of introducing this...
Definition: static_set.hpp:60
#define _ASSERT
else result
Definition: token2.c:20
Modified on Wed Sep 04 15:04:31 2024 by modify_doxy.py rev. 669887