mariadb/innobase/ut/ut0ut.c

596 lines
12 KiB
C
Raw Normal View History

2001-02-17 13:19:19 +01:00
/*******************************************************************
Various utilities for Innobase.
(c) 1994, 1995 Innobase Oy
Created 5/11/1994 Heikki Tuuri
********************************************************************/
#include "ut0ut.h"
#ifdef UNIV_NONINL
#include "ut0ut.ic"
#endif
#include <stdarg.h>
#include <string.h>
2001-02-17 13:19:19 +01:00
#include "ut0sort.h"
ibool ut_always_false = FALSE;
/************************************************************
On the 64-bit Windows we substitute the format string
%l -> %I64
because we define ulint as unsigned __int64 and lint as __int64 on Windows,
and both the Microsoft and Intel C compilers require the format string
%I64 in that case instead of %l. */
int
ut_printf(
/*======*/
/* out: the number of characters written, or
negative in case of an error */
const char* format, /* in: format of prints */
...) /* in: arguments to be printed */
{
va_list args;
ulint len;
char* format_end;
char* newformat;
char* ptr;
char* newptr;
int ret;
char format_buf_in_stack[500];
len = strlen(format);
if (len > 250) {
newformat = malloc(2 * len);
} else {
newformat = format_buf_in_stack;
}
format_end = (char*)format + len;
ptr = (char*)format;
newptr = newformat;
#if defined(__WIN__) && (defined(WIN64) || defined(_WIN64))
/* Replace %l with %I64 if it is not preceded with '\' */
while (ptr < format_end) {
if (*ptr == '%' && *(ptr + 1) == 'l'
&& (ptr == format || *(ptr - 1) != '\\')) {
memcpy(newptr, "%I64", 4);
ptr += 2;
newptr += 4;
} else {
*newptr = *ptr;
ptr++;
newptr++;
}
}
*newptr = '\0';
ut_a(newptr < newformat + 2 * len);
#else
strcpy(newformat, format);
#endif
va_start(args, format);
ret = vprintf((const char*)newformat, args);
va_end(args);
if (newformat != format_buf_in_stack) {
free(newformat);
}
return(ret);
}
/************************************************************
On the 64-bit Windows we substitute the format string
%l -> %I64
because we define ulint as unsigned __int64 and lint as __int64 on Windows,
and both the Microsoft and Intel C compilers require the format string
%I64 in that case instead of %l. */
int
ut_sprintf(
/*=======*/
/* out: the number of characters written, or
negative in case of an error */
char* buf, /* in: buffer where to print */
const char* format, /* in: format of prints */
...) /* in: arguments to be printed */
{
va_list args;
ulint len;
char* format_end;
char* newformat;
char* ptr;
char* newptr;
int ret;
char format_buf_in_stack[500];
len = strlen(format);
if (len > 250) {
newformat = malloc(2 * len);
} else {
newformat = format_buf_in_stack;
}
format_end = (char*)format + len;
ptr = (char*)format;
newptr = newformat;
#if defined(__WIN__) && (defined(WIN64) || defined(_WIN64))
/* Replace %l with %I64 if it is not preceded with '\' */
while (ptr < format_end) {
if (*ptr == '%' && *(ptr + 1) == 'l'
&& (ptr == format || *(ptr - 1) != '\\')) {
memcpy(newptr, "%I64", 4);
ptr += 2;
newptr += 4;
} else {
*newptr = *ptr;
ptr++;
newptr++;
}
}
*newptr = '\0';
ut_a(newptr < newformat + 2 * len);
#else
strcpy(newformat, format);
#endif
va_start(args, format);
ret = vsprintf(buf, (const char*)newformat, args);
va_end(args);
if (newformat != format_buf_in_stack) {
free(newformat);
}
return(ret);
}
/************************************************************
On the 64-bit Windows we substitute the format string
%l -> %I64
because we define ulint as unsigned __int64 and lint as __int64 on Windows,
and both the Microsoft and Intel C compilers require the format string
%I64 in that case instead of %l. */
int
ut_fprintf(
/*=======*/
/* out: the number of characters written, or
negative in case of an error */
FILE* stream, /* in: stream where to print */
const char* format, /* in: format of prints */
...) /* in: arguments to be printed */
{
va_list args;
ulint len;
char* format_end;
char* newformat;
char* ptr;
char* newptr;
int ret;
char format_buf_in_stack[500];
len = strlen(format);
if (len > 250) {
newformat = malloc(2 * len);
} else {
newformat = format_buf_in_stack;
}
format_end = (char*)format + len;
ptr = (char*)format;
newptr = newformat;
#if defined(__WIN__) && (defined(WIN64) || defined(_WIN64))
/* Replace %l with %I64 if it is not preceded with '\' */
while (ptr < format_end) {
if (*ptr == '%' && *(ptr + 1) == 'l'
&& (ptr == format || *(ptr - 1) != '\\')) {
memcpy(newptr, "%I64", 4);
ptr += 2;
newptr += 4;
} else {
*newptr = *ptr;
ptr++;
newptr++;
}
}
*newptr = '\0';
ut_a(newptr < newformat + 2 * len);
#else
strcpy(newformat, format);
#endif
va_start(args, format);
ret = vfprintf(stream, (const char*)newformat, args);
va_end(args);
if (newformat != format_buf_in_stack) {
free(newformat);
}
return(ret);
}
2002-03-21 17:03:09 +01:00
/************************************************************
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
but since there seem to be compiler bugs in both gcc and Visual C++,
we do this by a special conversion. */
ulint
ut_get_high32(
/*==========*/
/* out: a >> 32 */
ulint a) /* in: ulint */
{
#if SIZEOF_LONG == 4
UT_NOT_USED(a);
return 0;
#else
2002-03-21 17:03:09 +01:00
return(a >> 32);
#endif
2002-03-21 17:03:09 +01:00
}
2001-02-17 13:19:19 +01:00
/************************************************************
The following function returns elapsed CPU time in milliseconds. */
2001-02-17 13:19:19 +01:00
ulint
ut_clock(void)
{
return((clock() * 1000) / CLOCKS_PER_SEC);
}
/**************************************************************
Returns system time. We do not specify the format of the time returned:
the only way to manipulate it is to use the function ut_difftime. */
ib_time_t
ut_time(void)
/*=========*/
{
return(time(NULL));
}
/**************************************************************
Returns the difference of two times in seconds. */
double
ut_difftime(
/*========*/
/* out: time2 - time1 expressed in seconds */
ib_time_t time2, /* in: time */
ib_time_t time1) /* in: time */
{
return(difftime(time2, time1));
}
/**************************************************************
Prints a timestamp to a file. */
void
ut_print_timestamp(
/*===============*/
FILE* file) /* in: file where to print */
{
#ifdef __WIN__
2002-03-21 17:03:09 +01:00
SYSTEMTIME cal_tm;
2002-03-21 17:03:09 +01:00
GetLocalTime(&cal_tm);
2002-03-21 17:03:09 +01:00
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
(int)cal_tm.wYear % 100,
(int)cal_tm.wMonth,
(int)cal_tm.wDay,
(int)cal_tm.wHour,
(int)cal_tm.wMinute,
(int)cal_tm.wSecond);
#else
2002-03-21 17:03:09 +01:00
struct tm cal_tm;
struct tm* cal_tm_ptr;
time_t tm;
2002-03-21 17:03:09 +01:00
time(&tm);
#ifdef HAVE_LOCALTIME_R
2002-03-21 17:03:09 +01:00
localtime_r(&tm, &cal_tm);
cal_tm_ptr = &cal_tm;
#else
2002-03-21 17:03:09 +01:00
cal_tm_ptr = localtime(&tm);
#endif
2002-03-21 17:03:09 +01:00
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
cal_tm_ptr->tm_year % 100,
2002-03-21 17:03:09 +01:00
cal_tm_ptr->tm_mon + 1,
cal_tm_ptr->tm_mday,
cal_tm_ptr->tm_hour,
cal_tm_ptr->tm_min,
cal_tm_ptr->tm_sec);
#endif
}
2002-06-22 19:41:14 +02:00
/**************************************************************
Sprintfs a timestamp to a buffer. */
void
ut_sprintf_timestamp(
/*=================*/
char* buf) /* in: buffer where to sprintf */
{
#ifdef __WIN__
SYSTEMTIME cal_tm;
GetLocalTime(&cal_tm);
sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
(int)cal_tm.wYear % 100,
(int)cal_tm.wMonth,
(int)cal_tm.wDay,
(int)cal_tm.wHour,
(int)cal_tm.wMinute,
(int)cal_tm.wSecond);
#else
struct tm cal_tm;
struct tm* cal_tm_ptr;
time_t tm;
time(&tm);
#ifdef HAVE_LOCALTIME_R
localtime_r(&tm, &cal_tm);
cal_tm_ptr = &cal_tm;
#else
cal_tm_ptr = localtime(&tm);
#endif
sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
cal_tm_ptr->tm_year % 100,
cal_tm_ptr->tm_mon + 1,
cal_tm_ptr->tm_mday,
cal_tm_ptr->tm_hour,
cal_tm_ptr->tm_min,
cal_tm_ptr->tm_sec);
#endif
}
2002-03-21 17:03:09 +01:00
/**************************************************************
Sprintfs a timestamp to a buffer with no spaces and with ':' characters
replaced by '_'. */
void
ut_sprintf_timestamp_without_extra_chars(
/*=====================================*/
char* buf) /* in: buffer where to sprintf */
{
#ifdef __WIN__
SYSTEMTIME cal_tm;
GetLocalTime(&cal_tm);
sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
(int)cal_tm.wYear % 100,
(int)cal_tm.wMonth,
(int)cal_tm.wDay,
(int)cal_tm.wHour,
(int)cal_tm.wMinute,
(int)cal_tm.wSecond);
#else
struct tm cal_tm;
struct tm* cal_tm_ptr;
time_t tm;
time(&tm);
#ifdef HAVE_LOCALTIME_R
localtime_r(&tm, &cal_tm);
cal_tm_ptr = &cal_tm;
#else
cal_tm_ptr = localtime(&tm);
#endif
sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
cal_tm_ptr->tm_year % 100,
cal_tm_ptr->tm_mon + 1,
cal_tm_ptr->tm_mday,
cal_tm_ptr->tm_hour,
cal_tm_ptr->tm_min,
cal_tm_ptr->tm_sec);
#endif
}
/**************************************************************
2002-03-21 17:03:09 +01:00
Returns current year, month, day. */
void
ut_get_year_month_day(
/*==================*/
ulint* year, /* out: current year */
ulint* month, /* out: month */
ulint* day) /* out: day */
{
#ifdef __WIN__
SYSTEMTIME cal_tm;
GetLocalTime(&cal_tm);
*year = (ulint)cal_tm.wYear;
*month = (ulint)cal_tm.wMonth;
*day = (ulint)cal_tm.wDay;
#else
struct tm* cal_tm_ptr;
time_t tm;
time(&tm);
cal_tm_ptr = localtime(&tm);
*year = (ulint)cal_tm_ptr->tm_year + 1900;
2002-03-21 17:03:09 +01:00
*month = (ulint)cal_tm_ptr->tm_mon + 1;
*day = (ulint)cal_tm_ptr->tm_mday;
#endif
}
2001-02-17 13:19:19 +01:00
/*****************************************************************
Runs an idle loop on CPU. The argument gives the desired delay
in microseconds on 100 MHz Pentium + Visual C++. */
ulint
ut_delay(
/*=====*/
/* out: dummy value */
ulint delay) /* in: delay in microseconds on 100 MHz Pentium */
{
ulint i, j;
j = 0;
for (i = 0; i < delay * 50; i++) {
j += i;
}
if (ut_always_false) {
printf("%lu", (ulong) j);
2001-02-17 13:19:19 +01:00
}
return(j);
}
/*****************************************************************
Prints the contents of a memory buffer in hex and ascii. */
void
ut_print_buf(
/*=========*/
byte* buf, /* in: memory buffer */
ulint len) /* in: length of the buffer */
{
byte* data;
ulint i;
printf(" len %lu; hex ", (ulong) len);
2001-02-17 13:19:19 +01:00
data = buf;
for (i = 0; i < len; i++) {
printf("%02lx", (ulong) *data);
2001-02-17 13:19:19 +01:00
data++;
}
printf("; asc ");
data = buf;
for (i = 0; i < len; i++) {
if (isprint((int)(*data))) {
2001-02-17 13:19:19 +01:00
printf("%c", (char)*data);
}
data++;
}
printf(";");
}
/*****************************************************************
Prints the contents of a memory buffer in hex and ascii. */
ulint
ut_sprintf_buf(
/*===========*/
/* out: printed length in bytes */
char* str, /* in: buffer to print to */
byte* buf, /* in: memory buffer */
ulint len) /* in: length of the buffer */
{
byte* data;
ulint n;
ulint i;
n = 0;
n += sprintf(str + n, " len %lu; hex ", (ulong) len);
2001-02-17 13:19:19 +01:00
data = buf;
for (i = 0; i < len; i++) {
n += sprintf(str + n, "%02lx", (ulong) *data);
2001-02-17 13:19:19 +01:00
data++;
}
n += sprintf(str + n, "; asc ");
data = buf;
for (i = 0; i < len; i++) {
if (isprint((int)(*data))) {
2001-02-17 13:19:19 +01:00
n += sprintf(str + n, "%c", (char)*data);
ut0mem.c Merge changes in InnoDB-3.23.43b ut0ut.c Merge changes in InnoDB-3.23.43b trx0purge.c Merge changes in InnoDB-3.23.43b trx0rec.c Merge changes in InnoDB-3.23.43b trx0trx.c Merge changes in InnoDB-3.23.43b trx0undo.c Merge changes in InnoDB-3.23.43b thr0loc.c Merge changes in InnoDB-3.23.43b sync0arr.c Merge changes in InnoDB-3.23.43b sync0rw.c Merge changes in InnoDB-3.23.43b sync0sync.c Merge changes in InnoDB-3.23.43b srv0srv.c Merge changes in InnoDB-3.23.43b srv0start.c Merge changes in InnoDB-3.23.43b row0ins.c Merge changes in InnoDB-3.23.43b row0mysql.c Merge changes in InnoDB-3.23.43b row0purge.c Merge changes in InnoDB-3.23.43b row0sel.c Merge changes in InnoDB-3.23.43b row0umod.c Merge changes in InnoDB-3.23.43b row0upd.c Merge changes in InnoDB-3.23.43b row0vers.c Merge changes in InnoDB-3.23.43b rem0cmp.c Merge changes in InnoDB-3.23.43b que0que.c Merge changes in InnoDB-3.23.43b pars0opt.c Merge changes in InnoDB-3.23.43b pars0pars.c Merge changes in InnoDB-3.23.43b lexyy.c Merge changes in InnoDB-3.23.43b pars0grm.c Merge changes in InnoDB-3.23.43b page0page.c Merge changes in InnoDB-3.23.43b os0file.c Merge changes in InnoDB-3.23.43b mtr0log.c Merge changes in InnoDB-3.23.43b mem0pool.c Merge changes in InnoDB-3.23.43b log0log.c Merge changes in InnoDB-3.23.43b log0recv.c Merge changes in InnoDB-3.23.43b lock0lock.c Merge changes in InnoDB-3.23.43b ibuf0ibuf.c Merge changes in InnoDB-3.23.43b fil0fil.c Merge changes in InnoDB-3.23.43b dict0crea.c Merge changes in InnoDB-3.23.43b dict0dict.c Merge changes in InnoDB-3.23.43b dict0load.c Merge changes in InnoDB-3.23.43b dict0mem.c Merge changes in InnoDB-3.23.43b data0data.c Merge changes in InnoDB-3.23.43b data0type.c Merge changes in InnoDB-3.23.43b buf0buf.c Merge changes in InnoDB-3.23.43b buf0lru.c Merge changes in InnoDB-3.23.43b btr0btr.c Merge changes in InnoDB-3.23.43b btr0cur.c Merge changes in InnoDB-3.23.43b btr0pcur.c Merge changes in InnoDB-3.23.43b btr0sea.c Merge changes in InnoDB-3.23.43b data0type.ic Merge changes in InnoDB-3.23.43b dict0dict.ic Merge changes in InnoDB-3.23.43b mtr0mtr.ic Merge changes in InnoDB-3.23.43b row0upd.ic Merge changes in InnoDB-3.23.43b sync0ipm.ic Merge changes in InnoDB-3.23.43b sync0rw.ic Merge changes in InnoDB-3.23.43b sync0sync.ic Merge changes in InnoDB-3.23.43b trx0rseg.ic Merge changes in InnoDB-3.23.43b btr0pcur.ic Merge changes in InnoDB-3.23.43b buf0buf.ic Merge changes in InnoDB-3.23.43b data0data.ic Merge changes in InnoDB-3.23.43b row0upd.h Merge changes in InnoDB-3.23.43b srv0srv.h Merge changes in InnoDB-3.23.43b sync0arr.h Merge changes in InnoDB-3.23.43b sync0rw.h Merge changes in InnoDB-3.23.43b sync0sync.h Merge changes in InnoDB-3.23.43b trx0trx.h Merge changes in InnoDB-3.23.43b ut0mem.h Merge changes in InnoDB-3.23.43b data0data.h Merge changes in InnoDB-3.23.43b data0type.h Merge changes in InnoDB-3.23.43b db0err.h Merge changes in InnoDB-3.23.43b dict0crea.h Merge changes in InnoDB-3.23.43b dict0dict.h Merge changes in InnoDB-3.23.43b dict0load.h Merge changes in InnoDB-3.23.43b dict0mem.h Merge changes in InnoDB-3.23.43b dict0types.h Merge changes in InnoDB-3.23.43b fil0fil.h Merge changes in InnoDB-3.23.43b ibuf0ibuf.h Merge changes in InnoDB-3.23.43b lock0lock.h Merge changes in InnoDB-3.23.43b log0log.h Merge changes in InnoDB-3.23.43b mtr0mtr.h Merge changes in InnoDB-3.23.43b rem0cmp.h Merge changes in InnoDB-3.23.43b row0ins.h Merge changes in InnoDB-3.23.43b row0mysql.h Merge changes in InnoDB-3.23.43b btr0cur.h Merge changes in InnoDB-3.23.43b btr0pcur.h Merge changes in InnoDB-3.23.43b btr0sea.h Merge changes in InnoDB-3.23.43b buf0buf.h Merge changes in InnoDB-3.23.43b sql_table.cc Merge changes in InnoDB-3.23.43b sql_db.cc Merge changes in InnoDB-3.23.43b ha_innobase.cc Merge changes in InnoDB-3.23.43b handler.cc Merge changes in InnoDB-3.23.43b ha_innobase.h Merge changes in InnoDB-3.23.43b handler.h Merge changes in InnoDB-3.23.43b
2001-10-10 21:47:08 +02:00
} else {
n += sprintf(str + n, ".");
2001-02-17 13:19:19 +01:00
}
data++;
}
n += sprintf(str + n, ";");
return(n);
}
/****************************************************************
Sort function for ulint arrays. */
void
ut_ulint_sort(ulint* arr, ulint* aux_arr, ulint low, ulint high)
/*============================================================*/
{
UT_SORT_FUNCTION_BODY(ut_ulint_sort, arr, aux_arr, low, high,
ut_ulint_cmp);
}
2002-06-22 19:41:14 +02:00
/*****************************************************************
Calculates fast the number rounded up to the nearest power of 2. */
ulint
ut_2_power_up(
/*==========*/
/* out: first power of 2 which is >= n */
ulint n) /* in: number != 0 */
{
ulint res;
res = 1;
ut_ad(n > 0);
while (res < n) {
res = res * 2;
}
return(res);
}