1 #ifndef CONNECT__IMPL__SOCKET_ADDRESS__HPP
2 #define CONNECT__IMPL__SOCKET_ADDRESS__HPP
3 
4 /*  $Id: connect_misc.hpp 622184 2020-12-21 18:30:13Z ivanov $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Rafael Sadyrov
30  *
31  */
32 
33 #include <connect/connect_export.h>
34 
35 #include <corelib/ncbistl.hpp>
36 #include <corelib/ncbistr.hpp>
37 
38 #include <chrono>
39 #include <memory>
40 #include <mutex>
41 #include <regex>
42 #include <sstream>
43 #include <string>
44 #include <unordered_map>
45 #include <utility>
46 #include <vector>
47 
48 BEGIN_NCBI_SCOPE
49 
50 struct NCBI_XCONNECT_EXPORT SSocketAddress
51 {
52     unsigned host;
53     unsigned short port;
54 
55     struct NCBI_XCONNECT_EXPORT SHost
56     {
57         unsigned host;
SHostSSocketAddress::SHost58         SHost(unsigned h) : host(h) {}
59         SHost(const string& h);
60     };
61 
62     struct SPort
63     {
64         unsigned short port;
SPortSSocketAddress::SPort65         SPort(unsigned short p) : port(p) {}
SPortSSocketAddress::SPort66         SPort(const string& p)  : port(NStr::StringToNumeric<unsigned short>(p)) {}
SPortSSocketAddress::SPort67         SPort(CTempString p)    : port(NStr::StringToNumeric<unsigned short>(p)) {}
68     };
69 
SSocketAddressSSocketAddress70     SSocketAddress(SHost h, SPort p) : host(h.host), port(p.port) {}
71 
operator boolSSocketAddress72     explicit operator bool() const { return host && port; }
73     string GetHostName() const;
AsStringSSocketAddress74     string AsString() const { return GetHostName() + ':' + NStr::UIntToString(port); }
75 
76     static SSocketAddress Parse(const string& address);
77 };
78 
79 NCBI_XCONNECT_EXPORT bool operator==(const SSocketAddress& lhs, const SSocketAddress& rhs);
80 NCBI_XCONNECT_EXPORT bool operator< (const SSocketAddress& lhs, const SSocketAddress& rhs);
81 
82 class NCBI_XCONNECT_EXPORT CServiceDiscovery
83 {
84 public:
85     CServiceDiscovery(const string& service_name);
86 
87     using TServer = pair<SSocketAddress, double>;
88     using TServers = vector<TServer>;
89     TServers operator()();
90 
GetServiceName() const91     const string& GetServiceName() const { return m_ServiceName; }
IsSingleServer() const92     bool IsSingleServer() const { return m_IsSingleServer; }
93 
94     static TServers DiscoverImpl(const string&, unsigned, shared_ptr<void>&, pair<string, const char*>, int, unsigned long);
95 
96 private:
97     const string m_ServiceName;
98     shared_ptr<void> m_Data;
99     const bool m_IsSingleServer;
100 };
101 
102 template <class TType>
103 struct SThreadSafe
104 {
105     template <class T>
106     struct SLock : private unique_lock<std::mutex>
107     {
operator *SThreadSafe::SLock108         T& operator*()  { _ASSERT(m_Object); return *m_Object; }
operator ->SThreadSafe::SLock109         T* operator->() { _ASSERT(m_Object); return  m_Object; }
110 
111         // More convenient RAII alternative to explicit scopes or 'unlock' method.
112         // It allows locks to be declared inside 'if' condition.
113         using unique_lock<std::mutex>::operator bool;
114 
UnlockSThreadSafe::SLock115         void Unlock() { m_Object = nullptr; unlock(); }
116 
117     private:
SLockSThreadSafe::SLock118         SLock(T* c, std::mutex& m) : unique_lock(m), m_Object(c) { _ASSERT(m_Object); }
119 
120         T* m_Object;
121 
122         friend struct SThreadSafe;
123     };
124 
125     template <class... TArgs>
SThreadSafeSThreadSafe126     SThreadSafe(TArgs&&... args) : m_Object(forward<TArgs>(args)...) {}
127 
GetLockSThreadSafe128     SLock<      TType> GetLock()       { return { &m_Object, m_Mutex }; }
GetLockSThreadSafe129     SLock<const TType> GetLock() const { return { &m_Object, m_Mutex }; }
130 
131     // Direct access to the protected object (e.g. to access atomic members).
132     // All thread-safe members must be explicitly marked volatile to be available.
GetMTSafeSThreadSafe133           volatile TType& GetMTSafe()       { return m_Object; }
GetMTSafeSThreadSafe134     const volatile TType& GetMTSafe() const { return m_Object; }
135 
136 protected:
137     mutex m_Mutex;
138 
139 private:
140     TType m_Object;
141 };
142 
143 class NCBI_XCONNECT_EXPORT CLogLatencies
144 {
145 public:
146     template <size_t SIZE1, size_t SIZE2>
CLogLatencies(const char (& s1)[SIZE1],const char (& s2)[SIZE2])147     CLogLatencies(const char (&s1)[SIZE1], const char (&s2)[SIZE2]) :
148         m_Start(s1, SIZE1 - 1),
149         m_Stop(s2, SIZE2 - 1)
150     {}
151 
SetDebug(bool debug)152     void SetDebug(bool debug) { m_Debug = debug; }
153 
154     using TResult = unordered_map<string, chrono::microseconds>;
155     TResult Parse(istream& is);
156 
157 private:
158     regex m_Start;
159     regex m_Stop;
160     bool m_Debug = false;
161 };
162 
163 class NCBI_XCONNECT_EXPORT CLogLatencyReport : public CLogLatencies
164 {
165 public:
166     template <class... TArgs>
CLogLatencyReport(TArgs &&...args)167     CLogLatencyReport(TArgs&&... args) : CLogLatencies(forward<TArgs>(args)...) {}
168 
169     ~CLogLatencyReport();
170 
171     void Start();
operator bool() const172     explicit operator bool() const { return m_CerrBuf; }
173 
174 private:
175     struct SNullBuf : streambuf
176     {
overflowCLogLatencyReport::SNullBuf177         int_type overflow(int_type c) override { return traits_type::not_eof(c); }
178     };
179 
180     SNullBuf m_NullBuf;
181     stringstream m_CerrOutput;
182     streambuf* m_CerrBuf = nullptr;
183 };
184 
185 END_NCBI_SCOPE
186 
187 #endif
188