1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8 
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 
25 *****************************************************************************/
26 
27 /** @file ut/ut0ut.cc
28  Various utilities for Innobase.
29 
30  Created 5/11/1994 Heikki Tuuri
31  ********************************************************************/
32 
33 #include "my_config.h"
34 
35 #include <errno.h>
36 #include <time.h>
37 #include <string>
38 
39 #include "ha_prototypes.h"
40 
41 #ifdef HAVE_SYS_TIME_H
42 #include <sys/time.h>
43 #endif
44 
45 #ifndef UNIV_HOTBACKUP
46 #include <mysql_com.h>
47 #endif /* !UNIV_HOTBACKUP */
48 
49 #include "mysql_com.h"
50 #include "os0thread.h"
51 #include "ut0ut.h"
52 
53 #ifndef UNIV_HOTBACKUP
54 #include "sql/log.h"
55 #include "trx0trx.h"
56 #endif /* !UNIV_HOTBACKUP */
57 
58 #include "clone0api.h"
59 #include "mysql/components/services/log_builtins.h"
60 #include "sql/derror.h"
61 
62 namespace ut {
63 ulong spin_wait_pause_multiplier = 50;
64 }
65 
66 /** Returns system time. We do not specify the format of the time returned:
67  the only way to manipulate it is to use the function ut_difftime.
68  @return system time */
ut_time(void)69 ib_time_t ut_time(void) { return (time(nullptr)); }
70 
71 /** Returns the number of microseconds since epoch. Uses the monotonic clock.
72  @return us since epoch or 0 if failed to retrieve */
ut_time_monotonic_us(void)73 ib_time_monotonic_us_t ut_time_monotonic_us(void) {
74   const auto now = std::chrono::steady_clock::now();
75   return (std::chrono::duration_cast<std::chrono::microseconds>(
76               now.time_since_epoch())
77               .count());
78 }
79 
80 /** Returns the number of milliseconds since epoch. Uses the monotonic clock.
81  @return ms since epoch */
ut_time_monotonic_ms(void)82 ib_time_monotonic_ms_t ut_time_monotonic_ms(void) {
83   const auto now = std::chrono::steady_clock::now();
84   return (std::chrono::duration_cast<std::chrono::milliseconds>(
85               now.time_since_epoch())
86               .count());
87 }
88 
89 /** Returns the number of seconds since epoch. Uses the monotonic clock.
90  @return us since epoch or 0 if failed to retrieve */
ut_time_monotonic(void)91 ib_time_monotonic_t ut_time_monotonic(void) {
92   const auto now = std::chrono::steady_clock::now();
93 
94   const auto ret =
95       std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch())
96           .count();
97 
98   return (ret);
99 }
100 
101 /** Returns the difference of two times in seconds.
102  @return time2 - time1 expressed in seconds */
ut_difftime(ib_time_t time2,ib_time_t time1)103 double ut_difftime(ib_time_t time2, /*!< in: time */
104                    ib_time_t time1) /*!< in: time */
105 {
106   return (difftime(time2, time1));
107 }
108 
109 #ifdef UNIV_HOTBACKUP
110 /** Sprintfs a timestamp to a buffer with no spaces and with ':' characters
111 replaced by '_'.
112 @param[in]	buf	buffer where to sprintf */
meb_sprintf_timestamp_without_extra_chars(char * buf)113 void meb_sprintf_timestamp_without_extra_chars(
114     char *buf) /*!< in: buffer where to sprintf */
115 {
116 #ifdef _WIN32
117   SYSTEMTIME cal_tm;
118 
119   GetLocalTime(&cal_tm);
120 
121   sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", (int)cal_tm.wYear % 100,
122           (int)cal_tm.wMonth, (int)cal_tm.wDay, (int)cal_tm.wHour,
123           (int)cal_tm.wMinute, (int)cal_tm.wSecond);
124 #else
125   struct tm *cal_tm_ptr;
126   time_t tm;
127 
128   struct tm cal_tm;
129   time(&tm);
130   localtime_r(&tm, &cal_tm);
131   cal_tm_ptr = &cal_tm;
132   sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", cal_tm_ptr->tm_year % 100,
133           cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, cal_tm_ptr->tm_hour,
134           cal_tm_ptr->tm_min, cal_tm_ptr->tm_sec);
135 #endif
136 }
137 
138 #else  /* UNIV_HOTBACKUP */
139 
ut_delay(ulint delay)140 ulint ut_delay(ulint delay) {
141   ulint i, j;
142   /* We don't expect overflow here, as ut::spin_wait_pause_multiplier is limited
143   to 100, and values of delay are not larger than @@innodb_spin_wait_delay
144   which is limited by 1 000. Anyway, in case an overflow happened, the program
145   would still work (as iterations is unsigned). */
146   const ulint iterations = delay * ut::spin_wait_pause_multiplier;
147   UT_LOW_PRIORITY_CPU();
148 
149   j = 0;
150 
151   for (i = 0; i < iterations; i++) {
152     j += i;
153     UT_RELAX_CPU();
154   }
155 
156   UT_RESUME_PRIORITY_CPU();
157 
158   return (j);
159 }
160 #endif /* UNIV_HOTBACKUP */
161 
162 /** Calculates fast the number rounded up to the nearest power of 2.
163  @return first power of 2 which is >= n */
ut_2_power_up(ulint n)164 ulint ut_2_power_up(ulint n) /*!< in: number != 0 */
165 {
166   ulint res;
167 
168   res = 1;
169 
170   ut_ad(n > 0);
171 
172   while (res < n) {
173     res = res * 2;
174   }
175 
176   return (res);
177 }
178 
179 #ifndef UNIV_HOTBACKUP
180 /** Get a fixed-length string, quoted as an SQL identifier.
181 If the string contains a slash '/', the string will be
182 output as two identifiers separated by a period (.),
183 as in SQL database_name.identifier.
184  @param		[in]	trx		transaction (NULL=no quotes).
185  @param		[in]	name		table name.
186  @retval	String quoted as an SQL identifier.
187 */
ut_get_name(const trx_t * trx,const char * name)188 std::string ut_get_name(const trx_t *trx, const char *name) {
189   /* 2 * NAME_LEN for database and table name,
190   and some slack for the #mysql50# prefix and quotes */
191   char buf[3 * NAME_LEN];
192   const char *bufend;
193 
194   bufend = innobase_convert_name(buf, sizeof buf, name, strlen(name),
195                                  trx ? trx->mysql_thd : nullptr);
196   buf[bufend - buf] = '\0';
197   return (std::string(buf, 0, bufend - buf));
198 }
199 
200 /** Outputs a fixed-length string, quoted as an SQL identifier.
201  If the string contains a slash '/', the string will be
202  output as two identifiers separated by a period (.),
203  as in SQL database_name.identifier. */
ut_print_name(FILE * f,const trx_t * trx,const char * name)204 void ut_print_name(FILE *f,          /*!< in: output stream */
205                    const trx_t *trx, /*!< in: transaction */
206                    const char *name) /*!< in: name to print */
207 {
208   /* 2 * NAME_LEN for database and table name,
209   and some slack for the #mysql50# prefix and quotes */
210   char buf[3 * NAME_LEN];
211   const char *bufend;
212 
213   bufend = innobase_convert_name(buf, sizeof buf, name, strlen(name),
214                                  trx ? trx->mysql_thd : nullptr);
215 
216   if (fwrite(buf, 1, bufend - buf, f) != (size_t)(bufend - buf)) {
217     perror("fwrite");
218   }
219 }
220 
221 /** Format a table name, quoted as an SQL identifier.
222 If the name contains a slash '/', the result will contain two
223 identifiers separated by a period (.), as in SQL
224 database_name.table_name.
225 @see table_name_t
226 @param[in]	name		table or index name
227 @param[out]	formatted	formatted result, will be NUL-terminated
228 @param[in]	formatted_size	size of the buffer in bytes
229 @return pointer to 'formatted' */
ut_format_name(const char * name,char * formatted,ulint formatted_size)230 char *ut_format_name(const char *name, char *formatted, ulint formatted_size) {
231   switch (formatted_size) {
232     case 1:
233       formatted[0] = '\0';
234       /* FALL-THROUGH */
235     case 0:
236       return (formatted);
237   }
238 
239   char *end;
240 
241   end = innobase_convert_name(formatted, formatted_size, name, strlen(name),
242                               nullptr);
243 
244   /* If the space in 'formatted' was completely used, then sacrifice
245   the last character in order to write '\0' at the end. */
246   if ((ulint)(end - formatted) == formatted_size) {
247     end--;
248   }
249 
250   ut_a((ulint)(end - formatted) < formatted_size);
251 
252   *end = '\0';
253 
254   return (formatted);
255 }
256 
257 /** Catenate files. */
ut_copy_file(FILE * dest,FILE * src)258 void ut_copy_file(FILE *dest, /*!< in: output file */
259                   FILE *src)  /*!< in: input file to be appended to output */
260 {
261   long len = ftell(src);
262   char buf[4096];
263 
264   rewind(src);
265   do {
266     size_t maxs = len < (long)sizeof buf ? (size_t)len : sizeof buf;
267     size_t size = fread(buf, 1, maxs, src);
268     if (fwrite(buf, 1, size, dest) != size) {
269       perror("fwrite");
270     }
271     len -= (long)size;
272     if (size < maxs) {
273       break;
274     }
275   } while (len > 0);
276 }
277 
ut_format_byte_value(uint64_t data_bytes,std::string & data_str)278 void ut_format_byte_value(uint64_t data_bytes, std::string &data_str) {
279   int unit_sz = 1024;
280   auto exp = static_cast<int>(
281       (data_bytes == 0) ? 0 : std::log(data_bytes) / std::log(unit_sz));
282   auto data_value = data_bytes / std::pow(unit_sz, exp);
283 
284   char unit[] = " KMGTPE";
285   auto index = static_cast<size_t>(exp > 0 ? exp : 0);
286 
287   /* 64 BIT number should never go beyond Exabyte. */
288   auto max_index = sizeof(unit) - 2;
289   if (index > max_index) {
290     ut_ad(false);
291     index = max_index;
292   }
293 
294   std::stringstream data_strm;
295   if (index == 0) {
296     data_strm << std::setprecision(2) << std::fixed << data_value << " "
297               << "Bytes";
298   } else {
299     data_strm << std::setprecision(2) << std::fixed << data_value << " "
300               << unit[index] << "iB";
301   }
302   data_str = data_strm.str();
303 }
304 
305 #endif /* !UNIV_HOTBACKUP */
306 
307 #ifdef _WIN32
308 #include <stdarg.h>
309 
310 /** A substitute for vsnprintf(3), formatted output conversion into
311  a limited buffer. Note: this function DOES NOT return the number of
312  characters that would have been printed if the buffer was unlimited because
313  VC's _vsnprintf() returns -1 in this case and we would need to call
314  _vscprintf() in addition to estimate that but we would need another copy
315  of "ap" for that and VC does not provide va_copy(). */
ut_vsnprintf(char * str,size_t size,const char * fmt,va_list ap)316 void ut_vsnprintf(char *str,       /*!< out: string */
317                   size_t size,     /*!< in: str size */
318                   const char *fmt, /*!< in: format */
319                   va_list ap)      /*!< in: format values */
320 {
321   _vsnprintf(str, size, fmt, ap);
322   str[size - 1] = '\0';
323 }
324 
325 #endif /* _WIN32 */
326 
327 /** Convert an error number to a human readable text message.
328 The returned string is static and should not be freed or modified.
329 @param[in]	num	InnoDB internal error number
330 @return string, describing the error */
ut_strerr(dberr_t num)331 const char *ut_strerr(dberr_t num) {
332   switch (num) {
333     case DB_CACHE_RECORDS:
334       return ("Request caller to copy tuple");
335     case DB_SUCCESS:
336       return ("Success");
337     case DB_SUCCESS_LOCKED_REC:
338       return ("Success, record lock created");
339     case DB_SKIP_LOCKED:
340       return ("Skip locked records");
341     case DB_LOCK_NOWAIT:
342       return ("Don't wait for locks");
343     case DB_ERROR:
344       return ("Generic error");
345     case DB_READ_ONLY:
346       return ("Read only transaction");
347     case DB_INTERRUPTED:
348       return ("Operation interrupted");
349     case DB_OUT_OF_MEMORY:
350       return ("Cannot allocate memory");
351     case DB_OUT_OF_FILE_SPACE:
352     case DB_OUT_OF_DISK_SPACE:
353       return ("Out of disk space");
354     case DB_LOCK_WAIT:
355       return ("Lock wait");
356     case DB_DEADLOCK:
357       return ("Deadlock");
358     case DB_ROLLBACK:
359       return ("Rollback");
360     case DB_DUPLICATE_KEY:
361       return ("Duplicate key");
362     case DB_MISSING_HISTORY:
363       return ("Required history data has been deleted");
364     case DB_CLUSTER_NOT_FOUND:
365       return ("Cluster not found");
366     case DB_TABLE_NOT_FOUND:
367       return ("Table not found");
368     case DB_MUST_GET_MORE_FILE_SPACE:
369       return ("More file space needed");
370     case DB_TABLE_IS_BEING_USED:
371       return ("Table is being used");
372     case DB_TOO_BIG_RECORD:
373       return ("Record too big");
374     case DB_TOO_BIG_INDEX_COL:
375       return ("Index columns size too big");
376     case DB_LOCK_WAIT_TIMEOUT:
377       return ("Lock wait timeout");
378     case DB_NO_REFERENCED_ROW:
379       return ("Referenced key value not found");
380     case DB_ROW_IS_REFERENCED:
381       return ("Row is referenced");
382     case DB_CANNOT_ADD_CONSTRAINT:
383       return ("Cannot add constraint");
384     case DB_CORRUPTION:
385       return ("Data structure corruption");
386     case DB_CANNOT_DROP_CONSTRAINT:
387       return ("Cannot drop constraint");
388     case DB_NO_SAVEPOINT:
389       return ("No such savepoint");
390     case DB_TABLESPACE_EXISTS:
391       return ("Tablespace already exists");
392     case DB_TABLESPACE_DELETED:
393       return ("Tablespace deleted or being deleted");
394     case DB_TABLESPACE_NOT_FOUND:
395       return ("Tablespace not found");
396     case DB_LOCK_TABLE_FULL:
397       return ("Lock structs have exhausted the buffer pool");
398     case DB_FOREIGN_DUPLICATE_KEY:
399       return ("Foreign key activated with duplicate keys");
400     case DB_FOREIGN_EXCEED_MAX_CASCADE:
401       return ("Foreign key cascade delete/update exceeds max depth");
402     case DB_TOO_MANY_CONCURRENT_TRXS:
403       return ("Too many concurrent transactions");
404     case DB_UNSUPPORTED:
405       return ("Unsupported");
406     case DB_INVALID_NULL:
407       return ("NULL value encountered in NOT NULL column");
408     case DB_STATS_DO_NOT_EXIST:
409       return ("Persistent statistics do not exist");
410     case DB_FAIL:
411       return ("Failed, retry may succeed");
412     case DB_OVERFLOW:
413       return ("Overflow");
414     case DB_UNDERFLOW:
415       return ("Underflow");
416     case DB_STRONG_FAIL:
417       return ("Failed, retry will not succeed");
418     case DB_ZIP_OVERFLOW:
419       return ("Zip overflow");
420     case DB_RECORD_NOT_FOUND:
421       return ("Record not found");
422     case DB_CHILD_NO_INDEX:
423       return ("No index on referencing keys in referencing table");
424     case DB_PARENT_NO_INDEX:
425       return ("No index on referenced keys in referenced table");
426     case DB_FTS_INVALID_DOCID:
427       return ("FTS Doc ID cannot be zero");
428     case DB_INDEX_CORRUPT:
429       return ("Index corrupted");
430     case DB_UNDO_RECORD_TOO_BIG:
431       return ("Undo record too big");
432     case DB_END_OF_INDEX:
433       return ("End of index");
434     case DB_END_OF_BLOCK:
435       return ("End of block");
436     case DB_IO_ERROR:
437       return ("I/O error");
438     case DB_TABLE_IN_FK_CHECK:
439       return ("Table is being used in foreign key check");
440     case DB_DATA_MISMATCH:
441       return ("data mismatch");
442     case DB_SCHEMA_MISMATCH:
443       return ("schema mismatch");
444     case DB_NOT_FOUND:
445       return ("not found");
446     case DB_ONLINE_LOG_TOO_BIG:
447       return ("Log size exceeded during online index creation");
448     case DB_IDENTIFIER_TOO_LONG:
449       return ("Identifier name is too long");
450     case DB_FTS_EXCEED_RESULT_CACHE_LIMIT:
451       return ("FTS query exceeds result cache limit");
452     case DB_TEMP_FILE_WRITE_FAIL:
453       return ("Temp file write failure");
454     case DB_CANT_CREATE_GEOMETRY_OBJECT:
455       return ("Can't create specificed geometry data object");
456     case DB_CANNOT_OPEN_FILE:
457       return ("Cannot open a file");
458     case DB_TABLE_CORRUPT:
459       return ("Table is corrupted");
460     case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
461       return ("Too many words in a FTS phrase or proximity search");
462     case DB_IO_DECOMPRESS_FAIL:
463       return ("Page decompress failed after reading from disk");
464     case DB_IO_NO_PUNCH_HOLE:
465       return ("No punch hole support");
466     case DB_IO_NO_PUNCH_HOLE_FS:
467       return ("Punch hole not supported by the file system");
468     case DB_IO_NO_PUNCH_HOLE_TABLESPACE:
469       return ("Punch hole not supported by the tablespace");
470     case DB_IO_NO_ENCRYPT_TABLESPACE:
471       return ("Page encryption not supported by the tablespace");
472     case DB_IO_DECRYPT_FAIL:
473       return ("Page decryption failed after reading from disk");
474     case DB_IO_PARTIAL_FAILED:
475       return ("Partial IO failed");
476     case DB_FORCED_ABORT:
477       return (
478           "Transaction aborted by another higher priority "
479           "transaction");
480     case DB_WRONG_FILE_NAME:
481       return ("Invalid Filename");
482     case DB_NO_FK_ON_S_BASE_COL:
483       return (
484           "Cannot add foreign key on the base column "
485           "of stored column");
486     case DB_COMPUTE_VALUE_FAILED:
487       return ("Compute generated column failed");
488     case DB_V1_DBLWR_INIT_FAILED:
489       return (
490           "Failed to initialize the doublewrite extents "
491           "in the system tablespace");
492     case DB_V1_DBLWR_CREATE_FAILED:
493       return (
494           "Failed to create the doublewrite extents "
495           "in the system tablespace");
496     case DB_DBLWR_INIT_FAILED:
497       return ("Failed to create a doublewrite instance");
498     case DB_DBLWR_NOT_EXISTS:
499       return (
500           "Failed to find a doublewrite buffer "
501           "in the system tablespace");
502     case DB_INVALID_ENCRYPTION_META:
503       return ("Invalid encryption meta-data information");
504     case DB_ABORT_INCOMPLETE_CLONE:
505       return ("Incomplete cloned data directory");
506     case DB_SERVER_VERSION_LOW:
507       return (
508           "Cannot boot server with lower version than that built the "
509           "tablespace");
510     case DB_NO_SESSION_TEMP:
511       return ("No session temporary tablespace allocated");
512     case DB_TOO_LONG_PATH:
513       return (
514           "Cannot create tablespace since the filepath is too long for this "
515           "OS");
516     case DB_BTREE_LEVEL_LIMIT_EXCEEDED:
517       return ("Btree level limit exceeded");
518     case DB_END_SAMPLE_READ:
519       return ("Sample reader has been requested to stop sampling");
520     case DB_OUT_OF_RESOURCES:
521       return ("System has run out of resources");
522 
523     case DB_PAGE_IS_BLANK:
524       return ("Page is blank");
525 
526     case DB_ERROR_UNSET:;
527       /* Fall through. */
528 
529       /* do not add default: in order to produce a warning if new code
530       is added to the enum but not added here */
531   }
532 
533   /* we abort here because if unknown error code is given, this could
534   mean that memory corruption has happened and someone's error-code
535   variable has been overwritten with bogus data */
536   ut_error;
537 }
538 
539 namespace ib {
540 
541 #if !defined(UNIV_HOTBACKUP) && !defined(UNIV_NO_ERR_MSGS)
542 
log_event(std::string msg)543 void logger::log_event(std::string msg) {
544 #if !(defined XTRABACKUP)
545   LogEvent()
546       .type(LOG_TYPE_ERROR)
547       .prio(m_level)
548       .errcode(m_err)
549       .subsys("InnoDB")
550       .verbatim(msg.c_str());
551 #else
552   fprintf(stderr, "%s\n", msg.c_str());
553 #endif
554 }
~logger()555 logger::~logger() { log_event(m_oss.str()); }
556 
~fatal()557 fatal::~fatal() {
558 #if !(defined XTRABACKUP)
559   log_event("[FATAL] " + m_oss.str());
560 #else
561   fprintf(stderr, "%s\n", m_oss.str().c_str());
562 #endif
563   ut_error;
564 }
565 
~fatal_or_error()566 fatal_or_error::~fatal_or_error() {
567   if (m_fatal) {
568     log_event("[FATAL] " + m_oss.str());
569     ut_error;
570   }
571 }
572 
573 #endif /* !UNIV_NO_ERR_MSGS */
574 
575 }  // namespace ib
576