1 /*  $Id: ncbi_dbsvcmapper.cpp 626334 2021-02-25 18:42:15Z ivanov $
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 *   Database service name to server mapping policy.
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 
36 #include <corelib/impl/ncbi_dbsvcmapper.hpp>
37 #include <corelib/ncbierror.hpp>
38 
39 BEGIN_NCBI_SCOPE
40 
41 
CEndpointKey(const CTempString & name,NStr::TConvErrFlags flags)42 CEndpointKey::CEndpointKey(const CTempString& name, NStr::TConvErrFlags flags)
43 {
44     CTempString  address  = name;
45     SIZE_TYPE    pos      = name.find_first_not_of("0123456789.:");
46     if (pos != NPOS) {
47         string msg = ("Unsupported endpoint key character "
48                       + NStr::CEncode(CTempString(name.substr(pos, 1))));
49         if ((flags & NStr::fConvErr_NoThrow) == 0) {
50             NCBI_THROW2(CStringException, eFormat, msg, pos);
51         } else {
52             if ((flags & NStr::fConvErr_NoErrMessage) != 0) {
53                 CNcbiError::Set(CNcbiError::eInvalidArgument);
54             } else {
55                 CNcbiError::Set(CNcbiError::eInvalidArgument,
56                                 FORMAT(msg << " at position " << pos));
57             }
58             m_Value = 0;
59             return;
60         }
61     }
62     Uint2 port = 0;
63     pos = address.find(':');
64     if (pos != NPOS) {
65         if ( !NStr::StringToNumeric(address.substr(pos + 1), &port, flags)) {
66             m_Value = 0;
67             return;
68         }
69         address = address.substr(0, pos);
70     }
71     union { // to help produce network byte order
72         Uint4 i;
73         Uint1 c[4];
74     } host = { 0, };
75     if (count(address.begin(), address.end(), '.') != 3) {
76         string msg = "Wrong number of components in IP address " + address;
77         if ((flags & NStr::fConvErr_NoThrow) == 0) {
78             NCBI_THROW2(CStringException, eFormat, msg, address.size());
79         } else {
80             if ((flags & NStr::fConvErr_NoErrMessage) != 0) {
81                 CNcbiError::Set(CNcbiError::eInvalidArgument);
82             } else {
83                 CNcbiError::Set(CNcbiError::eInvalidArgument, msg);
84             }
85             m_Value = 0;
86             return;
87         }
88         return;
89     }
90     for (int i = 0;  i < 4;  ++i) {
91         CTempString component;
92         switch (i) {
93         case 0:
94             pos = address.find('.');
95             component = address.substr(0, pos);
96             break;
97         case 1: case 2:
98         {
99             SIZE_TYPE pos2 = address.find('.', pos + 1);
100             component = address.substr(pos + 1, pos2 - pos - 1);
101             pos = pos2;
102             break;
103         }
104         case 3:
105             component = address.substr(pos + 1);
106             break;
107         default:
108             _TROUBLE;
109         }
110         if ( !NStr::StringToNumeric(component, &host.c[i], flags)) {
111             m_Value = 0;
112             return;
113         }
114 
115     }
116     m_Value = (TValue(host.i) << 16) | port;
117 }
118 
119 
operator <<(ostream & os,const CEndpointKey & key)120 ostream& operator<<(ostream& os, const CEndpointKey& key)
121 {
122     auto host = key.GetHost();
123     const unsigned char* b = (const unsigned char*) &host;
124     os << Uint4(b[0]) << '.' << Uint4(b[1]) << '.' << Uint4(b[2]) << '.'
125        << Uint4(b[3]);
126     auto port = key.GetPort();
127     if (port != 0) {
128         os << ':' << port;
129     }
130     return os;
131 }
132 
133 
GetServerOptions(const string & name,TOptions * options)134 void IDBServiceMapper::GetServerOptions(const string& name, TOptions* options)
135 {
136     list<string> servers;
137     GetServersList(name, &servers);
138     options->clear();
139     CFastMutexGuard mg(m_Mtx);
140     const auto& exclusions = m_ExcludeMap[name];
141     for (const string& it : servers) {
142         options->emplace_back(new CDBServerOption(it, 0, 0, 1.0));
143         auto lb = exclusions.lower_bound(options->back());
144         if (lb != exclusions.end()  &&  (*lb)->GetName() == name) {
145             options->back()->m_State |= CDBServerOption::fState_Excluded;
146         }
147     }
148 }
149 
150 
151 END_NCBI_SCOPE
152