Commit c2a655f0 authored by Marc Alff's avatar Marc Alff

Local merge

parents b1f25ee9 4b86f399
...@@ -42,9 +42,7 @@ cat <<EOF ...@@ -42,9 +42,7 @@ cat <<EOF
Options used with this script always override any default behaviour. Options used with this script always override any default behaviour.
The default package is MySQL Cluster Carrier Grade (standard) Edition. The default package is MySQL Cluster Carrier Grade (standard) Edition.
For developers, the default package is MySQL Cluster Carrier Grade For developers, the default package is MySQL Cluster Carrier Grade
Extended Edition, and the default build behaviour is to build with Extended Edition.
autotools. If you want to skip autotools and start from a source code
release you can use the --no-autotools flag.
More information for developers can be found in --help, More information for developers can be found in --help,
--sysadmin-help, and --extended-help. --sysadmin-help, and --extended-help.
...@@ -102,7 +100,8 @@ cat <<EOF ...@@ -102,7 +100,8 @@ cat <<EOF
If your building on a Solaris SPARC machine and you want to compile If your building on a Solaris SPARC machine and you want to compile
using SunStudio you must set using SunStudio you must set
--compiler=forte; if you want to build using the Intel compiler on --compiler=forte; if you want to build using the Intel compiler on
Linux, you need to set --compiler=icc. Linux, you need to set --compiler=icc. If you want to use the AMD
compiler Open64 set --compiler=open64.
A synonym for forte is SunStudio, so one can also use A synonym for forte is SunStudio, so one can also use
--compiler=SunStudio. --compiler=SunStudio.
...@@ -150,14 +149,32 @@ Usage: $0 [options] ...@@ -150,14 +149,32 @@ Usage: $0 [options]
--without-debug Build non-debug version --without-debug Build non-debug version
--use-comment Set the comment in the build --use-comment Set the comment in the build
--with-fast-mutexes Use try/retry method of acquiring mutex --with-fast-mutexes Use try/retry method of acquiring mutex
--without-fast-mutexes Don't use try/retry method of acquiring mutex
--without-perfschema Don't build with performance schema
--generate-feedback path Compile with feedback using the specified directory
to store the feedback files
--use-feedback path Compile using feedback information from the specified
directory
--with-debug Build debug version --with-debug Build debug version
--extra-debug-flag flag Add -Dflag to compiler flags
InnoDB supports the following debug flags,
UNIV_DEBUG, UNIV_SYNC_DEBUG, UNIV_MEM_DEBUG,
UNIV_DEBUG_THREAD_CREATION, UNIV_DEBUG_LOCK_VALIDATE,
UNIV_DEBUG_PRINT, UNIV_DEBUG_FILE_ACCESS,
UNIV_LIGHT_MEM_DEBUG, UNIV_LOG_DEBUG,
UNIV_IBUF_COUNT_DEBUG, UNIV_SEARCH_DEBUG,
UNIV_LOG_LSN_DEBUG, UNIV_ZIP_DEBUG, UNIV_AHI_DEBUG,
UNIV_DEBUG_VALGRIND, UNIV_SQL_DEBUG, UNIV_AIO_DEBUG,
UNIV_BTR_DEBUG, UNIV_LRU_DEBUG, UNIV_BUF_DEBUG,
UNIV_HASH_DEBUG, UNIV_LIST_DEBUG, UNIV_IBUF_DEBUG
--with-link-time-optimizer --with-link-time-optimizer
Link time optimizations enabled (Requires GCC 4.5 Link time optimizations enabled (Requires GCC 4.5
if GCC used), available for icc as well. This flag if GCC used), available for icc as well. This flag
is only considered if also fast is set. is only considered if also fast is set.
--with-mso Special flag used by Open64 compiler (requres at
least version 4.2.3) that enables optimisations
for multi-core scalability.
--configure-only Stop after running configure. --configure-only Stop after running configure.
--use-autotools Start by running autoconf, automake,.. tools
--no-autotools Start from configure
--print-only Print commands that the script will execute, --print-only Print commands that the script will execute,
but do not actually execute but do not actually execute
--prefix=path Build with prefix 'path' --prefix=path Build with prefix 'path'
...@@ -170,7 +187,7 @@ Usage: $0 [options] ...@@ -170,7 +187,7 @@ Usage: $0 [options]
MySQL use MySQL use
--commercial Use commercial libraries --commercial Use commercial libraries
--gpl Use gpl libraries --gpl Use gpl libraries
--compiler=[gcc|icc|forte|SunStudio] Select compiler --compiler=[gcc|icc|forte|SunStudio|open64] Select compiler
--cpu=[x86|x86_64|sparc|itanium] Select CPU type --cpu=[x86|x86_64|sparc|itanium] Select CPU type
x86 => x86 and 32-bit binary x86 => x86 and 32-bit binary
x86_64 => x86 and 64 bit binary x86_64 => x86 and 64 bit binary
...@@ -389,7 +406,8 @@ extended_usage() ...@@ -389,7 +406,8 @@ extended_usage()
platforms supported by this script. platforms supported by this script.
The --fast option adds -mtune=cpu_arg to the C/C++ flags (provides The --fast option adds -mtune=cpu_arg to the C/C++ flags (provides
support for Nocona, K8, and other processors). support for Nocona, K8, and other processors), this option is valid
when gcc is the compiler.
Use of the --debug option adds -g to the C/C++ flags. Use of the --debug option adds -g to the C/C++ flags.
...@@ -397,10 +415,35 @@ extended_usage() ...@@ -397,10 +415,35 @@ extended_usage()
by calling the script as follows: by calling the script as follows:
CC="/usr/local/bin/gcc" CXX="/usr/local/bin/gcc" BUILD/build_mccge.sh CC="/usr/local/bin/gcc" CXX="/usr/local/bin/gcc" BUILD/build_mccge.sh
FreeBSD/x86/gcc Feedback profiler on gcc
--------------- ------------------------
No flags are used. Instead, configure determines the proper flags to Using gcc --generate-feedback=path causes the following flags to be added
use. to the compiler flags.
--fprofile-generate
--fprofile-dir=path
Using gcc with --use-feedback=path causes the following flags to be added
to the compiler flags. --fprofile-correction indicates MySQL is a multi-
threaded application and thus counters can be inconsistent with each other
and the compiler should take this into account.
--fprofile-use
--fprofile-dir=path
--fprofile-correction
Feedback compilation using Open64
---------------------------------
Using Open64 with --generate-feedback=path causes the following flags to
be added to the compiler flags.
-fb-create path/feedback
Using Open64 with --use-feedback=path causes the following flags to be
added to the compiler flags.
--fb-opt path/feedback
Linux/x86+Itanium/gcc Linux/x86+Itanium/gcc
------------- -------------
...@@ -410,6 +453,9 @@ extended_usage() ...@@ -410,6 +453,9 @@ extended_usage()
added to the C/C++ flags. (To build a 32-bit binary on a 64-bit CPU, added to the C/C++ flags. (To build a 32-bit binary on a 64-bit CPU,
use the --32 option as described previously.) use the --32 option as described previously.)
When gcc 4.5 is used and the user set --with-link-time-optimizer then
also --flto is added to compiler flags and linker flags.
Linux/x86+Itanium/icc Linux/x86+Itanium/icc
------------- -------------
Flags used: Flags used:
...@@ -433,6 +479,19 @@ extended_usage() ...@@ -433,6 +479,19 @@ extended_usage()
added to the C/C++ flags; this provides optimisations specific to Core added to the C/C++ flags; this provides optimisations specific to Core
2 Duo. This is added only when the --fast flag is set. 2 Duo. This is added only when the --fast flag is set.
Linux/x86/Open64
----------------
For normal builds use -O3, when fast flag is set one also adds
--march=auto to generate optimized builds for the CPU used. If
--with-link-time-optimizer is set also -ipa is set. There is also
a special flag --with-mso which can be set to get --mso set which
activates optimisation for multi-core scalability.
FreeBSD/x86/gcc
---------------
No flags are used. Instead, configure determines the proper flags to
use.
Solaris/x86/gcc Solaris/x86/gcc
--------------- ---------------
All builds on Solaris are by default 64-bit, so -m64 is always used in All builds on Solaris are by default 64-bit, so -m64 is always used in
...@@ -653,6 +712,9 @@ parse_compiler() ...@@ -653,6 +712,9 @@ parse_compiler()
forte | SunStudio | sunstudio ) forte | SunStudio | sunstudio )
compiler="forte" compiler="forte"
;; ;;
open64 | Open64 )
compiler="open64"
;;
*) *)
echo "Unknown compiler '$compiler'" echo "Unknown compiler '$compiler'"
exit 1 exit 1
...@@ -686,6 +748,15 @@ parse_options() ...@@ -686,6 +748,15 @@ parse_options()
--with-fast-mutexes) --with-fast-mutexes)
with_fast_mutexes="yes" with_fast_mutexes="yes"
;; ;;
--without-fast-mutexes)
with_fast_mutexes="no"
;;
--without-perfschema)
with_perfschema="no"
;;
--with-mso)
with_mso="yes"
;;
--use-tcmalloc) --use-tcmalloc)
use_tcmalloc="yes" use_tcmalloc="yes"
;; ;;
...@@ -693,6 +764,10 @@ parse_options() ...@@ -693,6 +764,10 @@ parse_options()
with_debug_flag="yes" with_debug_flag="yes"
fast_flag="no" fast_flag="no"
;; ;;
--extra-debug-flag)
shift
extra_debug_flags="$extra_debug_flags -D$1"
;;
--debug) --debug)
compile_debug_flag="yes" compile_debug_flag="yes"
;; ;;
...@@ -712,6 +787,14 @@ parse_options() ...@@ -712,6 +787,14 @@ parse_options()
compiler=`get_key_value "$1"` compiler=`get_key_value "$1"`
parse_compiler parse_compiler
;; ;;
--generate-feedback)
shift
GENERATE_FEEDBACK_PATH="$1"
;;
--use-feedback)
shift
USE_FEEDBACK_PATH="$1"
;;
--cpu=*) --cpu=*)
cpu_type=`get_key_value "$1"` cpu_type=`get_key_value "$1"`
parse_cpu_type parse_cpu_type
...@@ -746,12 +829,6 @@ parse_options() ...@@ -746,12 +829,6 @@ parse_options()
--parallelism=*) --parallelism=*)
parallelism=`get_key_value "$1"` parallelism=`get_key_value "$1"`
;; ;;
--use-autotools)
use_autotools="yes"
;;
--no-autotools)
use_autotools="no"
;;
--configure-only) --configure-only)
just_configure="yes" just_configure="yes"
;; ;;
...@@ -896,6 +973,9 @@ set_cpu_base() ...@@ -896,6 +973,9 @@ set_cpu_base()
# #
init_configure_commands() init_configure_commands()
{ {
path=`dirname $0`
cp $path/cmake_configure.sh $path/../configure
chmod +x $path/../configure
cflags="$c_warnings $base_cflags $compiler_flags" cflags="$c_warnings $base_cflags $compiler_flags"
cxxflags="$cxx_warnings $base_cxxflags $compiler_flags" cxxflags="$cxx_warnings $base_cxxflags $compiler_flags"
configure="./configure $base_configs $with_flags" configure="./configure $base_configs $with_flags"
...@@ -1084,6 +1164,7 @@ set_with_debug_flags() ...@@ -1084,6 +1164,7 @@ set_with_debug_flags()
loc_debug_flags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS " loc_debug_flags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS "
compiler_flags="$compiler_flags $loc_debug_flags" compiler_flags="$compiler_flags $loc_debug_flags"
fi fi
compiler_flags="$compiler_flags $extra_debug_flags"
fi fi
} }
...@@ -1105,7 +1186,7 @@ set_no_omit_frame_pointer_for_developers() ...@@ -1105,7 +1186,7 @@ set_no_omit_frame_pointer_for_developers()
# #
set_debug_flag() set_debug_flag()
{ {
if test "x$compile_debug_flags" = "xyes" ; then if test "x$compile_debug_flag" = "xyes" ; then
compiler_flags="$compiler_flags -g" compiler_flags="$compiler_flags -g"
fi fi
} }
...@@ -1152,7 +1233,9 @@ set_base_configs() ...@@ -1152,7 +1233,9 @@ set_base_configs()
fi fi
base_configs="$base_configs --with-pic" base_configs="$base_configs --with-pic"
base_configs="$base_configs --with-csv-storage-engine" base_configs="$base_configs --with-csv-storage-engine"
if test "x$with_perfschema" != "xno" ; then
base_configs="$base_configs --with-perfschema" base_configs="$base_configs --with-perfschema"
fi
} }
# #
...@@ -1251,6 +1334,19 @@ set_gcc_special_options() ...@@ -1251,6 +1334,19 @@ set_gcc_special_options()
fi fi
} }
#
# If we discover a Core 2 Duo architecture and we have enabled the fast
# flag, we enable a compile especially optimised for Core 2 Duo. This
# feature is currently available on Intel's icc compiler only.
#
set_icc_special_options()
{
if test "x$fast_flag" = "xyes" && test "x$cpu_arg" = "xcore2" && \
test "x$compiler" = "xicc" ; then
compiler_flags="$compiler_flags -xT"
fi
}
set_cc_and_cxx_for_gcc() set_cc_and_cxx_for_gcc()
{ {
if test "x$CC" = "x" ; then if test "x$CC" = "x" ; then
...@@ -1271,26 +1367,23 @@ set_cc_and_cxx_for_icc() ...@@ -1271,26 +1367,23 @@ set_cc_and_cxx_for_icc()
fi fi
} }
set_cc_and_cxx_for_forte() set_cc_and_cxx_for_open64()
{ {
if test "x$CC" = "x" ; then if test "x$CC" = "x" ; then
CC="cc" CC="opencc -static-libgcc -fno-exceptions"
fi fi
if test "x$CXX" = "x" ; then if test "x$CXX" = "x" ; then
CXX="CC" CXX="openCC -static-libgcc -fno-exceptions"
fi fi
} }
# set_cc_and_cxx_for_forte()
# If we discover a Core 2 Duo architecture and we have enabled the fast
# flag, we enable a compile especially optimised for Core 2 Duo. This
# feature is currently available on Intel's icc compiler only.
#
set_icc_special_options()
{ {
if test "x$fast_flag" = "xyes" && test "x$cpu_arg" = "xcore2" && \ if test "x$CC" = "x" ; then
test "x$compiler" = "xicc" ; then CC="cc"
compiler_flags="$compiler_flags -xT" fi
if test "x$CXX" = "x" ; then
CXX="CC"
fi fi
} }
...@@ -1357,12 +1450,45 @@ get_gcc_version() ...@@ -1357,12 +1450,45 @@ get_gcc_version()
fi fi
} }
#
# Link time optimizer (interprocedural optimizations) for Open64
#
check_for_open64_link_time_optimizer()
{
if test "x$with_link_time_optimizer" = "xyes" ; then
compiler_flags="$compiler_flags -ipa"
LDFLAGS="$LDFLAGS -ipa"
fi
}
#
# Link time optimizer (interprocedural optimizations) for icc
#
check_for_icc_link_time_optimizer()
{
if test "x$with_link_time_optimizer" = "xyes" ; then
compiler_flags="$compiler_flags -ipo"
LDFLAGS="$LDFLAGS -ipo"
fi
}
#
# Link time optimizer (interprocedural optimizations) for forte
#
check_for_forte_link_time_optimizer()
{
if test "x$with_link_time_optimizer" = "xyes" ; then
compiler_flags="$compiler_flags -ipo"
LDFLAGS="$LDFLAGS -ipo"
fi
}
# #
# Link Time Optimizer in GCC (LTO) uses a parameter -flto # Link Time Optimizer in GCC (LTO) uses a parameter -flto
# which was added to GCC 4.5, if --with-link-time-optimizer # which was added to GCC 4.5, if --with-link-time-optimizer
# is set then use this feature # is set then use this feature
# #
check_for_link_time_optimizer() check_for_gcc_link_time_optimizer()
{ {
get_gcc_version get_gcc_version
if test "$gcc_version" -ge 405 && \ if test "$gcc_version" -ge 405 && \
...@@ -1371,11 +1497,37 @@ check_for_link_time_optimizer() ...@@ -1371,11 +1497,37 @@ check_for_link_time_optimizer()
LDFLAGS="$LDFLAGS -flto" LDFLAGS="$LDFLAGS -flto"
fi fi
} }
set_feedback_for_gcc()
{
if test "x$GENERATE_FEEDBACK_PATH" != "x" ; then
compiler_flags="$compiler_flags -fprofile-generate"
compiler_flags="$compiler_flags -fprofile-dir=$GENERATE_FEEDBACK_PATH"
elif test "x$USE_FEEDBACK_PATH" != "x" ; then
compiler_flags="$compiler_flags -fprofile-use"
compiler_flags="$compiler_flags -fprofile-correction"
compiler_flags="$compiler_flags -fprofile-dir=$USE_FEEDBACK_PATH"
fi
}
set_feedback_for_open64()
{
if test "x$GENERATE_FEEDBACK_PATH" != "x" ; then
compiler_flags="$compiler_flags --fb-create=$GENERATE_FEEDBACK_PATH/feedback"
elif test "x$USE_FEEDBACK_PATH" != "x" ; then
compiler_flags="$compiler_flags --fb-opt=$USE_FEEDBACK_PATH/feedback"
fi
}
# #
# Linux Section # Linux Section
# #
set_linux_configs() set_linux_configs()
{ {
# Default to use --with-fast-mutexes on Linux
if test "x$with_fast_mutexes" = "x" ; then
base_configs="$base_configs --with-fast-mutexes"
fi
if test "x$cpu_base_type" != "xx86" && \ if test "x$cpu_base_type" != "xx86" && \
test "x$cpu_base_type" != "xitanium" ; then test "x$cpu_base_type" != "xitanium" ; then
usage "Only x86 and Itanium CPUs supported for Linux" usage "Only x86 and Itanium CPUs supported for Linux"
...@@ -1392,19 +1544,14 @@ set_linux_configs() ...@@ -1392,19 +1544,14 @@ set_linux_configs()
if test "x$fast_flag" != "xno" ; then if test "x$fast_flag" != "xno" ; then
if test "x$fast_flag" = "xyes" ; then if test "x$fast_flag" = "xyes" ; then
compiler_flags="$compiler_flags -O3" compiler_flags="$compiler_flags -O3"
check_for_link_time_optimizer check_for_gcc_link_time_optimizer
else else
compiler_flags="$compiler_flags -O2" compiler_flags="$compiler_flags -O3"
fi fi
else else
compiler_flags="$compiler_flags -O0" compiler_flags="$compiler_flags -O0"
fi fi
check_64_bits set_feedback_for_gcc
if test "x$m64" = "xyes" ; then
compiler_flags="$compiler_flags -m64"
else
compiler_flags="$compiler_flags -m32"
fi
# configure will set proper compiler flags for gcc on Linux # configure will set proper compiler flags for gcc on Linux
elif test "x$compiler" = "xicc" ; then elif test "x$compiler" = "xicc" ; then
compiler_flags="$compiler_flags -mp -restrict" compiler_flags="$compiler_flags -mp -restrict"
...@@ -1414,16 +1561,36 @@ set_linux_configs() ...@@ -1414,16 +1561,36 @@ set_linux_configs()
fi fi
if test "x$fast_flag" != "xno" ; then if test "x$fast_flag" != "xno" ; then
compiler_flags="$compiler_flags -O3 -unroll2 -ip" compiler_flags="$compiler_flags -O3 -unroll2 -ip"
if test "x$fast_flag" = "xyes" && \ if test "x$fast_flag" = "xyes" ; then
test "x$with_link_time_optimizer" = "xyes" ; then check_for_icc_link_time_optimizer
compiler_flags="$compiler_flags -ipo" fi
LDFLAGS="$LDFLAGS -ipo" fi
elif test "x$compiler" = "xopen64" ; then
set_cc_and_cxx_for_open64
if test "x$fast_flag" != "xno" ; then
if test "x$fast_flag" = "xyes" ; then
compiler_flags="$compiler_flags -O3"
# Generate code specific for the machine you run on
compiler_flags="$compiler_flags -march=auto"
check_for_open64_link_time_optimizer
if test "x$with_mso" = "xyes" ; then
compiler_flags="$compiler_flags -mso"
fi
else
compiler_flags="$compiler_flags -O3"
fi fi
fi fi
set_feedback_for_open64
else else
usage "Only gcc and icc compilers supported for Linux" usage "Only gcc,icc and Open64 compilers supported for Linux"
exit 1 exit 1
fi fi
check_64_bits
if test "x$m64" = "xyes" ; then
compiler_flags="$compiler_flags -m64"
else
compiler_flags="$compiler_flags -m32"
fi
} }
# #
...@@ -1475,7 +1642,7 @@ set_solaris_configs() ...@@ -1475,7 +1642,7 @@ set_solaris_configs()
if test "x$fast_flag" = "xyes" ; then if test "x$fast_flag" = "xyes" ; then
LDFLAGS="$LDFLAGS -O3" LDFLAGS="$LDFLAGS -O3"
compiler_flags="$compiler_flags -O3" compiler_flags="$compiler_flags -O3"
check_for_link_time_optimizer check_for_gcc_link_time_optimizer
else else
if test "x$fast_flag" = "xgeneric" ; then if test "x$fast_flag" = "xgeneric" ; then
LDFLAGS="$LDFLAGS -O2" LDFLAGS="$LDFLAGS -O2"
...@@ -1498,10 +1665,7 @@ set_solaris_configs() ...@@ -1498,10 +1665,7 @@ set_solaris_configs()
if test "x$fast_flag" = "xyes" ; then if test "x$fast_flag" = "xyes" ; then
compiler_flags="$compiler_flags -xtarget=native" compiler_flags="$compiler_flags -xtarget=native"
compiler_flags="$compiler_flags -xunroll=3" compiler_flags="$compiler_flags -xunroll=3"
if test "x$with_link_time_optimizer" = "xyes" ; then check_for_forte_link_time_optimizer
compiler_flags="$compiler_flags -xipo"
LDFLAGS="$LDFLAGS -xipo"
fi
else else
compiler_flags="$compiler_flags -xtarget=generic" compiler_flags="$compiler_flags -xtarget=generic"
fi fi
...@@ -1612,17 +1776,6 @@ set_default_package() ...@@ -1612,17 +1776,6 @@ set_default_package()
fi fi
} }
set_autotool_flags()
{
if test "x$use_autotools" = "x" ; then
if test "x$developer_flag" = "xno" ; then
use_autotools="no"
else
use_autotools="yes"
fi
fi
}
set_defaults_based_on_environment() set_defaults_based_on_environment()
{ {
if test ! -z "$MYSQL_DEVELOPER" ; then if test ! -z "$MYSQL_DEVELOPER" ; then
...@@ -1674,25 +1827,28 @@ base_cxxflags= ...@@ -1674,25 +1827,28 @@ base_cxxflags=
base_configs= base_configs=
debug_flags= debug_flags=
cxxflags= cxxflags=
extra_debug_flags=
m64= m64=
explicit_size_set= explicit_size_set=
datadir= datadir=
commands= commands=
use_autotools=
engine_configs= engine_configs=
ASFLAGS= ASFLAGS=
LDFLAGS= LDFLAGS=
use_tcmalloc= use_tcmalloc=
without_comment="yes" without_comment="yes"
with_fast_mutexes= with_fast_mutexes=
with_perfschema="yes"
with_link_time_optimizer= with_link_time_optimizer=
with_mso=
gcc_version="0" gcc_version="0"
generate_feedback_path=
use_feedback_path=
set_defaults_based_on_environment set_defaults_based_on_environment
parse_options "$@" parse_options "$@"
set_autotool_flags
set_default_package set_default_package
set -e set -e
...@@ -1793,9 +1949,6 @@ set_ccache_usage ...@@ -1793,9 +1949,6 @@ set_ccache_usage
# Set up commands variable from variables prepared for base # Set up commands variable from variables prepared for base
# configurations, compiler flags, and warnings flags. # configurations, compiler flags, and warnings flags.
# #
if test "x$use_autotools" = "xyes" ; then
init_auto_commands
fi
init_configure_commands init_configure_commands
if test "x$just_configure" != "xyes" ; then if test "x$just_configure" != "xyes" ; then
...@@ -1806,8 +1959,8 @@ fi ...@@ -1806,8 +1959,8 @@ fi
# The commands variable now contains the entire command to be run for # The commands variable now contains the entire command to be run for
# the build; we either execute it, or merely print it out. # the build; we either execute it, or merely print it out.
# #
if test "x$just_print" = "xyes" ; then echo "Running command:"
echo "$commands" echo "$commands"
else if test "x$just_print" != "xyes" ; then
eval "set -x; $commands" eval "set -x; $commands"
fi fi
...@@ -100,16 +100,16 @@ create trigger performance_schema.bi_file_instances ...@@ -100,16 +100,16 @@ create trigger performance_schema.bi_file_instances
before insert on performance_schema.file_instances before insert on performance_schema.file_instances
for each row begin end; for each row begin end;
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1(a int) engine=PERFORMANCE_SCHEMA; create table test.t1(a int) engine=PERFORMANCE_SCHEMA;
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1 like performance_schema.setup_instruments; create table test.t1 like performance_schema.setup_instruments;
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1 like performance_schema.file_instances; create table test.t1 like performance_schema.file_instances;
--error ER_TABLEACCESS_DENIED_ERROR --error ER_TABLEACCESS_DENIED_ERROR
......
...@@ -6,9 +6,9 @@ AND EVENT_NAME IN ...@@ -6,9 +6,9 @@ AND EVENT_NAME IN
WHERE NAME LIKE "wait/synch/%") WHERE NAME LIKE "wait/synch/%")
LIMIT 1; LIMIT 1;
create table test.t1(a int) engine=performance_schema; create table test.t1(a int) engine=performance_schema;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table performance_schema.t1(a int); create table performance_schema.t1(a int);
ERROR 42000: CREATE command denied to user 'root'@'localhost' for table 't1' ERROR 42000: CREATE command denied to user 'root'@'localhost' for table 't1'
drop table if exists test.ghost; drop table if exists test.ghost;
......
...@@ -16,6 +16,7 @@ operation, number_of_bytes, ...@@ -16,6 +16,7 @@ operation, number_of_bytes,
substring(object_name, locate("no_index_tab", object_name)) as short_name substring(object_name, locate("no_index_tab", object_name)) as short_name
from performance_schema.events_waits_history_long from performance_schema.events_waits_history_long
where operation not like "tell" where operation not like "tell"
and event_name like "wait/io/file/myisam/%"
order by thread_id, event_id; order by thread_id, event_id;
event_name short_source operation number_of_bytes short_name event_name short_source operation number_of_bytes short_name
wait/io/file/myisam/kfile mi_create.c: create NULL no_index_tab.MYI wait/io/file/myisam/kfile mi_create.c: create NULL no_index_tab.MYI
......
...@@ -152,13 +152,13 @@ before insert on performance_schema.file_instances ...@@ -152,13 +152,13 @@ before insert on performance_schema.file_instances
for each row begin end; for each row begin end;
ERROR 42000: Access denied for user 'root'@'localhost' to database 'performance_schema' ERROR 42000: Access denied for user 'root'@'localhost' to database 'performance_schema'
create table test.t1(a int) engine=PERFORMANCE_SCHEMA; create table test.t1(a int) engine=PERFORMANCE_SCHEMA;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.setup_instruments; create table test.t1 like performance_schema.setup_instruments;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.file_instances; create table test.t1 like performance_schema.file_instances;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
insert into performance_schema.setup_instruments insert into performance_schema.setup_instruments
set name="foo"; set name="foo";
ERROR 42000: INSERT command denied to user 'root'@'localhost' for table 'setup_instruments' ERROR 42000: INSERT command denied to user 'root'@'localhost' for table 'setup_instruments'
...@@ -250,13 +250,13 @@ before insert on performance_schema.file_instances ...@@ -250,13 +250,13 @@ before insert on performance_schema.file_instances
for each row begin end; for each row begin end;
ERROR 42000: Access denied for user 'pfs_user_1'@'localhost' to database 'performance_schema' ERROR 42000: Access denied for user 'pfs_user_1'@'localhost' to database 'performance_schema'
create table test.t1(a int) engine=PERFORMANCE_SCHEMA; create table test.t1(a int) engine=PERFORMANCE_SCHEMA;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.setup_instruments; create table test.t1 like performance_schema.setup_instruments;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.file_instances; create table test.t1 like performance_schema.file_instances;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
insert into performance_schema.setup_instruments insert into performance_schema.setup_instruments
set name="foo"; set name="foo";
ERROR 42000: INSERT command denied to user 'pfs_user_1'@'localhost' for table 'setup_instruments' ERROR 42000: INSERT command denied to user 'pfs_user_1'@'localhost' for table 'setup_instruments'
...@@ -348,13 +348,13 @@ before insert on performance_schema.file_instances ...@@ -348,13 +348,13 @@ before insert on performance_schema.file_instances
for each row begin end; for each row begin end;
ERROR 42000: Access denied for user 'pfs_user_2'@'localhost' to database 'performance_schema' ERROR 42000: Access denied for user 'pfs_user_2'@'localhost' to database 'performance_schema'
create table test.t1(a int) engine=PERFORMANCE_SCHEMA; create table test.t1(a int) engine=PERFORMANCE_SCHEMA;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.setup_instruments; create table test.t1 like performance_schema.setup_instruments;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.file_instances; create table test.t1 like performance_schema.file_instances;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
insert into performance_schema.setup_instruments insert into performance_schema.setup_instruments
set name="foo"; set name="foo";
ERROR 42000: INSERT command denied to user 'pfs_user_2'@'localhost' for table 'setup_instruments' ERROR 42000: INSERT command denied to user 'pfs_user_2'@'localhost' for table 'setup_instruments'
...@@ -446,13 +446,13 @@ before insert on performance_schema.file_instances ...@@ -446,13 +446,13 @@ before insert on performance_schema.file_instances
for each row begin end; for each row begin end;
ERROR 42000: Access denied for user 'pfs_user_3'@'localhost' to database 'performance_schema' ERROR 42000: Access denied for user 'pfs_user_3'@'localhost' to database 'performance_schema'
create table test.t1(a int) engine=PERFORMANCE_SCHEMA; create table test.t1(a int) engine=PERFORMANCE_SCHEMA;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.setup_instruments; create table test.t1 like performance_schema.setup_instruments;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
create table test.t1 like performance_schema.file_instances; create table test.t1 like performance_schema.file_instances;
ERROR HY000: Invalid performance_schema usage. ERROR HY000: Can't create table 'test.t1' (errno: 131)
insert into performance_schema.setup_instruments insert into performance_schema.setup_instruments
set name="foo"; set name="foo";
ERROR 42000: INSERT command denied to user 'pfs_user_3'@'localhost' for table 'setup_instruments' ERROR 42000: INSERT command denied to user 'pfs_user_3'@'localhost' for table 'setup_instruments'
......
flush status;
SET @saved_thread_cache_size = @@global.thread_cache_size; SET @saved_thread_cache_size = @@global.thread_cache_size;
set global thread_cache_size = 0; set global thread_cache_size = 0;
show variables like "thread_cache_size"; show variables like "thread_cache_size";
...@@ -32,3 +33,7 @@ select @thread_id_increment; ...@@ -32,3 +33,7 @@ select @thread_id_increment;
@thread_id_increment @thread_id_increment
1 1
set global thread_cache_size = @saved_thread_cache_size; set global thread_cache_size = @saved_thread_cache_size;
show status like "performance_schema_thread%";
Variable_name Value
Performance_schema_thread_classes_lost 0
Performance_schema_thread_instances_lost 0
...@@ -38,14 +38,14 @@ LIMIT 1; ...@@ -38,14 +38,14 @@ LIMIT 1;
# Bug#45088 Should not be able to create tables of engine PERFORMANCE_SCHEMA # Bug#45088 Should not be able to create tables of engine PERFORMANCE_SCHEMA
# #
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1(a int) engine=performance_schema; create table test.t1(a int) engine=performance_schema;
# #
# Bug#44897 Performance Schema: can create a ghost table in another database # Bug#44897 Performance Schema: can create a ghost table in another database
# #
--error ER_WRONG_PERFSCHEMA_USAGE --error ER_CANT_CREATE_TABLE
create table test.t1 like performance_schema.events_waits_current; create table test.t1 like performance_schema.events_waits_current;
# #
......
...@@ -46,6 +46,13 @@ insert into no_index_tab set a = 'foo', b = 1; ...@@ -46,6 +46,13 @@ insert into no_index_tab set a = 'foo', b = 1;
# Verification # Verification
# Note that mi_create.c contains mysql_file_tell() calls in debug only, # Note that mi_create.c contains mysql_file_tell() calls in debug only,
# so the result are filtered to remove 'tell'. # so the result are filtered to remove 'tell'.
# Note that even after setting other instruments to enabled='NO'
# and truncating the events_waits_history_long table,
# some events -- that were already started but not completed --
# for other instruments could still be added in the history.
# To protect against that, an extra where clause
# "and event_name like "wait/io/file/myisam/%"
# is added to the select to filter out the result.
select event_name, select event_name,
left(source, locate(":", source)) as short_source, left(source, locate(":", source)) as short_source,
...@@ -53,6 +60,7 @@ select event_name, ...@@ -53,6 +60,7 @@ select event_name,
substring(object_name, locate("no_index_tab", object_name)) as short_name substring(object_name, locate("no_index_tab", object_name)) as short_name
from performance_schema.events_waits_history_long from performance_schema.events_waits_history_long
where operation not like "tell" where operation not like "tell"
and event_name like "wait/io/file/myisam/%"
order by thread_id, event_id; order by thread_id, event_id;
# In case of failures, this will tell if file io are lost. # In case of failures, this will tell if file io are lost.
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
# Setup # Setup
flush status;
SET @saved_thread_cache_size = @@global.thread_cache_size; SET @saved_thread_cache_size = @@global.thread_cache_size;
set global thread_cache_size = 0; set global thread_cache_size = 0;
...@@ -40,7 +42,7 @@ let $con2_ID=`select connection_id()`; ...@@ -40,7 +42,7 @@ let $con2_ID=`select connection_id()`;
let $con2_THREAD_ID=`select thread_id from performance_schema.threads let $con2_THREAD_ID=`select thread_id from performance_schema.threads
where PROCESSLIST_ID = connection_id()`; where PROCESSLIST_ID = connection_id()`;
connection default; --connection default
--disable_query_log --disable_query_log
eval select ($con2_ID - $con1_ID) into @id_increment; eval select ($con2_ID - $con1_ID) into @id_increment;
...@@ -52,7 +54,15 @@ select @id_increment; ...@@ -52,7 +54,15 @@ select @id_increment;
# Expect 1, THREAD_ID is incremented for each new connection # Expect 1, THREAD_ID is incremented for each new connection
select @thread_id_increment; select @thread_id_increment;
disconnect con2; --disconnect con2
--connection default
# Wait for the disconnect con2 to complete
let $wait_condition=
select count(*) = 2 from performance_schema.threads
where name like "thread/sql/one_connection";
--source include/wait_condition.inc
connect (con3, localhost, root, , ); connect (con3, localhost, root, , );
...@@ -61,10 +71,16 @@ let $con3_ID=`select connection_id()`; ...@@ -61,10 +71,16 @@ let $con3_ID=`select connection_id()`;
let $con3_THREAD_ID=`select thread_id from performance_schema.threads let $con3_THREAD_ID=`select thread_id from performance_schema.threads
where PROCESSLIST_ID = connection_id()`; where PROCESSLIST_ID = connection_id()`;
disconnect con3; --disconnect con3
disconnect con1; --disconnect con1
--connection default
connection default; # Wait for the disconnect con1 and con3 to complete
let $wait_condition=
select count(*) = 1 from performance_schema.threads
where name like "thread/sql/one_connection";
--source include/wait_condition.inc
--disable_query_log --disable_query_log
eval select ($con3_ID - $con2_ID) into @id_increment; eval select ($con3_ID - $con2_ID) into @id_increment;
...@@ -92,7 +108,7 @@ let $con2_ID=`select connection_id()`; ...@@ -92,7 +108,7 @@ let $con2_ID=`select connection_id()`;
let $con2_THREAD_ID=`select thread_id from performance_schema.threads let $con2_THREAD_ID=`select thread_id from performance_schema.threads
where PROCESSLIST_ID = connection_id()`; where PROCESSLIST_ID = connection_id()`;
connection default; --connection default
--disable_query_log --disable_query_log
eval select ($con2_ID - $con1_ID) into @id_increment; eval select ($con2_ID - $con1_ID) into @id_increment;
...@@ -102,7 +118,15 @@ eval select ($con2_THREAD_ID - $con1_THREAD_ID) into @thread_id_increment; ...@@ -102,7 +118,15 @@ eval select ($con2_THREAD_ID - $con1_THREAD_ID) into @thread_id_increment;
select @id_increment; select @id_increment;
select @thread_id_increment; select @thread_id_increment;
disconnect con2; --disconnect con2
--connection default
# Wait for the disconnect con2 to complete
let $wait_condition=
select count(*) = 2 from performance_schema.threads
where name like "thread/sql/one_connection";
--source include/wait_condition.inc
connect (con3, localhost, root, , ); connect (con3, localhost, root, , );
...@@ -111,10 +135,16 @@ let $con3_ID=`select connection_id()`; ...@@ -111,10 +135,16 @@ let $con3_ID=`select connection_id()`;
let $con3_THREAD_ID=`select thread_id from performance_schema.threads let $con3_THREAD_ID=`select thread_id from performance_schema.threads
where PROCESSLIST_ID = connection_id()`; where PROCESSLIST_ID = connection_id()`;
disconnect con3; --disconnect con3
disconnect con1; --disconnect con1
connection default; --connection default
# Wait for the disconnect con1 and con3 to complete
let $wait_condition=
select count(*) = 1 from performance_schema.threads
where name like "thread/sql/one_connection";
--source include/wait_condition.inc
--disable_query_log --disable_query_log
eval select ($con3_ID - $con2_ID) into @id_increment; eval select ($con3_ID - $con2_ID) into @id_increment;
...@@ -132,3 +162,5 @@ select @thread_id_increment; ...@@ -132,3 +162,5 @@ select @thread_id_increment;
set global thread_cache_size = @saved_thread_cache_size; set global thread_cache_size = @saved_thread_cache_size;
show status like "performance_schema_thread%";
...@@ -228,7 +228,6 @@ int ha_perfschema::write_row(uchar *buf) ...@@ -228,7 +228,6 @@ int ha_perfschema::write_row(uchar *buf)
result= m_table_share->m_write_row(table, buf, table->field); result= m_table_share->m_write_row(table, buf, table->field);
else else
{ {
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
result= HA_ERR_WRONG_COMMAND; result= HA_ERR_WRONG_COMMAND;
} }
...@@ -339,7 +338,6 @@ int ha_perfschema::delete_all_rows(void) ...@@ -339,7 +338,6 @@ int ha_perfschema::delete_all_rows(void)
result= m_table_share->m_delete_all_rows(); result= m_table_share->m_delete_all_rows();
else else
{ {
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
result= HA_ERR_WRONG_COMMAND; result= HA_ERR_WRONG_COMMAND;
} }
DBUG_RETURN(result); DBUG_RETURN(result);
...@@ -370,7 +368,6 @@ int ha_perfschema::delete_table(const char *name) ...@@ -370,7 +368,6 @@ int ha_perfschema::delete_table(const char *name)
int ha_perfschema::rename_table(const char * from, const char * to) int ha_perfschema::rename_table(const char * from, const char * to)
{ {
DBUG_ENTER("ha_perfschema::rename_table "); DBUG_ENTER("ha_perfschema::rename_table ");
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
DBUG_RETURN(HA_ERR_WRONG_COMMAND); DBUG_RETURN(HA_ERR_WRONG_COMMAND);
} }
...@@ -395,7 +392,37 @@ int ha_perfschema::create(const char *name, TABLE *table_arg, ...@@ -395,7 +392,37 @@ int ha_perfschema::create(const char *name, TABLE *table_arg,
This is not a general purpose engine. This is not a general purpose engine.
Failure to CREATE TABLE is the expected result. Failure to CREATE TABLE is the expected result.
*/ */
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
DBUG_RETURN(HA_ERR_WRONG_COMMAND); DBUG_RETURN(HA_ERR_WRONG_COMMAND);
} }
void ha_perfschema::print_error(int error, myf errflag)
{
switch (error)
{
case HA_ERR_TABLE_NEEDS_UPGRADE:
/*
The error message for ER_TABLE_NEEDS_UPGRADE refers to REPAIR table,
which does not apply to performance schema tables.
*/
my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
table_share->db.str, table_share->table_name.str);
break;
case HA_ERR_WRONG_COMMAND:
/*
The performance schema is not a general purpose storage engine,
some operations are not supported, by design.
We do not want to print "Command not supported",
which gives the impression that a command implementation is missing,
and that the failure should be considered a bug.
We print "Invalid performance_schema usage." instead,
to emphasise that the operation attempted is not meant to be legal,
and that the failure returned is indeed the expected result.
*/
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
break;
default:
handler::print_error(error, errflag);
break;
}
}
...@@ -100,9 +100,6 @@ class ha_perfschema : public handler ...@@ -100,9 +100,6 @@ class ha_perfschema : public handler
double scan_time(void) double scan_time(void)
{ return 1.0; } { return 1.0; }
double read_time(ha_rows)
{ return 1.0; }
int open(const char *name, int mode, uint test_if_locked); int open(const char *name, int mode, uint test_if_locked);
int close(void); int close(void);
...@@ -149,6 +146,8 @@ class ha_perfschema : public handler ...@@ -149,6 +146,8 @@ class ha_perfschema : public handler
return FALSE; return FALSE;
} }
virtual void print_error(int error, myf errflags);
private: private:
/** MySQL lock */ /** MySQL lock */
THR_LOCK_DATA m_thr_lock; THR_LOCK_DATA m_thr_lock;
......
...@@ -232,8 +232,6 @@ int PFS_engine_table::read_row(TABLE *table, ...@@ -232,8 +232,6 @@ int PFS_engine_table::read_row(TABLE *table,
*/ */
if (! m_share_ptr->m_checked) if (! m_share_ptr->m_checked)
{ {
my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
PERFORMANCE_SCHEMA_str.str, m_share_ptr->m_name.str);
return HA_ERR_TABLE_NEEDS_UPGRADE; return HA_ERR_TABLE_NEEDS_UPGRADE;
} }
...@@ -279,8 +277,6 @@ int PFS_engine_table::update_row(TABLE *table, ...@@ -279,8 +277,6 @@ int PFS_engine_table::update_row(TABLE *table,
*/ */
if (! m_share_ptr->m_checked) if (! m_share_ptr->m_checked)
{ {
my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
PERFORMANCE_SCHEMA_str.str, m_share_ptr->m_name.str);
return HA_ERR_TABLE_NEEDS_UPGRADE; return HA_ERR_TABLE_NEEDS_UPGRADE;
} }
...@@ -351,7 +347,6 @@ int PFS_engine_table::update_row_values(TABLE *, ...@@ -351,7 +347,6 @@ int PFS_engine_table::update_row_values(TABLE *,
unsigned char *, unsigned char *,
Field **) Field **)
{ {
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND; return HA_ERR_WRONG_COMMAND;
} }
......
...@@ -192,7 +192,6 @@ int table_setup_consumers::update_row_values(TABLE *table, ...@@ -192,7 +192,6 @@ int table_setup_consumers::update_row_values(TABLE *table,
switch(f->field_index) switch(f->field_index)
{ {
case 0: /* NAME */ case 0: /* NAME */
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND; return HA_ERR_WRONG_COMMAND;
case 1: /* ENABLED */ case 1: /* ENABLED */
{ {
......
...@@ -253,7 +253,6 @@ int table_setup_instruments::update_row_values(TABLE *table, ...@@ -253,7 +253,6 @@ int table_setup_instruments::update_row_values(TABLE *table,
switch(f->field_index) switch(f->field_index)
{ {
case 0: /* NAME */ case 0: /* NAME */
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND; return HA_ERR_WRONG_COMMAND;
case 1: /* ENABLED */ case 1: /* ENABLED */
value= (enum_yes_no) get_field_enum(f); value= (enum_yes_no) get_field_enum(f);
......
...@@ -164,7 +164,6 @@ int table_setup_timers::update_row_values(TABLE *table, ...@@ -164,7 +164,6 @@ int table_setup_timers::update_row_values(TABLE *table,
switch(f->field_index) switch(f->field_index)
{ {
case 0: /* NAME */ case 0: /* NAME */
my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND; return HA_ERR_WRONG_COMMAND;
case 1: /* TIMER_NAME */ case 1: /* TIMER_NAME */
value= get_field_enum(f); value= get_field_enum(f);
......
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