1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef MY_XP_UTIL_INCLUDED 24 #define MY_XP_UTIL_INCLUDED 25 26 #include <mysql/gcs/mysql_gcs.h> 27 28 #ifdef _WIN32 29 #include <windows.h> 30 #else 31 #include <unistd.h> 32 #endif 33 34 #if defined(WIN32) || defined(WIN64) 35 #include <Winsock2.h> 36 #include <ws2tcpip.h> 37 #ifndef INET_ADDRSTRLEN 38 #define socklen_t int 39 #endif 40 #else 41 #include <arpa/inet.h> 42 #include <netinet/in.h> 43 #include <netinet/tcp.h> 44 #include <sys/types.h> 45 #include <sys/socket.h> 46 #include <sys/time.h> 47 #include <time.h> 48 #endif 49 #include <iostream> 50 #include <errno.h> 51 #include <stdint.h> 52 53 #define INT_MAX32 0x7FFFFFFFL 54 #define MY_MIN(a, b) ((a) < (b) ? (a) : (b)) 55 56 57 #ifdef _WIN32 58 59 #define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) 60 #define MS 10000000 61 62 #ifdef HAVE_STRUCT_TIMESPEC 63 #include<time.h> 64 #endif 65 66 #endif 67 68 #ifndef HAVE_STRUCT_TIMESPEC /* Windows before VS2015 */ 69 /* 70 Declare a union to make sure FILETIME is properly aligned 71 so it can be used directly as a 64 bit value. The value 72 stored is in 100ns units. 73 */ 74 union ft64 { 75 FILETIME ft; 76 __int64 i64; 77 }; 78 79 struct timespec { 80 union ft64 tv; 81 /* The max timeout value in millisecond for native_cond_timedwait */ 82 long max_timeout_msec; 83 }; 84 85 #endif /* !HAVE_STRUCT_TIMESPEC */ 86 87 88 /** 89 @class My_xp_util 90 91 Class where cross platform utilities reside as static methods. 92 */ 93 class My_xp_util 94 { 95 public: 96 /** 97 Current thread sleeps for the parameterized number of seconds. 98 99 @param seconds number of seconds for invoking thread to sleep 100 */ 101 102 static void sleep_seconds(unsigned int seconds); 103 104 /* Code ported from MySQL Server to deal with timespec. */ 105 #ifdef _WIN32 106 static uint64_t query_performance_frequency, query_performance_offset; 107 108 static void win_init_time(); 109 #endif 110 111 /** 112 Init time. 113 */ 114 115 static void init_time(); 116 117 118 /** 119 Get the system's time. 120 121 @return system's time in 100s of nanoseconds 122 */ 123 124 static uint64_t getsystime(void); 125 126 127 /** 128 Set the value of the timespec struct equal to the argument in nanoseconds. 129 */ 130 set_timespec_nsec(struct timespec * abstime,uint64_t nsec)131 static inline void set_timespec_nsec(struct timespec *abstime, uint64_t nsec) 132 { 133 #ifdef HAVE_STRUCT_TIMESPEC 134 uint64_t now= My_xp_util::getsystime() + (nsec / 100); 135 uint64_t tv_sec= now / 10000000ULL; 136 #if SIZEOF_TIME_T < SIZEOF_LONG_LONG 137 /* Ensure that the number of seconds don't overflow. */ 138 tv_sec= MY_MIN(tv_sec, ((uint64_t)INT_MAX32)); 139 #endif 140 abstime->tv_sec= (time_t)tv_sec; 141 abstime->tv_nsec= (now % 10000000ULL) * 100 + (nsec % 100); 142 #else /* !HAVE_STRUCT_TIMESPEC */ 143 uint64_t max_timeout_msec= (nsec / 1000000); 144 union ft64 tv; 145 GetSystemTimeAsFileTime(&tv.ft); 146 abstime->tv.i64= tv.i64 + (__int64)(nsec / 100); 147 #if SIZEOF_LONG < SIZEOF_LONG_LONG 148 /* Ensure that the msec value doesn't overflow. */ 149 max_timeout_msec= MY_MIN(max_timeout_msec, ((uint64_t)INT_MAX32)); 150 #endif 151 abstime->max_timeout_msec= (long)max_timeout_msec; 152 #endif /* !HAVE_STRUCT_TIMESPEC */ 153 } 154 155 156 /** 157 Set the value of the timespec struct equal to the argument in seconds. 158 */ 159 set_timespec(struct timespec * abstime,uint64_t sec)160 static inline void set_timespec(struct timespec *abstime, uint64_t sec) 161 { 162 My_xp_util::set_timespec_nsec(abstime, sec * 1000000000ULL); 163 } 164 165 166 /** 167 Compare two timespec structs. 168 169 @retval 1 If ts1 ends after ts2. 170 @retval -1 If ts1 ends before ts2. 171 @retval 0 If ts1 is equal to ts2. 172 */ 173 cmp_timespec(struct timespec * ts1,struct timespec * ts2)174 static inline int cmp_timespec(struct timespec *ts1, struct timespec *ts2) 175 { 176 #ifdef HAVE_STRUCT_TIMESPEC 177 if (ts1->tv_sec > ts2->tv_sec || 178 (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec > ts2->tv_nsec)) 179 return 1; 180 if (ts1->tv_sec < ts2->tv_sec || 181 (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec < ts2->tv_nsec)) 182 return -1; 183 #else 184 if (ts1->tv.i64 > ts2->tv.i64) 185 return 1; 186 if (ts1->tv.i64 < ts2->tv.i64) 187 return -1; 188 #endif 189 return 0; 190 } 191 192 193 /** 194 Diff two timespec structs. 195 196 @return difference between the two arguments. 197 */ 198 diff_timespec(struct timespec * ts1,struct timespec * ts2)199 static inline uint64_t diff_timespec(struct timespec *ts1, 200 struct timespec *ts2) 201 { 202 #ifdef HAVE_STRUCT_TIMESPEC 203 return (ts1->tv_sec - ts2->tv_sec) * 1000000000ULL + 204 ts1->tv_nsec - ts2->tv_nsec; 205 #else 206 return (ts1->tv.i64 - ts2->tv.i64) * 100; 207 #endif 208 } 209 }; 210 211 212 /** 213 @class My_xp_socket_util 214 215 Interface for socket utility methods. 216 */ 217 class My_xp_socket_util 218 { 219 public: 220 221 /** 222 Disable Nagle algorithm in the specified socket. 223 224 @param fd file descriptor of the socket 225 */ 226 227 virtual int disable_nagle_in_socket(int fd)= 0; 228 ~My_xp_socket_util()229 virtual ~My_xp_socket_util() {}; 230 }; 231 232 233 class My_xp_socket_util_impl : public My_xp_socket_util 234 { 235 public: 236 int disable_nagle_in_socket(int fd); My_xp_socket_util_impl()237 explicit My_xp_socket_util_impl() {}; ~My_xp_socket_util_impl()238 ~My_xp_socket_util_impl() {}; 239 }; 240 241 #endif // MY_XP_UTIL_INCLUDED 242