Commit 88755391 authored by serg@serg.mysql.com's avatar serg@serg.mysql.com

Merge work:/home/bk/mysql-4.0

into serg.mysql.com:/usr/home/serg/Abk/mysql-4.0
parents 31d87cd5 8cd2e709
......@@ -3,6 +3,15 @@
# Do-pkg - convert a binary distribution into a Mac OS X PKG and put it
# inside a Disk Image (.dmg)
#
# The script currently assumes the following environment (which should exist
# like that, if the Do-compile script was used to build the binary
# distribution)
#
# - there must be a binary distribution (*.tar.gz) in the directory
# `hostname` of the current directory
# - the extracted and compiled source tree should be located in the
# `hostname` directory, too
#
# Use the "--help" option for more info!
#
# written by Lenz Grimmer <lenz@mysql.com>
......@@ -15,6 +24,7 @@ $opt_dry_run= undef;
$opt_help= undef;
$opt_log= undef;
$opt_mail= "";
$opt_skip_dmg= undef;
$opt_suffix= undef;
$opt_verbose= undef;
$opt_version= undef;
......@@ -24,6 +34,7 @@ GetOptions(
"help|h",
"log|l:s",
"mail|m=s",
"skip-dmg",
"suffix=s",
"verbose|v",
"version=s",
......@@ -32,7 +43,7 @@ GetOptions(
# Include helper functions
chomp($PWD= `pwd`);
$LOGGER= "$PWD/logger.pm";
if (-f $LOGGER)
if (-f "$LOGGER")
{
do "$LOGGER";
}
......@@ -42,7 +53,8 @@ else
}
$PM= "/Developer/Applications/PackageMaker.app/Contents/MacOS/PackageMaker";
$TMP= "/tmp/PKGBUILD";
$TMP= $ENV{TMPDIR};
$TMP eq "" ? $TMP= $TMP . "/PKGBUILD": $TMP= "/tmp/PKGBUILD";
$PKGROOT= "$TMP/PMROOT";
$PKGDEST= "$TMP/PKG";
$RESOURCE_DIR= "$TMP/Resources";
......@@ -56,11 +68,13 @@ $HOST=~ /^([^.-]*)/;
$HOST= $1;
$LOGFILE= "$PWD/Logs/$HOST-$MAJOR.$MINOR$SUFFIX.log";
$BUILDDIR= "$PWD/$HOST";
$SUPFILEDIR= <$BUILDDIR/mysql*-$VERSION/support-files/MacOSX>;
$SRCBASEDIR= <$BUILDDIR/mysql*-$VERSION>;
$SUPFILEDIR= <$SRCBASEDIR/support-files/MacOSX>;
$TAR= <$BUILDDIR/$NAME-apple-darwin*-powerpc.tar.gz>;
$INFO= <$SUPFILEDIR/Info.plist>;
$DESC= <$SUPFILEDIR/Description.plist>;
@RESOURCES= qw/ ReadMe.txt postinstall preinstall /;
@LICENSES= qw{ $SRCBASEDIR/COPYING $SRCBASEDIR/MySQLEULA.txt };
&print_help("") if ($opt_help || !$opt_suffix || !$opt_version);
......@@ -87,7 +101,7 @@ die("You must be root to run this script!") if ($ID ne "root" && !$opt_dry_run);
foreach $file ($TAR, $INFO, $DESC)
{
&abort("Unable to find $file!") if (!-f $file);
&abort("Unable to find $file!") unless (-f "$file");
}
# Remove old temporary build directories first
......@@ -108,6 +122,16 @@ foreach $resfile (@RESOURCES)
&run_command($command, "Error while copying $SUPFILEDIR/$resfile to $RESOURCE_DIR");
}
# Search for license file
foreach $license (@LICENSES)
{
last if (-f "$license")
}
&abort("Could not find a license file!") unless (-f "$license");
$command= "cp $license $RESOURCE_DIR/License.txt";
&run_command($command, "Error while copying $license to $RESOURCE_DIR");
# Extract the binary tarball and create the "mysql" symlink
&logger("Extracting $TAR to $PKGROOT");
&run_command("gnutar zxf $TAR -C $PKGROOT", "Unable to extract $TAR!");
......@@ -124,6 +148,12 @@ $command= "$PM -build -p $PKGDEST/$NAME.pkg -f $PKGROOT -r $RESOURCE_DIR -i $INF
&logger("Removing $PKGROOT");
&run_command("rm -rf $PKGROOT", "Unable to remove $PKGROOT!");
if ($opt_skip_dmg)
{
&logger("SUCCESS: Package $PKGDEST/$NAME.pkg created");
exit 0;
}
# Determine the size of the Disk image to be created and add a 5% safety
# margin for filesystem overhead
&logger("Determining required disk image size for $PKGDEST");
......@@ -198,6 +228,8 @@ Options:
is enabled)
Note that the \@-Sign needs to be quoted!
Example: --mail=user\\\@domain.com
--skip-dmg Just build the PKG, don't put it into a
disk image afterwards
--suffix=<suffix> The package suffix (e.g. "-standard" or "-pro)
--version=<version> The MySQL version number (e.g. 4.0.11-gamma)
-v, --verbose Verbose execution
......
......@@ -994,13 +994,6 @@ int do_sync_with_master2(const char* p)
if (rpl_parse)
mysql_enable_rpl_parse(mysql);
#ifndef TO_BE_REMOVED
/*
We need this because wait_for_pos() only waits for the relay log,
which doesn't guarantee that the slave has executed the statement.
*/
my_sleep(2*1000000L);
#endif
return 0;
}
......@@ -2484,6 +2477,7 @@ int main(int argc, char** argv)
}
case Q_COMMENT: /* Ignore row */
case Q_COMMENT_WITH_COMMAND:
break;
case Q_PING:
(void) mysql_ping(&cur_con->mysql);
break;
......
......@@ -107,6 +107,7 @@ void thr_unlock(THR_LOCK_DATA *data);
int thr_multi_lock(THR_LOCK_DATA **data,uint count);
void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
void thr_abort_locks(THR_LOCK *lock);
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
void thr_print_locks(void); /* For debugging */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
......
......@@ -324,13 +324,21 @@ buf_page_print(
ut_dulint_get_high(btr_page_get_index_id(read_buf)),
ut_dulint_get_low(btr_page_get_index_id(read_buf)));
/* If the code is in ibbackup, dict_sys may be uninitialized,
i.e., NULL */
if (dict_sys != NULL) {
index = dict_index_find_on_id_low(
btr_page_get_index_id(read_buf));
if (index) {
fprintf(stderr, "InnoDB: and table %s index %s\n",
fprintf(stderr,
"InnoDB: and table %s index %s\n",
index->table_name,
index->name);
}
}
} else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
fprintf(stderr, "InnoDB: Page may be an 'inode' page\n");
} else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
......
......@@ -81,6 +81,7 @@ innobase_shutdown_for_mysql(void);
extern ulint srv_sizeof_trx_t_in_ha_innodb_cc;
extern ibool srv_is_being_started;
extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
......
......@@ -577,8 +577,11 @@ open_or_create_log_file(
|| size_high != srv_calc_high32(srv_log_file_size)) {
fprintf(stderr,
"InnoDB: Error: log file %s is of different size\n"
"InnoDB: than specified in the .cnf file!\n", name);
"InnoDB: Error: log file %s is of different size %lu %lu bytes\n"
"InnoDB: than specified in the .cnf file %lu %lu bytes!\n",
name, size_high, size,
srv_calc_high32(srv_log_file_size),
srv_calc_low32(srv_log_file_size));
return(DB_ERROR);
}
......@@ -770,8 +773,13 @@ open_or_create_data_files(
rounded_size_pages)) {
fprintf(stderr,
"InnoDB: Error: data file %s is of a different size\n"
"InnoDB: than specified in the .cnf file!\n", name);
"InnoDB: Error: auto-extending data file %s is of a different size\n"
"InnoDB: %lu pages (rounded down to MB) than specified in the .cnf file:\n"
"InnoDB: initial %lu pages, max %lu (relevant if non-zero) pages!\n",
name, rounded_size_pages,
srv_data_file_sizes[i], srv_last_file_size_max);
return(DB_ERROR);
}
srv_data_file_sizes[i] =
......@@ -782,8 +790,11 @@ open_or_create_data_files(
!= srv_data_file_sizes[i]) {
fprintf(stderr,
"InnoDB: Error: data file %s is of a different size\n"
"InnoDB: than specified in the .cnf file!\n", name);
"InnoDB: Error: data file %s is of a different size\n"
"InnoDB: %lu pages (rounded down to MB)\n"
"InnoDB: than specified in the .cnf file %lu pages!\n", name,
rounded_size_pages,
srv_data_file_sizes[i]);
return(DB_ERROR);
}
......
......@@ -21,6 +21,7 @@ Created 3/26/1996 Heikki Tuuri
#include "que0que.h"
#include "usr0sess.h"
#include "srv0que.h"
#include "srv0start.h"
#include "row0undo.h"
#include "row0mysql.h"
#include "lock0lock.h"
......@@ -29,6 +30,12 @@ Created 3/26/1996 Heikki Tuuri
/* This many pages must be undone before a truncate is tried within rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
/* In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */
ib_longlong trx_roll_max_undo_no;
/* Auxiliary variable which tells the previous progress % we printed */
ulint trx_roll_progress_printed_pct;
/***********************************************************************
Rollback a transaction used in MySQL. */
......@@ -174,6 +181,8 @@ trx_rollback_or_clean_all_without_sess(void)
roll_node_t* roll_node;
trx_t* trx;
dict_table_t* table;
ib_longlong rows_to_undo;
char* unit = (char*)"";
int err;
mutex_enter(&kernel_mutex);
......@@ -220,7 +229,6 @@ loop:
trx->sess = trx_dummy_sess;
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id));
......@@ -248,9 +256,19 @@ loop:
ut_a(thr == que_fork_start_command(fork, SESS_COMM_EXECUTE, 0));
fprintf(stderr, "InnoDB: Rolling back trx with id %lu %lu\n",
trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
trx_roll_progress_printed_pct = 0;
rows_to_undo = trx_roll_max_undo_no;
if (rows_to_undo > 1000000000) {
rows_to_undo = rows_to_undo / 1000000;
unit = (char*)"M";
}
fprintf(stderr,
"InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id));
ut_dulint_get_low(trx->id),
(ulint)rows_to_undo, unit);
mutex_exit(&kernel_mutex);
if (trx->dict_operation) {
......@@ -300,7 +318,7 @@ loop:
row_mysql_unlock_data_dictionary(trx);
}
fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
fprintf(stderr, "\nInnoDB: Rolling back of trx id %lu %lu completed\n",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id));
mem_heap_free(heap);
......@@ -614,6 +632,7 @@ trx_roll_pop_top_rec_of_trx(
dulint undo_no;
ibool is_insert;
trx_rseg_t* rseg;
ulint progress_pct;
mtr_t mtr;
rseg = trx->rseg;
......@@ -676,6 +695,26 @@ try_again:
ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0);
/* We print rollback progress info if we are in a crash recovery
and the transaction has at least 1000 row operations to undo */
if (srv_is_being_started && trx_roll_max_undo_no > 1000) {
progress_pct = 100 -
(ut_conv_dulint_to_longlong(undo_no) * 100)
/ trx_roll_max_undo_no;
if (progress_pct != trx_roll_progress_printed_pct) {
if (trx_roll_progress_printed_pct == 0) {
fprintf(stderr,
"\nInnoDB: Progress in percents: %lu", progress_pct);
} else {
fprintf(stderr,
" %lu", progress_pct);
}
fflush(stderr);
trx_roll_progress_printed_pct = progress_pct;
}
}
trx->undo_no = undo_no;
if (!trx_undo_arr_store_info(trx, undo_no)) {
......
......@@ -699,6 +699,9 @@ trx_sys_init_at_db_start(void)
/*==========================*/
{
trx_sysf_t* sys_header;
ib_longlong rows_to_undo = 0;
char* unit = (char*)"";
trx_t* trx;
mtr_t mtr;
mtr_start(&mtr);
......@@ -734,9 +737,28 @@ trx_sys_init_at_db_start(void)
trx_lists_init_at_db_start();
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
for (;;) {
rows_to_undo +=
ut_conv_dulint_to_longlong(trx->undo_no);
trx = UT_LIST_GET_NEXT(trx_list, trx);
if (!trx) {
break;
}
}
if (rows_to_undo > 1000000000) {
unit = (char*)"M";
rows_to_undo = rows_to_undo / 1000000;
}
fprintf(stderr,
"InnoDB: %lu transaction(s) which must be rolled back or cleaned up\n",
UT_LIST_GET_LEN(trx_sys->trx_list));
"InnoDB: %lu transaction(s) which must be rolled back or cleaned up\n"
"InnoDB: in total %lu%s row operations to undo\n",
UT_LIST_GET_LEN(trx_sys->trx_list),
(ulint)rows_to_undo, unit);
fprintf(stderr, "InnoDB: Trx id counter is %lu %lu\n",
ut_dulint_get_high(trx_sys->max_trx_id),
......
......@@ -31,6 +31,7 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
install-data-local:
$(mkinstalldirs) \
......@@ -47,6 +48,7 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data
SUFFIXES = .sh
......
......@@ -349,7 +349,8 @@ while test $# -gt 0; do
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
;;
--fast)
FAST_START=1
......@@ -810,8 +811,8 @@ start_master()
$RM -f $MASTER_MYDDIR/log.*
# Remove stale binary logs
$RM -f $MYSQL_TEST_DIR/var/log/master-bin.*
# Remove old master.info files
$RM -f $MYSQL_TEST_DIR/var/master-data/master.info
# Remove old master.info and relay-log.info files
$RM -f $MYSQL_TEST_DIR/var/master-data/master.info $MYSQL_TEST_DIR/var/master-data/relay-log.info
#run master initialization shell script if one exists
......@@ -915,7 +916,7 @@ start_slave()
slave_port=`expr $SLAVE_MYPORT + $1`
slave_log="$SLAVE_MYLOG.$1"
slave_err="$SLAVE_MYERR.$1"
slave_datadir="var/$slave_ident-data/"
slave_datadir="$SLAVE_MYDDIR/../$slave_ident-data/"
slave_pid="$MYRUN_DIR/mysqld-$slave_ident.pid"
slave_sock="$SLAVE_MYSOCK-$1"
else
......@@ -930,7 +931,7 @@ start_slave()
fi
# Remove stale binary logs and old master.info files
$RM -f $MYSQL_TEST_DIR/var/log/$slave_ident-*bin.*
$RM -f $MYSQL_TEST_DIR/$slave_datadir/master.info
$RM -f $slave_datadir/master.info $slave_datadir/relay-log.info
#run slave initialization shell script if one exists
if [ -f "$slave_init_script" ] ;
......
drop table if exists t1;
drop table if exists t1,t2;
create table t1(n int);
insert into t1 values (1);
lock tables t1 write;
......@@ -17,3 +17,10 @@ unlock tables;
n
1
drop table t1;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
insert t1 select * from t2;
drop table t2;
Table 'test.t2' doesn't exist
drop table t1;
......@@ -32,7 +32,7 @@ n
2
select sum(length(word)) from t1;
sum(length(word))
1021
1022
drop table t1,t3;
reset master;
slave stop;
......
slave stop;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
create table t1(a int);
select * into outfile '../../var/master-data/rpl_loaddatalocal.select_outfile' from t1;
truncate table t1;
load data local infile './var/master-data/rpl_loaddatalocal.select_outfile' into table t1;
select a,count(*) from t1 group by a;
a count(*)
1 10000
drop table t1;
......@@ -6,8 +6,9 @@
#
-- source include/not_embedded.inc
drop table if exists t1;
#test to see if select will get the lock ahead of low priority update
drop table if exists t1,t2;
# test to see if select will get the lock ahead of low priority update
connect (locker,localhost,root,,);
connect (reader,localhost,root,,);
......@@ -48,3 +49,22 @@ reap;
connection reader;
reap;
drop table t1;
#
# Test problem when using locks on many tables and droping a table that
# is to-be-locked by another thread
#
connection locker;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
connection reader;
send insert t1 select * from t2;
connection locker;
drop table t2;
connection reader;
--error 1146
reap;
connection locker;
drop table t1;
# See if "LOAD DATA LOCAL INFILE" is well replicated
# (LOAD DATA LOCAL INFILE is not written to the binlog
# the same way as LOAD DATA INFILE : Append_blocks are smaller).
# In MySQL 4.0 <4.0.12 there were 2 bugs with LOAD DATA LOCAL INFILE :
# - the loaded file was not written entirely to the master's binlog,
# only the first 4KB, 8KB or 16KB usually.
# - the loaded file's first line was not written entirely to the
# master's binlog (1st char was absent)
source include/master-slave.inc;
create table t1(a int);
let $1=10000;
disable_query_log;
set SQL_LOG_BIN=0;
while ($1)
{
#eval means expand $ expressions
eval insert into t1 values(1);
dec $1;
}
set SQL_LOG_BIN=1;
enable_query_log;
select * into outfile '../../var/master-data/rpl_loaddatalocal.select_outfile' from t1;
#This will generate a 20KB file, now test LOAD DATA LOCAL
truncate table t1;
load data local infile './var/master-data/rpl_loaddatalocal.select_outfile' into table t1;
system rm ./var/master-data/rpl_loaddatalocal.select_outfile ;
save_master_pos;
connection slave;
sync_with_master;
select a,count(*) from t1 group by a;
connection master;
drop table t1;
save_master_pos;
connection slave;
sync_with_master;
......@@ -945,6 +945,54 @@ void thr_abort_locks(THR_LOCK *lock)
}
/*
Abort all locks for specific table/thread combination
This is used to abort all locks for a specific thread
*/
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
{
THR_LOCK_DATA *data;
DBUG_ENTER("thr_abort_locks_for_thread");
pthread_mutex_lock(&lock->mutex);
for (data= lock->read_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */
pthread_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->read_wait.last= data->prev;
}
}
for (data= lock->write_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
pthread_cond_signal(data->cond);
data->cond= 0;
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->write_wait.last= data->prev;
}
}
pthread_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
......
#! /bin/sh
for package in . ./innobase
do
(cd $package
rm -rf config.cache autom4te.cache
aclocal
autoheader
libtoolize --force
aclocal
automake --add-missing --force-missing
autoconf)
done
#rm -rf ./bdb/build_unix/config.cache ./bdb/dist/autom4te.cache
#(cd ./bdb/dist && sh s_all)
#! /bin/sh
#debug
#set -x
if test ! -r ./sql/mysqld.cc
then
echo "you must start from the top source directory"
exit 1
fi
path=`dirname $0`
# clean
if test -e "Makefile"; then make -k clean; fi
# remove files
rm -f NEW-RPMS/*
rm -f */.deps/*.P
rm -f */*.linux
# run autotools
. $path/compile-AUTOTOOLS
# configure
./configure --without-innodb --without-docs
# build tools only
make clean config.h
(cd dbug; make libdbug.a)
(cd strings; make libmystrings.a)
(cd mysys; make libmysys.a)
(cd heap; make libheap.a)
(cd vio; make libvio.a)
(cd regex; make libregex.a)
(cd isam; make libnisam.a)
(cd merge; make libmerge.a)
(cd myisam; make libmyisam.a)
(cd myisammrg; make libmyisammrg.a)
(cd extra; make comp_err)
(cd libmysql; make conf_to_src)
(cd libmysql_r; make conf_to_src)
(cd sql; make gen_lex_hash)
(cd strings; make conf_to_src)
# copying required linux tools
cp extra/comp_err extra/comp_err.linux
cp libmysql/conf_to_src libmysql/conf_to_src.linux
cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux
cp sql/gen_lex_hash sql/gen_lex_hash.linux
cp strings/conf_to_src strings/conf_to_src.linux
#! /bin/sh
path=`dirname $0`
# clean
if test -e "Makefile"; then make -k clean; fi
# remove files
rm -f NEW-RPMS/*
rm -f */.deps/*.P
rm -rf Makefile.in.bk
# Metrowerks enviornment
. $path/mwenv
# run auto tools
. $path/compile-AUTOTOOLS
# configure
./configure $base_configs $extra_configs
# make
make clean bin-dist
# mark the build
for file in *.tar.gz
do
if (expr "$file" : "mysql-[1-9].*" > /dev/null)
then
new_file=`echo $file | sed -e "s/mysql-/mysql-$suffix-/"`
if test -e "$new_file"; then mv -f $new_file $new_file.old; fi
mv $file $new_file
fi
done
#! /bin/sh
#debug
#set -x
if test ! -r ./sql/mysqld.cc
then
echo "you must start from the top source directory"
exit 1
fi
path=`dirname $0`
# stop on errors
set -e
base_configs=" \
--host=i686-pc-netware \
--enable-local-infile \
--with-extra-charsets=all \
--prefix=N:/mysql \
"
#! /bin/sh
path=`dirname $0`
$path/compile-netware-standard
$path/compile-netware-debug
#$path/compile-netware-max
#$path/compile-netware-max-debug
#! /bin/sh
path=`dirname $0`
. $path/compile-netware-START
suffix="debug"
extra_configs=" \
--with-innodb \
--with-debug=full \
"
. $path/compile-netware-END
#! /bin/sh
path=`dirname $0`
. $path/compile-netware-START
suffix="standard"
extra_configs=" \
--with-innodb
"
. $path/compile-netware-END
#! /bin/sh
# WINE_BUILD_DIR, BUILD_DIR, and VERSION must be changed before compiling
# This values are normally changed by the nwbootstrap script
# the default for WINE_BUILD_DIR is "F:/mydev"
export MYDEV="WINE_BUILD_DIR"
export MWCNWx86Includes="$MYDEV/libc/include"
export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib"
export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib"
export WINEPATH="$MYDEV/mw/bin"
# the default for BUILD_DIR is "$HOME/mydev"
export PATH="$PATH:BUILD_DIR/mysql-VERSION/netware/BUILD"
export AR='mwldnlm'
export AR_FLAGS='-type library -o'
export AS='mwasmnlm'
export CC='mwccnlm -gccincludes'
export CFLAGS='-dialect c -proc 686 -bool on -relax_pointers -DUSE_OLD_FUNCTIONS'
export CXX='mwccnlm -gccincludes'
export CXXFLAGS='-dialect c++ -proc 686 -bool on -relax_pointers'
export LD='mwldnlm'
export LDFLAGS='-entry _LibCPrelude -exit _LibCPostlude -flags pseudopreemption'
export RANLIB=:
export STRIP=:
#! /bin/sh
# debug
#set -x
path=`dirname $0`
# stop on errors
set -e
# repository direcotry
repo_dir=`pwd`
# build direcotry
build_dir="$HOME/mydev"
wine_build_dir="F:/mydev"
# doc directory
doc_dir="$repo_dir/../mysqldoc"
# init
target_dir=""
temp_dir=""
revision=""
rev=""
build=""
mwenv=""
# show usage
show_usage()
{
cat << EOF
usage: nwbootstrap [options]
Exports a revision of the BitKeeper tree (nwbootstrap must be run inside a
directory of the BitKeeper tree to be used). Creates the ChangeLog file.
Adds the latest manual.texi from the mysqldoc BitKeeper tree. Builds the
Linux tools required for cross-platform builds. Optionally, builds the
binary distributions for NetWare.
options:
--build=<opt> Build the binary distributions for NetWare,
where <opt> is "standard", "debug", or "all"
(default is to not build a binary distribution)
--build-dir=<dir> Export the BitKeeper tree to the <dir> directroy
(default is "$build_dir")
--doc-dir=<dir> Use the mysqldoc BitKeeper tree located in the
<dir> directory
(default is parallel to current BitKeeper tree)
--help Show this help information
--revision=<rev> Export the BitKeeper tree as of revision <rev>
(default is the latest revision)
--wine-build-dir=<dir> Use the WINE directory <dir>, which should
correspond to the --build-dir directory
(default is "$wine_build_dir")
examples:
nwbootstrap
nwbootstrap --revision=1.1594 --build=all
nwbootstrap --build-dir=/home/jdoe/dev --wine-build-dir=F:/dev
EOF
exit 0;
}
# parse arguments
for arg do
case "$arg" in
--build-dir=*) build_dir=`echo "$arg" | sed -e "s;--build-dir=;;"` ;;
--wine-build-dir=*) wine_build_dir=`echo "$arg" | sed -e "s;--wine-build-dir=;;"` ;;
--revision=*) revision=`echo "$arg" | sed -e "s;--revision=;;"` ;;
--build=*) build=`echo "$arg" | sed -e "s;--build=;;"` ;;
--doc-dir=*) doc_dir=`echo "$arg" | sed -e "s;--doc-dir=;;"` ;;
*) show_usage ;;
esac
done
echo "starting build..."
# check for bk and repo_dir
bk help > /dev/null
repo_dir=`bk root $repo_dir`
cd $repo_dir
doc_dir="$repo_dir/../mysqldoc"
# build temporary directory
temp_dir="$build_dir/mysql-$$.tmp"
# export the bk tree
command="bk export";
if test $revision; then command="$command -r$revision"; fi
command="$command $temp_dir"
echo "exporting $repo_dir..."
$command
# determine version
version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < $temp_dir/configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"`
echo "version: $version"
# build target directory
target_dir="$build_dir/mysql-$version"
# delete any old target
if test -d $target_dir.old; then rm -rf $target_dir.old; fi
# rename old target
if test -d $target_dir; then mv -f $target_dir $target_dir.old; fi
# rename directory to use version
mv $temp_dir $target_dir
# create ChangeLog
if test $revision
then
rev=`bk changes -r..$revision -t -d':REV:' -n | head -2 | tail -1`
else
rev=`bk changes -t -d':REV:' -n | head -1`
fi
echo "creating ChangeLog..."
bk changes -v -r$rev > $target_dir/ChangeLog
# add the latest manual
if test -d $doc_dir
then
echo "adding the latest manual..."
install -m 644 $doc_dir/Docs/{manual,reservedwords}.texi $target_dir/Docs/
fi
# make files writeable
cd $target_dir
chmod -R u+rw,g+rw .
# edit the mvenv file
mwenv="./netware/BUILD/mwenv"
mv -f $mwenv $mwenv.org
sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \
-e "s;BUILD_DIR;$build_dir;g" \
-e "s;VERSION;$version;g" $mwenv.org > $mwenv
chmod +rwx $mwenv
# build linux tools
echo "compiling linux tools..."
./netware/BUILD/compile-linux-tools
# compile
if test $build
then
echo "compiling $build..."
./netware/BUILD/compile-netware-$build
fi
echo "done"
#! /bin/sh
export MYDEV="F:/mysql"
export MWCNWx86Includes="$MYDEV/libc/include"
export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib"
export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib"
export WINEPATH="$MYDEV/mw/bin"
export PATH="$PATH:$HOME/mysql/mysql-4.0/netware/mw"
#-----------------------------------------------------------------------------
# Copyright (C) 2002 MySQL AB
#
# 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 Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# This notice applies to changes, created by or for Novell, Inc.,
# to preexisting works for which notices appear elsewhere in this file.
# Copyright (c) 2003 Novell, Inc. 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 Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#-----------------------------------------------------------------------------
use strict;
use Mysql;
print "MySQL Fix Privilege Tables Script\n\n";
print "NOTE: This script updates your privilege tables to the lastest\n";
print " specifications!\n\n";
#-----------------------------------------------------------------------------
# get the current root password
#-----------------------------------------------------------------------------
print "In order to log into MySQL to update it, we'll need the current\n";
print "password for the root user. If you've just installed MySQL, and\n";
print "you haven't set the root password yet, the password will be blank,\n";
print "so you should just press enter here.\n\n";
print "Enter the current password for root: ";
my $password = <STDIN>;
chomp $password;
print "\n";
my $conn = Mysql->connect("localhost", "mysql", "root", $password)
|| die "Unable to connect to MySQL.";
print "OK, successfully used the password, moving on...\n\n";
#-----------------------------------------------------------------------------
# MySQL 4.0.2
#-----------------------------------------------------------------------------
print "Adding new fields used by MySQL 4.0.2 to the privilege tables...\n";
print "NOTE: You can ignore any Duplicate column errors.\n";
$conn->query(" \
ALTER TABLE user \
ADD Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv, \
ADD Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv, \
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv, \
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv, \
ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv, \
ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv, \
ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv; \
") && $conn->query(" \
UPDATE user SET show_db_priv=select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>''; \
");
#-----------------------------------------------------------------------------
# MySQL 4.0 Limitations
#-----------------------------------------------------------------------------
print "Adding new fields used by MySQL 4.0 security limitations...\n";
$conn->query(" \
ALTER TABLE user \
ADD max_questions int(11) NOT NULL AFTER x509_subject, \
ADD max_updates int(11) unsigned NOT NULL AFTER max_questions, \
ADD max_connections int(11) unsigned NOT NULL AFTER max_updates; \
");
#-----------------------------------------------------------------------------
# MySQL 4.0 DB and Host privs
#-----------------------------------------------------------------------------
print "Adding new fields used by MySQL 4.0 locking and temporary table security...\n";
$conn->query(" \
ALTER TABLE db \
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, \
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; \
");
$conn->query(" \
ALTER TABLE host \
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, \
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; \
");
#-----------------------------------------------------------------------------
# done
#-----------------------------------------------------------------------------
print "\n\nAll done!\n\n";
print "Thanks for using MySQL!\n\n";
......@@ -183,6 +183,7 @@ done
$CP mysql-test/include/*.inc $BASE/mysql-test/include
$CP mysql-test/std_data/*.dat mysql-test/std_data/*.001 $BASE/mysql-test/std_data
$CP mysql-test/std_data/des_key_file $BASE/mysql-test/std_data
$CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t
$CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r
......
......@@ -150,6 +150,19 @@ innobase_release_stat_resources(
}
}
/************************************************************************
Call this function when mysqld passes control to the client. That is to
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
documentation, see handler.cc. */
void
innobase_release_temporary_latches(
/*===============================*/
void* innobase_tid)
{
innobase_release_stat_resources((trx_t*)innobase_tid);
}
/************************************************************************
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
......@@ -877,12 +890,13 @@ innobase_commit_low(
/*================*/
trx_t* trx) /* in: transaction handle */
{
/* TODO: Guilhem should check if master_log_name, pending
etc. are right if the master log gets rotated! Possible bug here.
Comment by Heikki March 4, 2003. */
if (current_thd->slave_thread) {
/* Update the replication position info inside InnoDB */
#ifdef NEED_TO_BE_FIXED
trx->mysql_relay_log_file_name = active_mi->rli.log_file_name;
trx->mysql_relay_log_pos = active_mi->rli.relay_log_pos;
#endif
trx->mysql_master_log_file_name
= active_mi->rli.master_log_name;
trx->mysql_master_log_pos = ((ib_longlong)
......
......@@ -208,3 +208,4 @@ int innodb_show_status(THD* thd);
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
uint full_name_len);
void innobase_release_temporary_latches(void* innobase_tid);
......@@ -238,8 +238,10 @@ int ha_autocommit_or_rollback(THD *thd, int error)
handler must be the same as in the binlog.
arguments:
thd: the thread handle of the current connection
log_file_name: latest binlog file name
end_offset: the offset in the binlog file up to which we wrote
return value: 0 if success, 1 if error
*/
int ha_report_binlog_offset_and_commit(THD *thd,
......@@ -266,6 +268,34 @@ int ha_report_binlog_offset_and_commit(THD *thd,
return error;
}
/*
This function should be called when MySQL sends rows of a SELECT result set
or the EOF mark to the client. It releases a possible adaptive hash index
S-latch held by thd in InnoDB and also releases a possible InnoDB query
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
keep them over several calls of the InnoDB handler interface when a join
is executed. But when we let the control to pass to the client they have
to be released because if the application program uses mysql_use_result(),
it may deadlock on the S-latch if the application on another connection
performs another SQL query. In MySQL-4.1 this is even more important because
there a connection can have several SELECT queries open at the same time.
arguments:
thd: the thread handle of the current connection
return value: always 0
*/
int ha_release_temporary_latches(THD *thd)
{
#ifdef HAVE_INNOBASE_DB
THD_TRANS *trans;
trans = &thd->transaction.all;
if (trans->innobase_tid)
innobase_release_temporary_latches(trans->innobase_tid);
#endif
return 0;
}
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;
......@@ -473,7 +503,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
int error;
DBUG_ENTER("handler::open");
DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
name, table->db_type, table->db_stat, mode, test_if_locked));
name, table->db_type, table->db_stat, mode,
test_if_locked));
if ((error=open(name,mode,test_if_locked)))
{
......
......@@ -371,6 +371,7 @@ void ha_resize_key_cache(void);
int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
int ha_release_temporary_latches(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
......
......@@ -313,6 +313,25 @@ void mysql_lock_abort(THD *thd, TABLE *table)
}
/* Abort one thread / table combination */
void mysql_lock_abort_for_thread(THD *thd, TABLE *table)
{
MYSQL_LOCK *locked;
TABLE *write_lock_used;
DBUG_ENTER("mysql_lock_abort_for_thread");
if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
{
for (uint i=0; i < locked->lock_count; i++)
thr_abort_locks_for_thread(locked->locks[i]->lock,
table->in_use->real_id);
my_free((gptr) locked,MYF(0));
}
DBUG_VOID_RETURN;
}
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
{
MYSQL_LOCK *sql_lock;
......
......@@ -81,7 +81,6 @@ int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
info->read_pos++;
info->request_pos=info->read_pos;
DBUG_RETURN(0);
}
......
......@@ -711,6 +711,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
void mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
bool lock_global_read_lock(THD *thd);
void unlock_global_read_lock(THD *thd);
......
......@@ -4416,8 +4416,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_recover_options= HA_RECOVER_NONE; // To be changed
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
myisam_recover_options= HA_RECOVER_DEFAULT;
ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
break;
case (int) OPT_SKIP_PRIOR:
opt_specialflag|= SPECIAL_NO_PRIOR;
......
......@@ -322,17 +322,37 @@ int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
{
int error=0;
DBUG_ENTER("purge_relay_logs");
/*
Even if rli->inited==0, we still try to empty rli->master_log_* variables.
Indeed, rli->inited==0 does not imply that they already are empty.
It could be that slave's info initialization partly succeeded :
for example if relay-log.info existed but *relay-bin*.*
have been manually removed, init_relay_log_info reads the old
relay-log.info and fills rli->master_log_*, then init_relay_log_info
checks for the existence of the relay log, this fails and
init_relay_log_info leaves rli->inited to 0.
In that pathological case, rli->master_log_pos* will be properly reinited
at the next START SLAVE (as RESET SLAVE or CHANGE
MASTER, the callers of purge_relay_logs, will delete bogus *.info files
or replace them with correct files), however if the user does SHOW SLAVE
STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
to display fine in any case.
*/
rli->master_log_name[0]= 0;
rli->master_log_pos= 0;
rli->pending= 0;
if (!rli->inited)
DBUG_RETURN(0); /* successfully do nothing */
DBUG_RETURN(0);
DBUG_ASSERT(rli->slave_running == 0);
DBUG_ASSERT(rli->mi->slave_running == 0);
rli->slave_skip_counter=0;
pthread_mutex_lock(&rli->data_lock);
rli->pending=0;
rli->master_log_name[0]=0;
rli->master_log_pos=0; // 0 means uninitialized
if (rli->relay_log.reset_logs(thd))
{
*errmsg = "Failed during log reset";
......@@ -1193,8 +1213,9 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
&msg))
goto err;
rli->master_log_pos = 0; // uninitialized
rli->info_fd = info_fd;
rli->master_log_name[0]= 0;
rli->master_log_pos= 0;
rli->info_fd= info_fd;
}
else // file exists
{
......
......@@ -1244,25 +1244,44 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name)
}
/* lock table to force abort of any threads trying to use table */
/*
If we have the table open, which only happens when a LOCK TABLE has been
done on the table, change the lock type to a lock that will abort all
other threads trying to get the lock.
*/
void abort_locked_tables(THD *thd,const char *db, const char *table_name)
{
TABLE *table;
for (table=thd->open_tables; table ; table=table->next)
for (table= thd->open_tables; table ; table= table->next)
{
if (!strcmp(table->real_name,table_name) &&
!strcmp(table->table_cache_key,db))
{
mysql_lock_abort(thd,table);
break;
}
}
}
/****************************************************************************
** open_unireg_entry
** Purpose : Load a table definition from file and open unireg table
** Args : entry with DB and table given
** Returns : 0 if ok
** Note that the extra argument for open is taken from thd->open_options
/*
Load a table definition from file and open unireg table
SYNOPSIS
open_unireg_entry()
thd Thread handle
entry Store open table definition here
db Database name
name Table name
alias Alias name
NOTES
Extra argument for open is taken from thd->open_options
RETURN
0 ok
# Error
*/
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
......@@ -2277,6 +2296,17 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
}
pthread_mutex_unlock(&in_use->mysys_var->mutex);
}
/*
Now we must abort all tables locks used by this thread
as the thread may be waiting to get a lock for another table
*/
for (TABLE *thd_table= in_use->open_tables;
thd_table ;
thd_table= thd_table->next)
{
if (thd_table->db_stat) // If table is open
mysql_lock_abort_for_thread(thd, thd_table);
}
}
else
result= result || return_if_owned_by_thd;
......
......@@ -463,6 +463,14 @@ bool select_send::send_data(List<Item> &items)
String *packet= &thd->packet;
DBUG_ENTER("send_data");
#ifdef HAVE_INNOBASE_DB
/* We may be passing the control from mysqld to the client: release the
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd */
if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
#endif
if (thd->offset_limit)
{ // using limit offset,count
thd->offset_limit--;
......@@ -486,6 +494,14 @@ bool select_send::send_data(List<Item> &items)
bool select_send::send_eof()
{
#ifdef HAVE_INNOBASE_DB
/* We may be passing the control from mysqld to the client: release the
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd */
if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
#endif
/* Unlock tables before sending packet to gain some speed */
if (thd->lock)
{
......
......@@ -734,12 +734,18 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
error=1;
goto err;
}
//delete relay logs, clear relay log coordinates
if ((error= purge_relay_logs(&mi->rli, thd,
1 /* just reset */,
&errmsg)))
goto err;
//Clear master's log coordinates (only for good display of SHOW SLAVE STATUS)
mi->master_log_name[0]= 0;
mi->master_log_pos= BIN_LOG_HEADER_SIZE;
//close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
end_master_info(mi);
//and delete these two files
fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
{
......
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