diff options
author | unknown <monty@hundin.mysql.fi> | 2001-10-02 05:53:00 +0300 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2001-10-02 05:53:00 +0300 |
commit | 9e72e1ef534384ab53a0c5943399c946856bef76 (patch) | |
tree | b029d516fe4b48e540f64b01492d64cf5d68ad2f | |
parent | 003ed4cfaecf0c80dc2ced8593e869076cd8c34d (diff) | |
download | mariadb-git-9e72e1ef534384ab53a0c5943399c946856bef76.tar.gz |
Cleaned up SSL documentation
Fixes for embedded server
Made key_cache more configurable
Fixed that one can change key blocksize in MyISAM
A lot of optimizations to make MyISAM slightly faster
Docs/manual.texi:
Cleaned up SSL documentation
client/mysql.cc:
Fixes for embedded server
client/mysqltest.c:
Fixes for embedded server
Removed memory and file leaks
include/my_global.h:
Added C_MODE_START / C_MODE_END macros
include/my_sys.h:
Made key_cache more configurable
include/myisam.h:
Fixed that one can change MyISAM key block size
include/mysql.h:
Fixes for embedded server
libmysql/libmysql.c:
Cleanup
libmysqld/Makefile.am:
Cleanup
libmysqld/examples/test-run:
Added --debug
libmysqld/lib_sql.cc:
Cleanup
libmysqld/libmysqld.c:
Cleanup
myisam/ft_boolean_search.c:
Optimized mi_key_cmp to be faster
myisam/ft_nlq_search.c:
Optimized mi_key_cmp to be faster
myisam/ft_search.c:
Optimized mi_key_cmp to be faster
myisam/mi_changed.c:
Optimized mi_key_cmp to be faster
myisam/mi_check.c:
Optimized mi_key_cmp to be faster
myisam/mi_create.c:
Fixed that one can change blocksize by changing myisam_block_size
myisam/mi_delete.c:
Optimized mi_key_cmp to be faster
myisam/mi_delete_all.c:
Optimized mi_key_cmp to be faster
myisam/mi_dynrec.c:
Speed optimizations
myisam/mi_info.c:
Speed optimizations
myisam/mi_key.c:
Speed optimizations
myisam/mi_locking.c:
Speed optimizations
myisam/mi_open.c:
Fixed that one can change blocksize by changing myisam_block_size
myisam/mi_page.c:
Fixed that one can change blocksize by changing myisam_block_size
myisam/mi_range.c:
Speed optimizations
myisam/mi_rkey.c:
Speed optimizations
myisam/mi_rnext.c:
Speed optimizations
myisam/mi_rnext_same.c:
Speed optimizations
myisam/mi_rprev.c:
Speed optimizations
myisam/mi_rsame.c:
Speed optimizations
myisam/mi_search.c:
Speed optimizations
myisam/mi_static.c:
Fixed that one can change blocksize by changing myisam_block_size
myisam/mi_statrec.c:
Speed optimizations
myisam/mi_test2.c:
Added more test options
myisam/mi_test_all.res:
Added more test options
myisam/mi_test_all.sh:
Added more test options
myisam/mi_write.c:
Speed optimizations
myisam/myisamchk.c:
Added options to change block size and repair checksums
myisam/myisamdef.h:
Speed optimizations
mysys/Makefile.am:
Added bit handling functions
mysys/mf_keycache.c:
Made key_cache more configurable
mysys/my_init.c:
made my_init_done global
scripts/mysql_fix_privilege_tables.sh:
Fixes for SSL
scripts/mysql_install_db.sh:
Fixes for SSL
sql/derror.cc:
Don't call exit, call unireg_abort()
sql/item_cmpfunc.cc:
Speed optimizations
sql/item_cmpfunc.h:
Speed optimizations
sql/mysql_priv.h:
Fixes for embedded server
sql/mysqld.cc:
Fixes for embedded server
53 files changed, 792 insertions, 610 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi index a8a7844589c..f03c8aee889 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -5722,8 +5722,6 @@ Character set casts and syntax for handling multiple character sets. @item Help for all commands from the client. @item -Secure connections (with SSL). -@item @code{SHOW COLUMNS FROM table_name} (used by @code{mysql} client to allow expansions of column names) should not open the table, but only the definition file. This will require less memory and be much faster. @@ -9928,11 +9926,12 @@ that you also probably need to raise the @code{core file size} by adding @code{ulimit -c 1000000} to @code{safe_mysqld} or starting @code{safe_mysqld} with @code{--core-file-sizes=1000000}. @xref{safe_mysqld, , @code{safe_mysqld}}. -To get a core dump on Linux if @code{mysqld} dies with a SIGSEGV signal, you can -start @code{mysqld} with the @code{--core-file} option. Note that you also probably -need to raise the @code{core file size} by adding @code{ulimit -c 1000000} to -@code{safe_mysqld} or starting @code{safe_mysqld} with -@code{--core-file-sizes=1000000}. @xref{safe_mysqld, , @code{safe_mysqld}}. +To get a core dump on Linux if @code{mysqld} dies with a SIGSEGV signal, +you can start @code{mysqld} with the @code{--core-file} option. Note +that you also probably need to raise the @code{core file size} by adding +@code{ulimit -c 1000000} to @code{safe_mysqld} or starting +@code{safe_mysqld} with @code{--core-file-sizes=1000000}. +@xref{safe_mysqld, , @code{safe_mysqld}}. If you are linking your own MySQL client and get the error: @@ -14741,6 +14740,17 @@ FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\' @cindex options, command-line @cindex mysqld options +In most cases you should manage mysqld options through option files. +@xref{Option files}. + +@code{mysqld} and @code{mysqld.server} reads options from the +@code{mysqld} and @code{server} groups. @code{mysqld_safe} read options +from the @code{mysqld}, @code{server}, @code{mysqld_safe} and +@code{safe_mysqld} groups. An embedded MySQL server usually reads +options from the @code{server}, @code{embedded} and +@code{xxxxx_SERVER}, where @code{xxxxx} is the name of the application. + + @code{mysqld} accepts the following command-line options: @table @code @@ -15057,8 +15067,9 @@ Options specified on the command line or in option files take precedence over environment variable values. @xref{Environment variables}. The following programs support option files: @code{mysql}, -@code{mysqladmin}, @code{mysqld}, @code{mysqldump}, @code{mysqlimport}, -@code{mysql.server}, @code{myisamchk}, and @code{myisampack}. +@code{mysqladmin}, @code{mysqld}, @code{mysqld_safe}, @code{mysql.server}, +@code{mysqldump}, @code{mysqlimport}, @code{mysqlshow}, @code{mysqlcheck}, +@code{myisamchk}, and @code{myisampack}. You can use option files to specify any long option that a program supports! Run the program with @code{--help} to get a list of available options. @@ -15620,6 +15631,10 @@ to make things much harder. To make things even more secure you should use @uref{http://www.ssh.com}. With this, you can get an encrypted TCP/IP connection between a MySQL server and a MySQL client. +If you are using MySQL 4.0, you can also use internal openssl support. +@xref{Secure connections}. + + To make a MySQL system secure, you should strongly consider the following suggestions: @@ -16959,6 +16974,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run * Adding users:: Adding New Users to MySQL * Passwords:: Setting Up Passwords * Password security:: Keeping Your Password Secure +* Secure connections:: Using Secure Connections @end menu @@ -17206,120 +17222,8 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the MySQL grant tables. @end itemize ------------ -@cindex SSL and X509 Basics -MySQL has support for SSL encrypted connetions. To understand how MySQL uses -SSL we need to explain some basics about SSL and X509. People who are already -aware of it can skip this chapter. - -By default, MySQL uses unencrypted connections between client and server. This means -that anyone on the way can listen and read all your data which moves there. Even -more, some people can change content of data while it is moving between client and -server. Sometime you may need to move really secret data over public networks and -such publicity is unacceptable. - -SSL is a protocol which uses different encryption algorithms to ensure that data -which comes from public network can be trusted. It have mechanisms to detect any -change, loss or replay of data. SSL also incorpores algorithms to recognize and -verification of identity using X509 standard. - -@cindex What is encryption -Encryption is the way to make any kind of data unreadable. Even more, today's -practice require many additional security elements from encryption algorithms. -They should resist many kind of known attacks like just messing with order -of encrypted messages or replaying data twice. - -@cindex What is X509/Certificate? -X509 is standard which makes possible to identity someone in the Internet. Mostly -it is used in e-commerce over the Internet. Shortly speaking there should be some -company called "Certificate Authority" which assigns electronic certificates to -everyone who needs. Certificates rely on asymmetric encryption algorithms which -have two encryption keys - public and secret. Certificate owner can prove his -identity showing certificate to other party. Certificate consists his owner public -key. Any data encrypted with it can be decrypted only by secret key holder. - -@cindex Possible questions: -Q: Why MySQL not uses encrypted connections by default? -A: Because it makes MySQL slower. Any kind of additional functionality requires -computer to do additional work and encrypting data is CPU-intensive operation which -can overcome MySQL own work and consumed time. MySQL is tuned to be fast by default. - -Q: I need more information about SSL/X509/encrpytion/whatever -A: Use your favourite internet search engine and search for keywords you are interested in. - ------------- - - -@cindex SSL related options - -MySQL can check x509 certificate attributes additionally to most used username/password -cheme. All usual options are still required (username, password, IP address mask, database/table name). - -There are different possibilities to limit connections: - -@itemize @bullet -@item -Without any SSL/X509 options all kind of encrypted/unencrypted connections are allowed if - username and password are valid. - -@item -@code{REQUIRE SSL} option makes SSL encrypted connection must. Note that this requirement -can be omitted of there are any other ACL record which allows non-SSL connection. - -Example: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE SSL -@end example - +For a description of using @code{REQUIRE}, see @xref{Secure connections}. -@item -* @code{REQUIRE X509} Requiring X509 certificate means that client should have valid certificate -but we do not care about exact certificate, issuer or subject. Only restriction is it should -be possible to verify its signature with some of our CA certificates. - -Example: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE X509 -@end example - -@item -@code{REQUIRE ISSUER issuer} makes connection more restrictive: now client must present - valid x509 certificate issued by CA "issuer". Using x509 certificates always implies encryption, - so option "SSL" is not neccessary anymore. - -Example: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" -@end example - -@item -@code{REQUIRE SUBJECT subject} requires client to have valid x509 certificate with subject "subject" on it. If client have valid certificate but having different "subject" then connection is still -not allowed. - -Example: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" -@end example - -@item -@code{REQUIRE CIPHER cipher} is needed to assure enough strong ciphers and keylengths to be used. SSL himself can be weak if old algorithms with short encryption keys are used. Using this option we can ask for some exact cipher to allow connection. - -Example: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA" -@end example - -Also it is allowed to combine those options with each other like this: -@example -GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" - REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" - AND ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" - AND CIPHER "EDH-RSA-DES-CBC3-SHA" -@end example - -But it is not allowed to use any of options twice. Only different options can be mixed. -@end itemize ------------ @node User names, Privilege changes, GRANT, User Account Management @subsection MySQL User Names and Passwords @@ -17814,7 +17718,7 @@ your Unix password and your MySQL password are the same, that Unix password file. @xref{User names}. -@node Password security, , Passwords, User Account Management +@node Password security, Secure connections, Passwords, User Account Management @subsection Keeping Your Password Secure It is inadvisable to specify your password in a way that exposes it to @@ -17890,6 +17794,170 @@ All in all, the safest methods are to have the client program prompt for the password or to specify the password in a properly protected @file{.my.cnf} file. +@node Secure connections, , Password security, User Account Management +@subsection Using Secure Connections + +@cindex openssl +@cindex SSL and X509 Basics + +@menu +* Secure basics:: Basics +* Secure requirements:: Requirements +* Secure GRANT:: GRANT OPTIONS +@end menu + +@node Secure basics, Secure requirements, Secure connections, Secure connections +@subsubsection Basics + +MySQL has support for SSL encrypted connetions. To understand how MySQL +uses SSL we need to explain some basics about SSL and X509. People who +are already aware of it can skip this chapter. + +By default, MySQL uses unencrypted connections between client and +server. This means that anyone on the way can listen and read all your +data which moves there. Even more, some people can change content of +data while it is moving between client and server. Sometime you may need +to move really secret data over public networks and such publicity is +unacceptable. + +SSL is a protocol which uses different encryption algorithms to ensure +that data which comes from public network can be trusted. It have +mechanisms to detect any change, loss or replay of data. SSL also +incorpores algorithms to recognize and verification of identity using +X509 standard. + +@cindex What is encryption +Encryption is the way to make any kind of data unreadable. Even more, +today's practice require many additional security elements from +encryption algorithms. They should resist many kind of known attacks +like just messing with order of encrypted messages or replaying data +twice. + +@cindex What is X509/Certificate? +X509 is standard which makes possible to identity someone in the +Internet. Mostly it is used in e-commerce over the Internet. Shortly +speaking there should be some company called "Certificate Authority" +which assigns electronic certificates to everyone who +needs. Certificates rely on asymmetric encryption algorithms which have +two encryption keys - public and secret. Certificate owner can prove his +identity showing certificate to other party. Certificate consists his +owner public key. Any data encrypted with it can be decrypted only by +secret key holder. + +@cindex Possible questions: + +MySQL doesn't use encrypted on connections by default because this would +make the client/server protocol much slower. Any kind of additional +functionality requires computer to do additional work and encrypting +data is CPU-intensive operation which can overcome MySQL own work and +consumed time. By default MySQL is tuned to be fast as possible. + +If you need more information about SSL/X509/encryption, you should use +your favourite internet search engine and search for keywords you are +interested in. + +@node Secure requirements, Secure GRANT, Secure basics, Secure connections +@subsubsection Requirements + +To get secure connections to work with MySQL you must do the following: + +@enumerate +@item +Install the openssh library. We have tested MySQL with openssl 0.9.6. +@uref{http://www.openssh.org}. +@item +Configure MySQL with @code{--with-vio --with-openssl}. +@item +If you are using an old MySQL installation, you have to update your +@code{mysql.user} table with some new columns. You can do this by +running the @code{mysql_fix_privilege_tables.sh} script. +@item +You can check if a running mysqld server supports @code{openssl} by +examining if @code{show variables like 'have_openssl'} returns @code{YES}. +@end enumerate + + +@node Secure GRANT, , Secure requirements, Secure connections +@subsubsection GRANT options + +@cindex SSL related options +@findex REQUIRE GRANT option +@findex GRANT statemenet + +MySQL can check x509 certificate attributes additionally to most used +username/password cheme. All usual options are still required (username, +password, IP address mask, database/table name). + +There are different possibilities to limit connections: + +@itemize @bullet +@item +Without any SSL/X509 options all kind of encrypted/unencrypted +connections are allowed if username and password are valid. + +@item +@code{REQUIRE SSL} option makes SSL encrypted connection must. Note that +this requirement can be omitted of there are any other ACL record which +allows non-SSL connection. + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY +"goodsecret" REQUIRE SSL +@end example + +@item +@code{REQUIRE X509} Requiring X509 certificate means that client +should have valid certificate but we do not care about exact +certificate, issuer or subject. Only restriction is it should be +possible to verify its signature with some of our CA certificates. + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE X509 +@end example + +@item +@code{REQUIRE ISSUER issuer} makes connection more restrictive: now +client must present valid x509 certificate issued by CA "issuer". Using +x509 certificates always implies encryption, so option "SSL" is not +neccessary anymore. + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" +@end example + +@item +@code{REQUIRE SUBJECT subject} requires client to have valid x509 +certificate with subject "subject" on it. If client have valid +certificate but having different "subject" then connection is still not +allowed. + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" +@end example + +@item +@code{REQUIRE CIPHER cipher} is needed to assure enough strong ciphers +and keylengths to be used. SSL himself can be weak if old algorithms +with short encryption keys are used. Using this option we can ask for +some exact cipher to allow connection. + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA" +@end example + +Also it is allowed to combine those options with each other like this: + +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" +REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" +AND ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" +AND CIPHER "EDH-RSA-DES-CBC3-SHA" +@end example + +But it is not allowed to use any of options twice. Only different +options can be mixed. +@end itemize + @node Disaster Prevention, Database Administration, User Account Management, MySQL Database Administration @section Disaster Prevention and Recovery @@ -20077,10 +20145,10 @@ The default character set. The supported character sets. @item @code{concurrent_inserts} -If @code{ON} (the default), MySQL will allow you to use @code{INSERT} -on @code{MyISAM} tables at the same time as you run @code{SELECT} queries -on them. You can turn this option off by starting @code{mysqld} with @code{--safe} -or @code{--skip-new}. +If @code{ON} (the default), MySQL will allow you to use @code{INSERT} on +@code{MyISAM} tables at the same time as you run @code{SELECT} queries +on them. You can turn this option off by starting @code{mysqld} with +@code{--safe} or @code{--skip-new}. @cindex timeout @item @code{connect_timeout} @@ -39486,7 +39554,7 @@ likely it is that we can fix the problem! * C API function overview:: C API Function Overview * C API functions:: C API Function Descriptions * C Thread functions:: C Thread Functions -* C Embedded Server functions:: C Embedded Server functions. C Embedded Server Functions +* C Embedded Server functions:: C Embedded Server functions. C Embedded Server functions. C Embedded Server functions. C Embedded Server functions. C Embedded Server functions. C Embedded Server Functions * C API problems:: Common questions and problems when using the C API * Building clients:: Building Client Programs * Threaded clients:: How to Make a Threaded Client @@ -42266,7 +42334,7 @@ a stand-alone server without modifying any code. @findex @code{mysql_server_init()} -@code{void mysql_server_init(int argc, const char **argv, const char **groups)} +@code{int mysql_server_init(int argc, const char **argv, const char **groups)} @subsubheading Description @@ -42274,7 +42342,8 @@ This function @strong{must} be called once in the program before calling any other MySQL function. It starts up the server and initializes any subsystems (@code{mysys}, InnoDB, etc.) that the server uses. If this function is not called, the program will -crash. +crash. If you are using the DBUG package that comes with MySQL, +you should call this after you have called @code{MY_INIT()}. The @code{argc} and @code{argv} arguments are analogous to the arguments to @code{main()}. The first element of @code{argv} @@ -42319,7 +42388,7 @@ int main(void) @{ @subsubheading Return Values -none. +0 if ok, 1 if an error occurred. @node mysql_server_end(), , mysql_server_init(), C Embedded Server functions @subsubsection @code{mysql_server_end()} @@ -47675,6 +47744,8 @@ Removed @code{my_thread_init()} and @code{my_thread_end()} from mysql_com.h, and added @code{mysql_thread_init()} and @code{mysql_thread_end()} to mysql.h. @item +Secure connections (with SSL). +@item Unsigned @code{BIGINT} constants now work. @code{MIN()} and @code{MAX()} now handles signed and unsigned @code{BIGINT} numbers correctly. @item diff --git a/client/mysql.cc b/client/mysql.cc index 06b76ac81e9..91711752b09 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -243,7 +243,8 @@ static COMMANDS commands[] = { }; static const char *load_default_groups[]= { "mysql","client",0 }; -static const char *server_default_groups[]= { "server", "mysql_SERVER", 0 }; +static const char *server_default_groups[]= +{ "server", "embedded", "mysql_SERVER", 0 }; #ifdef HAVE_READLINE extern "C" void add_history(char *command); /* From readline directory */ @@ -271,7 +272,6 @@ int main(int argc,char *argv[]) { char buff[80]; - mysql_server_init(0, NULL, server_default_groups); MY_INIT(argv[0]); DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); @@ -302,6 +302,7 @@ int main(int argc,char *argv[]) !(status.line_buff=batch_readline_init(max_allowed_packet+512,stdin))) exit(1); glob_buffer.realloc(512); + mysql_server_init(0, NULL, server_default_groups); completion_hash_init(&ht,50); bzero((char*) &mysql, sizeof(mysql)); if (sql_connect(current_host,current_db,current_user,opt_password, @@ -368,7 +369,6 @@ int main(int argc,char *argv[]) if (opt_outfile) end_tee(); mysql_end(0); - mysql_server_end(); #ifndef _lint DBUG_RETURN(0); // Keep compiler happy #endif @@ -398,6 +398,7 @@ sig_handler mysql_end(int sig) my_free(current_db,MYF(MY_ALLOW_ZERO_PTR)); my_free(current_host,MYF(MY_ALLOW_ZERO_PTR)); my_free(current_user,MYF(MY_ALLOW_ZERO_PTR)); + mysql_server_end(); my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(status.exit_status); } diff --git a/client/mysqltest.c b/client/mysqltest.c index 9a2d3e4c137..5942843c6ce 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -306,17 +306,18 @@ static void close_cons() static void close_files() { - do + DBUG_ENTER("close_files"); + for (; cur_file != file_stack ; cur_file--) { if (*cur_file != stdin && *cur_file) my_fclose(*cur_file,MYF(0)); - } while (cur_file-- != file_stack); + } + DBUG_VOID_RETURN; } static void free_used_memory() { uint i; - DBUG_ENTER("free_used_memory"); close_cons(); close_files(); hash_free(&var_hash); @@ -336,8 +337,8 @@ static void free_used_memory() dynstr_free(&ds_res); my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(default_argv); + mysql_server_end(); my_end(MY_CHECK_ERROR); - DBUG_VOID_RETURN; } static void die(const char* fmt, ...) @@ -1303,15 +1304,11 @@ int read_line(char* buf, int size) { if ((*cur_file) != stdin) my_fclose(*cur_file,MYF(0)); - + cur_file--; + lineno--; if (cur_file == file_stack) return 1; - else - { - cur_file--; - lineno--; - continue; - } + continue; } switch(state) { @@ -1592,7 +1589,7 @@ int parse_args(int argc, char **argv) result_file = optarg; break; case 'x': - if (!(*cur_file = my_fopen(optarg, O_RDONLY, MYF(MY_WME)))) + if (!(*++cur_file = my_fopen(optarg, O_RDONLY, MYF(MY_WME)))) die("Could not open %s: errno = %d", optarg, errno); break; case 'p': @@ -1949,9 +1946,10 @@ int main(int argc, char** argv) struct st_query* q; my_bool require_file=0, q_send_flag=0; char save_file[FN_REFLEN]; - mysql_server_init(sizeof(embedded_server_args) / sizeof(char *) - 1, - embedded_server_args, embedded_server_groups); MY_INIT(argv[0]); + { + DBUG_ENTER("main"); + DBUG_PROCESS(argv[0]); save_file[0]=0; TMPDIR[0]=0; @@ -1976,9 +1974,12 @@ int main(int argc, char** argv) *block_ok = 1; init_dynamic_string(&ds_res, "", 0, 65536); parse_args(argc, argv); + if (mysql_server_init(sizeof(embedded_server_args) / sizeof(char *) - 1, + embedded_server_args, embedded_server_groups)) + die("Can't initialize MySQL server"); init_var_hash(); - if (!*cur_file) - *cur_file = stdin; + if (cur_file == file_stack) + *++cur_file = stdin; *lineno=1; if (!( mysql_init(&cur_con->mysql))) @@ -2114,10 +2115,10 @@ int main(int argc, char** argv) printf("ok\n"); } - mysql_server_end(); free_used_memory(); exit(error ? 1 : 0); - return error ? 1 : 0; /* Keep compiler happy */ + DBUG_RETURN(error ? 1 : 0); /* Keep compiler happy */ + } } diff --git a/include/my_global.h b/include/my_global.h index 7cd79b3e078..e8527e83e28 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -965,4 +965,13 @@ typedef union { #define statistic_add(V,C,L) (V)+=(C) #endif +/* Macros to make switching between C and C++ mode easier */ +#ifdef __cplusplus +#define C_MODE_START extern "C" { +#define C_MODE_END } +#else +#define C_MODE_START +#define C_MODE_END +#endif + #endif /* _global_h */ diff --git a/include/my_sys.h b/include/my_sys.h index b70d123a66a..0ab39f1146b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -106,7 +106,8 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */ #define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ #define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ -#define KEYCACHE_BLOCK_SIZE 1024 +#define DEFAULT_KEYCACHE_BLOCK_SIZE 1024 +#define MAX_KEYCACHE_BLOCK_SIZE 16384 /* root_alloc flags */ #define MY_KEEP_PREALLOC 1 @@ -190,9 +191,10 @@ extern char *get_charsets_dir(char *buf); /* statistics */ extern ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests, _my_cache_read; -extern ulong _my_blocks_used,_my_blocks_changed; +extern ulong _my_blocks_used,_my_blocks_changed; +extern uint key_cache_block_size; extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; -extern my_bool key_cache_inited; +extern my_bool key_cache_inited, my_init_done; /* Point to current my_message() */ extern void (*my_sigtstp_cleanup)(void), @@ -602,6 +604,7 @@ my_bool my_compress(byte *, ulong *, ulong *); my_bool my_uncompress(byte *, ulong *, ulong *); byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen); ulong checksum(const byte *mem, uint count); +uint my_bit_log2(ulong value); #if defined(_MSC_VER) && !defined(__WIN__) extern void sleep(int sec); diff --git a/include/myisam.h b/include/myisam.h index 78dbfd62cbe..36c0de5034f 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -46,6 +46,11 @@ extern "C" { /* Max extra space to use when sorting keys */ #define MI_MAX_TEMP_LENGTH 256*1024L*1024L +/* Possible values for myisam_block_size (must be power of 2) */ +#define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ +#define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ +#define MI_MAX_KEY_BLOCK_LENGTH 16384 + #define mi_portable_sizeof_char_ptr 8 typedef uint32 ha_checksum; @@ -192,7 +197,7 @@ extern uint myisam_block_size; extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; extern my_bool myisam_concurrent_insert; extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length; -extern uint myisam_bulk_insert_tree_size; +extern ulong myisam_bulk_insert_tree_size; /* Prototypes for myisam-functions */ diff --git a/include/mysql.h b/include/mysql.h index 7867dea2c31..a82a35efc4b 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -26,11 +26,9 @@ #undef __WIN__ #endif -#ifndef MYSQL_SERVER #ifdef __cplusplus extern "C" { #endif -#endif #ifndef _global_h /* If not standard header */ #include <sys/types.h> @@ -229,7 +227,7 @@ typedef struct st_mysql_res { /* Set up and bring down the server; to ensure that applications will * work when linked against either the standard client library or the * embedded server library, these functions should be called. */ -void mysql_server_init(int argc, const char **argv, const char **groups); +int mysql_server_init(int argc, const char **argv, const char **groups); void mysql_server_end(); /* Set up and bring down a thread; these function should be called @@ -382,10 +380,8 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); #define HAVE_MYSQL_REAL_CONNECT -#ifndef MYSQL_SERVER #ifdef __cplusplus } #endif -#endif -#endif +#endif /* _mysql_h */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 5924a4f13c2..c25e213f16b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -91,10 +91,12 @@ static sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); -void mysql_server_init(int argc __attribute__((unused)), +int mysql_server_init(int argc __attribute__((unused)), const char **argv __attribute__((unused)), const char **groups __attribute__((unused))) -{} +{ + return 0; +} void mysql_server_end() {} diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 1f0b15d15b6..e39cebff04a 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -39,6 +39,8 @@ libmysqlsources = errmsg.c get_password.c password.c ## XXX: we should not have to duplicate info from the sources list libmysqlobjects = errmsg.lo get_password.lo password.lo +noinst_HEADERS = embedded_priv.h + sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ ha_innobase.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \ diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h new file mode 100644 index 00000000000..96d2c96ed0b --- /dev/null +++ b/libmysqld/embedded_priv.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Prototypes for the embedded version of MySQL */ + +#include <my_global.h> +#include <mysql_embed.h> +#include <mysql.h> +#include <mysql_version.h> +#include <mysqld_error.h> +#include <my_pthread.h> + +C_MODE_START +extern void start_embedded_connection(NET * net); +extern void end_embedded_connection(NET * net); +extern void lib_connection_phase(NET *net, int phase); +extern bool lib_dispatch_command(enum enum_server_command command, NET *net, + const char *arg, ulong length); +C_MODE_END diff --git a/libmysqld/examples/test-run b/libmysqld/examples/test-run index 1e15126b126..58c21349519 100755 --- a/libmysqld/examples/test-run +++ b/libmysqld/examples/test-run @@ -43,6 +43,7 @@ usage: $0 [-g|-h|-r] [test-name ...] EOF } +init_args="" while test $# -gt 0 do arg= @@ -56,6 +57,7 @@ do -h | --help | -\? ) usage; exit 0;; -l | --list ) list=1 ; shift ;; -r | --run ) run="${cr}run"; shift;; + --debug) init_args="$init_args --debug" ; shift ;; -s | --start=* ) test $argset -eq 0 && { shift; arg="$1"; } start="$arg" @@ -103,7 +105,7 @@ do echo "test '$b' doesn't exist" >&2 continue } - args="-v -S /tmp/mysql.sock -R $r -x $t test" + args="$init_args -v -S /tmp/mysql.sock -R $r -x $t test" echo "set args $args$run" > test-gdbinit #if false && test -n "$run" if test -n "$run" -o $gdb -eq 1 diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index f2599fe4016..5641e920c9d 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -12,9 +12,7 @@ * modified is included with the above copyright notice. * */ -#include "my_global.h" -#include "mysql_embed.h" -#include "my_pthread.h" +#include "embedded_priv.h" #include "sys/types.h" #include "../regex/regex.h" #include "my_sys.h" @@ -47,13 +45,11 @@ static bool check_user(THD *thd, enum_server_command command, void free_defaults_internal(char ** argv) {if (argv) free_defaults(argv);} #define free_defaults free_defaults_internal -char mysql_data_home[FN_REFLEN]; -char * get_mysql_data_home() { return mysql_data_home; } -#define mysql_data_home mysql_data_home_internal #include "../sql/mysqld.cc" #define SCRAMBLE_LENGTH 8 -extern "C" { +C_MODE_START + char * get_mysql_home(){ return mysql_home;}; char * get_mysql_real_data_home(){ return mysql_real_data_home;}; @@ -85,7 +81,7 @@ void lib_connection_phase(NET * net, int phase) } } } -} /* extern "C" */ +C_MODE_END void start_embedded_conn1(NET * net) @@ -105,7 +101,6 @@ void start_embedded_conn1(NET * net) if (v) { v -> dest_thd = thd; - /* v -> dest_net = &thd->net; XXX: Probably not needed? */ } thd->net.vio = v; if (thd->store_globals()) @@ -296,10 +291,14 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, } -extern "C"{ -void mysql_server_init(int argc, const char **argv, const char **groups) +extern "C" +{ + +static my_bool inited, org_my_init_done; + +int mysql_server_init(int argc, const char **argv, const char **groups) { - char hostname[FN_REFLEN]; + char glob_hostname[FN_REFLEN]; /* This mess is to allow people to call the init function without * having to mess with a fake argv */ @@ -323,7 +322,16 @@ void mysql_server_init(int argc, const char **argv, const char **groups) my_umask=0660; // Default umask for new files my_umask_dir=0700; // Default umask for new directories - MY_INIT((char *)"mysqld_server"); // init my_sys library & pthreads + + /* Only call MY_INIT() if it hasn't been called before */ + if (!inited) + { + inited=1; + org_my_init_done=my_init_done; + } + if (!org_my_init_done) + MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads + tzset(); // Set tzname start_time=time((time_t*) 0); @@ -332,49 +340,34 @@ void mysql_server_init(int argc, const char **argv, const char **groups) { struct tm tm_tmp; localtime_r(&start_time,&tm_tmp); - strmov(time_zone,tzname[tm_tmp.tm_isdst == 1 ? 1 : 0]); + strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]); } #else { struct tm *start_tm; start_tm=localtime(&start_time); - strmov(time_zone=tzname[start_tm->tm_isdst == 1 ? 1 : 0]); + strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]); } #endif #endif - if (gethostname(hostname,sizeof(hostname)-4) < 0) - strmov(hostname,"mysql"); - strmov(pidfile_name,hostname); - strmov(strcend(pidfile_name,'.'),".pid"); // Add extension -#ifdef DEMO_VERSION - strcat(server_version,"-demo"); -#endif -#ifdef SHAREWARE_VERSION - strcat(server_version,"-shareware"); -#endif + if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) + strmov(glob_hostname,"mysql"); #ifndef DBUG_OFF strcat(server_version,"-debug"); #endif - strcat(server_version,"-library-ver"); -#ifdef _CUSTOMSTARTUPCONFIG_ - if (_cust_check_startup()) - { - /* _cust_check_startup will report startup failure error */ - exit( 1 ); - } -#endif + strcat(server_version,"-embedded"); load_defaults("my", groups, argcp, argvp); defaults_argv=*argvp; mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */ -#ifdef __WIN__ +#if defined( __WIN__) || defined(OS2) if (!mysql_tmpdir) mysql_tmpdir=getenv("TEMP"); if (!mysql_tmpdir) mysql_tmpdir=getenv("TMP"); #endif if (!mysql_tmpdir || !mysql_tmpdir[0]) - mysql_tmpdir=strdup((char*) P_tmpdir); + mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */ set_options(); get_options(*argcp, *argvp); @@ -415,23 +408,20 @@ void mysql_server_init(int argc, const char **argv, const char **groups) (void) pthread_cond_init(&COND_slave_start, NULL); if (set_default_charset_by_name(default_charset, MYF(MY_WME))) - unireg_abort(1); + { + mysql_server_end(); + return 1; + } charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS)); - - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),CONNECT_PRIOR); /* Parameter for threads created for connections */ (void) pthread_attr_init(&connection_attrib); (void) pthread_attr_setdetachstate(&connection_attrib, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&connection_attrib,thread_stack); - - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR); pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM); -#ifdef SET_RLIMIT_NOFILE +#if defined( SET_RLIMIT_NOFILE) || defined( OS2) /* connections and databases neads lots of files */ { uint wanted_files=10+(uint) max(max_connections*5, @@ -456,64 +446,57 @@ void mysql_server_init(int argc, const char **argv, const char **groups) #ifdef USE_REGEX regex_init(); #endif - select_thread=pthread_self(); - select_thread_in_use=1; + if (use_temp_pool && bitmap_init(&temp_pool,1024)) + { + mysql_server_end(); + return 1; + } /* ** We have enough space for fiddling with the argv, continue */ umask(((~my_umask) & 0666)); -// strcpy(mysql_real_data_home, "/usr/local"); - //if (my_setwd(mysql_real_data_home,MYF(MY_WME))) - //{ - // unireg_abort(1); /* purecov: inspected */ - //} - //mysql_data_home[0]=FN_CURLIB; // all paths are relative from here - //mysql_data_home[1]=0; - - strcpy(get_mysql_data_home(), mysql_real_data_home); - - //server_init(); table_cache_init(); hostname_cache_init(); sql_cache_init(); randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2); reset_floating_point_exceptions(); init_thr_lock(); + init_slave_list(); /* Setup log files */ if (opt_log) - open_log(&mysql_log, hostname, opt_logname, ".log", LOG_NORMAL); + open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL); if (opt_update_log) - open_log(&mysql_update_log, hostname, opt_update_logname, "", + { + open_log(&mysql_update_log, glob_hostname, opt_update_logname, "", LOG_NEW); + using_update_log=1; + } if (opt_bin_log) { - if(server_id) - { - if (!opt_bin_logname) - { - char tmp[FN_REFLEN]; - strnmov(tmp,hostname,FN_REFLEN-5); - strmov(strcend(tmp,'.'),"-bin"); - opt_bin_logname=my_strdup(tmp,MYF(MY_WME)); - } - mysql_bin_log.set_index_file_name(opt_binlog_index_name); - open_log(&mysql_bin_log, hostname, opt_bin_logname, "-bin", - LOG_BIN); - } - else - sql_print_error("Server id is not set - binary logging disabled"); + if (!opt_bin_logname) + { + char tmp[FN_REFLEN]; + strmake(tmp,glob_hostname,FN_REFLEN-5); + strmov(strcend(tmp,'.'),"-bin"); + opt_bin_logname=my_strdup(tmp,MYF(MY_WME)); + } + mysql_bin_log.set_index_file_name(opt_binlog_index_name); + open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", + LOG_BIN); + using_update_log=1; } if (opt_slow_log) - open_log(&mysql_slow_log, hostname, opt_slow_logname, "-slow.log", + open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log", LOG_NORMAL); if (ha_init()) { sql_print_error("Can't init databases"); exit(1); } + ha_key_cache(); #ifdef HAVE_MLOCKALL if (locked_in_memory && !geteuid()) { @@ -544,105 +527,61 @@ void mysql_server_init(int argc, const char **argv, const char **groups) sql_print_error("Can't create thread-keys"); exit(1); } - //init_signals(); - opt_noacl = 1; + opt_noacl = 1; // No permissions if (acl_init(opt_noacl)) { - select_thread_in_use=0; - (void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL); - exit(1); + mysql_server_end(); + return 1; } - if (!opt_noacl) - (void) grant_init(); #ifdef HAVE_DLOPEN if (!opt_noacl) udf_init(); #endif - if (opt_bootstrap) - { - int error=bootstrap(stdin); - end_thr_alarm(); // Don't allow alarms - unireg_abort(error ? 1 : 0); - } - if (opt_init_file) - { - if (read_init_file(opt_init_file)) - { - end_thr_alarm(); // Don't allow alarms - unireg_abort(1); - } - } (void) thr_setconcurrency(concurrency); // 10 by default - if (flush_time && flush_time != ~(ulong) 0L) + if ( +#ifdef HAVE_BERKELEY_DB + !berkeley_skip || +#endif + (flush_time && flush_time != ~(ulong) 0L)) { pthread_t hThread; if (pthread_create(&hThread,&connection_attrib,handle_manager,0)) + { sql_print_error("Warning: Can't create thread to manage maintenance"); + mysql_server_end(); + return 1; + } } - - // slave thread - if(master_host) - { - if(server_id) - { - pthread_t hThread; - if(!opt_skip_slave_start && - pthread_create(&hThread, &connection_attrib, handle_slave, 0)) - sql_print_error("Warning: Can't create thread to handle slave"); - } - else - sql_print_error("Server id is not set, slave thread will not be started"); - } - - //printf(ER(ER_READY),my_progname,server_version,""); - //printf("%s initialized.\n", server_version); - fflush(stdout); + return 0; } + void mysql_server_end() { - /* (void) pthread_attr_destroy(&connection_attrib); */ - - DBUG_PRINT("quit",("Exiting main thread")); - -#ifdef EXTRA_DEBUG - sql_print_error("Before Lock_thread_count"); -#endif - (void) pthread_mutex_lock(&LOCK_thread_count); - select_thread_in_use=0; // For close_connections - (void) pthread_cond_broadcast(&COND_thread_count); - (void) pthread_mutex_unlock(&LOCK_thread_count); -#ifdef EXTRA_DEBUG - sql_print_error("After lock_thread_count"); + clean_up(0); +#ifdef THREAD + /* Don't call my_thread_end() if the application is using MY_INIT() */ + if (!org_my_init_done) + my_thread_end(); #endif - -// /* Wait until cleanup is done */ -// (void) pthread_mutex_lock(&LOCK_thread_count); -// while (!ready_to_exit) -// { -// pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); -// } -// (void) pthread_mutex_unlock(&LOCK_thread_count); - unireg_end(0); - my_thread_end(); } my_bool mysql_thread_init() { #ifdef THREAD - return my_thread_init(); + return my_thread_init(); #else - return 0; + return 0; #endif } void mysql_thread_end() { #ifdef THREAD - my_thread_end(); + my_thread_end(); #endif } @@ -651,11 +590,10 @@ void start_embedded_connection(NET * net) start_embedded_conn1(net); } -} /* extern "C" */ - -int embedded_do_command(NET * net) +void end_embedded_connection(NET * net) { - THD * thd = (THD *) net ->vio; - do_command(thd); - return 0; + THD *thd = (THD *) net->vio->dest_thd; + delete thd; } + +} /* extern "C" */ diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 8931bc3cd48..c6860098ed8 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -15,15 +15,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#include <my_global.h> -#if defined(__WIN__) || defined(_WIN32) || defined(_WIN64) -#include <winsock.h> -#include <odbcinst.h> -#endif -#include "mysql_embed.h" -#include "mysql.h" -#include "mysql_version.h" -#include "mysqld_error.h" +#include "embedded_priv.h" #include <my_sys.h> #include <mysys_err.h> #include <m_string.h> @@ -51,9 +43,6 @@ #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif -#if defined(THREAD) && !defined(__WIN__) -#include <my_pthread.h> /* because of signal() */ -#endif #ifndef INADDR_NONE #define INADDR_NONE -1 #endif @@ -74,12 +63,6 @@ my_string mysql_unix_port=0; #define closesocket(A) close(A) #endif -/* XXX: this is real ugly... */ -extern void start_embedded_connection(NET * net); -extern void lib_connection_phase(NET *net, int phase); -extern bool lib_dispatch_command(enum enum_server_command command, NET *net, - const char *arg, ulong length); - static void mysql_once_init(void); static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields, uint field_count); @@ -89,7 +72,6 @@ static void end_server(MYSQL *mysql); static void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); static int send_file_to_server(MYSQL *mysql,const char *filename); -static sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); @@ -402,22 +384,6 @@ mysql_debug(const char *debug) #endif } - -/************************************************************************** -** Close the server connection if we get a SIGPIPE - ARGSUSED -**************************************************************************/ - -static sig_handler -pipe_sig_handler(int sig __attribute__((unused))) -{ - DBUG_PRINT("info",("Hit by signal %d",sig)); -#ifdef DONT_REMEMBER_SIGNAL - (void) signal(SIGPIPE,pipe_sig_handler); -#endif -} - - /************************************************************************** ** Shut down connection **************************************************************************/ @@ -428,11 +394,7 @@ end_server(MYSQL *mysql) DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { - init_sigpipe_variables - DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); - set_sigpipe(mysql); - vio_delete(mysql->net.vio); - reset_sigpipe(mysql); + end_embedded_connection(&mysql->net); mysql->net.vio= 0; /* Marker */ } net_end(&mysql->net); diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index ef248b5d62b..8f3138af989 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -173,7 +173,7 @@ int do_boolean(ALL_IN_ONE *aio, uint nested __attribute__((unused)), aio->key_root); else r=_mi_search(aio->info, aio->keyinfo, aio->info->lastkey, - aio->info->lastkey_length, SEARCH_BIGGER, + USE_WHOLE_KEY, SEARCH_BIGGER, aio->key_root); } break; diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c index 350a60708f6..644becb27ab 100644 --- a/myisam/ft_nlq_search.c +++ b/myisam/ft_nlq_search.c @@ -126,7 +126,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) aio->key_root); else r=_mi_search(aio->info, aio->keyinfo, aio->info->lastkey, - aio->info->lastkey_length, SEARCH_BIGGER, + USE_WHOLE_KEY, SEARCH_BIGGER, aio->key_root); } if(doc_cnt) { diff --git a/myisam/ft_search.c b/myisam/ft_search.c index c5a43734d9a..6970fa2835d 100644 --- a/myisam/ft_search.c +++ b/myisam/ft_search.c @@ -34,7 +34,7 @@ FT_DOCLIST *ft_init_search(void *info, uint keynr, byte *query, /* black magic ON */ if ((int) (keynr = _mi_check_index((MI_INFO *)info,keynr)) < 0) return NULL; - if (_mi_readinfo((MI_INFO *)info,F_RDLCK,1)) + if (fast_mi_readinfo((MI_INFO *) info)) return NULL; /* black magic OFF */ diff --git a/myisam/mi_changed.c b/myisam/mi_changed.c index bd6b14b0c6c..5b9003798b0 100644 --- a/myisam/mi_changed.c +++ b/myisam/mi_changed.c @@ -24,7 +24,7 @@ int mi_is_changed(MI_INFO *info) { int result; DBUG_ENTER("mi_is_changed"); - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(-1); VOID(_mi_writeinfo(info,0)); result=(int) info->data_changed; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 4ea52c1b565..656e6aa995f 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -231,7 +231,7 @@ wrong: static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) { my_off_t next_link; - uint block_size=(nr+1)*MI_KEY_BLOCK_LENGTH; + uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH; ha_rows records; char llbuff[21],*buff; DBUG_ENTER("check_k_link"); @@ -1205,8 +1205,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, param->glob_crc=0; if (param->testflag & T_CALC_CHECKSUM) param->calc_checksum=1; - if (!rep_quick) - share->state.checksum=0; info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); for (i=0 ; i < info->s->base.keys ; i++) @@ -1301,9 +1299,9 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, else { info->state->data_file_length=sort_info->max_pos; - if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; } + if (param->testflag & T_CALC_CHECKSUM) + share->state.checksum=param->glob_crc; if (!(param->testflag & T_SILENT)) { @@ -1886,8 +1884,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->glob_crc=0; if (param->testflag & T_CALC_CHECKSUM) param->calc_checksum=1; - if (! rep_quick) - share->state.checksum=0; rec_per_key_part= param->rec_per_key_part; for (sort_info->key=0 ; sort_info->key < share->base.keys ; @@ -2018,7 +2014,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, "Can't change size of datafile, error: %d", my_errno); } - else if (param->testflag & T_CALC_CHECKSUM) + if (param->testflag & T_CALC_CHECKSUM) share->state.checksum=param->glob_crc; if (my_chsize(share->kfile,info->state->key_file_length,MYF(0))) @@ -2115,6 +2111,7 @@ static int sort_key_read(SORT_INFO *sort_info, void *key) DBUG_RETURN(sort_write_record(sort_info)); } /* sort_key_read */ + static int sort_ft_key_read(SORT_INFO *sort_info, void *key) { int error; @@ -2540,7 +2537,7 @@ int sort_write_record(SORT_INFO *sort_info) DBUG_RETURN(1); } sort_info->filepos+=share->base.pack_reclength; - info->s->state.checksum+=mi_static_checksum(info, sort_info->record); + /* sort_info->param->glob_crc+=mi_static_checksum(info, sort_info->record); */ break; case DYNAMIC_RECORD: if (! info->blobs) @@ -2564,7 +2561,7 @@ int sort_write_record(SORT_INFO *sort_info) } info->checksum=mi_checksum(info,sort_info->record); reclength=_mi_rec_pack(info,from,sort_info->record); - info->s->state.checksum+=info->checksum; + /* sort_info->param->glob_crc+=info->checksum; */ block_length=reclength+ 3 + test(reclength >= (65520-3)); if (block_length < share->base.min_block_length) block_length=share->base.min_block_length; @@ -2578,7 +2575,7 @@ int sort_write_record(SORT_INFO *sort_info) DBUG_RETURN(1); } sort_info->filepos+=block_length; - info->s->state.checksum+=info->checksum; + /* sort_info->param->glob_crc+=info->checksum; */ break; case COMPRESSED_RECORD: reclength=info->packed_length; @@ -2591,7 +2588,7 @@ int sort_write_record(SORT_INFO *sort_info) mi_check_print_error(param,"%d when writing to datafile",my_errno); DBUG_RETURN(1); } - info->s->state.checksum+=info->checksum; + /* sort_info->param->glob_crc+=info->checksum; */ sort_info->filepos+=reclength+length; break; } @@ -2808,9 +2805,9 @@ static int sort_delete_record(MI_CHECK *param) DBUG_RETURN(1); } } - if (info->s->calc_checksum) - info->s->state.checksum-=(*info->s->calc_checksum)(info, - sort_info->record); + if (param->calc_checksum) + param->glob_crc-=(*info->s->calc_checksum)(info, + sort_info->record); } error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info); info->dfile=old_file; /* restore actual value */ diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 7033cd59639..aad0300c978 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -227,8 +227,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.state.key_del=key_del; if (uniques) { - max_key_block_length= MI_KEY_BLOCK_LENGTH; - max_key_length= MI_UNIQUE_HASH_LENGTH; + max_key_block_length= myisam_block_size; + max_key_length= MI_UNIQUE_HASH_LENGTH; } for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) @@ -370,7 +370,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE); - if (keydef->block_length/MI_KEY_BLOCK_LENGTH > MI_MAX_KEY_BLOCK_SIZE) + if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH) { my_errno=HA_WRONG_CREATE_OPTION; goto err; @@ -386,7 +386,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, (length*2)))* (ulong) keydef->block_length; } - for (i=max_key_block_length/MI_KEY_BLOCK_LENGTH ; i-- ; ) + for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) key_del[i]=HA_OFFSET_ERROR; unique_key_parts=0; @@ -401,7 +401,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, key_segs+=uniques; /* Each unique has 1 key seg */ base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE + - max_key_block_length/MI_KEY_BLOCK_LENGTH*MI_STATE_KEYBLOCK_SIZE+ + max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH* + MI_STATE_KEYBLOCK_SIZE+ key_segs*MI_STATE_KEYSEG_SIZE); info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+ keys * MI_KEYDEF_SIZE+ @@ -420,7 +421,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, mi_int2store(share.state.header.base_pos,base_pos); share.state.header.language= (ci->language ? ci->language : MY_CHARSET_CURRENT); - share.state.header.max_block_size=max_key_block_length/MI_KEY_BLOCK_LENGTH; + share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH; share.state.dellink = HA_OFFSET_ERROR; share.state.process= (ulong) getpid(); @@ -433,7 +434,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.base.rec_reflength=pointer; share.base.key_reflength= mi_get_pointer_length((tot_length + max_key_block_length * keys * - MI_INDEX_BLOCK_MARGIN) / MI_KEY_BLOCK_LENGTH, + MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH, 3); share.base.keys= share.state.header.keys = keys; share.state.header.uniques= uniques; @@ -575,7 +576,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, { tmp_keydef.keysegs=1; tmp_keydef.flag= HA_UNIQUE_CHECK; - tmp_keydef.block_length= MI_KEY_BLOCK_LENGTH; + tmp_keydef.block_length= myisam_block_size; tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer; tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength; tmp_keyseg.type= MI_UNIQUE_HASH_TYPE; diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 445e745b07d..65d245e64f9 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -196,7 +196,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, DBUG_ENTER("d_search"); DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff)); - flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,key_length,SEARCH_SAME, + flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, USE_WHOLE_KEY, + SEARCH_SAME, &keypos, lastkey, &last_key); if (flag == MI_FOUND_WRONG_KEY) { diff --git a/myisam/mi_delete_all.c b/myisam/mi_delete_all.c index 2c506da865f..6467246e779 100644 --- a/myisam/mi_delete_all.c +++ b/myisam/mi_delete_all.c @@ -43,7 +43,7 @@ int mi_delete_all_rows(MI_INFO *info) info->state->empty=info->state->key_empty=0; state->checksum=0; - for (i=share->base.max_key_block_length/MI_KEY_BLOCK_LENGTH ; i-- ; ) + for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) state->key_del[i]= HA_OFFSET_ERROR; for (i=0 ; i < share->base.keys ; i++) state->key_root[i]= HA_OFFSET_ERROR; diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index c9fe493744d..c07fa5aa080 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1059,11 +1059,11 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) } while (left_length); info->update|= HA_STATE_AKTIV; /* We have a aktive record */ - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); DBUG_RETURN(_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) != MY_FILE_ERROR ? 0 : -1); } - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); DBUG_RETURN(-1); /* Wrong data to read */ panic: @@ -1393,8 +1393,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, } while (left_len); info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - if (share->r_locks == 0 && share->w_locks == 0) - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) != MY_FILE_ERROR) DBUG_RETURN(0); diff --git a/myisam/mi_info.c b/myisam/mi_info.c index 867718de326..c55707ea00c 100644 --- a/myisam/mi_info.c +++ b/myisam/mi_info.c @@ -45,7 +45,7 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag) { pthread_mutex_lock(&share->intern_lock); VOID(_mi_readinfo(info,F_RDLCK,0)); - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); pthread_mutex_unlock(&share->intern_lock); } if (flag & HA_STATUS_VARIABLE) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 9f4e2cb1524..67772c250ac 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -346,7 +346,7 @@ err: int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf) { - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); if (filepos != HA_OFFSET_ERROR) { if (info->lastinx >= 0) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 8ef5db1d344..b8ffc300fa9 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -50,6 +50,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) count= --share->r_locks; else count= --share->w_locks; + --share->tot_locks; if (info->lock_type == F_WRLCK && !share->w_locks && !share->delay_key_write && flush_key_blocks(share->kfile,FLUSH_KEEP)) { @@ -153,6 +154,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) } VOID(_mi_test_if_changed(info)); share->r_locks++; + share->tot_locks++; info->lock_type=lock_type; break; case F_WRLCK: @@ -200,6 +202,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) VOID(_mi_test_if_changed(info)); info->lock_type=lock_type; share->w_locks++; + share->tot_locks++; break; default: break; /* Impossible */ @@ -295,13 +298,12 @@ my_bool mi_check_status(void* param) int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer) { - MYISAM_SHARE *share; DBUG_ENTER("_mi_readinfo"); - share=info->s; if (info->lock_type == F_UNLCK) { - if (!share->r_locks && !share->w_locks) + MYISAM_SHARE *share=info->s; + if (!share->tot_locks) { if ((info->tmp_lock_type=lock_type) != F_RDLCK) if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, @@ -339,7 +341,7 @@ int _mi_writeinfo(register MI_INFO *info, uint operation) DBUG_ENTER("_mi_writeinfo"); error=0; - if (share->r_locks == 0 && share->w_locks == 0) + if (share->tot_locks == 0) { olderror=my_errno; /* Remember last error */ if (operation) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index c34f2aa43f4..675dac38d41 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -217,7 +217,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) (mi_safe_mul(share->base.reclength, (ulonglong) 1 << (share->base.rec_reflength*8))-1); max_key_file_length= - mi_safe_mul(MI_KEY_BLOCK_LENGTH, + mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH, ((ulonglong) 1 << (share->base.key_reflength*8))-1); #if SIZEOF_OFF_T == 4 set_if_smaller(max_data_file_length, INT_MAX32); @@ -913,7 +913,7 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef) keydef->keylength = mi_uint2korr(ptr); ptr +=2; keydef->minlength = mi_uint2korr(ptr); ptr +=2; keydef->maxlength = mi_uint2korr(ptr); ptr +=2; - keydef->block_size = keydef->block_length/MI_KEY_BLOCK_LENGTH-1; + keydef->block_size = keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1; keydef->underflow_block_length=keydef->block_length/3; keydef->version = 0; /* Not saved */ return ptr; diff --git a/myisam/mi_page.c b/myisam/mi_page.c index f8e2a977754..d62970c7d98 100644 --- a/myisam/mi_page.c +++ b/myisam/mi_page.c @@ -64,9 +64,9 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, #ifndef FAST /* Safety check */ if (page < info->s->base.keystart || page+keyinfo->block_length > info->state->key_file_length || - page & (myisam_block_size-1)) + (page & (MI_MIN_KEY_BLOCK_LENGTH-1))) { - DBUG_PRINT("error",("Trying to write outside key region: %lu", + DBUG_PRINT("error",("Trying to write inside key status region: %lu", (long) page)); my_errno=EINVAL; return(-1); diff --git a/myisam/mi_range.c b/myisam/mi_range.c index 038f9abc3a6..6bf3356e449 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -45,7 +45,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key, if ((inx = _mi_check_index(info,inx)) < 0) DBUG_RETURN(HA_POS_ERROR); - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(HA_POS_ERROR); info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED); if (info->s->concurrent_insert) @@ -58,7 +58,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key, info->state->records+ (ha_rows) 1); if (info->s->concurrent_insert) rw_unlock(&info->s->key_root_lock[inx]); - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR) DBUG_RETURN(HA_POS_ERROR); DBUG_PRINT("info",("records: %ld",(ulong) (end_pos-start_pos))); @@ -72,7 +72,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key, static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, enum ha_rkey_function search_flag) { - uint inx=(uint) info->lastinx; + uint inx=(uint) info->lastinx, nextflag; MI_KEYDEF *keyinfo=info->s->keyinfo+inx; uchar *key_buff; double pos; @@ -86,8 +86,12 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg, (uchar*) key_buff,key_len);); + nextflag=myisam_read_vec[search_flag]; + if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) + key_len=USE_WHOLE_KEY; + pos=_mi_search_pos(info,keyinfo,key_buff,key_len, - myisam_read_vec[search_flag] | SEARCH_SAVE_BUFF, + nextflag | SEARCH_SAVE_BUFF, info->s->state.key_root[inx]); if (pos >= 0.0) { @@ -145,9 +149,9 @@ static double _mi_search_pos(register MI_INFO *info, ** Matches keynr+1 */ offset=1.0; /* Matches keynr+1 */ - if (nextflag & SEARCH_FIND && + if ((nextflag & SEARCH_FIND) && nod_flag && ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME || - key_len) && nod_flag) + key_len != USE_WHOLE_KEY)) { /* ** There may be identical keys in the tree. Try to match on of those. diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 0df390412b9..86547d3ef04 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -27,7 +27,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, { uchar *key_buff; MYISAM_SHARE *share=info->s; - uint pack_key_length; + uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", info,inx,search_flag)); @@ -55,11 +55,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, bmove(key_buff,key,key_len); } - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) goto err; if (share->concurrent_insert) rw_rdlock(&share->key_root_lock[inx]); - if (!_mi_search(info,info->s->keyinfo+inx,key_buff,pack_key_length, + + nextflag=myisam_read_vec[search_flag]; + use_key_length=pack_key_length; + if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) + use_key_length=USE_WHOLE_KEY; + + if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length, myisam_read_vec[search_flag],info->s->state.key_root[inx])) { while (info->lastpos >= info->state->data_file_length) diff --git a/myisam/mi_rnext.c b/myisam/mi_rnext.c index f297740af60..6d135462f96 100644 --- a/myisam/mi_rnext.c +++ b/myisam/mi_rnext.c @@ -35,7 +35,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx) if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_PREV_FOUND) flag=0; /* Read first */ - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(my_errno); if (info->s->concurrent_insert) rw_rdlock(&info->s->key_root_lock[inx]); @@ -51,7 +51,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx) info->s->state.key_root[inx]); else error=_mi_search(info,info->s->keyinfo+inx,info->lastkey, - info->lastkey_length,flag, info->s->state.key_root[inx]); + USE_WHOLE_KEY,flag, info->s->state.key_root[inx]); if (!error) { diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c index 0e172894cdf..44943ea9137 100644 --- a/myisam/mi_rnext_same.c +++ b/myisam/mi_rnext_same.c @@ -35,7 +35,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf) DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); keyinfo=info->s->keyinfo+inx; flag=SEARCH_BIGGER; /* Read next */ - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(my_errno); memcpy(info->lastkey2,info->lastkey,info->last_rkey_length); diff --git a/myisam/mi_rprev.c b/myisam/mi_rprev.c index fff2d2257b6..4807e636252 100644 --- a/myisam/mi_rprev.c +++ b/myisam/mi_rprev.c @@ -36,7 +36,7 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx) if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_NEXT_FOUND) flag=0; /* Read last */ - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(my_errno); changed=_mi_test_if_changed(info); if (share->concurrent_insert) @@ -50,7 +50,7 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx) share->state.key_root[inx]); else error=_mi_search(info,share->keyinfo+inx,info->lastkey, - info->lastkey_length, flag, share->state.key_root[inx]); + USE_WHOLE_KEY, flag, share->state.key_root[inx]); if (!error) { diff --git a/myisam/mi_rsame.c b/myisam/mi_rsame.c index a4092b53c0b..511c247760e 100644 --- a/myisam/mi_rsame.c +++ b/myisam/mi_rsame.c @@ -41,7 +41,7 @@ int mi_rsame(MI_INFO *info, byte *record, int inx) info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); /* Read row from data file */ - if (_mi_readinfo(info,F_RDLCK,1)) + if (fast_mi_readinfo(info)) DBUG_RETURN(my_errno); if (inx >= 0) @@ -51,7 +51,8 @@ int mi_rsame(MI_INFO *info, byte *record, int inx) info->lastpos); if (info->s->concurrent_insert) rw_rdlock(&info->s->key_root_lock[inx]); - VOID(_mi_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME, + VOID(_mi_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY, + SEARCH_SAME, info->s->state.key_root[inx])); if (info->s->concurrent_insert) rw_unlock(&info->s->key_root_lock[inx]); diff --git a/myisam/mi_search.c b/myisam/mi_search.c index b9895e9d6cd..96ddd9d789d 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -107,14 +107,15 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, } else { - if (nextflag & SEARCH_FIND && (!(keyinfo->flag & HA_NOSAME) - || key_len) && nod_flag) + if ((nextflag & SEARCH_FIND) && nod_flag && + ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME || + key_len != USE_WHOLE_KEY)) { if ((error=_mi_search(info,keyinfo,key,key_len,SEARCH_FIND, _mi_kpos(nod_flag,keypos))) >= 0 || my_errno != HA_ERR_KEY_NOT_FOUND) DBUG_RETURN(error); - info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in memory */ + info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */ } } if (pos != info->last_keypage) @@ -283,8 +284,6 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, LINT_INIT(saved_vseg); t_buff[0]=0; /* Avoid bugs */ - if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) - key_len=USE_WHOLE_KEY; end= page+mi_getint(page); nod_flag=mi_test_if_nod(page); page+=2+nod_flag; @@ -477,11 +476,11 @@ my_off_t _mi_kpos(uint nod_flag, uchar *after_key) switch (nod_flag) { #if SIZEOF_OFF_T > 4 case 7: - return mi_uint7korr(after_key)*MI_KEY_BLOCK_LENGTH; + return mi_uint7korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH; case 6: - return mi_uint6korr(after_key)*MI_KEY_BLOCK_LENGTH; + return mi_uint6korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH; case 5: - return mi_uint5korr(after_key)*MI_KEY_BLOCK_LENGTH; + return mi_uint5korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH; #else case 7: after_key++; @@ -491,13 +490,13 @@ my_off_t _mi_kpos(uint nod_flag, uchar *after_key) after_key++; #endif case 4: - return ((my_off_t) mi_uint4korr(after_key))*MI_KEY_BLOCK_LENGTH; + return ((my_off_t) mi_uint4korr(after_key))*MI_MIN_KEY_BLOCK_LENGTH; case 3: - return ((my_off_t) mi_uint3korr(after_key))*MI_KEY_BLOCK_LENGTH; + return ((my_off_t) mi_uint3korr(after_key))*MI_MIN_KEY_BLOCK_LENGTH; case 2: - return (my_off_t) (mi_uint2korr(after_key)*MI_KEY_BLOCK_LENGTH); + return (my_off_t) (mi_uint2korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH); case 1: - return (uint) (*after_key)*MI_KEY_BLOCK_LENGTH; + return (uint) (*after_key)*MI_MIN_KEY_BLOCK_LENGTH; case 0: /* At leaf page */ default: /* Impossible */ return(HA_OFFSET_ERROR); @@ -509,7 +508,7 @@ my_off_t _mi_kpos(uint nod_flag, uchar *after_key) void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos) { - pos/=MI_KEY_BLOCK_LENGTH; + pos/=MI_MIN_KEY_BLOCK_LENGTH; switch (info->s->base.key_reflength) { #if SIZEOF_OFF_T > 4 case 7: mi_int7store(buff,pos); break; @@ -719,10 +718,7 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a, double d_1,d_2; uint next_key_length; - if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) - key_length=USE_WHOLE_KEY; *diff_pos=0; - for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++) { uchar *end; @@ -1446,7 +1442,7 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, info->page_changed || (info->int_keytree_version != keyinfo->version && (info->int_nod_flag || info->buff_used))) - DBUG_RETURN(_mi_search(info,keyinfo,key,key_length, + DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, pos)); if (info->buff_used) @@ -1459,17 +1455,17 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, /* Last used buffer is in info->buff */ nod_flag=mi_test_if_nod(info->buff); - memcpy(lastkey,key,key_length); if (nextflag & SEARCH_BIGGER) /* Next key */ { my_off_t tmp_pos=_mi_kpos(nod_flag,info->int_keypos); if (tmp_pos != HA_OFFSET_ERROR) { - if ((error=_mi_search(info,keyinfo,key,key_length, + if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0) DBUG_RETURN(error); } + memcpy(lastkey,key,key_length); if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag, &info->int_keypos,lastkey))) DBUG_RETURN(-1); @@ -1483,12 +1479,14 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (!info->int_keypos) DBUG_RETURN(-1); if (info->int_keypos == info->buff+2) - DBUG_RETURN(_mi_search(info,keyinfo,key,key_length, + DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, pos)); - if ((error=_mi_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF, + if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY, + nextflag | SEARCH_SAVE_BUFF, _mi_kpos(nod_flag,info->int_keypos))) <= 0) DBUG_RETURN(error); + /* QQ: We should be able to optimize away the following call */ if (! _mi_get_last_key(info,keyinfo,info->buff,lastkey, info->int_keypos,&info->lastkey_length)) DBUG_RETURN(-1); diff --git a/myisam/mi_static.c b/myisam/mi_static.c index 389aac3142a..43e21340f5f 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -40,7 +40,7 @@ my_bool myisam_concurrent_insert=0; #endif my_off_t myisam_max_extra_temp_length= MI_MAX_TEMP_LENGTH; my_off_t myisam_max_temp_length= MAX_FILE_SIZE; -uint myisam_bulk_insert_tree_size=8192*1024; +ulong myisam_bulk_insert_tree_size=8192*1024; /* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */ /* Position is , == , >= , <= , > , < */ diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c index e0fce6d3e1c..2712c125f4e 100644 --- a/myisam/mi_statrec.c +++ b/myisam/mi_statrec.c @@ -181,8 +181,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos, error=my_pread(info->dfile,(char*) record,info->s->base.reclength, pos,MYF(MY_NABP)) != 0; - if (info->s->r_locks == 0 && info->s->w_locks == 0) - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); if (! error) { if (!*record) @@ -195,7 +194,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos, } return(-1); /* Error on read */ } - VOID(_mi_writeinfo(info,0)); /* No such record */ + fast_mi_writeinfo(info); /* No such record */ return(-1); } @@ -257,7 +256,7 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf, DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld", filepos/share->base.reclength,filepos, info->state->records, info->state->del)); - VOID(_mi_writeinfo(info,0)); + fast_mi_writeinfo(info); DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE); } info->lastpos= filepos; diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index b66b02afdf9..cb60aeb8618 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -343,68 +343,72 @@ int main(int argc, char *argv[]) } if (testflag==3) goto end; - if (!silent) - printf("- Same key: first - next -> last - prev -> first\n"); - DBUG_PRINT("progpos",("first - next -> last - prev -> first")); for (i=999, dupp_keys=j=0 ; i>0 ; i--) { - if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; } + if (key1[i] > dupp_keys) { dupp_keys=key1[i]; j=i; } } sprintf(key,"%6d",j); - if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err; - if (mi_rsame(file,read_record2,-1)) goto err; - if (memcmp(read_record,read_record2,reclength) != 0) - { - printf("mi_rsame didn't find same record\n"); - goto end; - } - info.recpos=mi_position(file); - if (mi_rfirst(file,read_record2,0) || - mi_rsame_with_pos(file,read_record2,0,info.recpos) || - memcmp(read_record,read_record2,reclength) != 0) + if (dupp_keys) { - printf("mi_rsame_with_pos didn't find same record\n"); - goto end; - } - { - int skr=mi_rnext(file,read_record2,0); - if ((skr && my_errno != HA_ERR_END_OF_FILE) || - mi_rprev(file,read_record2,-1) || + if (!silent) + printf("- Same key: first - next -> last - prev -> first\n"); + DBUG_PRINT("progpos",("first - next -> last - prev -> first")); + if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys); + + if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err; + if (mi_rsame(file,read_record2,-1)) goto err; + if (memcmp(read_record,read_record2,reclength) != 0) + { + printf("mi_rsame didn't find same record\n"); + goto end; + } + info.recpos=mi_position(file); + if (mi_rfirst(file,read_record2,0) || + mi_rsame_with_pos(file,read_record2,0,info.recpos) || memcmp(read_record,read_record2,reclength) != 0) { - printf("mi_rsame_with_pos lost position\n"); + printf("mi_rsame_with_pos didn't find same record\n"); + goto end; + } + { + int skr=mi_rnext(file,read_record2,0); + if ((skr && my_errno != HA_ERR_END_OF_FILE) || + mi_rprev(file,read_record2,-1) || + memcmp(read_record,read_record2,reclength) != 0) + { + printf("mi_rsame_with_pos lost position\n"); + goto end; + } + } + ant=1; + start=keyinfo[0].seg[0].start; length=keyinfo[0].seg[0].length; + while (mi_rnext(file,read_record2,0) == 0 && + memcmp(read_record2+start,key,length) == 0) ant++; + if (ant != dupp_keys) + { + printf("next: Found: %d keys of %d\n",ant,dupp_keys); + goto end; + } + ant=0; + while (mi_rprev(file,read_record3,0) == 0 && + bcmp(read_record3+start,key,length) == 0) ant++; + if (ant != dupp_keys) + { + printf("prev: Found: %d records of %d\n",ant,dupp_keys); goto end; } - } - ant=1; - start=keyinfo[0].seg[0].start; length=keyinfo[0].seg[0].length; - while (mi_rnext(file,read_record2,0) == 0 && - memcmp(read_record2+start,key,length) == 0) ant++; - if (ant != dupp_keys) - { - printf("next: Found: %d keys of %d\n",ant,dupp_keys); - goto end; - } - ant=0; - while (mi_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys) - { - printf("prev: Found: %d records of %d\n",ant,dupp_keys); - goto end; - } - /* Check of mi_rnext_same */ - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) - goto err; - ant=1; - while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10) - ant++; - if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE) - { - printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys); - goto end; + /* Check of mi_rnext_same */ + if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + goto err; + ant=1; + while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10) + ant++; + if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE) + { + printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys); + goto end; + } } if (!silent) @@ -776,9 +780,13 @@ end: printf("\nFollowing test have been made:\n"); printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); if (rec_pointer_size) - printf("Record pointer size: %d\n",rec_pointer_size); + printf("Record pointer size: %d\n",rec_pointer_size); + printf("myisam_block_size: %u\n", myisam_block_size); if (key_cacheing) + { puts("Key cacheing used"); + printf("key_cache_block_size: %u\n", key_cache_block_size); + } if (write_cacheing) puts("Write cacheing used"); if (write_cacheing) @@ -801,7 +809,7 @@ reads: %10lu\n", end_key_cache(); if (blob_buffer) my_free(blob_buffer,MYF(0)); - my_end(MY_CHECK_ERROR | MY_GIVE_INFO); + my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO); return(0); err: printf("got error: %d when using MyISAM-database\n",my_errno); @@ -861,7 +869,29 @@ static void get_options(int argc, char **argv) verbose=1; break; case 'm': /* records */ - recant=atoi(++pos); + if ((recant=atoi(++pos)) < 10) + { + fprintf(stderr,"record count must be >= 10\n"); + exit(1); + } + break; + case 'e': /* myisam_block_length */ + if ((myisam_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH || + myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH) + { + fprintf(stderr,"Wrong myisam_block_length\n"); + exit(1); + } + myisam_block_size=1 << my_bit_log2(myisam_block_size); + break; + case 'E': /* myisam_block_length */ + if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH || + key_cache_block_size > MI_MAX_KEY_BLOCK_LENGTH) + { + fprintf(stderr,"Wrong key_cache_block_size\n"); + exit(1); + } + key_cache_block_size=1 << my_bit_log2(key_cache_block_size); break; case 'f': if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS) @@ -904,7 +934,7 @@ static void get_options(int argc, char **argv) case 'V': printf("%s Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); puts("By Monty, for your professional use\n"); - printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-t#]\n", + printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n", progname); exit(0); case '#': diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res index d6b4703d702..94355bf1aa2 100644 --- a/myisam/mi_test_all.res +++ b/myisam/mi_test_all.res @@ -1,48 +1,50 @@ -Maximum memory usage: 545477 bytes (533k) -Maximum memory usage: 545477 bytes (533k) -Maximum memory usage: 545369 bytes (533k) -mi_test2-i686 -s -L -K -R1 -m2000 ; Should give error 135 +mi_test2 -s -L -K -R1 -m2000 ; Should give error 135 Error: 135 in write at record: 1105 got error: 135 when using MyISAM-database -Maximum memory usage: 29439 bytes (29k) -Maximum memory usage: 66541 bytes (65k) -Maximum memory usage: 5101 bytes (5k) -Maximum memory usage: 545488 bytes (533k) +myisamchk: MyISAM file test2 +myisamchk: warning: Datafile is almost full, 65532 of 65534 used +MyISAM-table 'test2' is usable but should be fixed Commands Used count Errors Recover errors -open 1 0 0 -write 50 0 0 -update 5 0 0 -delete 50 0 0 -close 1 0 0 -extra 6 0 0 -Total 113 0 0 -Maximum memory usage: 545744 bytes (533k) +open 17 0 0 +write 850 0 0 +update 85 0 0 +delete 850 0 0 +close 17 0 0 +extra 102 0 0 +Total 1921 0 0 Commands Used count Errors Recover errors -open 2 0 0 -write 100 0 0 -update 10 0 0 -delete 100 0 0 -close 2 0 0 -extra 12 0 0 -Total 226 0 0 -Maximum memory usage: 5101 bytes (5k) -1.12user 0.52system 0:01.71elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (214major+25minor)pagefaults 0swaps -Maximum memory usage: 21189 bytes (21k) -1.29user 0.55system 0:01.82elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (215major+29minor)pagefaults 0swaps -Maximum memory usage: 66541 bytes (65k) -1.10user 0.51system 0:01.66elapsed 96%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (216major+40minor)pagefaults 0swaps -Maximum memory usage: 82629 bytes (81k) -1.33user 0.24system 0:01.54elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (216major+44minor)pagefaults 0swaps -Maximum memory usage: 545477 bytes (533k) -1.31user 0.24system 0:01.55elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (216major+173minor)pagefaults 0swaps -Maximum memory usage: 545389 bytes (533k) -1.37user 0.18system 0:01.57elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (218major+180minor)pagefaults 0swaps -Maximum memory usage: 109165 bytes (107k) -1.42user 0.38system 0:01.78elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k -0inputs+0outputs (218major+51minor)pagefaults 0swaps +open 18 0 0 +write 900 0 0 +update 90 0 0 +delete 900 0 0 +close 18 0 0 +extra 108 0 0 +Total 2034 0 0 + +real 0m1.054s +user 0m0.410s +sys 0m0.640s + +real 0m1.077s +user 0m0.550s +sys 0m0.530s + +real 0m1.100s +user 0m0.420s +sys 0m0.680s + +real 0m0.783s +user 0m0.590s +sys 0m0.200s + +real 0m0.764s +user 0m0.560s +sys 0m0.210s + +real 0m0.699s +user 0m0.570s +sys 0m0.130s + +real 0m0.991s +user 0m0.630s +sys 0m0.350s diff --git a/myisam/mi_test_all.sh b/myisam/mi_test_all.sh index ccc9c39c64e..a2d57ea1a83 100755 --- a/myisam/mi_test_all.sh +++ b/myisam/mi_test_all.sh @@ -66,6 +66,14 @@ myisamchk$suffix -rs test1 myisamchk$suffix -se test1 myisamchk$suffix -rqs test1 myisamchk$suffix -se test1 +myisamchk$suffix -rs --correct-checksum test1 +myisamchk$suffix -se test1 +myisamchk$suffix -rqs --correct-checksum test1 +myisamchk$suffix -se test1 +myisamchk$suffix -ros --correct-checksum test1 +myisamchk$suffix -se test1 +myisamchk$suffix -rqos --correct-checksum test1 +myisamchk$suffix -se test1 # check of myisampack / myisamchk myisampack$suffix --force -s test1 @@ -105,13 +113,25 @@ mi_test1$suffix $silent --key_multiple -P -S myisamchk$suffix -sm test1 mi_test2$suffix $silent -L -K -W -P +myisamchk$suffix -sm test2 mi_test2$suffix $silent -L -K -W -P -A +myisamchk$suffix -sm test2 mi_test2$suffix $silent -L -K -W -P -S -R1 -m500 echo "mi_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135" +myisamchk$suffix -sm test2 mi_test2$suffix $silent -L -K -R1 -m2000 +myisamchk$suffix -sm test2 mi_test2$suffix $silent -L -K -P -S -R3 -m50 -b1000000 +myisamchk$suffix -sm test2 mi_test2$suffix $silent -L -B +myisamchk$suffix -sm test2 mi_test2$suffix $silent -D -B -c +myisamchk$suffix -sm test2 +mi_test2$suffix $silent -m10000 -e8192 -K +myisamchk$suffix -sm test2 +mi_test2$suffix $silent -m10000 -e16384 -E16384 -K -L +myisamchk$suffix -sm test2 + mi_test2$suffix $silent -L -K -W -P -m50 -l myisamlog$suffix mi_test2$suffix $silent -L -K -W -P -m50 -l -b100 diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 096d5829fed..e3de13d2d9a 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -291,7 +291,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_bool insert_last) { int error,flag; - uint comp_flag,nod_flag; + uint comp_flag,nod_flag, search_key_length; uchar *temp_buff,*keypos; uchar keybuff[MI_MAX_KEY_BUFF]; my_bool was_last_key; @@ -299,10 +299,14 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, DBUG_ENTER("w_search"); DBUG_PRINT("enter",("page: %ld",page)); + search_key_length=USE_WHOLE_KEY; if (keyinfo->flag & HA_SORT_ALLOWS_SAME) comp_flag=SEARCH_BIGGER; /* Put after same key */ else if (keyinfo->flag & HA_NOSAME) + { comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */ + search_key_length= key_length; + } else comp_flag=SEARCH_SAME; /* Keys in rec-pos order */ @@ -312,8 +316,8 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (!_mi_fetch_keypage(info,keyinfo,page,temp_buff,0)) goto err; - flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,key_length,comp_flag, - &keypos, keybuff, &was_last_key); + flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length, + comp_flag, &keypos, keybuff, &was_last_key); nod_flag=mi_test_if_nod(temp_buff); if (flag == 0) { diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 319539b44d4..b4c9e2f0fd6 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -40,6 +40,7 @@ static char **default_argv; static const char *load_default_groups[]= { "myisamchk", 0 }; static const char *set_charset_name; static CHARSET_INFO *set_charset; +static long opt_myisam_block_size; static const char *type_names[]= { "?","char","binary", "short", "long", "float", @@ -141,6 +142,9 @@ int main(int argc, char **argv) static CHANGEABLE_VAR changeable_vars[] = { { "key_buffer_size",(long*) &check_param.use_buffers,(long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L,(long) MALLOC_OVERHEAD,(long) IO_SIZE }, + { "myisam_block_size", (long*) &opt_myisam_block_size, + MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, + 0, MI_MIN_KEY_BLOCK_LENGTH }, { "read_buffer_size", (long*) &check_param.read_buffer_length,(long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L }, { "write_buffer_size", (long*) &check_param.write_buffer_length,(long) READ_BUFFER_INIT, @@ -159,7 +163,10 @@ static CHANGEABLE_VAR changeable_vars[] = { 20, 4, HA_FT_MAXLEN, 0, 1 }, { NullS,(long*) 0,0L,0L,0L,0L,0L,} }; -enum options {OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS}; +enum options { + OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS, + OPT_CORRECT_CHECKSUM +}; static struct option long_options[] = @@ -167,9 +174,10 @@ static struct option long_options[] = {"analyze", no_argument, 0, 'a'}, {"block-search", required_argument,0, 'b'}, {"backup", no_argument, 0, 'B'}, - {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR}, + {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR}, {"check", no_argument, 0, 'c'}, {"check-only-changed",no_argument, 0, 'C'}, + {"correct-checksum", no_argument, 0, OPT_CORRECT_CHECKSUM}, #ifndef DBUG_OFF {"debug", optional_argument, 0, '#'}, #endif @@ -205,7 +213,7 @@ static struct option long_options[] = static void print_version(void) { - printf("%s Ver 1.51 for %s at %s\n",my_progname,SYSTEM_TYPE, + printf("%s Ver 1.52 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE); } @@ -248,6 +256,7 @@ static void usage(void) puts("Repair options (When using -r or -o) \n\ -B, --backup Make a backup of the .MYD file as 'filename-time.BAK'\n\ + --correct-checksum Correct checksum information for table. \n\ -D, --data-file-length=# Max length of data file (when recreating data\n\ file when it's full)\n\ -e, --extend-check Try to recover every possible row from the data file\n\ @@ -433,6 +442,9 @@ static void get_options(register int *argc,register char ***argv) case 'V': print_version(); exit(0); + case OPT_CORRECT_CHECKSUM: + check_param.testflag|=T_CALC_CHECKSUM; + break; case OPT_CHARSETS_DIR: charsets_dir = optarg; break; @@ -449,6 +461,11 @@ static void get_options(register int *argc,register char ***argv) exit(0); } } + /* If using repair, then update checksum if one uses --update-state */ + if ((check_param.testflag & T_UPDATE_STATE) && + (check_param.testflag & (T_REP | T_REP_BY_SORT))) + check_param.testflag|= T_CALC_CHECKSUM; + (*argc)-=optind; (*argv)+=optind; if (*argc == 0) @@ -456,6 +473,7 @@ static void get_options(register int *argc,register char ***argv) usage(); exit(-1); } + if ((check_param.testflag & T_UNPACK) && (check_param.opt_rep_quick || (check_param.testflag & T_SORT_RECORDS))) { @@ -479,6 +497,7 @@ static void get_options(register int *argc,register char ***argv) if (!(set_charset=get_charset_by_name(set_charset_name, MYF(MY_WME)))) exit(1); + myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); return; } /* get options */ @@ -605,7 +624,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) (((ulonglong) 1L << share->base.keys)-1)) || test_if_almost_full(info) || info->s->state.header.file_version[3] != myisam_file_magic[3] || - (set_charset && set_charset->number != share->state.header.language))) + (set_charset && set_charset->number != share->state.header.language) || + myisam_block_size != MI_KEY_BLOCK_LENGTH)) { if (set_charset) check_param.language=set_charset->number; diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index a2a30ae50ce..33837dfda00 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -173,7 +173,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */ File data_file; /* Shared data file */ int mode; /* mode of file on open */ uint reopen; /* How many times reopened */ - uint w_locks,r_locks; /* Number of read/write locks */ + uint w_locks,r_locks,tot_locks; /* Number of read/write locks */ uint blocksize; /* blocksize of keyfile */ ulong min_pack_length; /* Theese are used by packed data */ ulong max_pack_length; @@ -365,10 +365,8 @@ struct st_myisam_info { #define PACK_TYPE_ZERO_FILL 4 #define MI_FOUND_WRONG_KEY 32738 /* Impossible value from _mi_key_cmp */ -#define MI_KEY_BLOCK_LENGTH 1024 /* Min key block length */ -#define MI_MAX_KEY_BLOCK_LENGTH 8192 -#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_KEY_BLOCK_LENGTH) -#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/MI_KEY_BLOCK_LENGTH+1)*MI_KEY_BLOCK_LENGTH) +#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH) +#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/myisam_block_size+1)*myisam_block_size) #define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */ #define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */ @@ -589,6 +587,9 @@ enum myisam_log_commands { #define myisam_log_command(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_command(a,b,c,d,e) #define myisam_log_record(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_record(a,b,c,d,e) +#define fast_mi_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _mi_writeinfo((INFO),0) +#define fast_mi_readinfo(INFO) (!(INFO)->lock_type == F_UNLCK) && _mi_readinfo((INFO),F_RDLCK,1) + #ifdef __cplusplus extern "C" { #endif diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 9a44d569e45..2a9841975ed 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -45,7 +45,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ my_quick.c my_lockmem.c my_static.c \ getopt.c getopt1.c getvar.c my_mkdir.c \ default.c my_compress.c checksum.c raid.cc my_net.c \ - my_vsnprintf.c charset.c my_bitmap.c + my_vsnprintf.c charset.c my_bitmap.c my_bit.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 5b8ec96b4d1..d223a4779a0 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -53,7 +53,6 @@ typedef struct sec_link { } SEC_LINK; -static uint find_next_bigger_power(uint value); static SEC_LINK *find_key_block(int file,my_off_t filepos,int *error); /* static variables in this file */ @@ -61,9 +60,11 @@ static SEC_LINK *_my_block_root,**_my_hash_root, *_my_used_first,*_my_used_last; static int _my_disk_blocks; static uint _my_disk_blocks_used, _my_hash_blocks; +static uint key_cache_shift; ulong _my_blocks_used,_my_blocks_changed; ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests, _my_cache_read; +uint key_cache_block_size=DEFAULT_KEYCACHE_BLOCK_SIZE; static byte HUGE_PTR *_my_block_mem; static SEC_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; static SEC_LINK *file_blocks[CHANGED_BLOCKS_HASH]; @@ -92,12 +93,16 @@ int init_key_cache(ulong use_mem, { key_cache_inited=TRUE; _my_disk_blocks= -1; + key_cache_shift=my_bit_log2(key_cache_block_size); + DBUG_PRINT("info",("key_cache_block_size: %u key_cache_shift: %u", + key_cache_block_size, key_cache_shift)); #ifndef DBUG_OFF _my_printed=0; #endif } - blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+KEYCACHE_BLOCK_SIZE)); + blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+ + key_cache_block_size)); /* No use to have very few blocks */ if (blocks >= 8 && _my_disk_blocks < 0) { @@ -107,13 +112,15 @@ int init_key_cache(ulong use_mem, #endif for (;;) { - if ((_my_hash_blocks=find_next_bigger_power((uint) blocks)) < blocks*5/4) - _my_hash_blocks<<=1; + /* Set my_hash_blocks to the next bigger 2 power */ + _my_hash_blocks=(uint) 1 << (my_bit_log2(blocks*5/4)+1); while ((length=(uint) blocks*sizeof(SEC_LINK)+ - sizeof(SEC_LINK*)*_my_hash_blocks)+(ulong) blocks*KEYCACHE_BLOCK_SIZE > + sizeof(SEC_LINK*)*_my_hash_blocks)+ + ((ulong) blocks << key_cache_shift) > use_mem) blocks--; - if ((_my_block_mem=my_malloc_lock((ulong) blocks * KEYCACHE_BLOCK_SIZE,MYF(0)))) + if ((_my_block_mem=my_malloc_lock((ulong) blocks << key_cache_shift, + MYF(0)))) { if ((_my_block_root=(SEC_LINK*) my_malloc((uint) length,MYF(0))) != 0) break; @@ -170,17 +177,6 @@ void end_key_cache(void) } /* end_key_cache */ -static uint find_next_bigger_power(uint value) -{ - uint old_value=1; - while (value) - { - old_value=value; - value&= value-1; - } - return (old_value << 1); -} - static inline void link_into_file_blocks(SEC_LINK *next, int file) { reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK]; @@ -243,7 +239,7 @@ static void test_key_cache(const char *where, my_bool lock); /* ** read a key_buffer - ** filepos must point at a even KEYCACHE_BLOCK_SIZE block + ** filepos must point at a even key_cache_block_size block ** if return_buffer is set then the intern buffer is returned if ** it can be used ** Returns adress to where data is read @@ -257,7 +253,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, int error=0; #ifndef THREAD - if (block_length > KEYCACHE_BLOCK_SIZE) + if (block_length > key_cache_block_size) return_buffer=0; #endif if (_my_disk_blocks > 0) @@ -268,7 +264,8 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, do { _my_cache_r_requests++; - read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length; + read_length= (length > key_cache_block_size ? key_cache_block_size : + length); if (!(next=find_key_block(file,filepos,&error))) { pthread_mutex_unlock(&THR_LOCK_keycache); @@ -310,7 +307,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, /* write a key_buffer */ /* We don't have to use pwrite because of write locking */ - /* buff must point at a even KEYCACHE_BLOCK_SIZE block */ + /* buff must point at a even key_cache_block_size block */ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length, uint block_length __attribute__((unused)), @@ -336,7 +333,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length, _my_cache_w_requests++; do { - read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length; + read_length= length > key_cache_block_size ? key_cache_block_size : length; if (!(next=find_key_block(file,filepos,&error))) goto end; /* Fatal error */ if (!dont_write) /* If we wrote buff at start */ @@ -385,7 +382,7 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error) #endif *error=0; - next= *(start= &_my_hash_root[((ulong) (filepos/KEYCACHE_BLOCK_SIZE)+(ulong) file) & + next= *(start= &_my_hash_root[((ulong) (filepos >> key_cache_shift)+(ulong) file) & (_my_hash_blocks-1)]); while (next && (next->diskpos != filepos || next->file != file)) next= next->next_hash; @@ -411,7 +408,8 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error) { /* There are unused blocks */ next= &_my_block_root[_my_blocks_used++]; /* Link in hash-chain */ next->buffer=ADD_TO_PTR(_my_block_mem, - (ulong) _my_disk_blocks_used*KEYCACHE_BLOCK_SIZE,byte*); + ((ulong) _my_disk_blocks_used << key_cache_shift), + byte*); /* link first in file_blocks */ next->changed=0; link_into_file_blocks(next,file); @@ -426,7 +424,8 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error) next= _my_used_first; if (next->changed) { - if (my_pwrite(next->file,next->buffer,KEYCACHE_BLOCK_SIZE,next->diskpos, + if (my_pwrite(next->file,next->buffer,key_cache_block_size, + next->diskpos, MYF(MY_NABP | MY_WAIT_IF_FULL))) { *error=1; @@ -505,7 +504,8 @@ static int flush_cached_blocks(File file, SEC_LINK **cache, uint count) qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); for ( ; count-- ; cache++) { - if (my_pwrite(file,(*cache)->buffer,KEYCACHE_BLOCK_SIZE,(*cache)->diskpos, + if (my_pwrite(file,(*cache)->buffer,key_cache_block_size, + (*cache)->diskpos, MYF(MY_NABP | MY_WAIT_IF_FULL))) { if (!last_errno) @@ -646,7 +646,7 @@ static void test_key_cache(const char *where, my_bool lock) i,(ulong) pos,(ulong) prev,(ulong) pos->prev_hash)); } - if (((pos->diskpos/KEYCACHE_BLOCK_SIZE)+pos->file) % _my_hash_blocks != i) + if (((pos->diskpos >> key_cache_shift)+pos->file) % _my_hash_blocks != i) { DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld", i,(ulong) pos,(ulong) pos->diskpos)); diff --git a/mysys/my_bit.c b/mysys/my_bit.c new file mode 100644 index 00000000000..19ffb74a5c5 --- /dev/null +++ b/mysys/my_bit.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Some useful bit functions */ + +#include "mysys_priv.h" + +/* + Find smallest X in 2^X >= value + This can be used to divide a number with value by doing a shift instead +*/ + +uint my_bit_log2(ulong value) +{ + uint bit; + for (bit=0 ; value > 1 ; value>>=1, bit++) ; + return bit; +} diff --git a/mysys/my_init.c b/mysys/my_init.c index c3b9cecf86e..f39b3f0ed6d 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -45,9 +45,8 @@ static my_bool win32_init_tcp_ip(); #else #define my_win_init() #endif -static my_bool my_init_done=0; - +my_bool my_init_done=0; static ulong atoi_octal(const char *str) { diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 86312fdab52..7226840b475 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -56,6 +56,13 @@ END_OF_DATA echo "" fi +echo "Adding columns needed by GRANT .. REQUIRE (openssl)" +echo "You can ignore any Duplicate column errors" +@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA +ALTER TABLE user ADD ssl_type enum('NONE','ANY','X509', 'SPECIFIED') DEFAULT 'NONE' NOT NULL, ADD ssl_cipher BLOB NOT NULL, ADD x509_issuer BLOB NOT NULL, ADD x509_subject BLOB NOT NULL +END_OF_DATA +echo "" + # # Create tables_priv and columns_priv if they don't exists # @@ -96,6 +103,7 @@ echo "You can ignore any errors from this" @bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL; END_OF_DATA +echo "" # # Add the new 'type' column to the func table. @@ -107,3 +115,14 @@ echo "You can ignore any Duplicate column errors" @bindir@/mysql --user=root --password=$root_password mysql <<EOF alter table func add type enum ('function','aggregate') NOT NULL; EOF +echo "" + +echo "Converting all privilege tables to MyISAM format" +@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA +ALTER TABLE user type=MyISAM; +ALTER TABLE db type=MyISAM; +ALTER TABLE host type=MyISAM; +ALTER TABLE func type=MyISAM; +ALTER TABLE columns_priv type=MyISAM; +ALTER TABLE tables_priv type=MyISAM; +END_OF_DATA diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index f064e6ca0ca..9b0cfd4eb66 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -225,9 +225,9 @@ then c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u ssl_type enum('NONE','ANY','X509', 'SPECIFIED') DEFAULT 'NONE' NOT NULL," - c_u="$c_u ssl_cipher BLOB NULL," - c_u="$c_u x509_issuer BLOB NULL," - c_u="$c_u x509_subject BLOB NULL," + c_u="$c_u ssl_cipher BLOB NOT NULL," + c_u="$c_u x509_issuer BLOB NOT NULL," + c_u="$c_u x509_subject BLOB NOT NULL," c_u="$c_u PRIMARY KEY Host (Host,User)" c_u="$c_u )" c_u="$c_u comment='Users and global privileges';" diff --git a/sql/derror.cc b/sql/derror.cc index 62971fde394..697d363b86b 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -72,8 +72,7 @@ static void read_texts(const char *file_name,const char ***point, Check that the above file is the right version for this program!\n\n", my_progname,name,ant,error_messages); VOID(my_close(file,MYF(MY_WME))); - clean_up(0); /* Clean_up frees everything */ - exit(1); /* We can't continue */ + unireg_abort(1); } x_free((gptr) *point); /* Free old language */ @@ -115,8 +114,7 @@ err: if (file != FERR) VOID(my_close(file,MYF(MY_WME))); fprintf(stderr,buff,my_progname,name); - clean_up(0); /* Clean_up frees everything */ - exit(1); /* We can't continue */ + unireg_abort(1); } /* read_texts */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index db1d6911119..ac8534916d6 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1197,13 +1197,19 @@ longlong Item_cond_or::val_int() longlong Item_func_isnull::val_int() { - (void) args[0]->val(); + if (internal_result_type == REAL_RESULT) + (void) args[0]->val(); + else + (void) args[0]->val_int(); return (args[0]->null_value) ? 1 : 0; } longlong Item_func_isnotnull::val_int() { - (void) args[0]->val(); + if (internal_result_type == REAL_RESULT) + (void) args[0]->val(); + else + (void) args[0]->val_int(); return !(args[0]->null_value) ? 1 : 0; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 5ee0687c064..9c9336264f7 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -429,6 +429,7 @@ class Item_func_in :public Item_int_func class Item_func_isnull :public Item_bool_func { + enum Item_result internal_result_type; public: Item_func_isnull(Item *a) :Item_bool_func(a) {} longlong val_int(); @@ -437,6 +438,7 @@ public: { decimals=0; max_length=1; maybe_null=0; Item_func_isnull::update_used_tables(); + internal_result_type=args[0]->result_type(); } const char *func_name() const { return "isnull"; } /* Optimize case of not_null_column IS NULL */ @@ -455,11 +457,16 @@ public: class Item_func_isnotnull :public Item_bool_func { + enum Item_result internal_result_type; public: Item_func_isnotnull(Item *a) :Item_bool_func(a) {} longlong val_int(); enum Functype functype() const { return ISNOTNULL_FUNC; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; } + void fix_length_and_dec() + { + decimals=0; max_length=1; maybe_null=0; + internal_result_type=args[0]->result_type(); + } const char *func_name() const { return "isnotnull"; } optimize_type select_optimize() const { return OPTIMIZE_NULL; } }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7a32a253d6c..851e33fca04 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -506,7 +506,7 @@ void sql_print_error(const char *format,...) __attribute__ ((format (printf, 1, 2))); extern uint32 server_id; -extern char mysql_data_home[2],server_version[SERVER_VERSION_LENGTH], +extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], max_sort_char, mysql_real_data_home[]; extern my_string mysql_unix_port,mysql_tmpdir; extern const char *first_keyword, *localhost, *delayed_user; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c14ae3aa61a..bd5769c3237 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -214,8 +214,9 @@ SHOW_COMP_OPTION have_symlink=SHOW_OPTION_YES; static bool opt_skip_slave_start = 0; // if set, slave is not autostarted static bool opt_do_pstack = 0; static ulong opt_specialflag=SPECIAL_ENGLISH; -static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET; static ulong back_log,connect_timeout,concurrency; +static ulong opt_myisam_block_size; +static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET; static my_string opt_logname=0,opt_update_logname=0, opt_binlog_index_name = 0,opt_slow_logname=0; static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN]; @@ -310,10 +311,16 @@ ulong slow_launch_threads = 0; ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size; char mysql_real_data_home[FN_REFLEN], - mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN], + language[LIBLEN],reg_ext[FN_EXTLEN], default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list, blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; +#ifndef EMBEDDED_LIBRARY +char mysql_data_home_buff[2], *mysql_data_home=mysql_data_home_buff; +#else +char *mysql_data_home=mysql_real_data_home; +#endif + char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; const char *first_keyword="first"; @@ -677,9 +684,8 @@ static sig_handler print_signal_warning(int sig) void unireg_end(int signal_number __attribute__((unused))) { clean_up(); -#ifndef EMBEDDED_LIBRARY + my_thread_end(); pthread_exit(0); // Exit is in main thread -#endif } @@ -688,6 +694,7 @@ void unireg_abort(int exit_code) if (exit_code) sql_print_error("Aborting\n"); clean_up(); /* purecov: inspected */ + my_thread_end(); exit(exit_code); /* purecov: inspected */ } @@ -730,14 +737,13 @@ void clean_up(bool print_message) free_max_user_conn(); end_slave_list(); -#ifndef __WIN__ +#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY) if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(0)); // This may not always exist #endif if (print_message) sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname); x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */ - my_thread_end(); /* Tell main we are ready */ (void) pthread_mutex_lock(&LOCK_thread_count); @@ -1782,10 +1788,6 @@ int main(int argc, char **argv) init_thr_lock(); init_slave_list(); - /* Fix varibles that are base 1024*1024 */ - myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE); - myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE); - /* Setup log files */ if (opt_log) open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL); @@ -1796,17 +1798,18 @@ int main(int argc, char **argv) using_update_log=1; } - //make sure slave thread gets started - // if server_id is set, valid master.info is present, and master_host has - // not been specified - if(server_id && !master_host) - { - char fname[FN_REFLEN+128]; - MY_STAT stat_area; - fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32); - if(my_stat(fname, &stat_area, MYF(0)) && !init_master_info(&glob_mi)) - master_host = glob_mi.host; - } + /* + make sure slave thread gets started if server_id is set, + valid master.info is present, and master_host has not been specified + */ + if (server_id && !master_host) + { + char fname[FN_REFLEN+128]; + MY_STAT stat_area; + fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32); + if (my_stat(fname, &stat_area, MYF(0)) && !init_master_info(&glob_mi)) + master_host = glob_mi.host; + } if (opt_bin_log && !server_id) { @@ -2882,6 +2885,9 @@ CHANGEABLE_VAR changeable_vars[] = { ~0L, 1, ~0L, 0, 1 }, { "myisam_bulk_insert_tree_size", (long*) &myisam_bulk_insert_tree_size, 8192*1024, 4, ~0L, 0, 1 }, + { "myisam_block_size", (long*) &opt_myisam_block_size, + MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, + 0, MI_MIN_KEY_BLOCK_LENGTH }, { "myisam_max_extra_sort_file_size", (long*) &myisam_max_extra_sort_file_size, (long) (MI_MAX_TEMP_LENGTH/(1024L*1024L)), 0, ~0L, 0, 1 }, @@ -4025,6 +4031,12 @@ static void get_options(int argc,char **argv) /* To be deleted in MySQL 4.0 */ if (!record_rnd_cache_size) record_rnd_cache_size=my_default_record_cache_size; + + /* Fix variables that are base 1024*1024 */ + myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE); + myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE); + + myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); } |