1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

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
This commit is contained in:
monty@hundin.mysql.fi
2001-10-02 05:53:00 +03:00
parent b5622e11dd
commit 880026ccf6
53 changed files with 793 additions and 611 deletions

View File

@ -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.
For a description of using @code{REQUIRE}, see @xref{Secure connections}.
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
@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

View File

@ -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);
}

View File

@ -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 */
}
}

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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()
{}

View File

@ -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 \

32
libmysqld/embedded_priv.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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"
{
char hostname[FN_REFLEN];
static my_bool inited, org_my_init_done;
int mysql_server_init(int argc, const char **argv, const char **groups)
{
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");
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
(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");
#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" */

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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]);

View File

@ -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);

View File

@ -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 , == , >= , <= , > , < */

View File

@ -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;

View File

@ -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)
if (dupp_keys)
{
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 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)
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_with_pos lost position\n");
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 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 '#':

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -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@

View File

@ -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));

32
mysys/my_bit.c Normal file
View File

@ -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;
}

View File

@ -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)
{

View File

@ -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

View File

@ -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';"

View File

@ -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 */

View File

@ -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;
}

View File

@ -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; }
};

View File

@ -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;

View File

@ -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);
}