Exemple #1
0
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;
}
Exemple #3
0
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();
}