Commit 84a6de3f authored by He Zhenxing's avatar He Zhenxing

Bug#49557 "semisync" plugin test fails on Windows

The problem was because the gettimeofday function was incorrect
implemented for Windows, and so the semisync master did not wait
for slave reply properly on Windows.

Fixed by removing the gettimeofday function for Windows, and using
set_timespec function to get current time for all platforms.


plugin/semisync/semisync_master.cc:
  removing the gettimeofday function for Windows, using set_timespec
  function to get current time for all platforms.
parent 12c5f656
...@@ -43,19 +43,16 @@ unsigned long long rpl_semi_sync_master_trx_wait_time = 0; ...@@ -43,19 +43,16 @@ unsigned long long rpl_semi_sync_master_trx_wait_time = 0;
char rpl_semi_sync_master_wait_no_slave = 1; char rpl_semi_sync_master_wait_no_slave = 1;
static int getWaitTime(const struct timeval& start_tv); static int getWaitTime(const struct timespec& start_ts);
#ifdef __WIN__ static unsigned long long timespec_to_usec(const struct timespec *ts)
static int gettimeofday(struct timeval *tv, void *tz)
{ {
unsigned int ticks; #ifndef __WIN__
ticks= GetTickCount(); return (unsigned long long) ts->tv_sec * TIME_MILLION + ts->tv_nsec / TIME_THOUSAND;
tv->tv_usec= ticks*1000; #else
tv->tv_sec= ticks/1000; return ts->tv.i64 / 10;
return 0;
}
#endif /* __WIN__ */ #endif /* __WIN__ */
}
/******************************************************************************* /*******************************************************************************
* *
...@@ -604,12 +601,12 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -604,12 +601,12 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
if (getMasterEnabled() && trx_wait_binlog_name) if (getMasterEnabled() && trx_wait_binlog_name)
{ {
struct timeval start_tv; struct timespec start_ts;
struct timespec abstime; struct timespec abstime;
int wait_result, start_time_err; int wait_result;
const char *old_msg= 0; const char *old_msg= 0;
start_time_err = gettimeofday(&start_tv, 0); set_timespec(start_ts, 0);
/* Acquire the mutex. */ /* Acquire the mutex. */
lock(); lock();
...@@ -677,98 +674,71 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -677,98 +674,71 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
kWho, wait_file_name_, (unsigned long)wait_file_pos_); kWho, wait_file_name_, (unsigned long)wait_file_pos_);
} }
if (start_time_err == 0) /* Calcuate the waiting period. */
{
int diff_usecs = start_tv.tv_usec + wait_timeout_ * TIME_THOUSAND;
/* Calcuate the waiting period. */
#ifdef __WIN__ #ifdef __WIN__
abstime.tv.i64 = (__int64)start_tv.tv_sec * TIME_MILLION * 10; abstime.tv.i64 = start_ts.tv.i64 + (__int64)wait_timeout_ * TIME_THOUSAND * 10;
abstime.tv.i64 += (__int64)diff_usecs * 10; abstime.max_timeout_msec= (long)wait_timeout_;
abstime.max_timeout_msec= (long)wait_timeout_;
#else #else
abstime.tv_sec = start_tv.tv_sec; unsigned long diff_nsecs = start_ts.tv_nsec + wait_timeout_ * TIME_MILLION;
if (diff_usecs < TIME_MILLION) abstime.tv_sec = start_ts.tv_sec;
{ while (diff_nsecs >= TIME_BILLION)
abstime.tv_nsec = diff_usecs * TIME_THOUSAND; {
} abstime.tv_sec++;
else diff_nsecs -= TIME_BILLION;
{ }
while (diff_usecs >= TIME_MILLION) abstime.tv_nsec = diff_nsecs;
{
abstime.tv_sec++;
diff_usecs -= TIME_MILLION;
}
abstime.tv_nsec = diff_usecs * TIME_THOUSAND;
}
#endif /* __WIN__ */ #endif /* __WIN__ */
/* In semi-synchronous replication, we wait until the binlog-dump /* In semi-synchronous replication, we wait until the binlog-dump
* thread has received the reply on the relevant binlog segment from the * thread has received the reply on the relevant binlog segment from the
* replication slave. * replication slave.
* *
* Let us suspend this thread to wait on the condition; * Let us suspend this thread to wait on the condition;
* when replication has progressed far enough, we will release * when replication has progressed far enough, we will release
* these waiting threads. * these waiting threads.
*/ */
rpl_semi_sync_master_wait_sessions++; rpl_semi_sync_master_wait_sessions++;
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: wait %lu ms for binlog sent (%s, %lu)", sql_print_information("%s: wait %lu ms for binlog sent (%s, %lu)",
kWho, wait_timeout_, kWho, wait_timeout_,
wait_file_name_, (unsigned long)wait_file_pos_); wait_file_name_, (unsigned long)wait_file_pos_);
wait_result = cond_timewait(&abstime); wait_result = cond_timewait(&abstime);
rpl_semi_sync_master_wait_sessions--; rpl_semi_sync_master_wait_sessions--;
if (wait_result != 0) if (wait_result != 0)
{ {
/* This is a real wait timeout. */ /* This is a real wait timeout. */
sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), " sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), "
"semi-sync up to file %s, position %lu.", "semi-sync up to file %s, position %lu.",
trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos, trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos,
reply_file_name_, (unsigned long)reply_file_pos_); reply_file_name_, (unsigned long)reply_file_pos_);
rpl_semi_sync_master_wait_timeouts++; rpl_semi_sync_master_wait_timeouts++;
/* switch semi-sync off */ /* switch semi-sync off */
switch_off(); switch_off();
}
else
{
int wait_time;
wait_time = getWaitTime(start_tv);
if (wait_time < 0)
{
if (trace_level_ & kTraceGeneral)
{
/* This is a time/gettimeofday function call error. */
sql_print_error("Replication semi-sync gettimeofday fail1 at "
"wait position (%s, %lu)",
trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos);
}
rpl_semi_sync_master_timefunc_fails++;
}
else
{
rpl_semi_sync_master_trx_wait_num++;
rpl_semi_sync_master_trx_wait_time += wait_time;
}
}
} }
else else
{ {
if (trace_level_ & kTraceGeneral) int wait_time;
{
/* This is a gettimeofday function call error. */ wait_time = getWaitTime(start_ts);
sql_print_error("Replication semi-sync gettimeofday fail2 at " if (wait_time < 0)
"wait position (%s, %lu)", {
trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos); if (trace_level_ & kTraceGeneral)
{
sql_print_error("Replication semi-sync getWaitTime fail at "
"wait position (%s, %lu)",
trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos);
}
rpl_semi_sync_master_timefunc_fails++;
}
else
{
rpl_semi_sync_master_trx_wait_num++;
rpl_semi_sync_master_trx_wait_time += wait_time;
} }
rpl_semi_sync_master_timefunc_fails++;
/* switch semi-sync off */
switch_off();
} }
} }
...@@ -1078,8 +1048,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id, ...@@ -1078,8 +1048,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id,
ulong packet_len; ulong packet_len;
int result = -1; int result = -1;
struct timeval start_tv; struct timespec start_ts;
int start_time_err= 0;
ulong trc_level = trace_level_; ulong trc_level = trace_level_;
function_enter(kWho); function_enter(kWho);
...@@ -1093,7 +1062,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id, ...@@ -1093,7 +1062,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id,
} }
if (trc_level & kTraceNetWait) if (trc_level & kTraceNetWait)
start_time_err = gettimeofday(&start_tv, 0); set_timespec(start_ts, 0);
/* We flush to make sure that the current event is sent to the network, /* We flush to make sure that the current event is sent to the network,
* instead of being buffered in the TCP/IP stack. * instead of being buffered in the TCP/IP stack.
...@@ -1118,28 +1087,17 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id, ...@@ -1118,28 +1087,17 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id,
if (trc_level & kTraceNetWait) if (trc_level & kTraceNetWait)
{ {
if (start_time_err != 0) int wait_time = getWaitTime(start_ts);
if (wait_time < 0)
{ {
sql_print_error("Semi-sync master wait for reply " sql_print_error("Semi-sync master wait for reply "
"gettimeofday fail to get start time"); "fail to get wait time.");
rpl_semi_sync_master_timefunc_fails++; rpl_semi_sync_master_timefunc_fails++;
} }
else else
{ {
int wait_time; rpl_semi_sync_master_net_wait_num++;
rpl_semi_sync_master_net_wait_time += wait_time;
wait_time = getWaitTime(start_tv);
if (wait_time < 0)
{
sql_print_error("Semi-sync master wait for reply "
"gettimeofday fail to get wait time.");
rpl_semi_sync_master_timefunc_fails++;
}
else
{
rpl_semi_sync_master_net_wait_num++;
rpl_semi_sync_master_net_wait_time += wait_time;
}
} }
} }
...@@ -1228,24 +1186,23 @@ void ReplSemiSyncMaster::setExportStats() ...@@ -1228,24 +1186,23 @@ void ReplSemiSyncMaster::setExportStats()
* *
* Return: * Return:
* >= 0: the waiting time in microsecons(us) * >= 0: the waiting time in microsecons(us)
* < 0: error in gettimeofday or time back traverse * < 0: error in get time or time back traverse
*/ */
static int getWaitTime(const struct timeval& start_tv) static int getWaitTime(const struct timespec& start_ts)
{ {
unsigned long long start_usecs, end_usecs; unsigned long long start_usecs, end_usecs;
struct timeval end_tv; struct timespec end_ts;
int end_time_err;
/* Starting time in microseconds(us). */ /* Starting time in microseconds(us). */
start_usecs = start_tv.tv_sec * TIME_MILLION + start_tv.tv_usec; start_usecs = timespec_to_usec(&start_ts);
/* Get the wait time interval. */ /* Get the wait time interval. */
end_time_err = gettimeofday(&end_tv, 0); set_timespec(end_ts, 0);
/* Ending time in microseconds(us). */ /* Ending time in microseconds(us). */
end_usecs = end_tv.tv_sec * TIME_MILLION + end_tv.tv_usec; end_usecs = timespec_to_usec(&end_ts);
if (end_time_err != 0 || end_usecs < start_usecs) if (end_usecs < start_usecs)
return -1; return -1;
return (int)(end_usecs - start_usecs); return (int)(end_usecs - start_usecs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment