mariadb/innobase/ut/ut0ut.c
unknown 805c2d52cd NULL MERGE this to 5.1
Apply the following InnoDB snapshots:
innodb-5.0-ss1319
innodb-5.0-ss1331
innodb-5.0-ss1333
innodb-5.0-ss1341

Fixes:
- Bug #21409: Incorrect result returned when in READ-COMMITTED with query_cache ON
  At low transaction isolation levels we let each consistent read set
  its own snapshot.
- Bug #23666: strange Innodb_row_lock_time_% values in show status; also millisecs wrong
  On Windows ut_usectime returns secs and usecs relative to the UNIX
  epoch (which is Jan, 1 1970).

- Bug #25494: LATEST DEADLOCK INFORMATION is not always cleared
  lock_deadlock_recursive(): When the search depth or length is exceeded,
  rewind lock_latest_err_file and display the two transactions at the
  point of aborting the search.

- Bug #25927: Foreign key with ON DELETE SET NULL on NOT NULL can crash server
  Prevent ALTER TABLE ... MODIFY ... NOT NULL on columns for which
  there is a foreign key constraint ON ... SET NULL.

- Bug #26835: Repeatable corruption of utf8-enabled tables inside InnoDB
  The bug could be reproduced as follows:

  Define a table so that the first column of the clustered index is
  a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes
  of differing length are considered equivalent.

  Insert and delete a record.  Before the delete-marked record is
  purged, insert another record whose first column is of different
  length but equivalent to the first record.  Under certain conditions,
  the insertion can be incorrectly performed as update-in-place.

  Likewise, an operation that could be done as update-in-place can
  unnecessarily be performed as delete and insert, but that would not
  cause corruption but merely degraded performance.


innobase/dict/dict0dict.c:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1317:
  branches/5.0: Port r1316 from trunk:
  
  Prevent ALTER TABLE ... MODIFY ... NOT NULL on columns for which
  there is a foreign key constraint ON ... SET NULL.  (Bug #25927)
  
  dict_foreign_find_index(): Add paramettter check_null.
  
  dict_foreign_add_to_cache(): Do not allow ON DELETE SET NULL
  or ON UPDATE SET NULL if any of the referencing columns are declared NOT NULL.
innobase/include/rem0rec.ic:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1339:
  branches/5.0: Merge r1338 from trunk:
  
  rec_offs_nth_size(): Treat n==0 as a special case.  (Bug #26835)
innobase/include/sync0sync.ic:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1293:
  branches/5.0: Fixed inline asm code, it didn't work with GCC > ver 3.x.
innobase/lock/lock0lock.c:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1331:
  branches/5.0: Merge r1330 from trunk:
  
  lock_deadlock_recursive(): When the search depth or length is exceeded,
  rewind lock_latest_err_file and display the two transactions at the
  point of aborting the search.  (Bug #25494)
  
  
  Revision r1333:
  branches/5.0: Merge r1332 from trunk:
  
  lock_deadlock_recursive(): When aborting the search, display a note
  regardless of start->undo_no.  Otherwise, aborted searches may show
  up as genuine deadlocks.  This mistake was made in r1330.
innobase/srv/srv0srv.c:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1261:
  branches/5.0: Fix for Bug# 23666. On Windows ut_usectime returns secs 
  and usecs relative to the UNIX epoch (which is Jan, 1 1970).
innobase/ut/ut0ut.c:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1261:
  branches/5.0: Fix for Bug# 23666. On Windows ut_usectime returns secs 
  and usecs relative to the UNIX epoch (which is Jan, 1 1970).
mysql-test/r/innodb.result:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1319:
  branches/5.0: Port r1318 from trunk:
  
  Add a test case for r1316 (Bug #25927).
  
  
  Revision r1328:
  branches/5.0: mysql-test: Merge changes from MySQL AB.
  
  
  Revision r1341:
  branches/5.0: Merge r1340 from trunk:
  
  innodb.test, innodb.result: Add test case for Bug #26835.
  The bug could be reproduced as follows:
  
  Define a table so that the first column of the clustered index is
  a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes
  of differing length are considered equivalent.
  
  Insert and delete a record.  Before the delete-marked record is
  purged, insert another record whose first column is of different
  length but equivalent to the first record.  Under certain conditions,
  the insertion can be incorrectly performed as update-in-place.
  
  Likewise, an operation that could be done as update-in-place can
  unnecessarily be performed as delete and insert, but that would not
  cause corruption but merely degraded performance.
  
  Revision r1284:
  Merge changes from MySQL AB:
  
  ChangeSet
    2007/01/24 14:49:36+04:00 holyfoot@mysql.com 
    bug #22682 Test fails --without-geometry
    geometry dependent parts moved to proper .test files
  
  mysql-test/r/innodb.result
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +0 -2
    result fixed
  
  mysql-test/r/innodb_gis.result
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +2 -0
    result fixed
  
  mysql-test/t/innodb.test
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +0 -6
    HAVE_GEOMETRY dependent part moved to innodb_gis.test
  
  mysql-test/t/innodb_gis.test
    2007/01/24 14:49:35+04:00 holyfoot@mysql.com +6 -0
    HAVE_GEOMETRY dependent part moved here from innodb.test
  
  
  Revision r1186:
  dict_load_foreign(): Use a local variable instead of the 10-bit field
  foreign->n_fields in order to preserve ON UPDATE CASCADE and
  ON DELETE CASCADE flags.  For some reason, gcc does not warn about
  shifting a 10-bit field to right by 24 bits.  (Bug #24741)
  
  This bug was introduced while reducing the memory footprint of the
  InnoDB data dictionary (Bug #20877).
  
  innodb.test, innodb.result: Add a test case.
  
  
  Revision r1318:
  Add a test case for r1316 (Bug #25927).
  
  
  Revision r1340:
  innodb.test, innodb.result: Add test case for Bug #26835.
  The bug could be reproduced as follows:
  
  Define a table so that the first column of the clustered index is
  a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes
  of differing length are considered equivalent.
  
  Insert and delete a record.  Before the delete-marked record is
  purged, insert another record whose first column is of different
  length but equivalent to the first record.  Under certain conditions,
  the insertion can be incorrectly performed as update-in-place.
  
  Likewise, an operation that could be done as update-in-place can
  unnecessarily be performed as delete and insert, but that would not
  cause corruption but merely degraded performance.
mysql-test/t/innodb.test:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1279:
  branches/5.0: Merge changes from MySQL AB:
  
  ChangeSet
    2006/11/20 22:42:06+02:00 monty@mysql.com 
    Remove compiler warnings
    (Mostly in DBUG_PRINT() and unused arguments)
    Fixed bug in query cache when used with traceing (--with-debug)
    Fixed memory leak in mysqldump
    Removed warnings from mysqltest scripts (replaced -- with #)
  
  mysql-test/t/innodb.test
    2006/11/20 22:41:41+02:00 monty@mysql.com +1 -1
    Remove mysqltest warnings
  
  sql/ha_innodb.cc
    2006/11/20 22:41:51+02:00 monty@mysql.com +2 -2
    Fixed compiler warning
  
  
  Revision r1319:
  branches/5.0: Port r1318 from trunk:
  
  Add a test case for r1316 (Bug #25927).
  
  
  Revision r1328:
  branches/5.0: mysql-test: Merge changes from MySQL AB.
  
  
  Revision r1341:
  branches/5.0: Merge r1340 from trunk:
  
  innodb.test, innodb.result: Add test case for Bug #26835.
  The bug could be reproduced as follows:
  
  Define a table so that the first column of the clustered index is
  a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes
  of differing length are considered equivalent.
  
  Insert and delete a record.  Before the delete-marked record is
  purged, insert another record whose first column is of different
  length but equivalent to the first record.  Under certain conditions,
  the insertion can be incorrectly performed as update-in-place.
  
  Likewise, an operation that could be done as update-in-place can
  unnecessarily be performed as delete and insert, but that would not
  cause corruption but merely degraded performance.
  
  Revision r1284:
  Merge changes from MySQL AB:
  
  ChangeSet
    2007/01/24 14:49:36+04:00 holyfoot@mysql.com 
    bug #22682 Test fails --without-geometry
    geometry dependent parts moved to proper .test files
  
  mysql-test/r/innodb.result
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +0 -2
    result fixed
  
  mysql-test/r/innodb_gis.result
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +2 -0
    result fixed
  
  mysql-test/t/innodb.test
    2007/01/24 14:49:34+04:00 holyfoot@mysql.com +0 -6
    HAVE_GEOMETRY dependent part moved to innodb_gis.test
  
  mysql-test/t/innodb_gis.test
    2007/01/24 14:49:35+04:00 holyfoot@mysql.com +6 -0
    HAVE_GEOMETRY dependent part moved here from innodb.test
  
  
  Revision r1283:
  Merge changes from MySQL AB:
  
  ChangeSet
    2007/01/22 18:42:52+02:00 monty@mysql.com 
    Give warnings for unused objects
    Changed error message to be compatible with old error file
    Added new error message for new DUP_ENTRY syntax
  
  mysql-test/t/innodb.test
    2007/01/22 18:42:49+02:00 monty@mysql.com +14 -14
    Changed to use new error message
  
  
  Revision r1186:
  dict_load_foreign(): Use a local variable instead of the 10-bit field
  foreign->n_fields in order to preserve ON UPDATE CASCADE and
  ON DELETE CASCADE flags.  For some reason, gcc does not warn about
  shifting a 10-bit field to right by 24 bits.  (Bug #24741)
  
  This bug was introduced while reducing the memory footprint of the
  InnoDB data dictionary (Bug #20877).
  
  innodb.test, innodb.result: Add a test case.
  
  
  Revision r1318:
  Add a test case for r1316 (Bug #25927).
  
  
  Revision r1329:
  Merge changes from MySQL AB to mysql-test directives.
  The results are not affected.
  
  
  Revision r1340:
  innodb.test, innodb.result: Add test case for Bug #26835.
  The bug could be reproduced as follows:
  
  Define a table so that the first column of the clustered index is
  a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes
  of differing length are considered equivalent.
  
  Insert and delete a record.  Before the delete-marked record is
  purged, insert another record whose first column is of different
  length but equivalent to the first record.  Under certain conditions,
  the insertion can be incorrectly performed as update-in-place.
  
  Likewise, an operation that could be done as update-in-place can
  unnecessarily be performed as delete and insert, but that would not
  cause corruption but merely degraded performance.
sql/ha_innodb.cc:
  NULL MERGE this to 5.1
  
  Apply the following InnoDB snapshots:
  innodb-5.0-ss1319
  innodb-5.0-ss1331
  innodb-5.0-ss1333
  innodb-5.0-ss1341
  
  Revision r1279:
  branches/5.0: Merge changes from MySQL AB:
  
  ChangeSet
    2006/11/20 22:42:06+02:00 monty@mysql.com 
    Remove compiler warnings
    (Mostly in DBUG_PRINT() and unused arguments)
    Fixed bug in query cache when used with traceing (--with-debug)
    Fixed memory leak in mysqldump
    Removed warnings from mysqltest scripts (replaced -- with #)
  
  mysql-test/t/innodb.test
    2006/11/20 22:41:41+02:00 monty@mysql.com +1 -1
    Remove mysqltest warnings
  
  sql/ha_innodb.cc
    2006/11/20 22:41:51+02:00 monty@mysql.com +2 -2
    Fixed compiler warning
  
  
  Revision r1280:
  branches/5.0: Merge a change from MySQL AB:
  
  ChangeSet
    2006/11/30 18:25:05+02:00 monty@mysql.com 
    Fixed portability issue in my_thr_init.c (was added in my last push)
    
    Fixed compiler warnings (detected by VC++):
    - Removed not used variables
    - Added casts
    - Fixed wrong assignments to bool
    - Fixed wrong calls with bool arguments
    - Added missing argument to store(longlong), which caused wrong store
    method to be called.
  
  sql/ha_innodb.cc
    2006/11/30 18:24:53+02:00 monty@mysql.com +0 -1
    Removed not used variable
  
  
  Revision r1260:
  branches/5.0: Fix for Bug# 21409. At low transaction isolation levels
  we let each consistent read set its own snapshot.
  
  
  Revision r1326:
  branches/5.0: Merge code from MySQL AB:
  
  ChangeSet@1.2417.3.1  2007-02-22 16:59:57+02:00  monty@mysql.fi
  
  Fixed compiler warnings (for linux and win32 and win64)
2007-03-22 14:40:52 -06:00

505 lines
11 KiB
C

/*******************************************************************
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>
#include "ut0sort.h"
#include "trx0trx.h"
ibool ut_always_false = FALSE;
#ifdef __WIN__
/*********************************************************************
NOTE: The Windows epoch starts from 1601/01/01 whereas the Unix
epoch starts from 1970/1/1. For selection of constant see:
http://support.microsoft.com/kb/167296/ */
#define WIN_TO_UNIX_DELTA_USEC ((ib_longlong) 11644473600000000ULL)
/*********************************************************************
This is the Windows version of gettimeofday(2).*/
static
int
ut_gettimeofday(
/*============*/
/* out: 0 if all OK else -1 */
struct timeval* tv, /* out: Values are relative to Unix epoch */
void* tz) /* in: not used */
{
FILETIME ft;
ib_longlong tm;
if (!tv) {
errno = EINVAL;
return(-1);
}
GetSystemTimeAsFileTime(&ft);
tm = (ib_longlong) ft.dwHighDateTime << 32;
tm |= ft.dwLowDateTime;
ut_a(tm >= 0); /* If tm wraps over to negative, the quotient / 10
does not work */
tm /= 10; /* Convert from 100 nsec periods to usec */
/* If we don't convert to the Unix epoch the value for
struct timeval::tv_sec will overflow.*/
tm -= WIN_TO_UNIX_DELTA_USEC;
tv->tv_sec = (long) (tm / 1000000L);
tv->tv_usec = (long) (tm % 1000000L);
return(0);
}
#else
#define ut_gettimeofday gettimeofday
#endif
/*********************************************************************
Get the quote character to be used in SQL identifiers.
This definition must match the one in sql/ha_innodb.cc! */
extern
int
mysql_get_identifier_quote_char(
/*============================*/
/* out: quote character to be
used in SQL identifiers; EOF if none */
trx_t* trx, /* in: transaction */
const char* name, /* in: name to print */
ulint namelen);/* in: length of name */
/************************************************************
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 */
{
ib_longlong i;
i = (ib_longlong)a;
i = i >> 32;
return((ulint)i);
}
/************************************************************
The following function returns elapsed CPU time in milliseconds. */
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 system time. */
void
ut_usectime(
/*========*/
ulint* sec, /* out: seconds since the Epoch */
ulint* ms) /* out: microseconds since the Epoch+*sec */
{
struct timeval tv;
ut_gettimeofday(&tv, NULL);
*sec = (ulint) tv.tv_sec;
*ms = (ulint) tv.tv_usec;
}
/**************************************************************
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__
SYSTEMTIME cal_tm;
GetLocalTime(&cal_tm);
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
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
fprintf(file,"%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
}
/**************************************************************
Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */
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
}
/**************************************************************
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
}
/**************************************************************
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;
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
*year = (ulint)cal_tm_ptr->tm_year + 1900;
*month = (ulint)cal_tm_ptr->tm_mon + 1;
*day = (ulint)cal_tm_ptr->tm_mday;
#endif
}
/*****************************************************************
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) {
ut_always_false = (ibool) j;
}
return(j);
}
/*****************************************************************
Prints the contents of a memory buffer in hex and ascii. */
void
ut_print_buf(
/*=========*/
FILE* file, /* in: file where to print */
const byte* buf, /* in: memory buffer */
ulint len) /* in: length of the buffer */
{
const byte* data;
ulint i;
fprintf(file, " len %lu; hex ", len);
for (data = buf, i = 0; i < len; i++) {
fprintf(file, "%02lx", (ulong)*data++);
}
fputs("; asc ", file);
data = buf;
for (i = 0; i < len; i++) {
int c = (int) *data++;
putc(isprint(c) ? c : ' ', file);
}
putc(';', file);
}
/****************************************************************
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);
}
/*****************************************************************
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);
}
/**************************************************************************
Outputs a NUL-terminated file name, quoted with apostrophes. */
void
ut_print_filename(
/*==============*/
FILE* f, /* in: output stream */
const char* name) /* in: name to print */
{
putc('\'', f);
for (;;) {
int c = *name++;
switch (c) {
case 0:
goto done;
case '\'':
putc(c, f);
/* fall through */
default:
putc(c, f);
}
}
done:
putc('\'', f);
}
/**************************************************************************
Outputs a NUL-terminated string, quoted as an SQL identifier. */
void
ut_print_name(
/*==========*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
const char* name) /* in: name to print */
{
ut_print_namel(f, trx, name, strlen(name));
}
/**************************************************************************
Outputs a fixed-length string, quoted as an SQL identifier. */
void
ut_print_namel(
/*==========*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction (NULL=no quotes) */
const char* name, /* in: name to print */
ulint namelen)/* in: length of name */
{
const char* s = name;
const char* e = s + namelen;
#ifdef UNIV_HOTBACKUP
int q = '"';
#else
int q = mysql_get_identifier_quote_char(trx, name, namelen);
#endif
if (q == EOF) {
fwrite(name, 1, namelen, f);
return;
}
putc(q, f);
while (s < e) {
int c = *s++;
if (c == q) {
putc(c, f);
}
putc(c, f);
}
putc(q, f);
}
/**************************************************************************
Catenate files. */
void
ut_copy_file(
/*=========*/
FILE* dest, /* in: output file */
FILE* src) /* in: input file to be appended to output */
{
long len = ftell(src);
char buf[4096];
rewind(src);
do {
size_t maxs =
len < (long) sizeof buf ? (size_t) len : sizeof buf;
size_t size = fread(buf, 1, maxs, src);
fwrite(buf, 1, size, dest);
len -= (long) size;
if (size < maxs) {
break;
}
} while (len > 0);
}