Commit 28a18fef authored by Otto Kekäläinen's avatar Otto Kekäläinen
Browse files

Merge tag 'upstream/5.5.50' into ubuntu-14.04

Upstream version 5.5.50
parents 3747036d 95c6357a
......@@ -33,7 +33,7 @@ int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control)
DBUG_ENTER("ma_service_thread_control_init");
DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
control->inited= TRUE;
control->status= THREAD_DEAD; /* not yet born == dead */
control->killed= FALSE;
res= (mysql_mutex_init(key_SERVICE_THREAD_CONTROL_lock,
control->LOCK_control, MY_MUTEX_INIT_SLOW) ||
mysql_cond_init(key_SERVICE_THREAD_CONTROL_cond,
......@@ -60,20 +60,17 @@ void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control)
DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
DBUG_ASSERT(control->inited);
mysql_mutex_lock(control->LOCK_control);
if (control->status != THREAD_DEAD) /* thread was started OK */
if (!control->killed)
{
DBUG_PRINT("info",("killing Maria background thread"));
control->status= THREAD_DYING; /* kill it */
do /* and wait for it to be dead */
{
/* wake it up if it was in a sleep */
mysql_cond_broadcast(control->COND_control);
DBUG_PRINT("info",("waiting for Maria background thread to die"));
mysql_cond_wait(control->COND_control, control->LOCK_control);
}
while (control->status != THREAD_DEAD);
control->killed= TRUE; /* kill it */
mysql_cond_broadcast(control->COND_control);
mysql_mutex_unlock(control->LOCK_control);
DBUG_PRINT("info", ("waiting for Maria background thread to die"));
pthread_join(control->thread, NULL);
}
mysql_mutex_unlock(control->LOCK_control);
else
mysql_mutex_unlock(control->LOCK_control);
mysql_mutex_destroy(control->LOCK_control);
mysql_cond_destroy(control->COND_control);
control->inited= FALSE;
......@@ -100,7 +97,7 @@ my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
DBUG_ENTER("my_service_thread_sleep");
DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
mysql_mutex_lock(control->LOCK_control);
if (control->status == THREAD_DYING)
if (control->killed)
{
mysql_mutex_unlock(control->LOCK_control);
DBUG_RETURN(TRUE);
......@@ -119,34 +116,8 @@ my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
control->LOCK_control, &abstime);
}
#endif
if (control->status == THREAD_DYING)
if (control->killed)
res= TRUE;
mysql_mutex_unlock(control->LOCK_control);
DBUG_RETURN(res);
}
/**
inform about thread exiting
@param control control block
*/
void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control)
{
DBUG_ENTER("my_service_thread_signal_end");
DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
mysql_mutex_lock(control->LOCK_control);
control->status = THREAD_DEAD; /* indicate that we are dead */
/*
wake up ma_service_thread_control_end which may be waiting for
our death
*/
mysql_cond_broadcast(control->COND_control);
/*
broadcast was inside unlock because ma_service_thread_control_end
destroys mutex
*/
mysql_mutex_unlock(control->LOCK_control);
DBUG_VOID_RETURN;
}
......@@ -16,12 +16,10 @@
#include <my_pthread.h>
enum ma_service_thread_state {THREAD_RUNNING, THREAD_DYING, THREAD_DEAD};
typedef struct st_ma_service_thread_control
{
/** 'kill' flag for the background thread */
enum ma_service_thread_state status;
pthread_t thread;
my_bool killed;
/** if thread module was inited or not */
my_bool inited;
/** for killing the background thread */
......@@ -35,4 +33,3 @@ int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control);
void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control);
my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
ulonglong sleep_time);
void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control);
......@@ -86,6 +86,27 @@ static int write_merge_key_varlen(MARIA_SORT_PARAM *info,
static inline int
my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs);
/*
Sets the appropriate read and write methods for the MARIA_SORT_PARAM
based on the variable length key flag.
*/
static void set_sort_param_read_write(MARIA_SORT_PARAM *sort_param)
{
if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sort_param->write_keys= write_keys_varlen;
sort_param->read_to_buffer= read_to_buffer_varlen;
sort_param->write_key= write_merge_key_varlen;
}
else
{
sort_param->write_keys= write_keys;
sort_param->read_to_buffer= read_to_buffer;
sort_param->write_key= write_merge_key;
}
}
/*
Creates a index of sorted keys
......@@ -115,18 +136,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
(ulong) sortbuff_size, info->key_length,
(ulong) info->sort_info->max_records));
if (info->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
info->write_keys= write_keys_varlen;
info->read_to_buffer=read_to_buffer_varlen;
info->write_key=write_merge_key_varlen;
}
else
{
info->write_keys= write_keys;
info->read_to_buffer=read_to_buffer;
info->write_key=write_merge_key;
}
set_sort_param_read_write(info);
my_b_clear(&tempfile);
my_b_clear(&tempfile_for_exceptions);
......@@ -323,181 +333,182 @@ static ha_rows find_all_keys(MARIA_SORT_PARAM *info, uint keys,
} /* find_all_keys */
/* Search after all keys and place them in a temp. file */
pthread_handler_t _ma_thr_find_all_keys(void *arg)
static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param)
{
MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg;
int error;
size_t memavl,old_memavl;
int error= 0;
ulonglong memavl, old_memavl;
uint UNINIT_VAR(keys), idx;
uint sort_length;
ulong idx, maxbuffer, keys;
uchar **sort_keys=0;
LINT_INIT(keys);
uint maxbuffer;
uchar **sort_keys= NULL;
DBUG_ENTER("_ma_thr_find_all_keys");
DBUG_PRINT("enter", ("master: %d", sort_param->master));
error=1;
if (sort_param->sort_info->got_error)
DBUG_RETURN(TRUE);
if (my_thread_init())
goto err;
{ /* Add extra block since DBUG_ENTER declare variables */
DBUG_ENTER("_ma_thr_find_all_keys");
DBUG_PRINT("enter", ("master: %d", sort_param->master));
if (sort_param->sort_info->got_error)
goto err;
set_sort_param_read_write(sort_param);
if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sort_param->write_keys= write_keys_varlen;
sort_param->read_to_buffer= read_to_buffer_varlen;
sort_param->write_key= write_merge_key_varlen;
}
else
{
sort_param->write_keys= write_keys;
sort_param->read_to_buffer= read_to_buffer;
sort_param->write_key= write_merge_key;
}
my_b_clear(&sort_param->tempfile);
my_b_clear(&sort_param->tempfile_for_exceptions);
bzero((char*) &sort_param->buffpek,sizeof(sort_param->buffpek));
bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
my_b_clear(&sort_param->tempfile);
my_b_clear(&sort_param->tempfile_for_exceptions);
bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY);
idx= (uint)sort_param->sort_info->max_records;
sort_length= sort_param->key_length;
maxbuffer= 1;
memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY);
idx= sort_param->sort_info->max_records;
sort_length= sort_param->key_length;
maxbuffer= 1;
while (memavl >= MIN_SORT_MEMORY)
while (memavl >= MIN_SORT_MEMORY)
{
if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl)
keys= idx+1;
else
{
if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl)
keys= idx+1;
else
{
ulong skr;
do
{
skr= maxbuffer;
if (memavl < sizeof(BUFFPEK)*maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
(sort_length+sizeof(char*))) <= 1 ||
keys < maxbuffer)
{
_ma_check_print_error(sort_param->sort_info->param,
"aria_sort_buffer_size is too small");
goto err;
}
}
while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
if ((sort_keys= (uchar **)
my_malloc(keys*(sort_length+sizeof(char*))+
((sort_param->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
ulong skr;
do
{
if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
maxbuffer, maxbuffer/2))
skr= maxbuffer;
if (memavl < sizeof(BUFFPEK)*maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
(sort_length+sizeof(char*))) <= 1 ||
keys < maxbuffer)
{
my_free(sort_keys);
sort_keys= (uchar **) NULL; /* for err: label */
_ma_check_print_error(sort_param->sort_info->param,
"aria_sort_buffer_size is too small.");
goto err;
}
else
break;
}
old_memavl= memavl;
if ((memavl= memavl/4*3) < MIN_SORT_MEMORY &&
old_memavl > MIN_SORT_MEMORY)
memavl= MIN_SORT_MEMORY;
while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
if (memavl < MIN_SORT_MEMORY)
if ((sort_keys= (uchar **)
my_malloc(keys*(sort_length+sizeof(char*))+
((sort_param->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
{
_ma_check_print_error(sort_param->sort_info->param,
"Aria sort buffer too small");
goto err; /* purecov: tested */
if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
maxbuffer, maxbuffer / 2))
{
my_free(sort_keys);
sort_keys= NULL; /* Safety against double free on error. */
}
else
break;
}
old_memavl= memavl;
if ((memavl= memavl/4*3) < MIN_SORT_MEMORY &&
old_memavl > MIN_SORT_MEMORY)
memavl= MIN_SORT_MEMORY;
}
if (sort_param->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %lu keys\n",
sort_param->key+1, (ulong) keys);
sort_param->sort_keys= sort_keys;
if (memavl < MIN_SORT_MEMORY)
{
/* purecov: begin inspected */
_ma_check_print_error(sort_param->sort_info->param,
"aria_sort_buffer_size is too small.");
my_errno= ENOMEM;
goto err;
/* purecov: end inspected */
}
idx= error= 0;
sort_keys[0]= (uchar*) (sort_keys+keys);
if (sort_param->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %llu keys\n",
sort_param->key + 1, (ulonglong) keys);
sort_param->sort_keys= sort_keys;
DBUG_PRINT("info", ("reading keys"));
while (!(error= sort_param->sort_info->got_error) &&
!(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
{
if (sort_param->real_key_length > sort_param->key_length)
{
if (write_key(sort_param,sort_keys[idx],
&sort_param->tempfile_for_exceptions))
goto err;
continue;
}
idx= error= 0;
sort_keys[0]= (uchar*) (sort_keys+keys);
if (++idx == keys)
{
if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
(BUFFPEK *)alloc_dynamic(&sort_param->
buffpek),
&sort_param->tempfile))
goto err;
sort_keys[0]= (uchar*) (sort_keys+keys);
memcpy(sort_keys[0], sort_keys[idx - 1],
(size_t) sort_param->key_length);
idx= 1;
}
sort_keys[idx]=sort_keys[idx - 1] + sort_param->key_length;
DBUG_PRINT("info", ("reading keys"));
while (!(error= sort_param->sort_info->got_error) &&
!(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
{
if (sort_param->real_key_length > sort_param->key_length)
{
if (write_key(sort_param, sort_keys[idx],
&sort_param->tempfile_for_exceptions))
goto err;
continue;
}
if (error > 0)
goto err;
if (sort_param->buffpek.elements)
if (++idx == keys)
{
if (sort_param->write_keys(sort_param,sort_keys, idx,
(BUFFPEK *) alloc_dynamic(&sort_param->
buffpek),
if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
(BUFFPEK *)alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
sort_keys[0]= (uchar*) (sort_keys+keys);
memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
idx= 1;
}
else
sort_param->keys= idx;
sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
}
if (error > 0)
goto err;
if (sort_param->buffpek.elements)
{
if (sort_param->write_keys(sort_param,sort_keys, idx,
(BUFFPEK *) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
}
else
sort_param->keys= idx;
sort_param->sort_keys_length= keys;
goto ok;
sort_param->sort_keys_length= keys;
DBUG_RETURN(FALSE);
err:
DBUG_PRINT("error", ("got some error"));
sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
my_free(sort_keys);
sort_param->sort_keys=0;
delete_dynamic(& sort_param->buffpek);
close_cached_file(&sort_param->tempfile);
close_cached_file(&sort_param->tempfile_for_exceptions);
ok:
free_root(&sort_param->wordroot, MYF(0));
/*
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
*/
if (sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
if (sort_param->read_cache.share)
remove_io_thread(&sort_param->read_cache);
mysql_mutex_lock(&sort_param->sort_info->mutex);
if (!--sort_param->sort_info->threads_running)
mysql_cond_signal(&sort_param->sort_info->cond);
mysql_mutex_unlock(&sort_param->sort_info->mutex);
DBUG_PRINT("exit", ("======== ending thread ========"));
}
DBUG_PRINT("error", ("got some error"));
my_free(sort_keys);
sort_param->sort_keys= 0;
delete_dynamic(& sort_param->buffpek);
close_cached_file(&sort_param->tempfile);
close_cached_file(&sort_param->tempfile_for_exceptions);
DBUG_RETURN(TRUE);
}
/* Search after all keys and place them in a temp. file */
pthread_handler_t _ma_thr_find_all_keys(void *arg)
{
MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg;
my_bool error= FALSE;
/* If my_thread_init fails */
if (my_thread_init() || _ma_thr_find_all_keys_exec(sort_param))
error= TRUE;
/*
Thread must clean up after itself.
*/
free_root(&sort_param->wordroot, MYF(0));
/*
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
That means that a writer always gets here first and readers -
only when they see EOF. But if a reader finishes prematurely
because of an error it may reach this earlier - don't allow it
to detach the writer thread.
*/
if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
if (sort_param->read_cache.share)
remove_io_thread(&sort_param->read_cache);
mysql_mutex_lock(&sort_param->sort_info->mutex);
if (error)
sort_param->sort_info->got_error= 1;
if (!--sort_param->sort_info->threads_running)
mysql_cond_signal(&sort_param->sort_info->cond);
mysql_mutex_unlock(&sort_param->sort_info->mutex);
my_thread_end();
return NULL;
}
......@@ -507,7 +518,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
{
MARIA_SORT_INFO *sort_info=sort_param->sort_info;
HA_CHECK *param=sort_info->param;
ulong UNINIT_VAR(length), keys;
size_t UNINIT_VAR(length), keys;
double *rec_per_key_part= param->new_rec_per_key_part;
int got_error=sort_info->got_error;
uint i;
......@@ -564,18 +575,9 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
{
if (got_error)
continue;
if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sinfo->write_keys=write_keys_varlen;
sinfo->read_to_buffer=read_to_buffer_varlen;
sinfo->write_key=write_merge_key_varlen;
}
else
{
sinfo->write_keys=write_keys;
sinfo->read_to_buffer=read_to_buffer;
sinfo->write_key=write_merge_key;
}
set_sort_param_read_write(sinfo);
if (sinfo->buffpek.elements)
{
uint maxbuffer=sinfo->buffpek.elements-1;
......
......@@ -67,7 +67,8 @@ typedef struct st_maria_sort_info
pgcache_page_no_t page;
ha_rows max_records;
uint current_key, total_keys;
uint got_error, threads_running;
volatile uint got_error;
uint threads_running;
myf myf_rw;
enum data_file_type new_data_file_type, org_data_file_type;
} MARIA_SORT_INFO;
......
......@@ -84,6 +84,28 @@ static int write_merge_key_varlen(MI_SORT_PARAM *info,
static inline int
my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs);
/*
Sets the appropriate read and write methods for the MI_SORT_PARAM
based on the variable length key flag.
*/
static void set_sort_param_read_write(MI_SORT_PARAM *sort_param)
{
if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sort_param->write_keys= write_keys_varlen;
sort_param->read_to_buffer= read_to_buffer_varlen;
sort_param->write_key= write_merge_key_varlen;
}
else
{
sort_param->write_keys= write_keys;
sort_param->read_to_buffer= read_to_buffer;
sort_param->write_key= write_merge_key;
}
}
/*
Creates a index of sorted keys
......@@ -111,18 +133,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
DBUG_ENTER("_create_index_by_sort");
DBUG_PRINT("enter",("sort_length: %d", info->key_length));
if (info->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
info->write_keys=write_keys_varlen;
info->read_to_buffer=read_to_buffer_varlen;
info->write_key= write_merge_key_varlen;
}
else
{
info->write_keys=write_keys;
info->read_to_buffer=read_to_buffer;
info->write_key=write_merge_key;
}
set_sort_param_read_write(info);
my_b_clear(&tempfile);
my_b_clear(&tempfile_for_exceptions);
......@@ -179,7 +190,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
}
if (memavl < MIN_SORT_BUFFER)
{
mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */
mi_check_print_error(info->sort_info->param,
"MyISAM sort buffer too small"); /* purecov: tested */
my_errno= ENOMEM; /* purecov: tested */
goto err; /* purecov: tested */
}
......@@ -307,189 +319,187 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys,
DBUG_RETURN((*maxbuffer)*(keys-1)+idx);
} /* find_all_keys */
/* Search after all keys and place them in a temp. file */
pthread_handler_t thr_find_all_keys(void *arg)
static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param)
{
MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
int error;
ulonglong memavl, old_memavl;
uint keys, sort_length;
uint idx, maxbuffer;
uchar **sort_keys=0;
LINT_INIT(keys);
error=1;
if (my_thread_init())
goto err;
{ /* Add extra block since DBUG_ENTER declare variables */
DBUG_ENTER("thr_find_all_keys");
DBUG_PRINT("enter", ("master: %d", sort_param->master));
if (sort_param->sort_info->got_error)
goto err;
uint UNINIT_VAR(keys), idx;
uint sort_length;
uint maxbuffer;
uchar **sort_keys= NULL;
int error= 0;
DBUG_ENTER("thr_find_all_keys");
DBUG_PRINT("enter", ("master: %d", sort_param->master));
if (sort_param->sort_info->got_error)
DBUG_RETURN(TRUE);
set_sort_param_read_write(sort_param);
my_b_clear(&sort_param->tempfile);
my_b_clear(&sort_param->tempfile_for_exceptions);
bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER);
idx= (uint) sort_param->sort_info->max_records;
sort_length= sort_param->key_length;
maxbuffer= 1;
if ((memavl - sizeof(BUFFPEK)) / (sort_length +
sizeof(char *)) > UINT_MAX32)
memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *));
if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sort_param->write_keys= write_keys_varlen;
sort_param->read_to_buffer= read_to_buffer_varlen;
sort_param->write_key= write_merge_key_varlen;
}
while (memavl >= MIN_SORT_BUFFER)
{
if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
(my_off_t) memavl)
keys= idx+1;
else
{
sort_param->write_keys= write_keys;
sort_param->read_to_buffer= read_to_buffer;
sort_param->write_key= write_merge_key;
}
my_b_clear(&sort_param->tempfile);
my_b_clear(&sort_param->tempfile_for_exceptions);
bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
sort_keys= (uchar **) NULL;
memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER);
idx= (uint)sort_param->sort_info->max_records;
sort_length= sort_param->key_length;
maxbuffer= 1;
if ((memavl - sizeof(BUFFPEK)) / (sort_length +
sizeof(char *)) > UINT_MAX32)
memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *));
while (memavl >= MIN_SORT_BUFFER)
{
if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
(my_off_t) memavl)
keys= idx+1;
else
{
uint skr;
do
{
skr= maxbuffer;
if (memavl < sizeof(BUFFPEK)*maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
(sort_length+sizeof(char*))) <= 1 ||
keys < (uint) maxbuffer)
{
mi_check_print_error(sort_param->sort_info->param,
"myisam_sort_buffer_size is too small");
goto err;
}
}
while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
if ((sort_keys= (uchar**)
my_malloc(keys*(sort_length+sizeof(char*))+
((sort_param->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
uint skr;
do
{
if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
maxbuffer, maxbuffer/2))
skr= maxbuffer;
if (memavl < sizeof(BUFFPEK)*maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
(sort_length+sizeof(char*))) <= 1 ||
keys < (uint) maxbuffer)
{
my_free(sort_keys);
sort_keys= (uchar **) NULL; /* for err: label */
mi_check_print_error(sort_param->sort_info->param,
"myisam_sort_buffer_size is too small");
DBUG_RETURN(TRUE);
}
else
break;
}
old_memavl= memavl;
if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
old_memavl > MIN_SORT_BUFFER)
memavl= MIN_SORT_BUFFER;
while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
if (memavl < MIN_SORT_BUFFER)
if ((sort_keys= my_malloc(keys * (sort_length + sizeof(char *)) +
((sort_param->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
{
mi_check_print_error(sort_param->sort_info->param,
"MyISAM sort buffer too small");
goto err; /* purecov: tested */
if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
maxbuffer, min(maxbuffer / 2, 1000)))
{
my_free(sort_keys);
sort_keys= NULL; /* Safety against double free on error. */
}
else
break;
}
old_memavl= memavl;
if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
old_memavl > MIN_SORT_BUFFER)
memavl= MIN_SORT_BUFFER;
}
if (memavl < MIN_SORT_BUFFER)
{
/* purecov: begin inspected */
mi_check_print_error(sort_param->sort_info->param,
"myisam_sort_buffer_size is too small");
my_errno= ENOMEM;
goto err;
/* purecov: end inspected */
}
if (sort_param->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %d keys\n",
sort_param->key + 1, keys);
sort_param->sort_keys= sort_keys;
if (sort_param->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %llu keys\n",
sort_param->key + 1, (ulonglong) keys);
sort_param->sort_keys= sort_keys;
idx= error= 0;
sort_keys[0]= (uchar*) (sort_keys+keys);
idx= error= 0;
sort_keys[0]= (uchar*) (sort_keys+keys);
DBUG_PRINT("info", ("reading keys"));
while (!(error= sort_param->sort_info->got_error) &&
!(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
DBUG_PRINT("info", ("reading keys"));
while (!(error= sort_param->sort_info->got_error) &&
!(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
{
if (sort_param->real_key_length > sort_param->key_length)
{
if (sort_param->real_key_length > sort_param->key_length)
{
if (write_key(sort_param, sort_keys[idx],
&sort_param->tempfile_for_exceptions))
goto err;
continue;
}
if (++idx == keys)
{
if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_keys[0]= (uchar*) (sort_keys+keys);
memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
idx= 1;
}
sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
if (write_key(sort_param, sort_keys[idx],
&sort_param->tempfile_for_exceptions))
goto err;
continue;
}
if (error > 0)
goto err;
if (sort_param->buffpek.elements)
if (++idx == keys)
{
if (sort_param->write_keys(sort_param, sort_keys, idx,
if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
sort_keys[0]= (uchar*) (sort_keys+keys);
memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
idx= 1;
}
else
sort_param->keys= idx;
sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
}
sort_param->sort_keys_length= keys;
goto ok;
if (error > 0)
goto err;
err:
DBUG_PRINT("error", ("got some error"));
sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
my_free(sort_keys);
sort_param->sort_keys= 0;
delete_dynamic(& sort_param->buffpek);
close_cached_file(&sort_param->tempfile);
close_cached_file(&sort_param->tempfile_for_exceptions);
ok:
free_root(&sort_param->wordroot, MYF(0));
/*
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
That means that a writer always gets here first and readers -
only when they see EOF. But if a reader finishes prematurely
because of an error it may reach this earlier - don't allow it
to detach the writer thread.
*/
if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
if (sort_param->read_cache.share)
remove_io_thread(&sort_param->read_cache);
mysql_mutex_lock(&sort_param->sort_info->mutex);
if (!--sort_param->sort_info->threads_running)
mysql_cond_signal(&sort_param->sort_info->cond);
mysql_mutex_unlock(&sort_param->sort_info->mutex);
DBUG_PRINT("exit", ("======== ending thread ========"));
if (sort_param->buffpek.elements)
{
if (sort_param->write_keys(sort_param, sort_keys, idx,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
}
else
sort_param->keys= idx;
sort_param->sort_keys_length= keys;
DBUG_RETURN(FALSE);
err:
DBUG_PRINT("error", ("got some error"));
sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
my_free(sort_keys);
sort_param->sort_keys= 0;
delete_dynamic(& sort_param->buffpek);
close_cached_file(&sort_param->tempfile);
close_cached_file(&sort_param->tempfile_for_exceptions);
DBUG_RETURN(TRUE);
}
/* Search after all keys and place them in a temp. file */
pthread_handler_t thr_find_all_keys(void *arg)
{
MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
my_bool error= FALSE;
/* If my_thread_init fails */
if (my_thread_init() || thr_find_all_keys_exec(sort_param))
error= TRUE;
/*
Thread must clean up after itself.
*/
free_root(&sort_param->wordroot, MYF(0));
/*
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
That means that a writer always gets here first and readers -
only when they see EOF. But if a reader finishes prematurely
because of an error it may reach this earlier - don't allow it
to detach the writer thread.
*/
if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
if (sort_param->read_cache.share)
remove_io_thread(&sort_param->read_cache);
mysql_mutex_lock(&sort_param->sort_info->mutex);
if (error)
sort_param->sort_info->got_error= 1;
if (!--sort_param->sort_info->threads_running)
mysql_cond_signal(&sort_param->sort_info->cond);
mysql_mutex_unlock(&sort_param->sort_info->mutex);
my_thread_end();
return NULL;
}
......@@ -550,18 +560,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
{
if (got_error)
continue;
if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sinfo->write_keys=write_keys_varlen;
sinfo->read_to_buffer=read_to_buffer_varlen;
sinfo->write_key=write_merge_key_varlen;
}
else
{
sinfo->write_keys=write_keys;
sinfo->read_to_buffer=read_to_buffer;
sinfo->write_key=write_merge_key;
}
set_sort_param_read_write(sinfo);
if (sinfo->buffpek.elements)
{
uint maxbuffer=sinfo->buffpek.elements-1;
......
......@@ -785,7 +785,7 @@ static int toku_recover_xcommit (struct logtype_xcommit *l, RECOVER_ENV renv) {
assert(txn!=NULL);
// commit the transaction
toku_txn_progress_extra extra = { time(NULL), l->lsn, "commit", l->xid };
toku_txn_progress_extra extra = { time(NULL), l->lsn, "commit", l->xid, 0 };
int r = toku_txn_commit_with_lsn(txn, true, l->lsn, toku_recover_txn_progress, &extra);
assert(r == 0);
......@@ -828,7 +828,7 @@ static int toku_recover_xabort (struct logtype_xabort *l, RECOVER_ENV renv) {
assert(txn!=NULL);
// abort the transaction
toku_txn_progress_extra extra = { time(NULL), l->lsn, "abort", l->xid };
toku_txn_progress_extra extra = { time(NULL), l->lsn, "abort", l->xid, 0 };
r = toku_txn_abort_with_lsn(txn, l->lsn, toku_recover_txn_progress, &extra);
assert(r == 0);
......@@ -1363,7 +1363,7 @@ static void recover_abort_live_txn(TOKUTXN txn) {
// sanity check that the recursive call successfully NULLs out txn->child
invariant(txn->child == NULL);
// abort the transaction
toku_txn_progress_extra extra = { time(NULL), ZERO_LSN, "abort live", txn->txnid };
toku_txn_progress_extra extra = { time(NULL), ZERO_LSN, "abort live", txn->txnid, 0 };
int r = toku_txn_abort_txn(txn, toku_recover_txn_progress, &extra);
assert(r == 0);
......
......@@ -643,7 +643,7 @@ serialize_and_compress_in_parallel(FTNODE node,
struct serialize_compress_work work[npartitions];
workset_lock(&ws);
for (int i = 0; i < npartitions; i++) {
work[i] = (struct serialize_compress_work) { .base = {{NULL}},
work[i] = (struct serialize_compress_work) { .base = {{NULL, NULL}},
.node = node,
.i = i,
.compression_method = compression_method,
......
......@@ -333,14 +333,14 @@ static txn_child_manager tcm;
.do_fsync = false,
.force_fsync_on_commit = false,
.do_fsync_lsn = ZERO_LSN,
.xa_xid = {0},
.xa_xid = {0, 0, 0, {}},
.progress_poll_fun = NULL,
.progress_poll_fun_extra = NULL,
.txn_lock = ZERO_MUTEX_INITIALIZER,
.txn_lock = TOKU_MUTEX_INITIALIZER,
.open_fts = open_fts,
.roll_info = roll_info,
.state_lock = ZERO_MUTEX_INITIALIZER,
.state_cond = ZERO_COND_INITIALIZER,
.state_lock = TOKU_MUTEX_INITIALIZER,
.state_cond = TOKU_COND_INITIALIZER,
.state = TOKUTXN_LIVE,
.num_pin = 0,
.client_id = 0,
......
......@@ -125,16 +125,6 @@ typedef struct toku_mutex_aligned {
toku_mutex_t aligned_mutex __attribute__((__aligned__(64)));
} toku_mutex_aligned_t;
// Different OSes implement mutexes as different amounts of nested structs.
// C++ will fill out all missing values with zeroes if you provide at least one zero, but it needs the right amount of nesting.
#if defined(__FreeBSD__)
# define ZERO_MUTEX_INITIALIZER {0}
#elif defined(__APPLE__)
# define ZERO_MUTEX_INITIALIZER {{0}}
#else // __linux__, at least
# define ZERO_MUTEX_INITIALIZER {{{0}}}
#endif
#if TOKU_PTHREAD_DEBUG
# define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true }
#else
......@@ -276,15 +266,6 @@ typedef struct toku_cond {
pthread_cond_t pcond;
} toku_cond_t;
// Different OSes implement mutexes as different amounts of nested structs.
// C++ will fill out all missing values with zeroes if you provide at least one zero, but it needs the right amount of nesting.
#if defined(__FreeBSD__)
# define ZERO_COND_INITIALIZER {0}
#elif defined(__APPLE__)
# define ZERO_COND_INITIALIZER {{0}}
#else // __linux__, at least
# define ZERO_COND_INITIALIZER {{{0}}}
#endif
#define TOKU_COND_INITIALIZER {PTHREAD_COND_INITIALIZER}
static inline void
......
......@@ -1825,7 +1825,7 @@ static int run_workers(
{
int r;
const struct perf_formatter *perf_formatter = &perf_formatters[cli_args->perf_output_format];
toku_mutex_t mutex = ZERO_MUTEX_INITIALIZER;
toku_mutex_t mutex = TOKU_MUTEX_INITIALIZER;
toku_mutex_init(&mutex, nullptr);
struct rwlock rwlock;
rwlock_init(&rwlock);
......
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2016, 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
......@@ -1255,7 +1255,7 @@ dict_create_index_step(
>= DICT_TF_FORMAT_ZIP);
node->index = dict_index_get_if_in_cache_low(index_id);
ut_a((node->index == 0) == (err != DB_SUCCESS));
ut_a((node->index == NULL) == (err != DB_SUCCESS));
if (err != DB_SUCCESS) {
......
......@@ -2409,7 +2409,6 @@ innobase_convert_name(
A wrapper function of innobase_convert_name(), convert a table or
index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
@return pointer to the end of buf */
static inline
void
innobase_format_name(
/*==================*/
......@@ -9859,6 +9858,36 @@ ha_innobase::check(
DBUG_RETURN(HA_ADMIN_CORRUPT);
}
if (prebuilt->table->corrupted) {
char index_name[MAX_FULL_NAME_LEN + 1];
/* If some previous operation has marked the table as
corrupted in memory, and has not propagated such to
clustered index, we will do so here */
index = dict_table_get_first_index(prebuilt->table);
if (!dict_index_is_corrupted(index)) {
row_mysql_lock_data_dictionary(prebuilt->trx);
dict_set_corrupted(index);
row_mysql_unlock_data_dictionary(prebuilt->trx);
}
innobase_format_name(index_name, sizeof index_name,
index->name, TRUE);
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_INDEX_CORRUPT,
"InnoDB: Index %s is marked as"
" corrupted",
index_name);
/* Now that the table is already marked as corrupted,
there is no need to check any index of this table */
prebuilt->trx->op_info = "";
DBUG_RETURN(HA_ADMIN_CORRUPT);
}
prebuilt->trx->op_info = "checking table";
old_isolation_level = prebuilt->trx->isolation_level;
......@@ -9935,6 +9964,15 @@ ha_innobase::check(
prebuilt->index_usable = row_merge_is_index_usable(
prebuilt->trx, prebuilt->index);
DBUG_EXECUTE_IF(
"dict_set_index_corrupted",
if (!dict_index_is_clust(index)) {
prebuilt->index_usable = FALSE;
row_mysql_lock_data_dictionary(prebuilt->trx);
dict_set_corrupted(index);
row_mysql_unlock_data_dictionary(prebuilt->trx);
});
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
innobase_format_name(
index_name, sizeof index_name,
......
......@@ -655,6 +655,19 @@ class ha_innobase_add_index : public handler_add_index
~ha_innobase_add_index() {}
};
/*****************************************************************//**
A wrapper function of innobase_convert_name(), convert a table or
index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
@return pointer to the end of buf */
void
innobase_format_name(
/*==================*/
char* buf, /*!< out: buffer for converted identifier */
ulint buflen, /*!< in: length of buf, in bytes */
const char* name, /*!< in: index or table name to format */
ibool is_index_name); /*!< in: index name */
/*******************************************************************//**
Create indexes.
@return 0 or error number */
......@@ -720,6 +733,28 @@ ha_innobase::add_index(
DBUG_RETURN(-1);
}
/* Check if any of the existing indexes are marked as corruption,
and if they are, refuse adding more indexes. */
for (dict_index_t* check_index = dict_table_get_first_index(indexed_table);
check_index != NULL;
check_index = dict_table_get_next_index(check_index)) {
if (dict_index_is_corrupted(check_index)) {
char index_name[MAX_FULL_NAME_LEN + 1];
innobase_format_name(index_name, sizeof index_name,
check_index->name, TRUE);
push_warning_printf(user_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_INDEX_CORRUPT,
"InnoDB: Index %s is marked as"
" corrupted",
index_name);
DBUG_RETURN(HA_ERR_INDEX_CORRUPT);
}
}
/* Check that index keys are sensible */
error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table);
......
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -41,7 +41,6 @@ Created 9/6/1995 Heikki Tuuri
|| defined _M_X64 || defined __WIN__
#define IB_STRONG_MEMORY_MODEL
#undef HAVE_IB_GCC_ATOMIC_TEST_AND_SET // Quick-and-dirty fix for bug 1519094
#endif /* __i386__ || __x86_64__ || _M_IX86 || M_X64 || __WIN__ */
......@@ -369,28 +368,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
# define os_atomic_test_and_set_byte_acquire(ptr, new_val) \
__sync_lock_test_and_set(ptr, (byte) new_val)
# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
/** Do an atomic test-and-set.
@param[in,out] ptr Memory location to set to non-zero
@return the previous value */
static inline
lock_word_t
os_atomic_test_and_set(volatile lock_word_t* ptr)
{
return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
}
/** Do an atomic clear.
@param[in,out] ptr Memory location to set to zero */
static inline
void
os_atomic_clear(volatile lock_word_t* ptr)
{
__atomic_clear(ptr, __ATOMIC_RELEASE);
}
# elif defined(IB_STRONG_MEMORY_MODEL)
# if defined(IB_STRONG_MEMORY_MODEL)
/** Do an atomic test and set.
@param[in,out] ptr Memory location to set to non-zero
......@@ -419,6 +397,27 @@ os_atomic_clear(volatile lock_word_t* ptr)
return(__sync_lock_test_and_set(ptr, 0));
}
# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
/** Do an atomic test-and-set.
@param[in,out] ptr Memory location to set to non-zero
@return the previous value */
static inline
lock_word_t
os_atomic_test_and_set(volatile lock_word_t* ptr)
{
return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
}
/** Do an atomic clear.
@param[in,out] ptr Memory location to set to zero */
static inline
void
os_atomic_clear(volatile lock_word_t* ptr)
{
__atomic_clear(ptr, __ATOMIC_RELEASE);
}
# else
# error "Unsupported platform"
......
......@@ -64,10 +64,10 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 37.8
#define PERCONA_INNODB_VERSION 37.9
#endif
#define INNODB_VERSION_STR "5.5.48-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
#define INNODB_VERSION_STR "5.5.49-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
#define REFMAN "http://dev.mysql.com/doc/refman/" \
IB_TO_STR(MYSQL_MAJOR_VERSION) "." \
......
/*****************************************************************************
Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2016, 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
......@@ -1844,7 +1844,7 @@ recv_apply_hashed_log_recs(
goto loop;
}
ut_ad((allow_ibuf == 0) == (mutex_own(&log_sys->mutex) != 0));
ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex));
if (!allow_ibuf) {
recv_no_ibuf_operations = TRUE;
......
......@@ -471,6 +471,43 @@ PIMAGE_TLS_CALLBACK p_thread_callback_base = win_tls_thread_exit;
#endif
#endif /*_WIN32 */
/***********************************************************************//**
For an EINVAL I/O error, prints a diagnostic message if innodb_flush_method
== ALL_O_DIRECT.
@return TRUE if the diagnostic message was printed
@return FALSE if the diagnostic message does not apply */
static
ibool
os_diagnose_all_o_direct_einval(
/*============================*/
ulint err) /*!< in: C error code */
{
if ((err == EINVAL)
&& (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT)) {
fprintf(stderr,
"InnoDB: The error might be caused by redo log I/O "
"not satisfying innodb_flush_method=ALL_O_DIRECT "
"requirements by the underlying file system.\n");
if (srv_log_block_size != 512)
fprintf(stderr,
"InnoDB: This might be caused by an "
"incompatible non-default "
"innodb_log_block_size value %lu.\n",
srv_log_block_size);
fprintf(stderr,
"InnoDB: Please file a bug at "
"https://bugs.percona.com and include this error "
"message, my.cnf settings, and information about the "
"file system where the redo log resides.\n");
fprintf(stderr,
"InnoDB: A possible workaround is to change "
"innodb_flush_method value to something else "
"than ALL_O_DIRECT.\n");
return(TRUE);
}
return(FALSE);
}
/***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function.
The number should be retrieved before any other OS calls (because they may
......@@ -596,7 +633,7 @@ os_file_get_last_error(
"InnoDB: The error means mysqld does not have"
" the access rights to\n"
"InnoDB: the directory.\n");
} else {
} else if (!os_diagnose_all_o_direct_einval(err)) {
if (strerror((int)err) != NULL) {
fprintf(stderr,
"InnoDB: Error number %lu"
......@@ -2622,6 +2659,9 @@ os_file_pwrite(
/* Handle partial writes and signal interruptions correctly */
for (ret = 0; ret < (ssize_t) n; ) {
n_written = pwrite(file, buf, (ssize_t)n - ret, offs);
DBUG_EXECUTE_IF("xb_simulate_all_o_direct_write_failure",
n_written = -1;
errno = EINVAL;);
if (n_written >= 0) {
ret += n_written;
offs += n_written;
......@@ -2787,6 +2827,10 @@ os_file_read_func(
try_again:
ret = os_file_pread(file, buf, n, offset, offset_high, trx);
DBUG_EXECUTE_IF("xb_simulate_all_o_direct_read_failure",
ret = -1;
errno = EINVAL;);
if ((ulint)ret == n) {
return(TRUE);
......@@ -3084,6 +3128,8 @@ os_file_write_func(
"InnoDB: "
REFMAN "operating-system-error-codes.html\n");
os_diagnose_all_o_direct_einval(errno);
os_has_said_disk_full = TRUE;
}
......
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2011, 2015, MariaDB
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2011, 2016, MariaDB
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
......@@ -236,7 +236,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
}
/* Load certs from the trusted ca */
if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0)
if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) <= 0)
{
DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
if (ca_file || ca_path)
......
......@@ -66,6 +66,7 @@
<CustomAction Id="LaunchUrl" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes" />
<!--
User interface dialogs
-->
......@@ -463,7 +464,7 @@
Key='SOFTWARE\@MANUFACTURER@\@CPACK_WIX_PACKAGE_NAME@'
Name='DATADIR' Value='[DATADIR]' Type='string' KeyPath='yes'/>
<CreateFolder>
<util:PermissionEx User="[LogonUser]" GenericAll="yes" />
<util:PermissionEx User="[LogonUser]" Domain="[USER_DOMAIN]" GenericAll="yes" />
<util:PermissionEx User="NetworkService" GenericAll="yes" />
</CreateFolder>
</Component>
......@@ -542,17 +543,6 @@
Value="utf8" />
</Component>
<!--- Grant service account permission to the database folder (Windows 7 and later) -->
<Component Id="C.serviceaccount.permission" Guid="*" Directory='DATADIR' Transitive='yes'>
<Condition><![CDATA[SERVICENAME AND (VersionNT > 600)]]></Condition>
<RegistryValue Root='HKLM'
Key='SOFTWARE\@MANUFACTURER@\@CPACK_WIX_PACKAGE_NAME@'
Name='servicepermission' Value='1' Type='string' KeyPath='yes'/>
<CreateFolder>
<util:PermissionEx User="NT SERVICE\[SERVICENAME]" GenericAll="yes" />
</CreateFolder>
</Component>
<!-- Shortcuts in program menu (mysql client etc) -->
<Component Id="c.shortcuts" Guid="*" Directory="ShortcutFolder">
<!-- shortcut to my.ini-->
......@@ -862,6 +852,7 @@
<Property Id="ARPSYSTEMCOMPONENT" Value="1" Secure="yes" />
<Property Id="ARPINSTALLLOCATION" Secure="yes"/>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="InstallValidate" Sequence="execute"/>
<SetProperty Id="USER_DOMAIN" Value="[%USERDOMAIN]" After="LaunchConditions" Sequence="first" />
<Feature Id='ARPRegistryEntries'
Title='Add or remove program entries'
Description='Add or remove program entries'
......@@ -908,6 +899,9 @@
<Condition Message=
'Setting the ALLUSERS property is not allowed because [ProductName] is a per-machine application. Setup will now exit.'>
<![CDATA[ALLUSERS = "1"]]>
</Condition>
<Condition Message='This application is only supported on Windows Vista, Windows Server 2008, or higher.'>
<![CDATA[Installed OR (VersionNT >= 600)]]>
</Condition>
</Fragment>
</Wix>
SET(HEIDISQL_BASE_NAME "HeidiSQL_9.1_Portable")
SET(HEIDISQL_BASE_NAME "HeidiSQL_9.3_Portable")
SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip")
SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}")
SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME})
......
Supports Markdown
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