Skip to content

Commit

Permalink
BUG#26734457 BACKPORT BUG#22305994 TO 5.6 AND 5.7
Browse files Browse the repository at this point in the history
Use GetSystemTimePreciseAsFileTime in my_micro_time on Windows when it
is available to achieve higher timer resolution.

Change-Id: I200c54b83fedb22c2e4c45bc151aed44fec0ff6c
  • Loading branch information
Daniel Blanchard committed Oct 27, 2017
1 parent 180adbe commit cd0b9f7
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 10 deletions.
30 changes: 30 additions & 0 deletions mysql-test/suite/innodb/r/timestamp.result
@@ -0,0 +1,30 @@
#
# Bug #47453: InnoDB incorrectly changes TIMESTAMP columns when
# JOINed during an UPDATE
#
CREATE TABLE t1 (d INT) ENGINE=InnoDB;
CREATE TABLE t2 (a INT, b INT,
c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6)) ENGINE=InnoDB;
# set up our data elements
INSERT INTO t1 (d) VALUES (1);
INSERT INTO t2 (a,b) VALUES (1,1);
SELECT c INTO @bug47453 FROM t2;
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
c!=@bug47453
0
UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1;
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
c!=@bug47453
0
UPDATE t1 JOIN t2 ON d=a SET b=1;
# should be 0
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
c!=@bug47453
0
UPDATE t1 JOIN t2 ON d=a SET b=2;
# should not be 0
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
c!=@bug47453
1
DROP TABLE t1, t2;
26 changes: 26 additions & 0 deletions mysql-test/suite/innodb/t/timestamp.test
@@ -0,0 +1,26 @@
--echo #
--echo # Bug #47453: InnoDB incorrectly changes TIMESTAMP columns when
--echo # JOINed during an UPDATE
--echo #

CREATE TABLE t1 (d INT) ENGINE=InnoDB;
CREATE TABLE t2 (a INT, b INT,
c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6)) ENGINE=InnoDB;

--echo # set up our data elements
INSERT INTO t1 (d) VALUES (1);
INSERT INTO t2 (a,b) VALUES (1,1);
SELECT c INTO @bug47453 FROM t2;

SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1;
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
UPDATE t1 JOIN t2 ON d=a SET b=1;
--echo # should be 0
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;
UPDATE t1 JOIN t2 ON d=a SET b=2;
--echo # should not be 0
SELECT c!=@bug47453 FROM t1 JOIN t2 ON d=a;

DROP TABLE t1, t2;
44 changes: 38 additions & 6 deletions mysys/my_getsystime.c
@@ -1,4 +1,4 @@
/* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand All @@ -25,6 +25,40 @@
#include "mysys_priv.h"
#include "my_static.h"

#if defined(_WIN32)
#include "my_sys.h" /* for my_printf_error */
typedef VOID(WINAPI *time_fn)(LPFILETIME);
static time_fn my_get_system_time_as_file_time= GetSystemTimeAsFileTime;

/**
Initialise highest available time resolution API on Windows
@return Initialization result
@retval FALSE Success
@retval TRUE Error. Couldn't initialize environment
*/
my_bool win_init_get_system_time_as_file_time()
{
HMODULE h= LoadLibrary("kernel32.dll");
if (h != NULL)
{
time_fn pfn= (time_fn) GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
if (pfn)
my_get_system_time_as_file_time= pfn;

return FALSE;
}

DWORD error= GetLastError();
my_printf_error(0,
"LoadLibrary(\"kernel32.dll\") failed: GetLastError returns %lu",
MYF(0),
error);

return TRUE;
}
#endif


/**
Get high-resolution time.
Expand Down Expand Up @@ -89,18 +123,16 @@ time_t my_time(myf flags)
Return time in microseconds.
@remark This function is to be used to measure performance in
micro seconds. As it's not defined whats the start time
for the clock, this function us only useful to measure
time between two moments.
micro seconds.
@retval Value in microseconds from some undefined point in time.
@retval Number of microseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)
*/

ulonglong my_micro_time()
{
#ifdef _WIN32
ulonglong newtime;
GetSystemTimeAsFileTime((FILETIME*)&newtime);
my_get_system_time_as_file_time((FILETIME*)&newtime);
newtime-= OFFSET_TO_EPOCH;
return (newtime/10);
#else
Expand Down
5 changes: 4 additions & 1 deletion mysys/my_init.c
@@ -1,4 +1,4 @@
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -30,6 +30,7 @@
my_bool have_tcpip=0;
static void my_win_init(void);
static my_bool win32_init_tcp_ip();
my_bool win_init_get_system_time_as_file_time();
#else
#define my_win_init()
#endif
Expand Down Expand Up @@ -109,6 +110,8 @@ my_bool my_init(void)
DBUG_PRINT("exit", ("home: '%s'", home_dir));
#ifdef __WIN__
win32_init_tcp_ip();
if (win_init_get_system_time_as_file_time())
DBUG_RETURN(1);
#endif
DBUG_RETURN(0);
}
Expand Down
8 changes: 8 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Expand Up @@ -3473,6 +3473,14 @@ innobase_init(
/* Turn on monitor counters that are default on */
srv_mon_default_on();

#ifndef UNIV_HOTBACKUP
#ifdef _WIN32
if (ut_win_init_time()) {
goto mem_free_and_error;
}
#endif /* _WIN32 */
#endif /* !UNIV_HOTBACKUP */

DBUG_RETURN(FALSE);
error:
DBUG_RETURN(TRUE);
Expand Down
11 changes: 10 additions & 1 deletion storage/innobase/include/ut0ut.h
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Expand Down Expand Up @@ -266,6 +266,15 @@ UNIV_INTERN
ulint
ut_time_ms(void);
/*============*/
#ifdef _WIN32
/**********************************************************//**
Initialise highest available time resolution API on Windows
@return 0 if all OK else -1 */
int
ut_win_init_time();

#endif /* _WIN32 */

#endif /* !UNIV_HOTBACKUP */

/**********************************************************//**
Expand Down
30 changes: 28 additions & 2 deletions storage/innobase/ut/ut0ut.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Expand Down Expand Up @@ -48,13 +48,39 @@ Created 5/11/1994 Heikki Tuuri
UNIV_INTERN ibool ut_always_false = FALSE;

#ifdef __WIN__
#include <mysql/innodb_priv.h> /* For sql_print_error */
typedef VOID(WINAPI *time_fn)(LPFILETIME);
static time_fn ut_get_system_time_as_file_time = GetSystemTimeAsFileTime;

/*****************************************************************//**
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_int64_t) 11644473600000000ULL)


/**
Initialise highest available time resolution API on Windows
@return 0 if all OK else -1 */
int
ut_win_init_time()
{
HMODULE h = LoadLibrary("kernel32.dll");
if (h != NULL)
{
time_fn pfn = (time_fn)GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
if (pfn != NULL)
{
ut_get_system_time_as_file_time = pfn;
}
return false;
}
DWORD error = GetLastError();
sql_print_error(
"LoadLibrary(\"kernel32.dll\") failed: GetLastError returns %lu", error);
return(-1);
}

/*****************************************************************//**
This is the Windows version of gettimeofday(2).
@return 0 if all OK else -1 */
Expand All @@ -73,7 +99,7 @@ ut_gettimeofday(
return(-1);
}

GetSystemTimeAsFileTime(&ft);
ut_get_system_time_as_file_time(&ft);

tm = (ib_int64_t) ft.dwHighDateTime << 32;
tm |= ft.dwLowDateTime;
Expand Down

0 comments on commit cd0b9f7

Please sign in to comment.