TSvrRef CDBDefaultServiceMapper::GetServer(const string& service) { if (m_SrvSet.find(service) != m_SrvSet.end()) { return TSvrRef(); } return TSvrRef(new CDBServer(service)); }
CDB_Connection* CDBConnectionFactory::MakeDBConnection( I_DriverContext& ctx, const CDBConnParams& params) { CFastMutexGuard mg(m_Mtx); CDB_UserHandler::ClearExceptions(m_Errors); CDB_Connection* t_con = NULL; CRuntimeData& rt_data = GetRuntimeData(params.GetConnValidator()); TSvrRef dsp_srv = rt_data.GetDispatchedServer(params.GetServerName()); // Prepare to collect messages, whose proper severity depends on whether // ANY attempt succeeds. impl::CDBHandlerStack ultimate_handlers; {{ const impl::CDriverContext* ctx_impl = dynamic_cast<impl::CDriverContext*>(&ctx); if (params.GetOpeningMsgHandlers().GetSize() > 0) { ultimate_handlers = params.GetOpeningMsgHandlers(); } else if (ctx_impl != NULL) { ultimate_handlers = ctx_impl->GetCtxHandlerStack(); } else { ultimate_handlers.Push(&CDB_UserHandler::GetDefault()); } }} SOpeningContext opening_ctx(ctx); CRef<CDB_UserHandler_Deferred> handler (new CDB_UserHandler_Deferred(ultimate_handlers)); opening_ctx.handlers.Push(&*handler, eTakeOwnership); // Store original query timeout ... unsigned int query_timeout = ctx.GetTimeout(); // Set "validation timeouts" ... ctx.SetTimeout(CalculateConnectionTimeout(ctx)); ctx.SetLoginTimeout(CalculateLoginTimeout(ctx)); if ( dsp_srv.Empty() ) { // We are here either because server name was never dispatched or // because a named connection pool has been used before. // Dispatch server name ... t_con = DispatchServerName(opening_ctx, params); } else { // Server name is already dispatched ... string single_server(params.GetParam("single_server")); // We probably need to re-dispatch it ... if (single_server != "true" && GetMaxNumOfDispatches() && rt_data.GetNumOfDispatches(params.GetServerName()) >= GetMaxNumOfDispatches()) { // We definitely need to re-dispatch it ... // Clean previous info ... rt_data.SetDispatchedServer(params.GetServerName(), TSvrRef()); t_con = DispatchServerName(opening_ctx, params); } else { // We do not need to re-dispatch it ... // Try to connect. try { // I_DriverContext::SConnAttr cur_conn_attr(conn_attr); // cur_conn_attr.srv_name = dsp_srv->GetName(); CDB_DBLB_Delegate cur_params( dsp_srv->GetName(), dsp_srv->GetHost(), dsp_srv->GetPort(), params); cur_params.SetOpeningMsgHandlers() = opening_ctx.handlers; // MakeValidConnection may return NULL here because a newly // created connection may not pass validation. t_con = MakeValidConnection(opening_ctx, // cur_conn_attr, cur_params); } catch (CDB_Exception& ex) { // m_Errors.push_back(ex.Clone()); opening_ctx.handlers.PostMsg(&ex); if (params.GetConnValidator()) { opening_ctx.conn_status = params.GetConnValidator()->ValidateException(ex); } } if (!t_con) { // We couldn't connect ... if (single_server != "true") { // Server might be temporarily unavailable ... // Check conn_status ... if (opening_ctx.conn_status == IConnValidator::eTempInvalidConn) { rt_data.IncNumOfValidationFailures(params.GetServerName(), dsp_srv); } // Re-dispatch ... t_con = DispatchServerName(opening_ctx, params); } } else { // Dispatched server is already set, but calling of this method // will increase number of successful dispatches. rt_data.SetDispatchedServer(params.GetServerName(), dsp_srv); } } } // Restore original connection timeout ... ctx.SetTimeout(query_timeout); // Restore original query timeout ... if (t_con) { t_con->SetTimeout(query_timeout); } x_LogConnection(opening_ctx, t_con, params); handler->Flush((t_con == NULL) ? eDiagSevMax : eDiag_Warning); return t_con; }
BEGIN_NCBI_SCOPE ////////////////////////////////////////////////////////////////////////////// static TSvrRef make_server(const CTempString& specification, double& preference) { CTempString server; // string host; Uint4 host = 0; Uint2 port = 0; string::size_type pos = 0; pos = specification.find_first_of("@(", pos); if (pos != string::npos) { server = specification.substr(0, pos); if (specification[pos] == '@') { // string::size_type old_pos = pos + 1; pos = specification.find_first_of(":(", pos + 1); if (pos != string::npos) { // string host_str = specification.substr(old_pos, pos - old_pos); // Ignore host in order to avoid dependebcy on libconnect. // SOCK_StringToHostPort(specification.c_str() + old_pos, &host, &port); if (specification[pos] == ':') { port = NStr::StringToUInt(specification.substr(pos + 1), NStr::fAllowLeadingSpaces | NStr::fAllowTrailingSymbols | NStr::fConvErr_NoThrow); pos = specification.find("(", pos + 1); if (pos != string::npos) { // preference = NStr::StringToDouble( preference = NStr::StringToUInt( specification.substr(pos + 1), NStr::fAllowLeadingSpaces | NStr::fAllowTrailingSymbols | NStr::fConvErr_NoThrow); } } else { // preference = NStr::StringToDouble( preference = NStr::StringToUInt( specification.substr(pos + 1), NStr::fAllowLeadingSpaces | NStr::fAllowTrailingSymbols | NStr::fConvErr_NoThrow); } } else { // host = specification.substr(old_pos); // Ignore host in order to avoid dependebcy on libconnect. // SOCK_StringToHostPort(specification.c_str() + old_pos, &host, &port); } } else { // preference = NStr::StringToDouble( preference = NStr::StringToUInt( specification.substr(pos + 1), NStr::fAllowLeadingSpaces | NStr::fAllowTrailingSymbols | NStr::fConvErr_NoThrow); } } else { server = specification; } if (server.empty() && host == 0) { DATABASE_DRIVER_ERROR("Either server name or host name expected.", 110100 ); } return TSvrRef(new CDBServer(server, host, port)); }
TSvrRef CDBLB_ServiceMapper::GetServer(const string& service) { CFastMutexGuard mg(m_Mtx); TSrvSet& exclude_list = m_ExcludeMap[service]; time_t cur_time = time(NULL); ERASE_ITERATE(TSrvSet, it, exclude_list) { if ((*it)->GetExpireTime() <= cur_time) { _TRACE("For " << service << ": erasing from excluded server '" << (*it)->GetName() << "', host " << (*it)->GetHost() << ", port " << (*it)->GetPort()); exclude_list.erase(it); m_LBEmptyMap.erase(service); } } TLBEmptyMap::iterator it = m_LBEmptyMap.find(service); if (it != m_LBEmptyMap.end()) { if (it->second >= cur_time) { // We've tried this service already. It is not served by load // balancer. There is no reason to try it again. _TRACE("Service " << service << " is known dead, bypassing LBSM."); return TSvrRef(); } else { m_LBEmptyMap.erase(it); } } vector<const char*> skip_names; std::for_each(exclude_list.begin(), exclude_list.end(), CCharInserter(skip_names)); skip_names.push_back(NULL); SDBLB_Preference preference; TSvrRef preferred_svr = m_PreferenceMap[service].second; if (!preferred_svr.Empty()) { preference.host = preferred_svr->GetHost(); preference.port = preferred_svr->GetPort(); preference.pref = m_PreferenceMap[service].first; } SDBLB_ConnPoint cp; char name_buff[256]; EDBLB_Status status; const char* svr_name = ::DBLB_GetServer(service.c_str(), fDBLB_AllowFallbackToStandby, preferred_svr.Empty() ? 0 : &preference, &skip_names.front(), &cp, name_buff, sizeof(name_buff), &status); if (cp.time == 0) { cp.time = TNCBI_Time(cur_time) + 10; } if (svr_name && *svr_name && status != eDBLB_NoDNSEntry) { return TSvrRef(new CDBServer(svr_name, cp.host, cp.port, cp.time)); } else if (cp.host) { return TSvrRef(new CDBServer(kEmptyStr, cp.host, cp.port, cp.time)); } _TRACE("Remembering: service " << service << " is dead."); m_LBEmptyMap[service] = cur_time + m_EmptyTTL; return TSvrRef(); }