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

Go to the SVN repository for this file.

1 /* $Id: dbapi_pool_balancer.cpp 102149 2024-04-09 13:58:35Z 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 * Help distribute connections within a pool across servers.
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 
39 #include <dbapi/error_codes.hpp>
40 
41 #include <numeric>
42 #include <random>
43 
44 #define NCBI_USE_ERRCODE_X Dbapi_PoolBalancer
45 
47 
49 {
50 public:
52  : CDBConnParamsDelegate(other)
53  { }
54 
55  string GetParam(const string& key) const
56  {
57  if (key == "do_not_connect") {
58  return "true";
59  } else {
61  }
62  }
63 };
64 
65 
67 {
68 public:
70  : m_Server(server)
71  { _ASSERT(server.NotEmpty()); }
72 
73  const string& ServerName(void) const override
74  { return m_Server->GetName(); }
75  Uint4 Host(void) const override
76  { return m_Server->GetHost(); }
77  Uint2 Port(void) const override
78  { return m_Server->GetPort(); }
79 
80 private:
82 };
83 
84 
86  const string& pool_name,
87  I_DriverContext* driver_ctx,
88  bool is_pooled)
89  : CPoolBalancer(service_info.GetServiceName(), service_info.GetOptions(),
90  x_GetFlags(driver_ctx, is_pooled)),
91  m_ServiceInfo(&service_info), m_PoolName(pool_name),
92  m_DriverCtx(driver_ctx), m_IsPooled(is_pooled)
93 {
95 }
96 
97 
98 CPoolBalancer::TFlags CDBPoolBalancer::x_GetFlags(I_DriverContext* driver_ctx,
99  bool is_pooled)
100 {
101  TFlags flags = static_cast<EFlags>(0);
102  if (driver_ctx != nullptr
103  && !NStr::StartsWith(driver_ctx->GetDriverName(), "ftds")) {
104  flags |= fIgnoreRawIPs;
105  }
106  if ( !is_pooled ) {
107  flags |= fNoPooling;
108  }
109  return flags;
110 }
111 
112 
114 {
115  const impl::CDriverContext* ctx_impl
116  = dynamic_cast<const impl::CDriverContext*>(m_DriverCtx);
118  if (ctx_impl == NULL) {
119  if (m_DriverCtx != nullptr) {
120  ERR_POST_X(1, Warning <<
121  "Called with non-standard IDriverContext");
122  }
123  } else if (x_NoPooling()) {
124  } else if (m_PoolName.empty()) {
126  &counts);
127  } else {
128  ctx_impl->GetCountsForPool(m_PoolName, &counts);
129  }
130  x_InitFromCounts(counts);
131 }
132 
133 
135 {
136  auto params = static_cast<const CDBConnParams*>(params_in);
137  _ASSERT(params != nullptr);
138  if (m_DriverCtx == nullptr) {
139  return nullptr;
140  } else if (x_NoPooling()) {
141  auto server = m_ServiceInfo->GetMappedServer();
142  if (server.Empty()) {
143  return nullptr;
144  } else {
146  auto it = m_FakeConnections.lower_bound(server);
147  if (it == m_FakeConnections.end() || it->first != server) {
148  it = m_FakeConnections.emplace_hint
149  (it, server, new CDB_FakeConnection(server));
150  }
151  return it->second.get();
152  }
153  } else {
154  CDBConnParams_DNC dnc_params(*params);
155  IBalanceable * conn = nullptr;
156  {{
159  dnc_params);
160  }}
161  if (conn == nullptr) {
163  }
164  return conn;
165  }
166 }
167 
168 
169 unsigned int CDBPoolBalancer::x_GetCount(const void* params_in,
170  const string& name)
171 {
172  auto params = static_cast<const CDBConnParams*>(params_in);
173  _ASSERT(params != nullptr);
174  string pool_name = params->GetParam("pool_name");
175  return m_DriverCtx->NofConnections(name, pool_name);
176 }
177 
178 
179 unsigned int CDBPoolBalancer::x_GetPoolMax(const void* params_in)
180 {
181  auto params = static_cast<const CDBConnParams*>(params_in);
182  _ASSERT(params != nullptr);
183  string pool_max_str = params->GetParam("pool_maxsize");
184  unsigned int pool_max = 0u;
185  if ( !pool_max_str.empty() && pool_max_str != "default") {
186  NStr::StringToNumeric(pool_max_str, &pool_max,
188  }
189  return pool_max;
190 }
191 
192 
193 void CDBPoolBalancer::x_Discard(const void* params_in, IBalanceable* conn_in)
194 {
195  auto params = static_cast<const CDBConnParams*>(params_in);
196  _ASSERT(params != nullptr);
197  auto conn = dynamic_cast<const CDB_Connection*>(conn_in);
198  if (conn == nullptr) {
199  _ASSERT(dynamic_cast<const CDB_FakeConnection*>(conn_in) != nullptr);
200  return;
201  }
202  _TRACE("Proceeding to request turnover");
203  string server_name = conn->ServerName();
204  bool was_reusable = conn->IsReusable();
205  delete conn;
206  if (was_reusable) {
207  // This call might not close the exact connection we
208  // considered, but closing any connection to the
209  // relevant server is sufficient here.
211  (server_name, params->GetParam("pool_name"), 1u);
212  }
213 }
214 
215 
CDBConnParams_DNC(const CDBConnParams &other)
string GetParam(const string &key) const
Parameters, which are not listed above explicitly, should be retrieved via SetParam() method.
CDBConnParams::
Definition: interfaces.hpp:258
Uint2 GetPort(void) const
const string & GetName(void) const
Uint4 GetHost(void) const
Uint4 Host(void) const override
CDB_FakeConnection(TSvrRef server)
const string & ServerName(void) const override
Uint2 Port(void) const override
void x_InitFromCounts(const TCounts &counts)
bool x_NoPooling(void) const
static CDB_Connection * CtxMakeConnection(I_DriverContext &ctx, const CDBConnParams &params)
Helper method to provide access to a protected method in I_DriverContext for child classses.
void GetCountsForPool(const string &pool_name, TCounts *counts) const
void GetCountsForService(const string &service, TCounts *counts) const
const_iterator end() const
Definition: map.hpp:152
const_iterator lower_bound(const key_type &key) const
Definition: map.hpp:154
static uch flags
Help distribute connections within a pool across servers.
static CS_CONNECTION * conn
Definition: ct_dynamic.c:25
#define NULL
Definition: ncbistd.hpp:225
static TFlags x_GetFlags(I_DriverContext *driver_ctx, bool is_pooled)
TFakeConnections m_FakeConnections
I_DriverContext * m_DriverCtx
void x_Discard(const void *params, IBalanceable *conn) override
virtual TSvrRef GetMappedServer(void)=0
virtual const string & GetServiceName(void) const =0
CRef< IDBServiceInfo > m_ServiceInfo
unsigned int x_GetCount(const void *params, const string &name) override
IBalanceable * x_TryPool(const void *params) override
unsigned int x_GetPoolMax(const void *params) override
CDBPoolBalancer(IDBServiceInfo &service_info, const string &pool_name, I_DriverContext *driver_ctx=nullptr, bool is_pooled=true)
virtual string GetParam(const string &key) const
Parameters, which are not listed above explicitly, should be retrieved via SetParam() method.
Definition: interfaces.cpp:128
virtual string GetDriverName(void) const
Definition: interfaces.cpp:342
virtual void CloseUnusedConnections(const string &srv_name=kEmptyStr, const string &pool_name=kEmptyStr, unsigned int max_closings=kMax_UInt)=0
Close reusable deleted connections for specified server and/or pool.
virtual unsigned int NofConnections(const string &srv_name="", const string &pool_name="") const =0
Return number of currently open connections in this context.
#define _TRACE(message)
Definition: ncbidbg.hpp:122
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
bool NotEmpty(void) const THROWS_NONE
Check if CRef is not empty – pointing to an object and has a non-null value.
Definition: ncbiobj.hpp:726
uint32_t Uint4
4-byte (32-bit) unsigned integer
Definition: ncbitype.h:103
uint16_t Uint2
2-byte (16-bit) unsigned integer
Definition: ncbitype.h:101
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static TNumeric StringToNumeric(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to a numeric value.
Definition: ncbistr.hpp:330
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:5412
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
Definition of all error codes used in dbapi libraries (dbapi_driver.lib and others).
const struct ncbi::grid::netcache::search::fields::KEY key
#define _ASSERT
Modified on Wed Apr 24 14:19:28 2024 by modify_doxy.py rev. 669887