merge with 3.23.50
BitKeeper/etc/logging_ok: auto-union BUILD/SETUP.sh: Auto merged Build-tools/Do-compile: Auto merged Build-tools/Do-rpm: Auto merged configure.in: Auto merged include/mysql_com.h: Auto merged innobase/btr/btr0btr.c: Auto merged innobase/btr/btr0cur.c: Auto merged innobase/btr/btr0sea.c: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/dict/dict0load.c: Auto merged innobase/fil/fil0fil.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/include/srv0srv.h: Auto merged innobase/include/sync0rw.ic: Auto merged innobase/log/log0log.c: Auto merged innobase/rem/rem0cmp.c: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/row/row0upd.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged myisam/myisampack.c: Auto merged mysql-test/t/range.test: Auto merged scripts/mysqldumpslow.sh: Auto merged sql/ha_innodb.h: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/lock.cc: Auto merged sql/share/Makefile.am: Auto merged sql/sql_rename.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged support-files/mysql.spec.sh: Auto merged Docs/manual.texi: merge client/mysql.cc: merge client/mysqldump.c: merge innobase/buf/buf0buf.c: merge innobase/os/os0file.c: merge innobase/row/row0mysql.c: merge mysql-test/r/range.result: merge sql/ha_innodb.cc: merge sql/log_event.h: merge sql/mysqld.cc: merge sql/sql_base.cc: merge sql/sql_load.cc: merge
This commit is contained in:
commit
36b38aa503
@ -71,11 +71,4 @@ else
|
||||
make=make
|
||||
fi
|
||||
|
||||
if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1
|
||||
then
|
||||
CXX="gcc -DUSE_MYSYS_NEW"
|
||||
CXXLDFLAGS="-Wl,--defsym -Wl,__cxa_pure_virtual=0"
|
||||
else
|
||||
CXX=gcc
|
||||
CXXLDFLAGS=""
|
||||
fi
|
||||
CXX=gcc
|
||||
|
@ -5,6 +5,7 @@ Miguel@light.local
|
||||
Sinisa@sinisa.nasamreza.org
|
||||
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
||||
arjen@co3064164-a.bitbike.com
|
||||
arjen@fred.bitbike.com
|
||||
bell@sanja.is.com.ua
|
||||
davida@isil.mysql.com
|
||||
heikki@donna.mysql.fi
|
||||
@ -14,10 +15,12 @@ jani@janikt.pp.saunalahti.fi
|
||||
jani@rhols221.adsl.netsonic.fi
|
||||
jcole@abel.spaceapes.com
|
||||
jcole@main.burghcom.com
|
||||
jcole@mugatu.spaceapes.com
|
||||
jcole@sarvik.tfr.cafe.ee
|
||||
jcole@tetra.spaceapes.com
|
||||
jorge@linux.jorge.mysql.com
|
||||
kaj@work.mysql.com
|
||||
miguel@hegel.local
|
||||
miguel@light.local
|
||||
monty@bitch.mysql.fi
|
||||
monty@donna.mysql.fi
|
||||
@ -46,5 +49,3 @@ tonu@x153.internalnet
|
||||
tonu@x3.internalnet
|
||||
venu@work.mysql.com
|
||||
zak@linux.local
|
||||
jcole@mugatu.spaceapes.com
|
||||
arjen@fred.bitbike.com
|
||||
|
@ -92,7 +92,7 @@ if ($opt_stage == 0)
|
||||
{
|
||||
system("mkdir $host") if (! -d $host);
|
||||
system("touch $host/mysql-fix-for-glob");
|
||||
rm_all(<$host/mysql-*>);
|
||||
rm_all(<$host/mysql*>);
|
||||
system("mkdir $host/bin") if (! -d "$host/bin");
|
||||
}
|
||||
rm_all("$host/test");
|
||||
|
@ -159,10 +159,10 @@ cat > $logdir/$TMP_SCRIPT_MYSQL <<END
|
||||
set -x
|
||||
|
||||
# Check environment
|
||||
export MYSQL_BUILD_PATH="/usr/cygnus/redhat-980810/H-i386-pc-linux-gnu/bin/:/usr/bin:/bin"
|
||||
export MYSQL_BUILD_CFLAGS="-O6 -fno-omit-frame-pointer -mpentium"
|
||||
export MYSQL_BUILD_PATH="/usr/local/bin:/my/gnu/bin:/usr/bin:/bin"
|
||||
export MYSQL_BUILD_CFLAGS="-O6 -fno-omit-frame-pointer -mcpu=pentiumpro"
|
||||
export MYSQL_BUILD_CXXFLAGS="-O6 -fno-omit-frame-pointer \
|
||||
-felide-constructors -fno-exceptions -fno-rtti -mpentium"
|
||||
-felide-constructors -fno-exceptions -fno-rtti -mcpu=pentiumpro"
|
||||
gcc -v
|
||||
|
||||
# Make RPM
|
||||
|
@ -5534,10 +5534,12 @@ created and you must have TCP/IP installed.
|
||||
Optimised binary with support for symbolic links,
|
||||
InnoDB and BDB tables.
|
||||
@item @code{mysqld-max-nt} @tab
|
||||
Like @code{mysqld-max}, but compiled with support for named
|
||||
pipes.
|
||||
Like @code{mysqld-max}, but compiled with support for named pipes.
|
||||
@end multitable
|
||||
|
||||
Starting from 3.23.50, named pipes are only enabled if one starts mysqld with
|
||||
@code{--enable-named-pipe}.
|
||||
|
||||
All of the above binaries are optimised for the Pentium Pro
|
||||
processor but should work on any Intel processor >= i386.
|
||||
|
||||
@ -9321,6 +9323,11 @@ You can force a MySQL client to use named pipes by specifying the
|
||||
@code{--pipe} option or by specifying @code{.} as the host name. Use the
|
||||
@code{--socket} option to specify the name of the pipe.
|
||||
|
||||
Note that starting from 3.23.50, named pipes are only enabled if start
|
||||
mysqld with @code{--enable-named-pipe}. This is because some users have
|
||||
experienced problems shutting down the MySQL server when one uses named
|
||||
pipes.
|
||||
|
||||
You can test whether or not MySQL is working by executing the
|
||||
following commands:
|
||||
|
||||
@ -9597,6 +9604,9 @@ option to the new MySQL clients or create an option file
|
||||
host = localhost
|
||||
@end example
|
||||
|
||||
Starting from 3.23.50, named pipes are only enabled if start mysqld with
|
||||
@code{--enable-named-pipe}.
|
||||
|
||||
@item @code{Access denied for user} error
|
||||
If you get the error @code{Access denied for user: 'some-user@@unknown'
|
||||
to database 'mysql'} when accessing a MySQL server on the same
|
||||
@ -14157,6 +14167,10 @@ Enable system locking. Note that if you use this option on a system
|
||||
which a not fully working lockd() (as on Linux) you will easily get
|
||||
mysqld to deadlock.
|
||||
|
||||
@item --enable-named-pipe
|
||||
Enable support for named pipes; This only works on NT and newer windows
|
||||
versions.
|
||||
|
||||
@item -T, --exit-info
|
||||
This is a bit mask of different flags one can use for debugging the
|
||||
mysqld server; One should not use this option if one doesn't know
|
||||
@ -32743,7 +32757,7 @@ mysql> select INET_ATON("209.207.224.40");
|
||||
@end example
|
||||
|
||||
The generated number is always in network byte order; For example the
|
||||
above number is calculated as @code{209*255^3 + 207*255^2 + 224*255 +40}.
|
||||
above number is calculated as @code{209*256^3 + 207*256^2 + 224*256 +40}.
|
||||
|
||||
@findex MASTER_POS_WAIT()
|
||||
@item MASTER_POS_WAIT(log_name, log_pos)
|
||||
@ -45670,12 +45684,13 @@ are used if you don't specify a hostname or if you specify the special
|
||||
hostname @code{localhost}.
|
||||
|
||||
On Windows you can connect only with TCP/IP if the @code{mysqld} server
|
||||
is running on Win95/Win98. If it's running on NT, you can also connect
|
||||
with named pipes. The name of the named pipe is MySQL. If you
|
||||
don't give a hostname when connecting to @code{mysqld}, a MySQL client
|
||||
will first try to connect to the named pipe, and if this doesn't work it
|
||||
will connect to the TCP/IP port. You can force the use of named pipes
|
||||
on Windows by using @code{.} as the hostname.
|
||||
is running on Win95/Win98. If mysqld is running on NT and started with
|
||||
@code{enable-named-pipe}, you can also connect with named pipes. The
|
||||
name of the named pipe is MySQL. If you don't give a hostname when
|
||||
connecting to @code{mysqld}, a MySQL client will first try to connect to
|
||||
the named pipe, and if this doesn't work it will connect to the TCP/IP
|
||||
port. You can force the use of named pipes on Windows by using @code{.}
|
||||
as the hostname.
|
||||
|
||||
The error (2002) @code{Can't connect to ...} normally means that there
|
||||
isn't a MySQL server running on the system or that you are
|
||||
@ -49143,6 +49158,23 @@ not yet 100% confident in this code.
|
||||
Our Linux RPMS and binaries are now compiled with gcc 3.0.4, which should
|
||||
make them a bit faster.
|
||||
@item
|
||||
Fixed some buffer overflow problems when reading startup parameters.
|
||||
@item
|
||||
Because of problems on shutdown we have now disabled named pipes on
|
||||
windows by default. One can enable this with by starting mysqld with
|
||||
@code{--enable-named-pipe}.
|
||||
@item
|
||||
Fixed bug when using @code{WHERE key_column = 'J' or key_column='j'}.
|
||||
@item
|
||||
Fixed core-dump bug when using @code{--log-bin} with @code{LOAD DATA
|
||||
INFILE} without an active database.
|
||||
@item
|
||||
Fixed bug in @code{RENAME TABLE} when used with
|
||||
@code{lower_case_table_names=1} (default on Windows).
|
||||
@item
|
||||
Fixed unlikely core-dump bug when using @code{DROP TABLE} on a table
|
||||
that was in use by a thread that also used queries on only temporary tables.
|
||||
@item
|
||||
Fixed problem with @code{SHOW CREATE TABLE} and @code{PRIMARY KEY} when using
|
||||
32 indexes.
|
||||
@item
|
||||
@ -49171,7 +49203,7 @@ Don't give warning for statement that is only a comment; This is needed for
|
||||
@code{mysqldump --disable-keys} to work.
|
||||
@item
|
||||
Fixed unlikely caching bug when doing a join without keys. In this case
|
||||
the last used field for a table always returned @code{NULL}.
|
||||
the last used column for a table always returned @code{NULL}.
|
||||
@item
|
||||
Added options to make @code{LOAD DATA LOCAL INFILE} more secure.
|
||||
@item
|
||||
|
@ -810,17 +810,6 @@ static int get_options(int argc, char **argv)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if defined(OS2)
|
||||
static char* readline( char* prompt)
|
||||
{
|
||||
#if defined(OS2)
|
||||
static char linebuffer[254];
|
||||
#endif
|
||||
puts( prompt);
|
||||
return gets( linebuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int read_lines(bool execute_commands)
|
||||
{
|
||||
#if defined( __WIN__) || defined(OS2)
|
||||
|
@ -149,7 +149,7 @@ CHANGEABLE_VAR md_changeable_vars[] = {
|
||||
{ "max_allowed_packet", (long*) &max_allowed_packet,24*1024*1024,4096,
|
||||
512*1024L*1024L,MALLOC_OVERHEAD,1024},
|
||||
{ "net_buffer_length", (long*) &net_buffer_length,1024*1024L-1025,4096,
|
||||
512*1024L*1024L,MALLOC_OVERHEAD+1024,1024},
|
||||
16*1024L*1024L,MALLOC_OVERHEAD-1024,1024},
|
||||
{ 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -651,7 +651,7 @@ static uint getTableStructure(char *table, char* db)
|
||||
/* Make an sql-file, if path was given iow. option -T was given */
|
||||
char buff[20+FN_REFLEN];
|
||||
|
||||
sprintf(buff,"show create table %s",table_name);
|
||||
sprintf(buff,"show create table `%s`",table);
|
||||
if (mysql_query(sock, buff))
|
||||
{
|
||||
fprintf(stderr, "%s: Can't get CREATE TABLE for table '%s' (%s)\n",
|
||||
@ -784,7 +784,7 @@ static uint getTableStructure(char *table, char* db)
|
||||
{
|
||||
if (opt_keywords)
|
||||
fprintf(sql_file, " %s.%s %s", table_name,
|
||||
quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]);
|
||||
quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]);
|
||||
else
|
||||
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
|
||||
name_buff), row[SHOW_TYPE]);
|
||||
@ -1072,6 +1072,9 @@ static void dumpTable(uint numFields, char *table)
|
||||
fputs(insert_pat,md_result_file);
|
||||
mysql_field_seek(res,0);
|
||||
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t<row>\n");
|
||||
|
||||
for (i = 0; i < mysql_num_fields(res); i++)
|
||||
{
|
||||
if (!(field = mysql_fetch_field(res)))
|
||||
@ -1161,6 +1164,9 @@ static void dumpTable(uint numFields, char *table)
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t</row>\n");
|
||||
|
||||
if (extended_insert)
|
||||
{
|
||||
ulong row_length;
|
||||
|
56
configure.in
56
configure.in
@ -38,7 +38,7 @@ for i in $AVAILABLE_LANGUAGES
|
||||
do
|
||||
AVAILABLE_LANGUAGES_ERRORS="$AVAILABLE_LANGUAGES_ERRORS $i/errmsg.sys"
|
||||
echo "$i/errmsg.sys: $i/errmsg.txt
|
||||
\$(top_builddir)/extra/comp_err $i/errmsg.txt $i/errmsg.sys" \
|
||||
\$(top_builddir)/extra/comp_err \$^ $i/errmsg.sys" \
|
||||
>> $AVAILABLE_LANGUAGES_ERRORS_RULES
|
||||
done
|
||||
|
||||
@ -126,6 +126,20 @@ AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
|
||||
# Print version of CC and CXX compiler (if they support --version)
|
||||
CC_VERSION=`$CC --version`
|
||||
if test $? -eq "0"
|
||||
then
|
||||
AC_MSG_CHECKING("C Compiler version");
|
||||
AC_MSG_RESULT("$CC $CC_VERSION")
|
||||
fi
|
||||
CXX_VERSION=`$CXX --version`
|
||||
if test $? -eq "0"
|
||||
then
|
||||
AC_MSG_CHECKING("C++ compiler version");
|
||||
AC_MSG_RESULT("$CXX $CXX_VERSION")
|
||||
fi
|
||||
|
||||
# Fix for sgi gcc / sgiCC which tries to emulate gcc
|
||||
if test "$CC" = "sgicc"
|
||||
then
|
||||
@ -307,6 +321,19 @@ then
|
||||
# Disable exceptions as they seams to create problems with gcc and threads.
|
||||
# mysqld doesn't use run-time-type-checking, so we disable it.
|
||||
CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
|
||||
|
||||
# If you are using 'gcc' 3.0 (not g++) to compile C++ programs,
|
||||
# we will gets some problems when linking static programs.
|
||||
# The following code is used to fix this problem.
|
||||
|
||||
if test "$CXX" = "gcc"
|
||||
then
|
||||
if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW"
|
||||
CXXLDFLAGS="$CXXLDFLAGS -Wl,--defsym -Wl,__cxa_pure_virtual=0"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Avoid bug in fcntl on some versions of linux
|
||||
@ -435,16 +462,17 @@ AC_ARG_WITH(other-libc,
|
||||
enable_shared="no"
|
||||
all_is_static="yes"
|
||||
CFLAGS="$CFLAGS -I$other_libc_include"
|
||||
# There seems to be a feature in gcc that treats system and libc headers
|
||||
# silently when they violatate ANSI C++ standard, but it is strict otherwise
|
||||
# since gcc cannot now recognize that our headers are libc, we work around
|
||||
# by telling it to be permissive. Note that this option only works with
|
||||
# new versions of gcc (2.95.x and above)
|
||||
CXXFLAGS="$CXXFLAGS -fpermissive -I$other_libc_include"
|
||||
#There seems to be a feature in gcc that treats system and libc headers
|
||||
#leniently when they violatate ANSI C++ standard, but it is strict otherwise
|
||||
#since gcc cannot now recognize that our headers are libc, we work around
|
||||
#by telling it to be permissive
|
||||
static_nss=
|
||||
if test -f "$other_libc_lib/libnss_files.a"
|
||||
then
|
||||
# libc has been compiled with --enable-static-nss
|
||||
# we need special flags, but we will have to add those later
|
||||
# libc has been compiled with --enable-static-nss
|
||||
# we need special flags, but we will have to add those later
|
||||
STATIC_NSS_FLAGS="-Wl,--start-group -lc -lnss_files -lnss_dns -lresolv \
|
||||
-Wl,--end-group"
|
||||
static_nss=1
|
||||
@ -460,12 +488,12 @@ AC_ARG_WITH(other-libc,
|
||||
LDFLAGS="$LDFLAGS -static -L$other_libc_lib "
|
||||
fi
|
||||
|
||||
# When linking against custom libc installed separately, we want to force
|
||||
# all binary builds to be static, including the build done by configure
|
||||
# itself to test for system features.
|
||||
with_mysqld_ldflags="-all-static"
|
||||
with_client_ldflags="-all-static"
|
||||
NOINST_LDFLAGS="-all-static"
|
||||
#when linking against custom libc installed separately, we want to force all
|
||||
#binary builds to be static, including the build done by configure itself
|
||||
#to test for system features
|
||||
],
|
||||
[
|
||||
other_libc_include=
|
||||
@ -1558,9 +1586,9 @@ ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
AC_CACHE_CHECK([style of gethost* routines], mysql_cv_gethost_style,
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_CPLUSPLUS
|
||||
#do not treat warnings as errors if we are linking agaist other libc
|
||||
#this is to work around gcc not being permissive on non-system includes
|
||||
#with respect to ANSI C++
|
||||
# Do not treat warnings as errors if we are linking agaist other libc
|
||||
# this is to work around gcc not being permissive on non-system includes
|
||||
# with respect to ANSI C++
|
||||
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -Werror"
|
||||
@ -2289,7 +2317,7 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
#IMPORTANT - do not modify LIBS past this line - this hack is the only way
|
||||
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
|
||||
# I know to add the static NSS magic if we have static NSS libraries with
|
||||
# glibc - Sasha
|
||||
|
||||
|
@ -67,7 +67,7 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
|
||||
#define REFRESH_TABLES 4 /* close all tables */
|
||||
#define REFRESH_HOSTS 8 /* Flush host cache */
|
||||
#define REFRESH_STATUS 16 /* Flush status variables */
|
||||
#define REFRESH_THREADS 32 /* Flush status variables */
|
||||
#define REFRESH_THREADS 32 /* Flush thread cache */
|
||||
#define REFRESH_SLAVE 64 /* Reset master info and restart slave
|
||||
thread */
|
||||
#define REFRESH_MASTER 128 /* Remove all bin logs in the index
|
||||
|
@ -570,6 +570,19 @@ btr_page_get_father_for_rec(
|
||||
|
||||
node_ptr = btr_cur_get_rec(&cursor);
|
||||
|
||||
if (btr_node_ptr_get_child_page_no(node_ptr) !=
|
||||
buf_frame_get_page_no(page)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Corruption of an index tree: table %s, index %s,\n"
|
||||
"InnoDB: father ptr page no %lu, child page no %lu\n",
|
||||
(UT_LIST_GET_FIRST(tree->tree_indexes))->table_name,
|
||||
(UT_LIST_GET_FIRST(tree->tree_indexes))->name,
|
||||
btr_node_ptr_get_child_page_no(node_ptr),
|
||||
buf_frame_get_page_no(page));
|
||||
page_rec_print(page_rec_get_next(page_get_infimum_rec(page)));
|
||||
page_rec_print(node_ptr);
|
||||
}
|
||||
|
||||
ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
|
||||
buf_frame_get_page_no(page));
|
||||
mem_heap_free(heap);
|
||||
|
@ -204,7 +204,7 @@ btr_cur_search_to_nth_level(
|
||||
the caller uses his search latch
|
||||
to protect the record! */
|
||||
btr_cur_t* cursor, /* in/out: tree cursor; the cursor page is
|
||||
s- or x-latched, but see also above! */
|
||||
s- or x-latched, but see also above! */
|
||||
ulint has_search_latch,/* in: info on the latch mode the
|
||||
caller currently has on btr_search_latch:
|
||||
RW_S_LATCH, or 0 */
|
||||
|
@ -743,7 +743,7 @@ btr_search_guess_on_hash(
|
||||
|
||||
#ifdef notdefined
|
||||
/* These lines of code can be used in a debug version to check
|
||||
correctness of the searched cursor position: */
|
||||
the correctness of the searched cursor position: */
|
||||
|
||||
info->last_hash_succ = FALSE;
|
||||
|
||||
|
@ -220,6 +220,10 @@ buf_calc_page_checksum(
|
||||
{
|
||||
ulint checksum;
|
||||
|
||||
/* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
|
||||
are written outside the buffer pool to the first pages of data
|
||||
files, we have to skip them in page checksum calculation */
|
||||
|
||||
checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
|
||||
+ ut_fold_binary(page + FIL_PAGE_DATA,
|
||||
UNIV_PAGE_SIZE - FIL_PAGE_DATA
|
||||
@ -279,8 +283,9 @@ buf_page_print(
|
||||
|
||||
ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Page dump in ascii and hex (%u bytes):\n%s",
|
||||
" InnoDB: Page dump in ascii and hex (%u bytes):\n%s",
|
||||
UNIV_PAGE_SIZE, buf);
|
||||
fprintf(stderr, "InnoDB: End of page dump\n");
|
||||
|
||||
@ -288,7 +293,8 @@ buf_page_print(
|
||||
|
||||
checksum = buf_calc_page_checksum(read_buf);
|
||||
|
||||
fprintf(stderr, "InnoDB: Page checksum %lu stored checksum %lu\n",
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Page checksum %lu stored checksum %lu\n",
|
||||
checksum, mach_read_from_4(read_buf
|
||||
+ UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN));
|
||||
@ -1358,47 +1364,87 @@ buf_page_io_complete(
|
||||
/*=================*/
|
||||
buf_block_t* block) /* in: pointer to the block in question */
|
||||
{
|
||||
dulint id;
|
||||
dict_index_t* index;
|
||||
dulint id;
|
||||
ulint io_type;
|
||||
|
||||
ulint read_page_no;
|
||||
|
||||
ut_ad(block);
|
||||
|
||||
io_type = block->io_fix;
|
||||
|
||||
if (io_type == BUF_IO_READ) {
|
||||
/* If this page is not uninitialized and not in the
|
||||
doublewrite buffer, then the page number should be the
|
||||
same as in block */
|
||||
|
||||
read_page_no = mach_read_from_4((block->frame)
|
||||
+ FIL_PAGE_OFFSET);
|
||||
if (read_page_no != 0
|
||||
&& !trx_doublewrite_page_inside(read_page_no)
|
||||
&& read_page_no != block->offset) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
|
||||
read_page_no, block->offset);
|
||||
}
|
||||
#ifdef notdefined
|
||||
if (block->offset != 0 && read_page_no == 0) {
|
||||
/* Check that the page is really uninited */
|
||||
|
||||
for (i = 0; i < UNIV_PAGE_SIZE; i++) {
|
||||
|
||||
if (*((block->frame) + i) != '\0') {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page n:o in the page read in is 0, but page %lu is inited!\n",
|
||||
block->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* From version 3.23.38 up we store the page checksum
|
||||
to the 4 upper bytes of the page end lsn field */
|
||||
to the 4 first bytes of the page end lsn field */
|
||||
|
||||
if (buf_page_is_corrupted(block->frame)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Database page corruption or a failed\n"
|
||||
"InnoDB: file read of page %lu.\n", block->offset);
|
||||
"InnoDB: Database page corruption on disk or a failed\n"
|
||||
"InnoDB: file read of page %lu.\n", block->offset);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: You may have to recover from a backup.\n");
|
||||
"InnoDB: You may have to recover from a backup.\n");
|
||||
|
||||
buf_page_print(block->frame);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Database page corruption or a failed\n"
|
||||
"InnoDB: file read of page %lu.\n", block->offset);
|
||||
"InnoDB: Database page corruption on disk or a failed\n"
|
||||
"InnoDB: file read of page %lu.\n", block->offset);
|
||||
fprintf(stderr,
|
||||
"InnoDB: You may have to recover from a backup.\n");
|
||||
"InnoDB: You may have to recover from a backup.\n");
|
||||
fprintf(stderr,
|
||||
"InnoDB: It is also possible that your operating\n"
|
||||
"InnoDB: system has corrupted its own file cache\n"
|
||||
"InnoDB: and rebooting your computer removes the\n"
|
||||
"InnoDB: error.\n");
|
||||
"InnoDB: It is also possible that your operating\n"
|
||||
"InnoDB: system has corrupted its own file cache\n"
|
||||
"InnoDB: and rebooting your computer removes the\n"
|
||||
"InnoDB: error.\n"
|
||||
"InnoDB: If the corrupt page is an index page\n"
|
||||
"InnoDB: you can also try to fix the corruption\n"
|
||||
"InnoDB: by dumping, dropping, and reimporting\n"
|
||||
"InnoDB: the corrupt table. You can use CHECK\n"
|
||||
"InnoDB: TABLE to scan your table for corruption.\n"
|
||||
"InnoDB: Look also at section 6.1 of\n"
|
||||
"InnoDB: http://www.innodb.com/ibman.html about\n"
|
||||
"InnoDB: forcing recovery.\n");
|
||||
|
||||
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
|
||||
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Ending processing because of a corrupt database page.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (recv_recovery_is_on()) {
|
||||
recv_recover_page(TRUE, block->frame, block->space,
|
||||
block->offset);
|
||||
recv_recover_page(FALSE, TRUE, block->frame,
|
||||
block->space, block->offset);
|
||||
}
|
||||
|
||||
if (!recv_no_ibuf_operations) {
|
||||
|
@ -327,6 +327,34 @@ try_again:
|
||||
mutex_exit(&(trx_doublewrite->mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Initializes a page for writing to the tablespace. */
|
||||
|
||||
void
|
||||
buf_flush_init_for_writing(
|
||||
/*=======================*/
|
||||
byte* page, /* in: page */
|
||||
dulint newest_lsn, /* in: newest modification lsn to the page */
|
||||
ulint space, /* in: space id */
|
||||
ulint page_no) /* in: page number */
|
||||
{
|
||||
/* Write the newest modification lsn to the page */
|
||||
mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);
|
||||
|
||||
mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, newest_lsn);
|
||||
|
||||
/* Write to the page the space id and page number */
|
||||
|
||||
mach_write_to_4(page + FIL_PAGE_SPACE, space);
|
||||
mach_write_to_4(page + FIL_PAGE_OFFSET, page_no);
|
||||
|
||||
/* We overwrite the first 4 bytes of the end lsn field to store
|
||||
a page checksum */
|
||||
|
||||
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
|
||||
buf_calc_page_checksum(page));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Does an asynchronous write of a buffer page. NOTE: in simulated aio and
|
||||
also when the doublewrite buffer is used, we must call
|
||||
@ -349,23 +377,8 @@ buf_flush_write_block_low(
|
||||
/* Force the log to the disk before writing the modified block */
|
||||
log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS);
|
||||
#endif
|
||||
/* Write the newest modification lsn to the page */
|
||||
mach_write_to_8(block->frame + FIL_PAGE_LSN,
|
||||
block->newest_modification);
|
||||
mach_write_to_8(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
|
||||
block->newest_modification);
|
||||
|
||||
/* Write to the page the space id and page number */
|
||||
|
||||
mach_write_to_4(block->frame + FIL_PAGE_SPACE, block->space);
|
||||
mach_write_to_4(block->frame + FIL_PAGE_OFFSET, block->offset);
|
||||
|
||||
/* We overwrite the first 4 bytes of the end lsn field to store
|
||||
a page checksum */
|
||||
|
||||
mach_write_to_4(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
|
||||
buf_calc_page_checksum(block->frame));
|
||||
|
||||
buf_flush_init_for_writing(block->frame, block->newest_modification,
|
||||
block->space, block->offset);
|
||||
if (!trx_doublewrite) {
|
||||
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
|
||||
|
@ -281,7 +281,8 @@ dict_table_autoinc_initialize(
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Gets the next autoinc value, 0 if not yet initialized. */
|
||||
Gets the next autoinc value, 0 if not yet initialized. If initialized,
|
||||
increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
@ -306,6 +307,32 @@ dict_table_autoinc_get(
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Reads the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_read(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
@ -648,7 +675,10 @@ dict_table_rename_in_cache(
|
||||
/*=======================*/
|
||||
/* out: TRUE if success */
|
||||
dict_table_t* table, /* in: table */
|
||||
char* new_name) /* in: new name */
|
||||
char* new_name, /* in: new name */
|
||||
ibool rename_also_foreigns)/* in: in ALTER TABLE we want
|
||||
to preserve the original table name
|
||||
in constraints which reference it */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
dict_index_t* index;
|
||||
@ -706,6 +736,41 @@ dict_table_rename_in_cache(
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
if (!rename_also_foreigns) {
|
||||
/* In ALTER TABLE we think of the rename table operation
|
||||
in the direction table -> temporary table (#sql...)
|
||||
as dropping the table with the old name and creating
|
||||
a new with the new name. Thus we kind of drop the
|
||||
constraints from the dictionary cache here. The foreign key
|
||||
constraints will be inherited to the new table from the
|
||||
system tables through a call of dict_load_foreigns. */
|
||||
|
||||
/* Remove the foreign constraints from the cache */
|
||||
foreign = UT_LIST_GET_LAST(table->foreign_list);
|
||||
|
||||
while (foreign != NULL) {
|
||||
dict_foreign_remove_from_cache(foreign);
|
||||
foreign = UT_LIST_GET_LAST(table->foreign_list);
|
||||
}
|
||||
|
||||
/* Reset table field in referencing constraints */
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->referenced_list);
|
||||
|
||||
while (foreign != NULL) {
|
||||
foreign->referenced_table = NULL;
|
||||
foreign->referenced_index = NULL;
|
||||
|
||||
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
|
||||
}
|
||||
|
||||
/* Make the list of referencing constraints empty */
|
||||
|
||||
UT_LIST_INIT(table->referenced_list);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* Update the table name fields in foreign constraints */
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||
@ -772,8 +837,6 @@ dict_table_remove_from_cache(
|
||||
foreign = UT_LIST_GET_LAST(table->foreign_list);
|
||||
|
||||
while (foreign != NULL) {
|
||||
ut_a(0 == ut_strcmp(foreign->foreign_table_name, table->name));
|
||||
|
||||
dict_foreign_remove_from_cache(foreign);
|
||||
foreign = UT_LIST_GET_LAST(table->foreign_list);
|
||||
}
|
||||
@ -783,8 +846,6 @@ dict_table_remove_from_cache(
|
||||
foreign = UT_LIST_GET_FIRST(table->referenced_list);
|
||||
|
||||
while (foreign != NULL) {
|
||||
ut_a(0 == ut_strcmp(foreign->referenced_table_name,
|
||||
table->name));
|
||||
foreign->referenced_table = NULL;
|
||||
foreign->referenced_index = NULL;
|
||||
|
||||
@ -1632,8 +1693,9 @@ dict_foreign_add_to_cache(
|
||||
{
|
||||
dict_table_t* for_table;
|
||||
dict_table_t* ref_table;
|
||||
dict_foreign_t* for_in_cache = NULL;
|
||||
dict_foreign_t* for_in_cache = NULL;
|
||||
dict_index_t* index;
|
||||
ibool added_to_referenced_list = FALSE;
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
@ -1677,6 +1739,7 @@ dict_foreign_add_to_cache(
|
||||
UT_LIST_ADD_LAST(referenced_list,
|
||||
ref_table->referenced_list,
|
||||
for_in_cache);
|
||||
added_to_referenced_list = TRUE;
|
||||
}
|
||||
|
||||
if (for_in_cache->foreign_table == NULL && for_table) {
|
||||
@ -1687,6 +1750,12 @@ dict_foreign_add_to_cache(
|
||||
|
||||
if (index == NULL) {
|
||||
if (for_in_cache == foreign) {
|
||||
if (added_to_referenced_list) {
|
||||
UT_LIST_REMOVE(referenced_list,
|
||||
ref_table->referenced_list,
|
||||
for_in_cache);
|
||||
}
|
||||
|
||||
mem_heap_free(foreign->heap);
|
||||
}
|
||||
|
||||
@ -1806,9 +1875,14 @@ dict_scan_col(
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
if (*ptr == '`') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
old_ptr = ptr;
|
||||
|
||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')') {
|
||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
@ -1829,6 +1903,10 @@ dict_scan_col(
|
||||
}
|
||||
}
|
||||
|
||||
if (*ptr == '`') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
@ -1859,9 +1937,13 @@ dict_scan_table_name(
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
if (*ptr == '`') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
old_ptr = ptr;
|
||||
|
||||
while (!isspace(*ptr) && *ptr != '(') {
|
||||
while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
|
||||
if (*ptr == '.') {
|
||||
dot_ptr = ptr;
|
||||
}
|
||||
@ -1902,6 +1984,10 @@ dict_scan_table_name(
|
||||
|
||||
*table = dict_table_get_low(second_table_name);
|
||||
|
||||
if (*ptr == '`') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
@ -1944,8 +2030,8 @@ dict_create_foreign_constraints(
|
||||
/*============================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
trx_t* trx, /* in: transaction */
|
||||
char* sql_string, /* in: table create statement where
|
||||
foreign keys are declared like:
|
||||
char* sql_string, /* in: table create or ALTER TABLE
|
||||
statement where foreign keys are declared like:
|
||||
FOREIGN KEY (a, b) REFERENCES table2(c, d),
|
||||
table2 can be written also with the database
|
||||
name before it: test.table2; the default
|
||||
@ -1971,10 +2057,11 @@ dict_create_foreign_constraints(
|
||||
if (table == NULL) {
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
loop:
|
||||
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
|
||||
|
||||
if (*ptr == '\0' || dict_bracket_count(sql_string, ptr) != 1) {
|
||||
if (*ptr == '\0') {
|
||||
|
||||
/* The following call adds the foreign key constraints
|
||||
to the data dictionary system tables on disk */
|
||||
@ -2889,19 +2976,21 @@ dict_field_print_low(
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Sprintfs to a string info on foreign keys of a table. */
|
||||
|
||||
Sprintfs to a string info on foreign keys of a table in a format suitable
|
||||
for CREATE TABLE. */
|
||||
static
|
||||
void
|
||||
dict_print_info_on_foreign_keys(
|
||||
/*============================*/
|
||||
dict_print_info_on_foreign_keys_in_create_format(
|
||||
/*=============================================*/
|
||||
char* buf, /* in: auxiliary buffer of 10000 chars */
|
||||
char* str, /* in/out: pointer to a string */
|
||||
ulint len, /* in: space in str available for info */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
|
||||
dict_foreign_t* foreign;
|
||||
ulint i;
|
||||
char* buf2;
|
||||
char buf[10000];
|
||||
|
||||
buf2 = buf;
|
||||
|
||||
@ -2916,11 +3005,93 @@ dict_print_info_on_foreign_keys(
|
||||
}
|
||||
|
||||
while (foreign != NULL) {
|
||||
buf2 += sprintf(buf2, "; (");
|
||||
|
||||
buf2 += sprintf(buf2, ",\n FOREIGN KEY (");
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
buf2 += sprintf(buf2, "`%s`",
|
||||
foreign->foreign_col_names[i]);
|
||||
|
||||
if (i + 1 < foreign->n_fields) {
|
||||
buf2 += sprintf(buf2, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
|
||||
foreign->referenced_table_name);
|
||||
/* Change the '/' in the table name to '.' */
|
||||
|
||||
for (i = ut_strlen(buf); i > 0; i--) {
|
||||
if (buf[i] == '/') {
|
||||
|
||||
buf[i] = '.';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
buf2 += sprintf(buf2, "`%s`",
|
||||
foreign->referenced_col_names[i]);
|
||||
if (i + 1 < foreign->n_fields) {
|
||||
buf2 += sprintf(buf2, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
buf2 += sprintf(buf2, ")");
|
||||
|
||||
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
buf[len - 1] = '\0';
|
||||
ut_memcpy(str, buf, len);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Sprintfs to a string info on foreign keys of a table. */
|
||||
|
||||
void
|
||||
dict_print_info_on_foreign_keys(
|
||||
/*============================*/
|
||||
ibool create_table_format, /* in: if TRUE then print in
|
||||
a format suitable to be inserted into
|
||||
a CREATE TABLE, otherwise in the format
|
||||
of SHOW TABLE STATUS */
|
||||
char* str, /* in/out: pointer to a string */
|
||||
ulint len, /* in: space in str available for info */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
ulint i;
|
||||
char* buf2;
|
||||
char buf[10000];
|
||||
|
||||
if (create_table_format) {
|
||||
dict_print_info_on_foreign_keys_in_create_format(
|
||||
buf, str, len, table);
|
||||
return;
|
||||
}
|
||||
|
||||
buf2 = buf;
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||
|
||||
if (foreign == NULL) {
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (foreign != NULL) {
|
||||
buf2 += sprintf(buf2, "; (");
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
buf2 += sprintf(buf2, "%s",
|
||||
foreign->foreign_col_names[i]);
|
||||
|
||||
if (i + 1 < foreign->n_fields) {
|
||||
buf2 += sprintf(buf2, " ");
|
||||
}
|
||||
|
@ -688,7 +688,16 @@ dict_load_indexes(
|
||||
|
||||
dict_load_fields(table, index, heap);
|
||||
|
||||
dict_index_add_to_cache(table, index);
|
||||
if (index->type & DICT_CLUSTERED == 0
|
||||
&& NULL == dict_table_get_first_index(table)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to load index %s for table %s\n"
|
||||
"InnoDB: but the first index was not clustered\n",
|
||||
index->name, table->name);
|
||||
} else {
|
||||
dict_index_add_to_cache(table, index);
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||
|
@ -89,8 +89,8 @@ struct fil_node_struct {
|
||||
char* name; /* the file name or path */
|
||||
ibool open; /* TRUE if file open */
|
||||
os_file_t handle; /* OS handle to the file, if file open */
|
||||
ulint size; /* size of the file in database blocks
|
||||
(where the possible last incomplete block
|
||||
ulint size; /* size of the file in database pages
|
||||
(where the possible last incomplete megabyte
|
||||
is ignored) */
|
||||
ulint n_pending;
|
||||
/* count of pending i/o-ops on this file */
|
||||
@ -945,6 +945,76 @@ fil_node_complete_io(
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Tries to extend a data file by the number of pages given. Any fractions of a
|
||||
megabyte are ignored. */
|
||||
|
||||
ibool
|
||||
fil_extend_last_data_file(
|
||||
/*======================*/
|
||||
/* out: TRUE if success, also if we run
|
||||
out of disk space we may return TRUE */
|
||||
ulint* actual_increase,/* out: number of pages we were able to
|
||||
extend, here the orginal size of the file and
|
||||
the resulting size of the file are rounded
|
||||
downwards to a full megabyte, and the
|
||||
difference expressed in pages is returned */
|
||||
ulint size_increase) /* in: try to extend this many pages */
|
||||
{
|
||||
fil_node_t* node;
|
||||
fil_space_t* space;
|
||||
fil_system_t* system = fil_system;
|
||||
byte* buf;
|
||||
ibool success;
|
||||
ulint i;
|
||||
|
||||
mutex_enter(&(system->mutex));
|
||||
|
||||
HASH_SEARCH(hash, system->spaces, 0, space, space->id == 0);
|
||||
|
||||
ut_a(space);
|
||||
|
||||
node = UT_LIST_GET_LAST(space->chain);
|
||||
|
||||
fil_node_prepare_for_io(node, system, space);
|
||||
|
||||
buf = mem_alloc(1024 * 1024);
|
||||
|
||||
memset(buf, '\0', 1024 * 1024);
|
||||
|
||||
for (i = 0; i < size_increase / ((1024 * 1024) / UNIV_PAGE_SIZE); i++) {
|
||||
|
||||
success = os_file_write(node->name, node->handle, buf,
|
||||
(node->size << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFF,
|
||||
node->size >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
1024 * 1024);
|
||||
|
||||
if (!success) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
node->size += ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
space->size += ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
|
||||
os_has_said_disk_full = FALSE;
|
||||
}
|
||||
|
||||
mem_free(buf);
|
||||
|
||||
fil_node_complete_io(node, system, OS_FILE_WRITE);
|
||||
|
||||
mutex_exit(&(system->mutex));
|
||||
|
||||
*actual_increase = i * ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
|
||||
fil_flush(0);
|
||||
|
||||
srv_data_file_sizes[srv_n_data_files - 1] += *actual_increase;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Reads or writes data. This operation is asynchronous (aio). */
|
||||
|
||||
@ -966,9 +1036,9 @@ fil_io(
|
||||
ulint byte_offset, /* in: remainder of offset in bytes; in
|
||||
aio this must be divisible by the OS block
|
||||
size */
|
||||
ulint len, /* in: how many bytes to read; this must
|
||||
not cross a file boundary; in aio this must
|
||||
be a block size multiple */
|
||||
ulint len, /* in: how many bytes to read or write; this
|
||||
must not cross a file boundary; in aio this
|
||||
must be a block size multiple */
|
||||
void* buf, /* in/out: buffer where to store read data
|
||||
or from where to write; in aio this must be
|
||||
appropriately aligned */
|
||||
|
@ -50,7 +50,7 @@ descriptor page, but used only in the first. */
|
||||
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
|
||||
free list has not been initialized:
|
||||
the pages >= this limit are, by
|
||||
definition free */
|
||||
definition, free */
|
||||
#define FSP_LOWEST_NO_WRITE 16 /* The lowest page offset for which
|
||||
the page has not been written to disk
|
||||
(if it has been written, we know that
|
||||
@ -898,6 +898,106 @@ fsp_header_inc_size(
|
||||
mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Gets the current free limit of a tablespace. The free limit means the
|
||||
place of the first page which has never been put to the the free list
|
||||
for allocation. The space above that address is initialized to zero.
|
||||
Sets also the global variable log_fsp_current_free_limit. */
|
||||
|
||||
ulint
|
||||
fsp_header_get_free_limit(
|
||||
/*======================*/
|
||||
/* out: free limit in megabytes */
|
||||
ulint space) /* in: space id */
|
||||
{
|
||||
fsp_header_t* header;
|
||||
ulint limit;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_a(space == 0); /* We have only one log_fsp_current_... variable */
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
mtr_x_lock(fil_space_get_latch(space), &mtr);
|
||||
|
||||
header = fsp_get_space_header(space, &mtr);
|
||||
|
||||
limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr);
|
||||
|
||||
limit = limit / ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
|
||||
log_fsp_current_free_limit_set_and_checkpoint(limit);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(limit);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Tries to extend the last data file file if it is defined as auto-extending. */
|
||||
static
|
||||
ibool
|
||||
fsp_try_extend_last_file(
|
||||
/*=====================*/
|
||||
/* out: FALSE if not auto-extending */
|
||||
ulint* actual_increase,/* out: actual increase in pages */
|
||||
ulint space, /* in: space */
|
||||
fsp_header_t* header, /* in: space header */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ulint size;
|
||||
ulint size_increase;
|
||||
ibool success;
|
||||
|
||||
ut_a(space == 0);
|
||||
|
||||
*actual_increase = 0;
|
||||
|
||||
if (!srv_auto_extend_last_data_file) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
|
||||
|
||||
if (srv_last_file_size_max != 0) {
|
||||
if (srv_last_file_size_max
|
||||
< srv_data_file_sizes[srv_n_data_files - 1]) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Last data file size is %lu, max size allowed %lu\n",
|
||||
srv_data_file_sizes[srv_n_data_files - 1],
|
||||
srv_last_file_size_max);
|
||||
}
|
||||
|
||||
size_increase = srv_last_file_size_max
|
||||
- srv_data_file_sizes[srv_n_data_files - 1];
|
||||
if (size_increase > SRV_AUTO_EXTEND_INCREMENT) {
|
||||
size_increase = SRV_AUTO_EXTEND_INCREMENT;
|
||||
}
|
||||
} else {
|
||||
size_increase = SRV_AUTO_EXTEND_INCREMENT;
|
||||
}
|
||||
|
||||
if (size_increase == 0) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* Extend the data file. If we are not able to extend
|
||||
the full requested length, the function tells us
|
||||
the number of full megabytes (but the unit is pages!)
|
||||
we were able to extend. */
|
||||
|
||||
success = fil_extend_last_data_file(actual_increase, size_increase);
|
||||
|
||||
if (success) {
|
||||
mlog_write_ulint(header + FSP_SIZE, size + *actual_increase,
|
||||
MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Puts new extents to the free list if there are free extents above the free
|
||||
limit. If an extent happens to contain an extent descriptor page, the extent
|
||||
@ -917,8 +1017,9 @@ fsp_fill_free_list(
|
||||
ulint frag_n_used;
|
||||
page_t* descr_page;
|
||||
page_t* ibuf_page;
|
||||
mtr_t ibuf_mtr;
|
||||
ulint actual_increase;
|
||||
ulint i;
|
||||
mtr_t ibuf_mtr;
|
||||
|
||||
ut_ad(header && mtr);
|
||||
|
||||
@ -926,12 +1027,28 @@ fsp_fill_free_list(
|
||||
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
|
||||
limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
|
||||
|
||||
if (srv_auto_extend_last_data_file
|
||||
&& size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
|
||||
|
||||
/* Try to increase the last data file size */
|
||||
fsp_try_extend_last_file(&actual_increase, space, header,
|
||||
mtr);
|
||||
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
i = limit;
|
||||
|
||||
while ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD)) {
|
||||
|
||||
mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
|
||||
MLOG_4BYTES, mtr);
|
||||
|
||||
/* Update the free limit info in the log system and make
|
||||
a checkpoint */
|
||||
log_fsp_current_free_limit_set_and_checkpoint(
|
||||
(i + FSP_EXTENT_SIZE)
|
||||
/ ((1024 * 1024) / UNIV_PAGE_SIZE));
|
||||
|
||||
if (0 == i % XDES_DESCRIBED_PER_PAGE) {
|
||||
|
||||
/* We are going to initialize a new descriptor page
|
||||
@ -1172,6 +1289,7 @@ fsp_free_page(
|
||||
xdes_t* descr;
|
||||
ulint state;
|
||||
ulint frag_n_used;
|
||||
char buf[1000];
|
||||
|
||||
ut_ad(mtr);
|
||||
|
||||
@ -1183,10 +1301,38 @@ fsp_free_page(
|
||||
|
||||
state = xdes_get_state(descr, mtr);
|
||||
|
||||
ut_a((state == XDES_FREE_FRAG) || (state == XDES_FULL_FRAG));
|
||||
if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: File space extent descriptor of page %lu has state %lu\n",
|
||||
page, state);
|
||||
ut_sprintf_buf(buf, ((byte*)descr) - 50, 200);
|
||||
|
||||
ut_a(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
|
||||
== FALSE);
|
||||
fprintf(stderr, "InnoDB: Dump of descriptor: %s\n", buf);
|
||||
|
||||
if (state == XDES_FREE) {
|
||||
/* We put here some fault tolerance: if the page
|
||||
is already free, return without doing anything! */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
|
||||
== TRUE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: File space extent descriptor of page %lu says it is free\n",
|
||||
page);
|
||||
ut_sprintf_buf(buf, ((byte*)descr) - 50, 200);
|
||||
|
||||
fprintf(stderr, "InnoDB: Dump of descriptor: %s\n", buf);
|
||||
|
||||
/* We put here some fault tolerance: if the page
|
||||
is already free, return without doing anything! */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
|
||||
xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
|
||||
@ -2243,13 +2389,15 @@ fsp_reserve_free_extents(
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
fsp_header_t* space_header;
|
||||
rw_lock_t* latch;
|
||||
ulint n_free_list_ext;
|
||||
ulint free_limit;
|
||||
ulint size;
|
||||
ulint n_free;
|
||||
ulint n_free_up;
|
||||
ulint reserve;
|
||||
rw_lock_t* latch;
|
||||
ibool success;
|
||||
ulint n_pages_added;
|
||||
|
||||
ut_ad(mtr);
|
||||
ut_ad(!mutex_own(&kernel_mutex)
|
||||
@ -2260,7 +2408,7 @@ fsp_reserve_free_extents(
|
||||
mtr_x_lock(latch, mtr);
|
||||
|
||||
space_header = fsp_get_space_header(space, mtr);
|
||||
|
||||
try_again:
|
||||
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr);
|
||||
|
||||
n_free_list_ext = flst_get_len(space_header + FSP_FREE, mtr);
|
||||
@ -2291,7 +2439,7 @@ fsp_reserve_free_extents(
|
||||
|
||||
if (n_free <= reserve + n_ext) {
|
||||
|
||||
return(FALSE);
|
||||
goto try_to_extend;
|
||||
}
|
||||
} else if (alloc_type == FSP_UNDO) {
|
||||
/* We reserve 1 % of the space size to cleaning operations */
|
||||
@ -2300,13 +2448,26 @@ fsp_reserve_free_extents(
|
||||
|
||||
if (n_free <= reserve + n_ext) {
|
||||
|
||||
return(FALSE);
|
||||
goto try_to_extend;
|
||||
}
|
||||
} else {
|
||||
ut_a(alloc_type == FSP_CLEANING);
|
||||
}
|
||||
|
||||
return(fil_space_reserve_free_extents(space, n_free, n_ext));
|
||||
success = fil_space_reserve_free_extents(space, n_free, n_ext);
|
||||
|
||||
if (success) {
|
||||
return(TRUE);
|
||||
}
|
||||
try_to_extend:
|
||||
success = fsp_try_extend_last_file(&n_pages_added, space,
|
||||
space_header, mtr);
|
||||
if (success && n_pages_added > 0) {
|
||||
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -28,6 +28,16 @@ a margin of replaceable pages there. */
|
||||
void
|
||||
buf_flush_free_margin(void);
|
||||
/*=======================*/
|
||||
/************************************************************************
|
||||
Initializes a page for writing to the tablespace. */
|
||||
|
||||
void
|
||||
buf_flush_init_for_writing(
|
||||
/*=======================*/
|
||||
byte* page, /* in: page */
|
||||
dulint newest_lsn, /* in: newest modification lsn to the page */
|
||||
ulint space, /* in: space id */
|
||||
ulint page_no); /* in: page number */
|
||||
/***********************************************************************
|
||||
This utility flushes dirty blocks from the end of the LRU list or flush_list.
|
||||
NOTE 1: in the case of an LRU flush the calling thread may own latches to
|
||||
|
@ -105,7 +105,8 @@ dict_table_autoinc_initialize(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: value which was assigned to a row */
|
||||
/************************************************************************
|
||||
Gets the next autoinc value, 0 if not yet initialized. */
|
||||
Gets the next autoinc value, 0 if not yet initialized. If initialized,
|
||||
increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
@ -113,6 +114,15 @@ dict_table_autoinc_get(
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Reads the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_read(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
@ -143,7 +153,10 @@ dict_table_rename_in_cache(
|
||||
/*=======================*/
|
||||
/* out: TRUE if success */
|
||||
dict_table_t* table, /* in: table */
|
||||
char* new_name); /* in: new name */
|
||||
char* new_name, /* in: new name */
|
||||
ibool rename_also_foreigns);/* in: in ALTER TABLE we want
|
||||
to preserve the original table name
|
||||
in constraints which reference it */
|
||||
/**************************************************************************
|
||||
Adds a foreign key constraint object to the dictionary cache. May free
|
||||
the object if there already is an object with the same identifier in.
|
||||
@ -284,6 +297,10 @@ Sprintfs to a string info on foreign keys of a table. */
|
||||
void
|
||||
dict_print_info_on_foreign_keys(
|
||||
/*============================*/
|
||||
ibool create_table_format, /* in: if TRUE then print in
|
||||
a format suitable to be inserted into
|
||||
a CREATE TABLE, otherwise in the format
|
||||
of SHOW TABLE STATUS */
|
||||
char* str, /* in/out: pointer to a string */
|
||||
ulint len, /* in: space in str available for info */
|
||||
dict_table_t* table); /* in: table */
|
||||
|
@ -64,8 +64,10 @@ extern fil_addr_t fil_addr_null;
|
||||
#define FIL_PAGE_DATA 38 /* start of the data on the page */
|
||||
|
||||
/* File page trailer */
|
||||
#define FIL_PAGE_END_LSN 8 /* this should be same as
|
||||
FIL_PAGE_LSN */
|
||||
#define FIL_PAGE_END_LSN 8 /* the low 4 bytes of this are used
|
||||
to store the page checksum, the
|
||||
last 4 bytes should be identical
|
||||
to the last 4 bytes of FIL_PAGE_LSN */
|
||||
#define FIL_PAGE_DATA_END 8
|
||||
|
||||
/* File page types */
|
||||
@ -134,6 +136,21 @@ fil_space_truncate_start(
|
||||
ulint trunc_len); /* in: truncate by this much; it is an error
|
||||
if this does not equal to the combined size of
|
||||
some initial files in the space */
|
||||
/**************************************************************************
|
||||
Tries to extend a data file by the number of pages given. Any fractions of a
|
||||
megabyte are ignored. */
|
||||
|
||||
ibool
|
||||
fil_extend_last_data_file(
|
||||
/*======================*/
|
||||
/* out: TRUE if success, also if we run
|
||||
out of disk space we may return TRUE */
|
||||
ulint* actual_increase,/* out: number of pages we were able to
|
||||
extend, here the orginal size of the file and
|
||||
the resulting size of the file are rounded
|
||||
downwards to a full megabyte, and the
|
||||
difference expressed in pages is returned */
|
||||
ulint size_increase); /* in: try to extend this many pages */
|
||||
/***********************************************************************
|
||||
Frees a space object from a file system. Closes the files in the chain
|
||||
but does not delete them. */
|
||||
|
@ -46,6 +46,17 @@ void
|
||||
fsp_init(void);
|
||||
/*==========*/
|
||||
/**************************************************************************
|
||||
Gets the current free limit of a tablespace. The free limit means the
|
||||
place of the first page which has never been put to the the free list
|
||||
for allocation. The space above that address is initialized to zero.
|
||||
Sets also the global variable log_fsp_current_free_limit. */
|
||||
|
||||
ulint
|
||||
fsp_header_get_free_limit(
|
||||
/*======================*/
|
||||
/* out: free limit in megabytes */
|
||||
ulint space); /* in: space id */
|
||||
/**************************************************************************
|
||||
Initializes the space header of a new created space. */
|
||||
|
||||
void
|
||||
|
@ -26,6 +26,32 @@ extern ibool log_debug_writes;
|
||||
#define LOG_WAIT_ALL_GROUPS 93
|
||||
#define LOG_MAX_N_GROUPS 32
|
||||
|
||||
/********************************************************************
|
||||
Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
|
||||
so that we know that the limit has been written to a log checkpoint field
|
||||
on disk. */
|
||||
|
||||
void
|
||||
log_fsp_current_free_limit_set_and_checkpoint(
|
||||
/*==========================================*/
|
||||
ulint limit); /* in: limit to set */
|
||||
/***********************************************************************
|
||||
Calculates where in log files we find a specified lsn. */
|
||||
|
||||
ulint
|
||||
log_calc_where_lsn_is(
|
||||
/*==================*/
|
||||
/* out: log file number */
|
||||
ib_longlong* log_file_offset, /* out: offset in that file
|
||||
(including the header) */
|
||||
dulint first_header_lsn, /* in: first log file start
|
||||
lsn */
|
||||
dulint lsn, /* in: lsn whose position to
|
||||
determine */
|
||||
ulint n_log_files, /* in: total number of log
|
||||
files */
|
||||
ib_longlong log_file_size); /* in: log file size
|
||||
(including the header) */
|
||||
/****************************************************************
|
||||
Writes to the log the string given. The log must be released with
|
||||
log_release. */
|
||||
@ -225,6 +251,16 @@ Writes checkpoint info to groups. */
|
||||
void
|
||||
log_groups_write_checkpoint_info(void);
|
||||
/*==================================*/
|
||||
/**********************************************************
|
||||
Writes info to a buffer of a log group when log files are created in
|
||||
backup restoration. */
|
||||
|
||||
void
|
||||
log_reset_first_header_and_checkpoint(
|
||||
/*==================================*/
|
||||
byte* hdr_buf,/* in: buffer which will be written to the start
|
||||
of the first log file */
|
||||
dulint lsn); /* in: lsn of the start of the first log file */
|
||||
/************************************************************************
|
||||
Starts an archiving operation. */
|
||||
|
||||
@ -507,7 +543,16 @@ extern log_t* log_sys;
|
||||
+ LOG_MAX_N_GROUPS * 8)
|
||||
#define LOG_CHECKPOINT_CHECKSUM_1 LOG_CHECKPOINT_ARRAY_END
|
||||
#define LOG_CHECKPOINT_CHECKSUM_2 (4 + LOG_CHECKPOINT_ARRAY_END)
|
||||
#define LOG_CHECKPOINT_SIZE (8 + LOG_CHECKPOINT_ARRAY_END)
|
||||
#define LOG_CHECKPOINT_FSP_FREE_LIMIT (8 + LOG_CHECKPOINT_ARRAY_END)
|
||||
/* current fsp free limit in the
|
||||
tablespace, in units of one megabyte */
|
||||
#define LOG_CHECKPOINT_FSP_MAGIC_N (12 + LOG_CHECKPOINT_ARRAY_END)
|
||||
/* this magic number tells if the
|
||||
checkpoint contains the above field:
|
||||
the field was added to InnoDB-3.23.50 */
|
||||
#define LOG_CHECKPOINT_SIZE (16 + LOG_CHECKPOINT_ARRAY_END)
|
||||
|
||||
#define LOG_CHECKPOINT_FSP_MAGIC_N_VAL 1441231243
|
||||
|
||||
/* Offsets of a log file header */
|
||||
#define LOG_GROUP_ID 0 /* log group number */
|
||||
|
@ -15,6 +15,39 @@ Created 9/20/1997 Heikki Tuuri
|
||||
#include "hash0hash.h"
|
||||
#include "log0log.h"
|
||||
|
||||
/***********************************************************************
|
||||
Reads the checkpoint info needed in hot backup. */
|
||||
|
||||
ibool
|
||||
recv_read_cp_info_for_backup(
|
||||
/*=========================*/
|
||||
/* out: TRUE if success */
|
||||
byte* hdr, /* in: buffer containing the log group header */
|
||||
dulint* lsn, /* out: checkpoint lsn */
|
||||
ulint* offset, /* out: checkpoint offset in the log group */
|
||||
ulint* fsp_limit,/* out: fsp limit, 1000000000 if the database
|
||||
is running with < version 3.23.50 of InnoDB */
|
||||
dulint* cp_no, /* out: checkpoint number */
|
||||
dulint* first_header_lsn);
|
||||
/* out: lsn of of the start of the first log file */
|
||||
/***********************************************************************
|
||||
Scans the log segment and n_bytes_scanned is set to the length of valid
|
||||
log scanned. */
|
||||
|
||||
void
|
||||
recv_scan_log_seg_for_backup(
|
||||
/*=========================*/
|
||||
byte* buf, /* in: buffer containing log data */
|
||||
ulint buf_len, /* in: data length in that buffer */
|
||||
dulint* scanned_lsn, /* in/out: lsn of buffer start,
|
||||
we return scanned lsn */
|
||||
ulint* scanned_checkpoint_no,
|
||||
/* in/out: 4 lowest bytes of the
|
||||
highest scanned checkpoint number so
|
||||
far */
|
||||
ulint* n_bytes_scanned);/* out: how much we were able to
|
||||
scan, smaller than buf_len if log
|
||||
data ended here */
|
||||
/***********************************************************************
|
||||
Returns TRUE if recovery is currently running. */
|
||||
UNIV_INLINE
|
||||
@ -35,6 +68,10 @@ read in, or also for a page already in the buffer pool. */
|
||||
void
|
||||
recv_recover_page(
|
||||
/*==============*/
|
||||
ibool recover_backup, /* in: TRUE if we are recovering a backup
|
||||
page: then we do not acquire any latches
|
||||
since the page was read in outside the
|
||||
buffer pool */
|
||||
ibool just_read_in, /* in: TRUE if the i/o-handler calls this for
|
||||
a freshly read page */
|
||||
page_t* page, /* in: buffer page */
|
||||
@ -69,8 +106,15 @@ recv_scan_log_recs(
|
||||
/*===============*/
|
||||
/* out: TRUE if limit_lsn has been reached, or
|
||||
not able to scan any more in this log group */
|
||||
ibool apply_automatically,/* in: TRUE if we want this function to
|
||||
apply log records automatically when the
|
||||
hash table becomes full; in the hot backup tool
|
||||
the tool does the applying, not this
|
||||
function */
|
||||
ulint available_memory,/* in: we let the hash table of recs to grow
|
||||
to this size, at the maximum */
|
||||
ibool store_to_hash, /* in: TRUE if the records should be stored
|
||||
to the hash table; this is set FALSE if just
|
||||
to the hash table; this is set to FALSE if just
|
||||
debug checking is needed */
|
||||
byte* buf, /* in: buffer containing a log segment or
|
||||
garbage */
|
||||
@ -92,6 +136,16 @@ recv_reset_logs(
|
||||
ibool new_logs_created);/* in: TRUE if resetting logs is done
|
||||
at the log creation; FALSE if it is done
|
||||
after archive recovery */
|
||||
/**********************************************************
|
||||
Creates new log files after a backup has been restored. */
|
||||
|
||||
void
|
||||
recv_reset_log_files_for_backup(
|
||||
/*============================*/
|
||||
char* log_dir, /* in: log file directory path */
|
||||
ulint n_log_files, /* in: number of log files */
|
||||
ulint log_file_size, /* in: log file size */
|
||||
dulint lsn); /* in: new start lsn */
|
||||
/************************************************************
|
||||
Creates the recovery system. */
|
||||
|
||||
@ -102,8 +156,11 @@ recv_sys_create(void);
|
||||
Inits the recovery system for a recovery operation. */
|
||||
|
||||
void
|
||||
recv_sys_init(void);
|
||||
/*===============*/
|
||||
recv_sys_init(
|
||||
/*==========*/
|
||||
ibool recover_from_backup, /* in: TRUE if this is called
|
||||
to recover from a hot backup */
|
||||
ulint available_memory); /* in: available memory in bytes */
|
||||
/***********************************************************************
|
||||
Empties the hash table of stored log records, applying them to appropriate
|
||||
pages. */
|
||||
@ -118,6 +175,17 @@ recv_apply_hashed_log_recs(
|
||||
disk and invalidated in buffer pool: this
|
||||
alternative means that no new log records
|
||||
can be generated during the application */
|
||||
/***********************************************************************
|
||||
Applies log records in the hash table to a backup. */
|
||||
|
||||
void
|
||||
recv_apply_log_recs_for_backup(
|
||||
/*===========================*/
|
||||
ulint n_data_files, /* in: number of data files */
|
||||
char** data_files, /* in: array containing the paths to the
|
||||
data files */
|
||||
ulint* file_sizes); /* in: sizes of the data files in database
|
||||
pages */
|
||||
/************************************************************
|
||||
Recovers from archived log files, and also from log files, if they exist. */
|
||||
|
||||
@ -260,6 +328,14 @@ extern ibool recv_recovery_on;
|
||||
extern ibool recv_no_ibuf_operations;
|
||||
extern ibool recv_needed_recovery;
|
||||
|
||||
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
|
||||
times! */
|
||||
#define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024)
|
||||
|
||||
/* Size of block reads when the log groups are scanned forward to do a
|
||||
roll-forward */
|
||||
#define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE)
|
||||
|
||||
/* States of recv_addr_struct */
|
||||
#define RECV_NOT_PROCESSED 71
|
||||
#define RECV_BEING_READ 72
|
||||
|
@ -41,11 +41,11 @@ page buffer pool; the latter method is used for very big heaps */
|
||||
|
||||
/* The following start size is used for the first block in the memory heap if
|
||||
the size is not specified, i.e., 0 is given as the parameter in the call of
|
||||
create. The standard size is the maximum size of the blocks used for
|
||||
create. The standard size is the maximum (payload) size of the blocks used for
|
||||
allocations of small buffers. */
|
||||
|
||||
#define MEM_BLOCK_START_SIZE 64
|
||||
#define MEM_BLOCK_STANDARD_SIZE 8192
|
||||
#define MEM_BLOCK_STANDARD_SIZE 8000
|
||||
|
||||
/* If a memory heap is allowed to grow into the buffer pool, the following
|
||||
is the maximum size for a single allocated buffer: */
|
||||
|
@ -11,6 +11,12 @@ Created 10/21/1995 Heikki Tuuri
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
|
||||
/* If the following is set to TRUE, we do not call os_file_flush in every
|
||||
os_file_write */
|
||||
extern ibool os_do_not_call_flush_at_each_write;
|
||||
extern ibool os_has_said_disk_full;
|
||||
|
||||
#ifdef __WIN__
|
||||
|
||||
/* We define always WIN_ASYNC_IO, and check at run-time whether
|
||||
@ -55,6 +61,9 @@ log. */
|
||||
#define OS_FILE_CREATE 52
|
||||
#define OS_FILE_OVERWRITE 53
|
||||
|
||||
#define OS_FILE_READ_ONLY 333
|
||||
#define OS_FILE_READ_WRITE 444
|
||||
|
||||
/* Options for file_create */
|
||||
#define OS_FILE_AIO 61
|
||||
#define OS_FILE_NORMAL 62
|
||||
@ -118,6 +127,27 @@ os_get_os_version(void);
|
||||
/*===================*/
|
||||
/* out: OS_WIN95, OS_WIN31, OS_WINNT (2000 == NT) */
|
||||
/********************************************************************
|
||||
Creates the seek mutexes used in positioned reads and writes. */
|
||||
|
||||
void
|
||||
os_io_init_simple(void);
|
||||
/*===================*/
|
||||
/********************************************************************
|
||||
A simple function to open or create a file. */
|
||||
|
||||
os_file_t
|
||||
os_file_create_simple(
|
||||
/*==================*/
|
||||
/* out, own: handle to the file, not defined if error,
|
||||
error number can be retrieved with os_get_last_error */
|
||||
char* name, /* in: name of the file or path as a null-terminated
|
||||
string */
|
||||
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
|
||||
(if does not exist, error), or OS_FILE_CREATE if a new
|
||||
file is created (if exists, error) */
|
||||
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
|
||||
ibool* success);/* out: TRUE if succeed, FALSE if error */
|
||||
/********************************************************************
|
||||
Opens an existing file or creates a new. */
|
||||
|
||||
os_file_t
|
||||
|
@ -402,13 +402,13 @@ struct row_prebuilt_struct {
|
||||
byte* ins_upd_rec_buff;/* buffer for storing data converted
|
||||
to the Innobase format from the MySQL
|
||||
format */
|
||||
ibool in_update_remember_pos;
|
||||
/* if an update is processed, then if
|
||||
this flag is set to TRUE, it means
|
||||
that the stored cursor position in
|
||||
SELECT is the right position also
|
||||
for the update: we can just restore
|
||||
the cursor and save CPU time */
|
||||
ibool hint_no_need_to_fetch_extra_cols;
|
||||
/* normally this is TRUE, but
|
||||
MySQL will set this to FALSE
|
||||
if we might be required to fetch also
|
||||
other columns than mentioned in the
|
||||
query: the clustered index column(s),
|
||||
or an auto-increment column*/
|
||||
upd_node_t* upd_node; /* Innobase SQL update node used
|
||||
to perform updates and deletes */
|
||||
que_fork_t* ins_graph; /* Innobase SQL query graph used
|
||||
|
@ -24,10 +24,13 @@ extern char srv_fatal_errbuf[];
|
||||
thread starts running */
|
||||
extern os_event_t srv_lock_timeout_thread_event;
|
||||
|
||||
/* If the last data file is auto-extended, we add this many pages to it
|
||||
at a time */
|
||||
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE))
|
||||
|
||||
/* Server parameters which are read from the initfile */
|
||||
|
||||
extern char* srv_data_home;
|
||||
extern char* srv_logs_home;
|
||||
extern char* srv_arch_dir;
|
||||
|
||||
extern ulint srv_n_data_files;
|
||||
@ -35,6 +38,9 @@ extern char** srv_data_file_names;
|
||||
extern ulint* srv_data_file_sizes;
|
||||
extern ulint* srv_data_file_is_raw_partition;
|
||||
|
||||
extern ibool srv_auto_extend_last_data_file;
|
||||
extern ulint srv_last_file_size_max;
|
||||
|
||||
extern ibool srv_created_new_raw;
|
||||
|
||||
#define SRV_NEW_RAW 1
|
||||
@ -186,6 +192,19 @@ srv_boot(void);
|
||||
/*==========*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
/*************************************************************************
|
||||
Initializes the server. */
|
||||
|
||||
void
|
||||
srv_init(void);
|
||||
/*==========*/
|
||||
/*************************************************************************
|
||||
Initializes the synchronization primitives, memory system, and the thread
|
||||
local storage. */
|
||||
|
||||
void
|
||||
srv_general_init(void);
|
||||
/*==================*/
|
||||
/*************************************************************************
|
||||
Gets the number of threads in the system. */
|
||||
|
||||
ulint
|
||||
|
@ -12,6 +12,56 @@ Created 10/10/1995 Heikki Tuuri
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
/*************************************************************************
|
||||
Normalizes a directory path for Windows: converts slashes to backslashes. */
|
||||
|
||||
void
|
||||
srv_normalize_path_for_win(
|
||||
/*=======================*/
|
||||
char* str); /* in/out: null-terminated character string */
|
||||
/*************************************************************************
|
||||
Adds a slash or a backslash to the end of a string if it is missing
|
||||
and the string is not empty. */
|
||||
|
||||
char*
|
||||
srv_add_path_separator_if_needed(
|
||||
/*=============================*/
|
||||
/* out, own: string which has the separator if the
|
||||
string is not empty */
|
||||
char* str); /* in: null-terminated character string */
|
||||
/*************************************************************************
|
||||
Reads the data files and their sizes from a character string given in
|
||||
the .cnf file. */
|
||||
|
||||
ibool
|
||||
srv_parse_data_file_paths_and_sizes(
|
||||
/*================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
char* str, /* in: the data file path string */
|
||||
char*** data_file_names, /* out, own: array of data file
|
||||
names */
|
||||
ulint** data_file_sizes, /* out, own: array of data file sizes
|
||||
in megabytes */
|
||||
ulint** data_file_is_raw_partition,/* out, own: array of flags
|
||||
showing which data files are raw
|
||||
partitions */
|
||||
ulint* n_data_files, /* out: number of data files */
|
||||
ibool* is_auto_extending, /* out: TRUE if the last data file is
|
||||
auto-extending */
|
||||
ulint* max_auto_extend_size); /* out: max auto extend size for the
|
||||
last file if specified, 0 if not */
|
||||
/*************************************************************************
|
||||
Reads log group home directories from a character string given in
|
||||
the .cnf file. */
|
||||
|
||||
ibool
|
||||
srv_parse_log_group_home_dirs(
|
||||
/*==========================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
char* str, /* in: character string */
|
||||
char*** log_group_home_dirs); /* out, own: log group home dirs */
|
||||
/********************************************************************
|
||||
Starts Innobase and creates a new database if database files
|
||||
are not found and the user wants. Server parameters are
|
||||
|
@ -357,7 +357,7 @@ rw_lock_s_unlock_func(
|
||||
|
||||
/* Reset the shared lock by decrementing the reader count */
|
||||
|
||||
ut_ad(lock->reader_count > 0);
|
||||
ut_a(lock->reader_count > 0);
|
||||
lock->reader_count--;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -44,6 +44,15 @@ half-written pages in the data files. */
|
||||
void
|
||||
trx_sys_doublewrite_restore_corrupt_pages(void);
|
||||
/*===========================================*/
|
||||
/********************************************************************
|
||||
Determines if a page number is located inside the doublewrite buffer. */
|
||||
|
||||
ibool
|
||||
trx_doublewrite_page_inside(
|
||||
/*========================*/
|
||||
/* out: TRUE if the location is inside
|
||||
the two blocks of the doublewrite buffer */
|
||||
ulint page_no); /* in: page number */
|
||||
/*******************************************************************
|
||||
Checks if a page address is the trx sys header page. */
|
||||
UNIV_INLINE
|
||||
|
@ -55,6 +55,15 @@ ut_dulint_get_low(
|
||||
/* out: 32 bits in ulint */
|
||||
dulint d); /* in: dulint */
|
||||
/***********************************************************
|
||||
Converts a dulint (a struct of 2 ulints) to ib_longlong, which is a 64-bit
|
||||
integer type. */
|
||||
UNIV_INLINE
|
||||
ib_longlong
|
||||
ut_conv_dulint_to_longlong(
|
||||
/*=======================*/
|
||||
/* out: value in ib_longlong type */
|
||||
dulint d); /* in: dulint */
|
||||
/***********************************************************
|
||||
Tests if a dulint is zero. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
|
@ -51,6 +51,20 @@ ut_dulint_get_low(
|
||||
return(d.low);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Converts a dulint (a struct of 2 ulints) to ib_longlong, which is a 64-bit
|
||||
integer type. */
|
||||
UNIV_INLINE
|
||||
ib_longlong
|
||||
ut_conv_dulint_to_longlong(
|
||||
/*=======================*/
|
||||
/* out: value in ib_longlong type */
|
||||
dulint d) /* in: dulint */
|
||||
{
|
||||
return((ib_longlong)d.low
|
||||
+ (((ib_longlong)d.high) << 32));
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Tests if a dulint is zero. */
|
||||
UNIV_INLINE
|
||||
|
@ -35,7 +35,7 @@ ut_rnd_gen_next_ulint(
|
||||
/*************************************************************
|
||||
The following function generates 'random' ulint integers which
|
||||
enumerate the value space (let there be N of them) of ulint integers
|
||||
in a pseudo random fashion. Note that the same integer is repeated
|
||||
in a pseudo-random fashion. Note that the same integer is repeated
|
||||
always after N calls to the generator. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
|
@ -17,6 +17,16 @@ Created 1/20/1994 Heikki Tuuri
|
||||
|
||||
typedef time_t ib_time_t;
|
||||
|
||||
/************************************************************
|
||||
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
|
||||
but since there seem to be compiler bugs in both gcc and Visual C++,
|
||||
we do this by a special conversion. */
|
||||
|
||||
ulint
|
||||
ut_get_high32(
|
||||
/*==========*/
|
||||
/* out: a >> 32 */
|
||||
ulint a); /* in: ulint */
|
||||
/**********************************************************
|
||||
Calculates the minimum of two ulints. */
|
||||
UNIV_INLINE
|
||||
@ -144,6 +154,15 @@ void
|
||||
ut_print_timestamp(
|
||||
/*===============*/
|
||||
FILE* file); /* in: file where to print */
|
||||
/**************************************************************
|
||||
Returns current year, month, day. */
|
||||
|
||||
void
|
||||
ut_get_year_month_day(
|
||||
/*==================*/
|
||||
ulint* year, /* out: current year */
|
||||
ulint* month, /* out: month */
|
||||
ulint* day); /* out: day */
|
||||
/*****************************************************************
|
||||
Runs an idle loop on CPU. The argument gives the desired delay
|
||||
in microseconds on 100 MHz Pentium + Visual C++. */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/******************************************************
|
||||
Database log
|
||||
|
||||
(c) 1995-1997 InnoDB Oy
|
||||
(c) 1995-1997 Innobase Oy
|
||||
|
||||
Created 12/9/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
@ -24,6 +24,9 @@ Created 12/9/1995 Heikki Tuuri
|
||||
#include "trx0sys.h"
|
||||
#include "trx0trx.h"
|
||||
|
||||
/* Current free limit; protected by the log sys mutex; 0 means uninitialized */
|
||||
ulint log_fsp_current_free_limit = 0;
|
||||
|
||||
/* Global log system variable */
|
||||
log_t* log_sys = NULL;
|
||||
|
||||
@ -95,6 +98,32 @@ void
|
||||
log_archive_margin(void);
|
||||
/*====================*/
|
||||
|
||||
/********************************************************************
|
||||
Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
|
||||
so that we know that the limit has been written to a log checkpoint field
|
||||
on disk. */
|
||||
|
||||
void
|
||||
log_fsp_current_free_limit_set_and_checkpoint(
|
||||
/*==========================================*/
|
||||
ulint limit) /* in: limit to set */
|
||||
{
|
||||
ibool success;
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
log_fsp_current_free_limit = limit;
|
||||
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
|
||||
/* Try to make a synchronous checkpoint */
|
||||
|
||||
success = FALSE;
|
||||
|
||||
while (!success) {
|
||||
success = log_checkpoint(TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Returns the oldest modified block lsn in the pool, or log_sys->lsn if none
|
||||
@ -436,6 +465,51 @@ log_group_calc_lsn_offset(
|
||||
return(log_group_calc_real_offset(offset, group));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Calculates where in log files we find a specified lsn. */
|
||||
|
||||
ulint
|
||||
log_calc_where_lsn_is(
|
||||
/*==================*/
|
||||
/* out: log file number */
|
||||
ib_longlong* log_file_offset, /* out: offset in that file
|
||||
(including the header) */
|
||||
dulint first_header_lsn, /* in: first log file start
|
||||
lsn */
|
||||
dulint lsn, /* in: lsn whose position to
|
||||
determine */
|
||||
ulint n_log_files, /* in: total number of log
|
||||
files */
|
||||
ib_longlong log_file_size) /* in: log file size
|
||||
(including the header) */
|
||||
{
|
||||
ib_longlong ib_lsn;
|
||||
ib_longlong ib_first_header_lsn;
|
||||
ib_longlong capacity = log_file_size - LOG_FILE_HDR_SIZE;
|
||||
ulint file_no;
|
||||
ib_longlong add_this_many;
|
||||
|
||||
ib_lsn = ut_conv_dulint_to_longlong(lsn);
|
||||
ib_first_header_lsn = ut_conv_dulint_to_longlong(first_header_lsn);
|
||||
|
||||
if (ib_lsn < ib_first_header_lsn) {
|
||||
add_this_many = 1 + (ib_first_header_lsn - ib_lsn)
|
||||
/ (capacity * (ib_longlong)n_log_files);
|
||||
ib_lsn += add_this_many
|
||||
* capacity * (ib_longlong)n_log_files;
|
||||
}
|
||||
|
||||
ut_a(ib_lsn >= ib_first_header_lsn);
|
||||
|
||||
file_no = ((ulint)((ib_lsn - ib_first_header_lsn) / capacity))
|
||||
% n_log_files;
|
||||
*log_file_offset = (ib_lsn - ib_first_header_lsn) % capacity;
|
||||
|
||||
*log_file_offset = *log_file_offset + LOG_FILE_HDR_SIZE;
|
||||
|
||||
return(file_no);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Sets the field values in group to correspond to a given lsn. For this function
|
||||
to work, the values must already be correctly initialized to correspond to
|
||||
@ -653,7 +727,7 @@ log_init(void)
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
recv_sys_create();
|
||||
recv_sys_init();
|
||||
recv_sys_init(FALSE, buf_pool_get_curr_size());
|
||||
|
||||
recv_sys->parse_start_lsn = log_sys->lsn;
|
||||
recv_sys->scanned_lsn = log_sys->lsn;
|
||||
@ -961,7 +1035,7 @@ log_group_write_buf(
|
||||
ibool sync;
|
||||
ibool write_header;
|
||||
ulint next_offset;
|
||||
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
@ -1002,9 +1076,28 @@ loop:
|
||||
}
|
||||
|
||||
if (log_debug_writes) {
|
||||
ulint i;
|
||||
|
||||
printf(
|
||||
"Writing log file segment to group %lu offset %lu len %lu\n",
|
||||
group->id, next_offset, write_len);
|
||||
"Writing log file segment to group %lu offset %lu len %lu\n"
|
||||
"start lsn %lu %lu\n",
|
||||
group->id, next_offset, write_len,
|
||||
ut_dulint_get_high(start_lsn),
|
||||
ut_dulint_get_low(start_lsn));
|
||||
printf(
|
||||
"First block n:o %lu last block n:o %lu\n",
|
||||
log_block_get_hdr_no(buf),
|
||||
log_block_get_hdr_no(
|
||||
buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
|
||||
ut_a(log_block_get_hdr_no(buf)
|
||||
== log_block_convert_lsn_to_no(start_lsn));
|
||||
|
||||
for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
|
||||
|
||||
ut_a(log_block_get_hdr_no(buf) + i
|
||||
== log_block_get_hdr_no(buf
|
||||
+ i * OS_FILE_LOG_BLOCK_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
if (log_do_write) {
|
||||
@ -1346,7 +1439,7 @@ log_group_checkpoint(
|
||||
ulint i;
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
ut_ad(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
|
||||
ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
buf = group->checkpoint_buf;
|
||||
|
||||
@ -1394,6 +1487,15 @@ log_group_checkpoint(
|
||||
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
|
||||
|
||||
/* Starting from InnoDB-3.23.50, we also write info on allocated
|
||||
size in the tablespace */
|
||||
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_FSP_FREE_LIMIT,
|
||||
log_fsp_current_free_limit);
|
||||
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_FSP_MAGIC_N,
|
||||
LOG_CHECKPOINT_FSP_MAGIC_N_VAL);
|
||||
|
||||
/* We alternate the physical place of the checkpoint info in the first
|
||||
log file */
|
||||
|
||||
@ -1428,6 +1530,48 @@ log_group_checkpoint(
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Writes info to a buffer of a log group when log files are created in
|
||||
backup restoration. */
|
||||
|
||||
void
|
||||
log_reset_first_header_and_checkpoint(
|
||||
/*==================================*/
|
||||
byte* hdr_buf,/* in: buffer which will be written to the start
|
||||
of the first log file */
|
||||
dulint lsn) /* in: lsn of the start of the first log file
|
||||
+ LOG_BLOCK_HDR_SIZE */
|
||||
{
|
||||
ulint fold;
|
||||
byte* buf;
|
||||
|
||||
mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0);
|
||||
mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, lsn);
|
||||
|
||||
buf = hdr_buf + LOG_CHECKPOINT_1;
|
||||
|
||||
mach_write_to_8(buf + LOG_CHECKPOINT_NO, ut_dulint_zero);
|
||||
mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn);
|
||||
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
|
||||
LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE);
|
||||
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024);
|
||||
|
||||
mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
|
||||
|
||||
fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
|
||||
|
||||
fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
|
||||
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
|
||||
|
||||
/* Starting from InnoDB-3.23.50, we should also write info on
|
||||
allocated size in the tablespace, but unfortunately we do not
|
||||
know it here */
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Reads a checkpoint info from a log group header to log_sys->checkpoint_buf. */
|
||||
|
||||
@ -2800,7 +2944,10 @@ log_check_log_recs(
|
||||
|
||||
ut_memcpy(scan_buf, start, end - start);
|
||||
|
||||
recv_scan_log_recs(FALSE, scan_buf, end - start,
|
||||
recv_scan_log_recs(TRUE,
|
||||
buf_pool_get_curr_size() -
|
||||
RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
|
||||
FALSE, scan_buf, end - start,
|
||||
ut_dulint_align_down(buf_start_lsn,
|
||||
OS_FILE_LOG_BLOCK_SIZE),
|
||||
&contiguous_lsn, &scanned_lsn);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/******************************************************
|
||||
Recovery
|
||||
|
||||
(c) 1997 InnoDB Oy
|
||||
(c) 1997 Innobase Oy
|
||||
|
||||
Created 9/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
@ -33,13 +33,6 @@ Created 9/20/1997 Heikki Tuuri
|
||||
#include "dict0boot.h"
|
||||
#include "fil0fil.h"
|
||||
|
||||
/* Size of block reads when the log groups are scanned forward to do a
|
||||
roll-forward */
|
||||
#define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE)
|
||||
|
||||
/* Size of the parsing buffer */
|
||||
#define RECV_PARSING_BUF_SIZE LOG_BUFFER_SIZE
|
||||
|
||||
/* Log records are stored in the hash table in chunks at most of this size;
|
||||
this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */
|
||||
#define RECV_DATA_BLOCK_SIZE (MEM_MAX_ALLOC_IN_BUF - sizeof(recv_data_t))
|
||||
@ -69,6 +62,9 @@ ibool recv_no_ibuf_operations = FALSE;
|
||||
log scan */
|
||||
ulint recv_scan_print_counter = 0;
|
||||
|
||||
ibool recv_is_from_backup = FALSE;
|
||||
|
||||
|
||||
/************************************************************
|
||||
Creates the recovery system. */
|
||||
|
||||
@ -94,8 +90,11 @@ recv_sys_create(void)
|
||||
Inits the recovery system for a recovery operation. */
|
||||
|
||||
void
|
||||
recv_sys_init(void)
|
||||
/*===============*/
|
||||
recv_sys_init(
|
||||
/*==========*/
|
||||
ibool recover_from_backup, /* in: TRUE if this is called
|
||||
to recover from a hot backup */
|
||||
ulint available_memory) /* in: available memory in bytes */
|
||||
{
|
||||
if (recv_sys->heap != NULL) {
|
||||
|
||||
@ -104,13 +103,18 @@ recv_sys_init(void)
|
||||
|
||||
mutex_enter(&(recv_sys->mutex));
|
||||
|
||||
recv_sys->heap = mem_heap_create_in_buffer(256);
|
||||
if (!recover_from_backup) {
|
||||
recv_sys->heap = mem_heap_create_in_buffer(256);
|
||||
} else {
|
||||
recv_sys->heap = mem_heap_create(256);
|
||||
recv_is_from_backup = TRUE;
|
||||
}
|
||||
|
||||
recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE);
|
||||
recv_sys->len = 0;
|
||||
recv_sys->recovered_offset = 0;
|
||||
|
||||
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 64);
|
||||
recv_sys->addr_hash = hash_create(available_memory / 64);
|
||||
recv_sys->n_addrs = 0;
|
||||
|
||||
recv_sys->apply_log_recs = FALSE;
|
||||
@ -337,7 +341,7 @@ recv_synchronize_groups(
|
||||
start_lsn = ut_dulint_align_down(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE);
|
||||
end_lsn = ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
ut_ad(ut_dulint_cmp(start_lsn, end_lsn) != 0);
|
||||
ut_a(ut_dulint_cmp(start_lsn, end_lsn) != 0);
|
||||
|
||||
log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block,
|
||||
up_to_date_group, start_lsn, end_lsn);
|
||||
@ -377,6 +381,35 @@ recv_synchronize_groups(
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Checks the consistency of the checkpoint info */
|
||||
static
|
||||
ibool
|
||||
recv_check_cp_is_consistent(
|
||||
/*========================*/
|
||||
/* out: TRUE if ok */
|
||||
byte* buf) /* in: buffer containing checkpoint info */
|
||||
{
|
||||
ulint fold;
|
||||
|
||||
fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
|
||||
|
||||
if ((fold & 0xFFFFFFFF) != mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_1)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
|
||||
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
|
||||
|
||||
if ((fold & 0xFFFFFFFF) != mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_2)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Looks for the maximum consistent checkpoint from the log groups. */
|
||||
static
|
||||
@ -392,7 +425,6 @@ recv_find_max_checkpoint(
|
||||
dulint max_no;
|
||||
dulint checkpoint_no;
|
||||
ulint field;
|
||||
ulint fold;
|
||||
byte* buf;
|
||||
|
||||
group = UT_LIST_GET_FIRST(log_sys->log_groups);
|
||||
@ -410,17 +442,11 @@ recv_find_max_checkpoint(
|
||||
|
||||
log_group_read_checkpoint_info(group, field);
|
||||
|
||||
/* Check the consistency of the checkpoint info */
|
||||
fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
|
||||
|
||||
if ((fold & 0xFFFFFFFF)
|
||||
!= mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_1)) {
|
||||
if (!recv_check_cp_is_consistent(buf)) {
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu, %lu\n",
|
||||
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
|
||||
group->id, field,
|
||||
fold & 0xFFFFFFFF,
|
||||
mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_1));
|
||||
|
||||
@ -429,23 +455,6 @@ recv_find_max_checkpoint(
|
||||
goto not_consistent;
|
||||
}
|
||||
|
||||
fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
|
||||
LOG_CHECKPOINT_CHECKSUM_2
|
||||
- LOG_CHECKPOINT_LSN);
|
||||
if ((fold & 0xFFFFFFFF)
|
||||
!= mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_2)) {
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu, %lu\n",
|
||||
group->id, field,
|
||||
fold & 0xFFFFFFFF,
|
||||
mach_read_from_4(buf
|
||||
+ LOG_CHECKPOINT_CHECKSUM_2));
|
||||
}
|
||||
goto not_consistent;
|
||||
}
|
||||
|
||||
group->state = LOG_GROUP_OK;
|
||||
|
||||
group->lsn = mach_read_from_8(buf
|
||||
@ -476,7 +485,13 @@ recv_find_max_checkpoint(
|
||||
|
||||
if (*max_group == NULL) {
|
||||
|
||||
fprintf(stderr, "InnoDB: No valid checkpoint found\n");
|
||||
fprintf(stderr,
|
||||
"InnoDB: No valid checkpoint found.\n"
|
||||
"InnoDB: If this error appears when you are creating an InnoDB database,\n"
|
||||
"InnoDB: the problem may be that during an earlier attempt you managed\n"
|
||||
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
|
||||
"InnoDB: If that is the case, please refer to section 3.1 of\n"
|
||||
"InnoDB: http://www.innodb.com/ibman.html\n");
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
@ -484,6 +499,162 @@ recv_find_max_checkpoint(
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Reads the checkpoint info needed in hot backup. */
|
||||
|
||||
ibool
|
||||
recv_read_cp_info_for_backup(
|
||||
/*=========================*/
|
||||
/* out: TRUE if success */
|
||||
byte* hdr, /* in: buffer containing the log group header */
|
||||
dulint* lsn, /* out: checkpoint lsn */
|
||||
ulint* offset, /* out: checkpoint offset in the log group */
|
||||
ulint* fsp_limit,/* out: fsp limit, 1000000000 if the database
|
||||
is running with < version 3.23.50 of InnoDB */
|
||||
dulint* cp_no, /* out: checkpoint number */
|
||||
dulint* first_header_lsn)
|
||||
/* out: lsn of of the start of the first log file */
|
||||
{
|
||||
ulint max_cp = 0;
|
||||
dulint max_cp_no = ut_dulint_zero;
|
||||
byte* cp_buf;
|
||||
|
||||
cp_buf = hdr + LOG_CHECKPOINT_1;
|
||||
|
||||
if (recv_check_cp_is_consistent(cp_buf)) {
|
||||
max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
|
||||
max_cp = LOG_CHECKPOINT_1;
|
||||
}
|
||||
|
||||
cp_buf = hdr + LOG_CHECKPOINT_2;
|
||||
|
||||
if (recv_check_cp_is_consistent(cp_buf)) {
|
||||
if (ut_dulint_cmp(mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO),
|
||||
max_cp_no) > 0) {
|
||||
max_cp = LOG_CHECKPOINT_2;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_cp == 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
cp_buf = hdr + max_cp;
|
||||
|
||||
*lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN);
|
||||
*offset = mach_read_from_4(cp_buf + LOG_CHECKPOINT_OFFSET);
|
||||
|
||||
/* If the user is running a pre-3.23.50 version of InnoDB, its
|
||||
checkpoint data does not contain the fsp limit info */
|
||||
if (mach_read_from_4(cp_buf + LOG_CHECKPOINT_FSP_MAGIC_N)
|
||||
== LOG_CHECKPOINT_FSP_MAGIC_N_VAL) {
|
||||
|
||||
*fsp_limit = mach_read_from_4(
|
||||
cp_buf + LOG_CHECKPOINT_FSP_FREE_LIMIT);
|
||||
|
||||
if (*fsp_limit == 0) {
|
||||
*fsp_limit = 1000000000;
|
||||
}
|
||||
} else {
|
||||
*fsp_limit = 1000000000;
|
||||
}
|
||||
|
||||
/* printf("fsp limit %lu MB\n", *fsp_limit); */
|
||||
|
||||
*cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
|
||||
|
||||
*first_header_lsn = mach_read_from_8(hdr + LOG_FILE_START_LSN);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Scans the log segment and n_bytes_scanned is set to the length of valid
|
||||
log scanned. */
|
||||
|
||||
void
|
||||
recv_scan_log_seg_for_backup(
|
||||
/*=========================*/
|
||||
byte* buf, /* in: buffer containing log data */
|
||||
ulint buf_len, /* in: data length in that buffer */
|
||||
dulint* scanned_lsn, /* in/out: lsn of buffer start,
|
||||
we return scanned lsn */
|
||||
ulint* scanned_checkpoint_no,
|
||||
/* in/out: 4 lowest bytes of the
|
||||
highest scanned checkpoint number so
|
||||
far */
|
||||
ulint* n_bytes_scanned)/* out: how much we were able to
|
||||
scan, smaller than buf_len if log
|
||||
data ended here */
|
||||
{
|
||||
ulint data_len;
|
||||
byte* log_block;
|
||||
ulint no;
|
||||
|
||||
*n_bytes_scanned = 0;
|
||||
|
||||
for (log_block = buf; log_block < buf + buf_len;
|
||||
log_block += OS_FILE_LOG_BLOCK_SIZE) {
|
||||
|
||||
no = log_block_get_hdr_no(log_block);
|
||||
|
||||
/* fprintf(stderr, "Log block header no %lu\n", no); */
|
||||
|
||||
if (no != log_block_get_trl_no(log_block)
|
||||
|| no != log_block_convert_lsn_to_no(*scanned_lsn)) {
|
||||
|
||||
/* printf(
|
||||
"Log block n:o %lu, trailer n:o %lu, scanned lsn n:o %lu\n",
|
||||
no, log_block_get_trl_no(log_block),
|
||||
log_block_convert_lsn_to_no(*scanned_lsn));
|
||||
*/
|
||||
/* Garbage or an incompletely written log block */
|
||||
|
||||
log_block += OS_FILE_LOG_BLOCK_SIZE;
|
||||
|
||||
/* printf(
|
||||
"Next log block n:o %lu, trailer n:o %lu\n",
|
||||
log_block_get_hdr_no(log_block),
|
||||
log_block_get_trl_no(log_block));
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (*scanned_checkpoint_no > 0
|
||||
&& log_block_get_checkpoint_no(log_block)
|
||||
< *scanned_checkpoint_no
|
||||
&& *scanned_checkpoint_no
|
||||
- log_block_get_checkpoint_no(log_block)
|
||||
> 0x80000000) {
|
||||
|
||||
/* Garbage from a log buffer flush which was made
|
||||
before the most recent database recovery */
|
||||
|
||||
printf("Scanned cp n:o %lu, block cp n:o %lu\n",
|
||||
*scanned_checkpoint_no,
|
||||
log_block_get_checkpoint_no(log_block));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
data_len = log_block_get_data_len(log_block);
|
||||
|
||||
*scanned_checkpoint_no
|
||||
= log_block_get_checkpoint_no(log_block);
|
||||
*scanned_lsn = ut_dulint_add(*scanned_lsn, data_len);
|
||||
|
||||
*n_bytes_scanned += data_len;
|
||||
|
||||
if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
|
||||
/* Log data ends here */
|
||||
|
||||
/* printf("Log block data len %lu\n", data_len); */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tries to parse a single log record body and also applies it to a page if
|
||||
specified. */
|
||||
@ -625,7 +796,6 @@ recv_get_fil_addr_struct(
|
||||
|
||||
recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
|
||||
recv_hash(space, page_no));
|
||||
|
||||
while (recv_addr) {
|
||||
if ((recv_addr->space == space)
|
||||
&& (recv_addr->page_no == page_no)) {
|
||||
@ -755,6 +925,10 @@ read in, or also for a page already in the buffer pool. */
|
||||
void
|
||||
recv_recover_page(
|
||||
/*==============*/
|
||||
ibool recover_backup, /* in: TRUE if we are recovering a backup
|
||||
page: then we do not acquire any latches
|
||||
since the page was read in outside the
|
||||
buffer pool */
|
||||
ibool just_read_in, /* in: TRUE if the i/o-handler calls this for
|
||||
a freshly read page */
|
||||
page_t* page, /* in: buffer page */
|
||||
@ -799,39 +973,48 @@ recv_recover_page(
|
||||
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
|
||||
block = buf_block_align(page);
|
||||
|
||||
if (just_read_in) {
|
||||
/* Move the ownership of the x-latch on the page to this OS
|
||||
thread, so that we can acquire a second x-latch on it. This
|
||||
is needed for the operations to the page to pass the debug
|
||||
checks. */
|
||||
|
||||
rw_lock_x_lock_move_ownership(&(block->lock));
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
mtr_set_log_mode(&mtr, MTR_LOG_NONE);
|
||||
|
||||
success = buf_page_get_known_nowait(RW_X_LATCH, page, BUF_KEEP_OLD,
|
||||
if (!recover_backup) {
|
||||
block = buf_block_align(page);
|
||||
|
||||
if (just_read_in) {
|
||||
/* Move the ownership of the x-latch on the page to this OS
|
||||
thread, so that we can acquire a second x-latch on it. This
|
||||
is needed for the operations to the page to pass the debug
|
||||
checks. */
|
||||
|
||||
rw_lock_x_lock_move_ownership(&(block->lock));
|
||||
}
|
||||
|
||||
success = buf_page_get_known_nowait(RW_X_LATCH, page,
|
||||
BUF_KEEP_OLD,
|
||||
IB__FILE__, __LINE__,
|
||||
&mtr);
|
||||
ut_a(success);
|
||||
ut_a(success);
|
||||
|
||||
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
|
||||
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
|
||||
}
|
||||
|
||||
/* Read the newest modification lsn from the page */
|
||||
page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
|
||||
|
||||
/* It may be that the page has been modified in the buffer pool: read
|
||||
the newest modification lsn there */
|
||||
if (!recover_backup) {
|
||||
/* It may be that the page has been modified in the buffer
|
||||
pool: read the newest modification lsn there */
|
||||
|
||||
page_newest_lsn = buf_frame_get_newest_modification(page);
|
||||
page_newest_lsn = buf_frame_get_newest_modification(page);
|
||||
|
||||
if (!ut_dulint_is_zero(page_newest_lsn)) {
|
||||
if (!ut_dulint_is_zero(page_newest_lsn)) {
|
||||
|
||||
page_lsn = page_newest_lsn;
|
||||
page_lsn = page_newest_lsn;
|
||||
}
|
||||
} else {
|
||||
/* In recovery from a backup we do not use the buffer
|
||||
pool */
|
||||
|
||||
page_newest_lsn = ut_dulint_zero;
|
||||
}
|
||||
|
||||
modification_to_page = FALSE;
|
||||
@ -852,13 +1035,13 @@ recv_recover_page(
|
||||
buf = ((byte*)(recv->data)) + sizeof(recv_data_t);
|
||||
}
|
||||
|
||||
if ((recv->type == MLOG_INIT_FILE_PAGE)
|
||||
|| (recv->type == MLOG_FULL_PAGE)) {
|
||||
/* A new file page may has been taken into use,
|
||||
if (recv->type == MLOG_INIT_FILE_PAGE
|
||||
|| recv->type == MLOG_FULL_PAGE) {
|
||||
/* A new file page may have been taken into use,
|
||||
or we have stored the full contents of the page:
|
||||
in this case it may be that the original log record
|
||||
type was MLOG_INIT_FILE_PAGE, and we replaced it
|
||||
with MLOG_FULL_PAGE, thus to we have to apply
|
||||
with MLOG_FULL_PAGE, thus we have to apply
|
||||
any record of type MLOG_FULL_PAGE */
|
||||
|
||||
page_lsn = page_newest_lsn;
|
||||
@ -885,6 +1068,13 @@ recv_recover_page(
|
||||
|
||||
recv_parse_or_apply_log_rec_body(recv->type, buf,
|
||||
buf + recv->len, page, &mtr);
|
||||
mach_write_to_8(page + UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN,
|
||||
ut_dulint_add(recv->start_lsn,
|
||||
recv->len));
|
||||
mach_write_to_8(page + FIL_PAGE_LSN,
|
||||
ut_dulint_add(recv->start_lsn,
|
||||
recv->len));
|
||||
}
|
||||
|
||||
if (recv->len > RECV_DATA_BLOCK_SIZE) {
|
||||
@ -903,7 +1093,7 @@ recv_recover_page(
|
||||
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
|
||||
if (modification_to_page) {
|
||||
if (!recover_backup && modification_to_page) {
|
||||
buf_flush_recv_note_modification(block, start_lsn, end_lsn);
|
||||
}
|
||||
|
||||
@ -1038,8 +1228,8 @@ loop:
|
||||
|
||||
buf_page_dbg_add_level(page,
|
||||
SYNC_NO_ORDER_CHECK);
|
||||
recv_recover_page(FALSE, page, space,
|
||||
page_no);
|
||||
recv_recover_page(FALSE, FALSE, page,
|
||||
space, page_no);
|
||||
mtr_commit(&mtr);
|
||||
} else {
|
||||
recv_read_in_area(space, page_no);
|
||||
@ -1111,6 +1301,95 @@ loop:
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Applies log records in the hash table to a backup. */
|
||||
|
||||
void
|
||||
recv_apply_log_recs_for_backup(
|
||||
/*===========================*/
|
||||
ulint n_data_files, /* in: number of data files */
|
||||
char** data_files, /* in: array containing the paths to the
|
||||
data files */
|
||||
ulint* file_sizes) /* in: sizes of the data files in database
|
||||
pages */
|
||||
{
|
||||
recv_addr_t* recv_addr;
|
||||
os_file_t data_file;
|
||||
ulint n_pages_total = 0;
|
||||
ulint nth_file = 0;
|
||||
ulint nth_page_in_file= 0;
|
||||
byte* page;
|
||||
ibool success;
|
||||
ulint i;
|
||||
|
||||
recv_sys->apply_log_recs = TRUE;
|
||||
recv_sys->apply_batch_on = TRUE;
|
||||
|
||||
page = buf_pool->frame_zero;
|
||||
|
||||
for (i = 0; i < n_data_files; i++) {
|
||||
n_pages_total += file_sizes[i];
|
||||
}
|
||||
|
||||
printf(
|
||||
"InnoDB: Starting an apply batch of log records to the database...\n"
|
||||
"InnoDB: Progress in percents: ");
|
||||
|
||||
for (i = 0; i < n_pages_total; i++) {
|
||||
|
||||
if (i == 0 || nth_page_in_file == file_sizes[nth_file]) {
|
||||
if (i != 0) {
|
||||
nth_file++;
|
||||
nth_page_in_file = 0;
|
||||
os_file_flush(data_file);
|
||||
os_file_close(data_file);
|
||||
}
|
||||
|
||||
data_file = os_file_create_simple(data_files[nth_file],
|
||||
OS_FILE_OPEN,
|
||||
OS_FILE_READ_WRITE,
|
||||
&success);
|
||||
ut_a(success);
|
||||
}
|
||||
|
||||
recv_addr = recv_get_fil_addr_struct(0, i);
|
||||
|
||||
if (recv_addr != NULL) {
|
||||
os_file_read(data_file, page,
|
||||
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
|
||||
& 0xFFFFFFFF,
|
||||
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
UNIV_PAGE_SIZE);
|
||||
|
||||
recv_recover_page(TRUE, FALSE, page, 0, i);
|
||||
|
||||
buf_flush_init_for_writing(page,
|
||||
mach_read_from_8(page + FIL_PAGE_LSN),
|
||||
0, i);
|
||||
|
||||
os_file_write(data_files[nth_file],
|
||||
data_file, page,
|
||||
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
|
||||
& 0xFFFFFFFF,
|
||||
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
if ((100 * i) / n_pages_total
|
||||
!= (100 * (i + 1)) / n_pages_total) {
|
||||
printf("%lu ", (100 * i) / n_pages_total);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
nth_page_in_file++;
|
||||
}
|
||||
|
||||
os_file_flush(data_file);
|
||||
os_file_close(data_file);
|
||||
|
||||
recv_sys_empty_hash();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
In the debug version, updates the replica of a file page, based on a log
|
||||
record. */
|
||||
@ -1430,12 +1709,13 @@ recv_check_incomplete_log_recs(
|
||||
|
||||
/***********************************************************
|
||||
Parses log records from a buffer and stores them to a hash table to wait
|
||||
merging to file pages. If the hash table becomes too full, applies it
|
||||
automatically to file pages. */
|
||||
|
||||
void
|
||||
merging to file pages. */
|
||||
static
|
||||
ibool
|
||||
recv_parse_log_recs(
|
||||
/*================*/
|
||||
/* out: TRUE if the hash table of parsed log
|
||||
records became full */
|
||||
ibool store_to_hash) /* in: TRUE if the records should be stored
|
||||
to the hash table; this is set to FALSE if just
|
||||
debug checking is needed */
|
||||
@ -1462,7 +1742,7 @@ loop:
|
||||
|
||||
if (ptr == end_ptr) {
|
||||
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
single_rec = (ulint)*ptr & MLOG_SINGLE_REC_FLAG;
|
||||
@ -1476,7 +1756,7 @@ loop:
|
||||
&page_no, &body);
|
||||
if (len == 0) {
|
||||
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len);
|
||||
@ -1487,7 +1767,7 @@ loop:
|
||||
that also the next log block should have been scanned
|
||||
in */
|
||||
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
recv_sys->recovered_offset += len;
|
||||
@ -1529,7 +1809,7 @@ loop:
|
||||
&page_no, &body);
|
||||
if (len == 0) {
|
||||
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
|
||||
@ -1570,27 +1850,9 @@ loop:
|
||||
that also the next log block should have been scanned
|
||||
in */
|
||||
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (2 * n_recs * (sizeof(recv_t) + sizeof(recv_addr_t))
|
||||
+ total_len
|
||||
+ mem_heap_get_size(recv_sys->heap)
|
||||
+ RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE
|
||||
> buf_pool_get_curr_size()) {
|
||||
|
||||
/* Hash table of log records will grow too big:
|
||||
empty it */
|
||||
|
||||
recv_apply_hashed_log_recs(FALSE);
|
||||
}
|
||||
|
||||
ut_ad(2 * n_recs * (sizeof(recv_t) + sizeof(recv_addr_t))
|
||||
+ total_len
|
||||
+ mem_heap_get_size(recv_sys->heap)
|
||||
+ RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE
|
||||
< buf_pool_get_curr_size());
|
||||
|
||||
/* Add all the records to the hash table */
|
||||
|
||||
ptr = recv_sys->buf + recv_sys->recovered_offset;
|
||||
@ -1627,18 +1889,7 @@ loop:
|
||||
ptr += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (store_to_hash && buf_get_free_list_len()
|
||||
< RECV_POOL_N_FREE_BLOCKS) {
|
||||
|
||||
/* Hash table of log records has grown too big: empty it;
|
||||
FALSE means no ibuf operations allowed, as we cannot add
|
||||
new records to the log yet: they would be produced by ibuf
|
||||
operations */
|
||||
|
||||
recv_apply_hashed_log_recs(FALSE);
|
||||
}
|
||||
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
@ -1713,7 +1964,7 @@ recv_sys_add_to_parsing_buf(
|
||||
|
||||
recv_sys->len += end_offset - start_offset;
|
||||
|
||||
ut_ad(recv_sys->len <= RECV_PARSING_BUF_SIZE);
|
||||
ut_a(recv_sys->len <= RECV_PARSING_BUF_SIZE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
@ -1743,6 +1994,13 @@ recv_scan_log_recs(
|
||||
/*===============*/
|
||||
/* out: TRUE if limit_lsn has been reached, or
|
||||
not able to scan any more in this log group */
|
||||
ibool apply_automatically,/* in: TRUE if we want this function to
|
||||
apply log records automatically when the
|
||||
hash table becomes full; in the hot backup tool
|
||||
the tool does the applying, not this
|
||||
function */
|
||||
ulint available_memory,/* in: we let the hash table of recs to grow
|
||||
to this size, at the maximum */
|
||||
ibool store_to_hash, /* in: TRUE if the records should be stored
|
||||
to the hash table; this is set to FALSE if just
|
||||
debug checking is needed */
|
||||
@ -1764,7 +2022,9 @@ recv_scan_log_recs(
|
||||
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
ut_ad(len > 0);
|
||||
|
||||
ut_a(apply_automatically <= TRUE);
|
||||
ut_a(store_to_hash <= TRUE);
|
||||
|
||||
finished = FALSE;
|
||||
|
||||
log_block = buf;
|
||||
@ -1845,6 +2105,13 @@ recv_scan_log_recs(
|
||||
/* We were able to find more log data: add it to the
|
||||
parsing buffer if parse_start_lsn is already non-zero */
|
||||
|
||||
if (recv_sys->len + 4 * OS_FILE_LOG_BLOCK_SIZE
|
||||
>= RECV_PARSING_BUF_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n");
|
||||
finished = TRUE;
|
||||
}
|
||||
|
||||
more_data = recv_sys_add_to_parsing_buf(log_block,
|
||||
scanned_lsn);
|
||||
recv_sys->scanned_lsn = scanned_lsn;
|
||||
@ -1863,25 +2130,36 @@ recv_scan_log_recs(
|
||||
|
||||
*group_scanned_lsn = scanned_lsn;
|
||||
|
||||
if (more_data) {
|
||||
if (recv_needed_recovery || recv_is_from_backup) {
|
||||
recv_scan_print_counter++;
|
||||
|
||||
if (recv_scan_print_counter < 10
|
||||
|| (recv_scan_print_counter % 10 == 0)) {
|
||||
if (finished || (recv_scan_print_counter % 80 == 0)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Doing recovery: scanned up to log sequence number %lu %lu\n",
|
||||
ut_dulint_get_high(*group_scanned_lsn),
|
||||
ut_dulint_get_low(*group_scanned_lsn));
|
||||
if (recv_scan_print_counter == 10) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: After this prints a line for every 10th scan sweep:\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (more_data) {
|
||||
/* Try to parse more log records */
|
||||
|
||||
recv_parse_log_recs(store_to_hash);
|
||||
|
||||
if (store_to_hash && mem_heap_get_size(recv_sys->heap)
|
||||
> available_memory
|
||||
&& apply_automatically) {
|
||||
|
||||
/* Hash table of log records has grown too big:
|
||||
empty it; FALSE means no ibuf operations
|
||||
allowed, as we cannot add new records to the
|
||||
log yet: they would be produced by ibuf
|
||||
operations */
|
||||
|
||||
recv_apply_hashed_log_recs(FALSE);
|
||||
}
|
||||
|
||||
if (recv_sys->recovered_offset > RECV_PARSING_BUF_SIZE / 4) {
|
||||
/* Move parsing buffer data to the buffer start */
|
||||
|
||||
@ -1918,10 +2196,12 @@ recv_group_scan_log_recs(
|
||||
log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
|
||||
group, start_lsn, end_lsn);
|
||||
|
||||
finished = recv_scan_log_recs(TRUE, log_sys->buf,
|
||||
RECV_SCAN_SIZE, start_lsn,
|
||||
contiguous_lsn,
|
||||
group_scanned_lsn);
|
||||
finished = recv_scan_log_recs(TRUE,
|
||||
buf_pool_get_curr_size()
|
||||
- RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
|
||||
TRUE, log_sys->buf,
|
||||
RECV_SCAN_SIZE, start_lsn,
|
||||
contiguous_lsn, group_scanned_lsn);
|
||||
start_lsn = end_lsn;
|
||||
}
|
||||
|
||||
@ -1969,7 +2249,7 @@ recv_recovery_from_checkpoint_start(
|
||||
if (type == LOG_CHECKPOINT) {
|
||||
|
||||
recv_sys_create();
|
||||
recv_sys_init();
|
||||
recv_sys_init(FALSE, buf_pool_get_curr_size());
|
||||
}
|
||||
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO) {
|
||||
@ -2280,6 +2560,84 @@ recv_reset_logs(
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Creates new log files after a backup has been restored. */
|
||||
|
||||
void
|
||||
recv_reset_log_files_for_backup(
|
||||
/*============================*/
|
||||
char* log_dir, /* in: log file directory path */
|
||||
ulint n_log_files, /* in: number of log files */
|
||||
ulint log_file_size, /* in: log file size */
|
||||
dulint lsn) /* in: new start lsn, must be divisible by
|
||||
OS_FILE_LOG_BLOCK_SIZE */
|
||||
{
|
||||
os_file_t log_file;
|
||||
ibool success;
|
||||
byte* buf;
|
||||
ulint i;
|
||||
char name[5000];
|
||||
|
||||
buf = ut_malloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
for (i = 0; i < n_log_files; i++) {
|
||||
|
||||
sprintf(name, "%sib_logfile%lu", log_dir, i);
|
||||
|
||||
log_file = os_file_create_simple(name, OS_FILE_CREATE,
|
||||
OS_FILE_READ_WRITE, &success);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Cannot create %s. Check that the file does not exist yet.\n", name);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Setting log file size to %lu %lu\n", ut_get_high32(log_file_size),
|
||||
log_file_size & 0xFFFFFFFF);
|
||||
|
||||
success = os_file_set_size(name, log_file,
|
||||
log_file_size & 0xFFFFFFFF,
|
||||
ut_get_high32(log_file_size));
|
||||
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Cannot set %s size to %lu %lu\n", name, ut_get_high32(log_file_size),
|
||||
log_file_size & 0xFFFFFFFF);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
os_file_flush(log_file);
|
||||
os_file_close(log_file);
|
||||
}
|
||||
|
||||
/* We pretend there is a checkpoint at lsn + LOG_BLOCK_HDR_SIZE */
|
||||
|
||||
log_reset_first_header_and_checkpoint(buf,
|
||||
ut_dulint_add(lsn, LOG_BLOCK_HDR_SIZE));
|
||||
|
||||
log_block_init(buf + LOG_FILE_HDR_SIZE, lsn);
|
||||
log_block_set_first_rec_group(buf + LOG_FILE_HDR_SIZE,
|
||||
LOG_BLOCK_HDR_SIZE);
|
||||
sprintf(name, "%sib_logfile%lu", log_dir, 0);
|
||||
|
||||
log_file = os_file_create_simple(name, OS_FILE_OPEN,
|
||||
OS_FILE_READ_WRITE, &success);
|
||||
if (!success) {
|
||||
printf("InnoDB: Cannot open %s.\n", name);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
os_file_write(name, log_file, buf, 0, 0,
|
||||
LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
os_file_flush(log_file);
|
||||
os_file_close(log_file);
|
||||
|
||||
ut_free(buf);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Reads from the archive of a log group and performs recovery. */
|
||||
static
|
||||
@ -2296,13 +2654,13 @@ log_group_recover_from_archive_file(
|
||||
dulint dummy_lsn;
|
||||
dulint scanned_lsn;
|
||||
ulint len;
|
||||
char name[10000];
|
||||
ibool ret;
|
||||
byte* buf;
|
||||
ulint read_offset;
|
||||
ulint file_size;
|
||||
ulint file_size_high;
|
||||
int input_char;
|
||||
char name[10000];
|
||||
|
||||
try_open_again:
|
||||
buf = log_sys->buf;
|
||||
@ -2438,9 +2796,11 @@ ask_again:
|
||||
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
|
||||
read_offset % UNIV_PAGE_SIZE, len, buf, NULL);
|
||||
|
||||
|
||||
ret = recv_scan_log_recs(TRUE, buf, len, start_lsn,
|
||||
&dummy_lsn, &scanned_lsn);
|
||||
ret = recv_scan_log_recs(TRUE,
|
||||
buf_pool_get_curr_size() -
|
||||
RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
|
||||
TRUE, buf, len, start_lsn,
|
||||
&dummy_lsn, &scanned_lsn);
|
||||
|
||||
if (ut_dulint_cmp(scanned_lsn, file_end_lsn) == 0) {
|
||||
|
||||
@ -2485,7 +2845,7 @@ recv_recovery_from_archive_start(
|
||||
ulint err;
|
||||
|
||||
recv_sys_create();
|
||||
recv_sys_init();
|
||||
recv_sys_init(FALSE, buf_pool_get_curr_size());
|
||||
|
||||
sync_order_checks_on = TRUE;
|
||||
|
||||
|
@ -234,7 +234,8 @@ mem_heap_add_block(
|
||||
new_size = 2 * mem_block_get_len(block);
|
||||
|
||||
if (heap->type != MEM_HEAP_DYNAMIC) {
|
||||
ut_ad(n <= MEM_MAX_ALLOC_IN_BUF);
|
||||
/* From the buffer pool we allocate buffer frames */
|
||||
ut_a(n <= MEM_MAX_ALLOC_IN_BUF);
|
||||
|
||||
if (new_size > MEM_MAX_ALLOC_IN_BUF) {
|
||||
new_size = MEM_MAX_ALLOC_IN_BUF;
|
||||
@ -249,7 +250,7 @@ mem_heap_add_block(
|
||||
}
|
||||
|
||||
new_block = mem_heap_create_block(heap, new_size, NULL, heap->type,
|
||||
heap->file_name, heap->line);
|
||||
heap->file_name, heap->line);
|
||||
if (new_block == NULL) {
|
||||
|
||||
return(NULL);
|
||||
|
@ -10,17 +10,22 @@ Created 10/21/1995 Heikki Tuuri
|
||||
#include "os0sync.h"
|
||||
#include "ut0mem.h"
|
||||
#include "srv0srv.h"
|
||||
#include "trx0sys.h"
|
||||
#include "fil0fil.h"
|
||||
|
||||
#undef HAVE_FDATASYNC
|
||||
|
||||
#undef UNIV_NON_BUFFERED_IO
|
||||
|
||||
#ifdef POSIX_ASYNC_IO
|
||||
/* We assume in this case that the OS has standard Posix aio (at least SunOS
|
||||
2.6, HP-UX 11i and AIX 4.3 have) */
|
||||
|
||||
#endif
|
||||
|
||||
/* If the following is set to TRUE, we do not call os_file_flush in every
|
||||
os_file_write. We can set this TRUE if the doublewrite buffer is used. */
|
||||
ibool os_do_not_call_flush_at_each_write = FALSE;
|
||||
|
||||
/* We use these mutexes to protect lseek + file i/o operation, if the
|
||||
OS does not provide an atomic pread or pwrite, or similar */
|
||||
#define OS_FILE_N_SEEK_MUTEXES 16
|
||||
@ -118,6 +123,9 @@ ulint os_n_file_writes_old = 0;
|
||||
ulint os_n_fsyncs_old = 0;
|
||||
time_t os_last_printout;
|
||||
|
||||
ibool os_has_said_disk_full = FALSE;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Gets the operating system version. Currently works only on Windows. */
|
||||
|
||||
@ -167,27 +175,28 @@ os_file_get_last_error(void)
|
||||
|
||||
err = (ulint) GetLastError();
|
||||
|
||||
if (err != ERROR_FILE_EXISTS) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Operating system error number %li in a file operation.\n"
|
||||
if (err != ERROR_FILE_EXISTS && err != ERROR_DISK_FULL) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Operating system error number %li in a file operation.\n"
|
||||
"InnoDB: See http://www.innodb.com/ibman.html for installation help.\n",
|
||||
(long) err);
|
||||
|
||||
if (err == ERROR_PATH_NOT_FOUND) {
|
||||
if (err == ERROR_PATH_NOT_FOUND) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The error means the system cannot find the path specified.\n"
|
||||
"InnoDB: In installation you must create directories yourself, InnoDB\n"
|
||||
"InnoDB: does not create them.\n");
|
||||
} else if (err == ERROR_ACCESS_DENIED) {
|
||||
} else if (err == ERROR_ACCESS_DENIED) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The error means mysqld does not have the access rights to\n"
|
||||
"InnoDB: the directory. It may also be you have created a subdirectory\n"
|
||||
"InnoDB: of the same name as a data file.\n");
|
||||
} else {
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||
"InnoDB: what the error number means.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
@ -202,26 +211,28 @@ os_file_get_last_error(void)
|
||||
#else
|
||||
err = (ulint) errno;
|
||||
|
||||
if (err != EEXIST) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Operating system error number %li in a file operation.\n"
|
||||
if (err != EEXIST && err != ENOSPC ) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Operating system error number %li in a file operation.\n"
|
||||
"InnoDB: See http://www.innodb.com/ibman.html for installation help.\n",
|
||||
(long) err);
|
||||
|
||||
if (err == ENOENT) {
|
||||
if (err == ENOENT) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The error means the system cannot find the path specified.\n"
|
||||
"InnoDB: In installation you must create directories yourself, InnoDB\n"
|
||||
"InnoDB: does not create them.\n");
|
||||
} else if (err == EACCES) {
|
||||
} else if (err == EACCES) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The error means mysqld does not have the access rights to\n"
|
||||
"InnoDB: the directory.\n");
|
||||
} else {
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||
"InnoDB: what the error number means or use the perror program of MySQL.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ENOSPC ) {
|
||||
@ -259,18 +270,26 @@ os_file_handle_error(
|
||||
err = os_file_get_last_error();
|
||||
|
||||
if (err == OS_FILE_DISK_FULL) {
|
||||
fprintf(stderr, "\n");
|
||||
if (name) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Encountered a problem with file %s.\n",
|
||||
name);
|
||||
}
|
||||
fprintf(stderr,
|
||||
"InnoDB: Cannot continue operation.\n"
|
||||
"InnoDB: Disk is full. Try to clean the disk to free space.\n"
|
||||
"InnoDB: Delete a possible created file and restart.\n");
|
||||
/* We only print a warning about disk full once */
|
||||
|
||||
exit(1);
|
||||
if (os_has_said_disk_full) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Encountered a problem with file %s\n", name);
|
||||
}
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Disk is full. Try to clean the disk to free space.\n");
|
||||
|
||||
os_has_said_disk_full = TRUE;
|
||||
|
||||
return(FALSE);
|
||||
|
||||
} else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
|
||||
return(TRUE);
|
||||
@ -290,6 +309,130 @@ os_file_handle_error(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Creates the seek mutexes used in positioned reads and writes. */
|
||||
|
||||
void
|
||||
os_io_init_simple(void)
|
||||
/*===================*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
|
||||
os_file_seek_mutexes[i] = os_mutex_create(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
A simple function to open or create a file. */
|
||||
|
||||
os_file_t
|
||||
os_file_create_simple(
|
||||
/*==================*/
|
||||
/* out, own: handle to the file, not defined if error,
|
||||
error number can be retrieved with os_get_last_error */
|
||||
char* name, /* in: name of the file or path as a null-terminated
|
||||
string */
|
||||
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
|
||||
(if does not exist, error), or OS_FILE_CREATE if a new
|
||||
file is created (if exists, error) */
|
||||
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
|
||||
ibool* success)/* out: TRUE if succeed, FALSE if error */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
os_file_t file;
|
||||
DWORD create_flag;
|
||||
DWORD access;
|
||||
DWORD attributes = 0;
|
||||
ibool retry;
|
||||
|
||||
try_again:
|
||||
ut_a(name);
|
||||
|
||||
if (create_mode == OS_FILE_OPEN) {
|
||||
create_flag = OPEN_EXISTING;
|
||||
} else if (create_mode == OS_FILE_CREATE) {
|
||||
create_flag = CREATE_NEW;
|
||||
} else {
|
||||
create_flag = 0;
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (access_type == OS_FILE_READ_ONLY) {
|
||||
access = GENERIC_READ;
|
||||
} else if (access_type == OS_FILE_READ_WRITE) {
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
} else {
|
||||
access = 0;
|
||||
ut_error;
|
||||
}
|
||||
|
||||
file = CreateFile(name,
|
||||
access,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
/* file can be read and written
|
||||
also by other processes */
|
||||
NULL, /* default security attributes */
|
||||
create_flag,
|
||||
attributes,
|
||||
NULL); /* no template file */
|
||||
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
}
|
||||
} else {
|
||||
*success = TRUE;
|
||||
}
|
||||
|
||||
return(file);
|
||||
#else
|
||||
os_file_t file;
|
||||
int create_flag;
|
||||
ibool retry;
|
||||
|
||||
try_again:
|
||||
ut_a(name);
|
||||
|
||||
if (create_mode == OS_FILE_OPEN) {
|
||||
if (access_type == OS_FILE_READ_ONLY) {
|
||||
create_flag = O_RDONLY;
|
||||
} else {
|
||||
create_flag = O_RDWR;
|
||||
}
|
||||
} else if (create_mode == OS_FILE_CREATE) {
|
||||
create_flag = O_RDWR | O_CREAT | O_EXCL;
|
||||
} else {
|
||||
create_flag = 0;
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (create_mode == OS_FILE_CREATE) {
|
||||
file = open(name, create_flag, S_IRUSR | S_IWUSR | S_IRGRP
|
||||
| S_IWGRP | S_IROTH | S_IWOTH);
|
||||
} else {
|
||||
file = open(name, create_flag);
|
||||
}
|
||||
|
||||
if (file == -1) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
}
|
||||
} else {
|
||||
*success = TRUE;
|
||||
}
|
||||
|
||||
return(file);
|
||||
#endif
|
||||
}
|
||||
/********************************************************************
|
||||
Opens an existing file or creates a new. */
|
||||
|
||||
@ -355,8 +498,9 @@ try_again:
|
||||
file = CreateFile(name,
|
||||
GENERIC_READ | GENERIC_WRITE, /* read and write
|
||||
access */
|
||||
FILE_SHARE_READ,/* file can be read by other
|
||||
processes */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
/* file can be read and written
|
||||
also by other processes */
|
||||
NULL, /* default security attributes */
|
||||
create_flag,
|
||||
attributes,
|
||||
@ -494,6 +638,11 @@ os_file_get_size(
|
||||
|
||||
offs = lseek(file, 0, SEEK_END);
|
||||
|
||||
if (offs == ((off_t)-1)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#if SIZEOF_OFF_T > 4
|
||||
*size = (ulint)(offs & 0xFFFFFFFF);
|
||||
*size_high = (ulint)(offs >> 32);
|
||||
@ -523,13 +672,11 @@ os_file_set_size(
|
||||
ib_longlong low;
|
||||
ulint n_bytes;
|
||||
ibool ret;
|
||||
ibool retry;
|
||||
byte* buf;
|
||||
ulint i;
|
||||
|
||||
ut_a(size == (size & 0xFFFFFFFF));
|
||||
|
||||
try_again:
|
||||
/* We use a very big 8 MB buffer in writing because Linux may be
|
||||
extremely slow in fsync on 1 MB writes */
|
||||
|
||||
@ -570,14 +717,6 @@ try_again:
|
||||
}
|
||||
|
||||
error_handling:
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
ut_error;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
@ -722,8 +861,7 @@ os_file_pwrite(
|
||||
64-bit address */
|
||||
|
||||
if (sizeof(off_t) > 4) {
|
||||
offs = (off_t)offset + (((off_t)offset_high) << 32);
|
||||
|
||||
offs = (off_t)offset + (((off_t)offset_high) << 32);
|
||||
} else {
|
||||
offs = (off_t)offset;
|
||||
|
||||
@ -740,8 +878,8 @@ os_file_pwrite(
|
||||
|
||||
if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
|
||||
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC
|
||||
&& !trx_doublewrite) {
|
||||
|
||||
&& !os_do_not_call_flush_at_each_write) {
|
||||
|
||||
/* Always do fsync to reduce the probability that when
|
||||
the OS crashes, a database page is only partially
|
||||
physically written to disk. */
|
||||
@ -771,7 +909,7 @@ os_file_pwrite(
|
||||
|
||||
if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
|
||||
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC
|
||||
&& !trx_doublewrite) {
|
||||
&& !os_do_not_call_flush_at_each_write) {
|
||||
|
||||
/* Always do fsync to reduce the probability that when
|
||||
the OS crashes, a database page is only partially
|
||||
@ -896,13 +1034,12 @@ os_file_write(
|
||||
DWORD ret2;
|
||||
DWORD low;
|
||||
DWORD high;
|
||||
ibool retry;
|
||||
ulint i;
|
||||
|
||||
ut_a((offset & 0xFFFFFFFF) == offset);
|
||||
|
||||
os_n_file_writes++;
|
||||
try_again:
|
||||
|
||||
ut_ad(file);
|
||||
ut_ad(buf);
|
||||
ut_ad(n > 0);
|
||||
@ -921,7 +1058,15 @@ try_again:
|
||||
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
|
||||
goto error_handling;
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: File pointer positioning to file %s failed at\n"
|
||||
"InnoDB: offset %lu %lu. Operating system error number %lu.\n",
|
||||
name, offset_high, offset,
|
||||
(ulint)GetLastError());
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ret = WriteFile(file, buf, n, &len, NULL);
|
||||
@ -929,38 +1074,61 @@ try_again:
|
||||
/* Always do fsync to reduce the probability that when the OS crashes,
|
||||
a database page is only partially physically written to disk. */
|
||||
|
||||
if (!trx_doublewrite) {
|
||||
if (!os_do_not_call_flush_at_each_write) {
|
||||
ut_a(TRUE == os_file_flush(file));
|
||||
}
|
||||
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
|
||||
if (ret && len == n) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (!os_has_said_disk_full) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: Write to file %s failed at offset %lu %lu.\n"
|
||||
"InnoDB: %lu bytes should have been written, only %lu were written.\n"
|
||||
"InnoDB: Operating system error number %lu.\n"
|
||||
"InnoDB: Check that your OS and file system support files of this size.\n"
|
||||
"InnoDB: Check also the disk is not full or a disk quota exceeded.\n",
|
||||
name, offset_high, offset, n, len,
|
||||
(ulint)GetLastError());
|
||||
|
||||
os_has_said_disk_full = TRUE;
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
#else
|
||||
ibool retry;
|
||||
ssize_t ret;
|
||||
|
||||
try_again:
|
||||
ret = os_file_pwrite(file, buf, n, offset, offset_high);
|
||||
|
||||
if ((ulint)ret == n) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#ifdef __WIN__
|
||||
error_handling:
|
||||
#endif
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
}
|
||||
if (!os_has_said_disk_full) {
|
||||
|
||||
ut_error;
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
return(FALSE);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: Write to file %s failed at offset %lu %lu.\n"
|
||||
"InnoDB: %lu bytes should have been written, only %lu were written.\n"
|
||||
"InnoDB: Operating system error number %lu.\n"
|
||||
"InnoDB: Check that your OS and file system support files of this size.\n"
|
||||
"InnoDB: Check also the disk is not full or a disk quota exceeded.\n",
|
||||
name, offset_high, offset, n, ret, (ulint)errno);
|
||||
|
||||
os_has_said_disk_full = TRUE;
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
@ -1031,7 +1199,8 @@ os_aio_array_create(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Initializes the asynchronous io system. Creates separate aio array for
|
||||
Initializes the asynchronous io system. Calls also os_io_init_simple.
|
||||
Creates a separate aio array for
|
||||
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
|
||||
segment, two aio arrays for log reads and writes with one segment, and a
|
||||
synchronous aio array of the specified size. The combined number of segments
|
||||
@ -1058,6 +1227,8 @@ os_aio_init(
|
||||
ut_ad(n % n_segments == 0);
|
||||
ut_ad(n_segments >= 4);
|
||||
|
||||
os_io_init_simple();
|
||||
|
||||
n_per_seg = n / n_segments;
|
||||
n_write_segs = (n_segments - 2) / 2;
|
||||
n_read_segs = n_segments - 2 - n_write_segs;
|
||||
@ -1078,10 +1249,6 @@ os_aio_init(
|
||||
|
||||
os_aio_validate();
|
||||
|
||||
for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
|
||||
os_file_seek_mutexes[i] = os_mutex_create(NULL);
|
||||
}
|
||||
|
||||
os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
|
||||
|
||||
for (i = 0; i < n_segments; i++) {
|
||||
@ -1739,7 +1906,8 @@ os_aio_windows_handle(
|
||||
if (ret && len == slot->len) {
|
||||
ret_val = TRUE;
|
||||
|
||||
if (slot->type == OS_FILE_WRITE && !trx_doublewrite) {
|
||||
if (slot->type == OS_FILE_WRITE
|
||||
&& !os_do_not_call_flush_at_each_write) {
|
||||
ut_a(TRUE == os_file_flush(slot->file));
|
||||
}
|
||||
} else {
|
||||
@ -1824,7 +1992,8 @@ os_aio_posix_handle(
|
||||
*message1 = slot->message1;
|
||||
*message2 = slot->message2;
|
||||
|
||||
if (slot->type == OS_FILE_WRITE && !trx_doublewrite) {
|
||||
if (slot->type == OS_FILE_WRITE
|
||||
&& !os_do_not_call_flush_at_each_write) {
|
||||
ut_a(TRUE == os_file_flush(slot->file));
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,8 @@ cmp_debug_dtuple_rec_with_match(
|
||||
contains the value for current comparison */
|
||||
/*****************************************************************
|
||||
This function is used to compare two data fields for which the data type
|
||||
is such that we must use MySQL code to compare them. */
|
||||
is such that we must use MySQL code to compare them. The prototype here
|
||||
must be a copy of the the one in ha_innobase.cc! */
|
||||
|
||||
int
|
||||
innobase_mysql_cmp(
|
||||
|
@ -391,7 +391,7 @@ row_ins_check_foreign_constraint(
|
||||
/* out: DB_SUCCESS, DB_LOCK_WAIT,
|
||||
DB_NO_REFERENCED_ROW,
|
||||
or DB_ROW_IS_REFERENCED */
|
||||
ibool check_ref,/* in: TRUE If we want to check that
|
||||
ibool check_ref,/* in: TRUE if we want to check that
|
||||
the referenced table is ok, FALSE if we
|
||||
want to to check the foreign key table */
|
||||
dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the
|
||||
@ -411,10 +411,23 @@ row_ins_check_foreign_constraint(
|
||||
ibool moved;
|
||||
int cmp;
|
||||
ulint err;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad(rw_lock_own(&dict_foreign_key_check_lock, RW_LOCK_SHARED));
|
||||
|
||||
/* If any of the foreign key fields in entry is SQL NULL, we
|
||||
suppress the foreign key check: this is compatible with Oracle,
|
||||
for example */
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
if (UNIV_SQL_NULL == dfield_get_len(
|
||||
dtuple_get_nth_field(entry, i))) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_ref) {
|
||||
check_table = foreign->referenced_table;
|
||||
check_index = foreign->referenced_index;
|
||||
@ -591,6 +604,8 @@ row_ins_scan_sec_index_for_duplicate(
|
||||
dtuple_t* entry, /* in: index entry */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
ulint n_unique;
|
||||
ulint i;
|
||||
int cmp;
|
||||
ulint n_fields_cmp;
|
||||
rec_t* rec;
|
||||
@ -599,6 +614,20 @@ row_ins_scan_sec_index_for_duplicate(
|
||||
ibool moved;
|
||||
mtr_t mtr;
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
/* If the secondary index is unique, but one of the fields in the
|
||||
n_unique first fields is NULL, a unique key violation cannot occur,
|
||||
since we define NULL != NULL in this case */
|
||||
|
||||
for (i = 0; i < n_unique; i++) {
|
||||
if (UNIV_SQL_NULL == dfield_get_len(
|
||||
dtuple_get_nth_field(entry, i))) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Store old value on n_fields_cmp */
|
||||
|
@ -1886,6 +1886,28 @@ loop:
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a table name contains the string "/#sql" which denotes temporary
|
||||
tables in MySQL. */
|
||||
static
|
||||
ibool
|
||||
row_is_mysql_tmp_table_name(
|
||||
/*========================*/
|
||||
/* out: TRUE if temporary table */
|
||||
char* name) /* in: table name in the form 'database/tablename' */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i <= ut_strlen(name) - 5; i++) {
|
||||
if (ut_memcmp(name + i, "/#sql", 5) == 0) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Renames a table for MySQL. */
|
||||
|
||||
@ -1949,16 +1971,27 @@ row_rename_table_for_mysql(
|
||||
str2 = (char *)
|
||||
"';\nold_table_name := '";
|
||||
|
||||
str3 = (char *)
|
||||
"';\n"
|
||||
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
|
||||
"WHERE NAME = old_table_name;\n"
|
||||
"UPDATE SYS_FOREIGN SET FOR_NAME = new_table_name\n"
|
||||
"WHERE FOR_NAME = old_table_name;\n"
|
||||
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
|
||||
"WHERE REF_NAME = old_table_name;\n"
|
||||
"COMMIT WORK;\n"
|
||||
"END;\n";
|
||||
if (row_is_mysql_tmp_table_name(new_name)) {
|
||||
|
||||
/* We want to preserve the original foreign key
|
||||
constraint definitions despite the name change */
|
||||
|
||||
str3 = (char*)
|
||||
"';\n"
|
||||
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
|
||||
"WHERE NAME = old_table_name;\n"
|
||||
"END;\n";
|
||||
} else {
|
||||
str3 = (char*)
|
||||
"';\n"
|
||||
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
|
||||
"WHERE NAME = old_table_name;\n"
|
||||
"UPDATE SYS_FOREIGN SET FOR_NAME = new_table_name\n"
|
||||
"WHERE FOR_NAME = old_table_name;\n"
|
||||
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
|
||||
"WHERE REF_NAME = old_table_name;\n"
|
||||
"END;\n";
|
||||
}
|
||||
|
||||
len = ut_strlen(str1);
|
||||
|
||||
@ -2033,7 +2066,32 @@ row_rename_table_for_mysql(
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
} else {
|
||||
ut_a(dict_table_rename_in_cache(table, new_name));
|
||||
ut_a(dict_table_rename_in_cache(table, new_name,
|
||||
!row_is_mysql_tmp_table_name(new_name)));
|
||||
|
||||
if (row_is_mysql_tmp_table_name(old_name)) {
|
||||
|
||||
err = dict_load_foreigns(new_name);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: in ALTER TABLE table %s\n"
|
||||
"InnoDB: has or is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
new_name);
|
||||
|
||||
ut_a(dict_table_rename_in_cache(table,
|
||||
old_name, FALSE));
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE,
|
||||
NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
funct_exit:
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
@ -2234,7 +2234,7 @@ row_sel_get_clust_rec_for_mysql(
|
||||
(or old_vers) is not rec; in that case we must ignore
|
||||
such row because in our snapshot rec would not have existed.
|
||||
Remember that from rec we cannot see directly which transaction
|
||||
id corrsponds to it: we have to go to the clustered index
|
||||
id corresponds to it: we have to go to the clustered index
|
||||
record. A query where we want to fetch all rows where
|
||||
the secondary index value is in some interval would return
|
||||
a wrong result if we would not drop rows which we come to
|
||||
@ -2245,6 +2245,12 @@ row_sel_get_clust_rec_for_mysql(
|
||||
&& !row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
|
||||
clust_rec, clust_index)) {
|
||||
clust_rec = NULL;
|
||||
} else {
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ut_a(clust_rec == NULL ||
|
||||
row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
|
||||
clust_rec, clust_index));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -2400,7 +2406,12 @@ row_sel_try_search_shortcut_for_mysql(
|
||||
|
||||
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, pcur,
|
||||
RW_S_LATCH, mtr);
|
||||
#ifndef UNIV_SEARCH_DEBUG
|
||||
RW_S_LATCH,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
mtr);
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (!page_rec_is_user_rec(rec)) {
|
||||
@ -2624,15 +2635,18 @@ row_search_for_mysql(
|
||||
|
||||
goto no_shortcut;
|
||||
}
|
||||
|
||||
#ifndef UNIV_SEARCH_DEBUG
|
||||
if (!trx->has_search_latch) {
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
trx->has_search_latch = TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
|
||||
prebuilt, &mtr);
|
||||
if (shortcut == SEL_FOUND) {
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
|
||||
#endif
|
||||
row_sel_store_mysql_rec(buf, prebuilt, rec);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
@ -2794,7 +2808,9 @@ rec_loop:
|
||||
/* The record matches enough */
|
||||
|
||||
ut_ad(mode == PAGE_CUR_GE);
|
||||
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
|
||||
#endif
|
||||
} else if (match_mode == ROW_SEL_EXACT) {
|
||||
/* Test if the index record matches completely to search_tuple
|
||||
in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */
|
||||
|
@ -142,7 +142,7 @@ try_again:
|
||||
|
||||
/*************************************************************************
|
||||
Checks if possible foreign key constraints hold after a delete of the record
|
||||
under pcur. NOTE that this function will temporarily commit mtr and lose
|
||||
under pcur. NOTE that this function will temporarily commit mtr and lose the
|
||||
pcur position! */
|
||||
static
|
||||
ulint
|
||||
|
@ -69,13 +69,19 @@ char* srv_main_thread_op_info = (char *) "";
|
||||
names, where the file name itself may also contain a path */
|
||||
|
||||
char* srv_data_home = NULL;
|
||||
char* srv_logs_home = NULL;
|
||||
char* srv_arch_dir = NULL;
|
||||
|
||||
ulint srv_n_data_files = 0;
|
||||
char** srv_data_file_names = NULL;
|
||||
ulint* srv_data_file_sizes = NULL; /* size in database pages */
|
||||
|
||||
ibool srv_auto_extend_last_data_file = FALSE; /* if TRUE, then we
|
||||
auto-extend the last data
|
||||
file */
|
||||
ulint srv_last_file_size_max = 0; /* if != 0, this tells
|
||||
the max size auto-extending
|
||||
may increase the last data
|
||||
file size */
|
||||
ulint* srv_data_file_is_raw_partition = NULL;
|
||||
|
||||
/* If the following is TRUE we do not allow inserts etc. This protects
|
||||
@ -1605,7 +1611,7 @@ srv_read_initfile(
|
||||
|
||||
/*************************************************************************
|
||||
Initializes the server. */
|
||||
static
|
||||
|
||||
void
|
||||
srv_init(void)
|
||||
/*==========*/
|
||||
@ -1673,7 +1679,7 @@ srv_init(void)
|
||||
/*************************************************************************
|
||||
Initializes the synchronization primitives, memory system, and the thread
|
||||
local storage. */
|
||||
static
|
||||
|
||||
void
|
||||
srv_general_init(void)
|
||||
/*==================*/
|
||||
@ -1695,6 +1701,7 @@ srv_conc_enter_innodb(
|
||||
trx_t* trx) /* in: transaction object associated with the
|
||||
thread */
|
||||
{
|
||||
ibool has_slept = FALSE;
|
||||
srv_conc_slot_t* slot;
|
||||
ulint i;
|
||||
|
||||
@ -1712,7 +1719,7 @@ srv_conc_enter_innodb(
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
retry:
|
||||
os_fast_mutex_lock(&srv_conc_mutex);
|
||||
|
||||
if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
|
||||
@ -1725,7 +1732,23 @@ srv_conc_enter_innodb(
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the transaction is not holding resources, let it sleep
|
||||
for 100 milliseconds, and try again then */
|
||||
|
||||
if (!has_slept && !trx->has_search_latch
|
||||
&& NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
|
||||
|
||||
has_slept = TRUE; /* We let is sleep only once to avoid
|
||||
starvation */
|
||||
|
||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||
|
||||
os_thread_sleep(100000);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Too many threads inside: put the current thread to a queue */
|
||||
|
||||
for (i = 0; i < OS_THREAD_MAX_N; i++) {
|
||||
@ -1917,6 +1940,9 @@ srv_normalize_init_values(void)
|
||||
* ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
srv_last_file_size_max = srv_last_file_size_max
|
||||
* ((1024 * 1024) / UNIV_PAGE_SIZE);
|
||||
|
||||
srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
|
||||
|
||||
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
|
||||
|
@ -84,6 +84,308 @@ we may get an assertion failure in os0file.c */
|
||||
|
||||
#define SRV_LOG_SPACE_FIRST_ID 1000000000
|
||||
|
||||
/*************************************************************************
|
||||
Reads the data files and their sizes from a character string given in
|
||||
the .cnf file. */
|
||||
|
||||
ibool
|
||||
srv_parse_data_file_paths_and_sizes(
|
||||
/*================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
char* str, /* in: the data file path string */
|
||||
char*** data_file_names, /* out, own: array of data file
|
||||
names */
|
||||
ulint** data_file_sizes, /* out, own: array of data file sizes
|
||||
in megabytes */
|
||||
ulint** data_file_is_raw_partition,/* out, own: array of flags
|
||||
showing which data files are raw
|
||||
partitions */
|
||||
ulint* n_data_files, /* out: number of data files */
|
||||
ibool* is_auto_extending, /* out: TRUE if the last data file is
|
||||
auto-extending */
|
||||
ulint* max_auto_extend_size) /* out: max auto extend size for the
|
||||
last file if specified, 0 if not */
|
||||
{
|
||||
char* input_str;
|
||||
char* endp;
|
||||
char* path;
|
||||
ulint size;
|
||||
ulint i = 0;
|
||||
|
||||
*is_auto_extending = FALSE;
|
||||
*max_auto_extend_size = 0;
|
||||
|
||||
input_str = str;
|
||||
|
||||
/* First calculate the number of data files and check syntax:
|
||||
path:size[M | G];path:size[M | G]... . Note that a Windows path may
|
||||
contain a drive name and a ':'. */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == '\0') {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
str++;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (strlen(str) >= ut_strlen(":autoextend")
|
||||
&& 0 == ut_memcmp(str, ":autoextend",
|
||||
ut_strlen(":autoextend"))) {
|
||||
|
||||
str += ut_strlen(":autoextend");
|
||||
|
||||
if (strlen(str) >= ut_strlen(":max:")
|
||||
&& 0 == ut_memcmp(str, ":max:",
|
||||
ut_strlen(":max:"))) {
|
||||
|
||||
str += ut_strlen(":max:");
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
*data_file_names = (char**)ut_malloc(i * sizeof(void*));
|
||||
*data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
*data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
|
||||
*n_data_files = i;
|
||||
|
||||
/* Then store the actual values to our arrays */
|
||||
|
||||
str = input_str;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
/* Note that we must ignore the ':' in a Windows path */
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ':') {
|
||||
/* Make path a null-terminated string */
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
(*data_file_names)[i] = path;
|
||||
(*data_file_sizes)[i] = size;
|
||||
|
||||
if (strlen(str) >= ut_strlen(":autoextend")
|
||||
&& 0 == ut_memcmp(str, ":autoextend",
|
||||
ut_strlen(":autoextend"))) {
|
||||
|
||||
*is_auto_extending = TRUE;
|
||||
|
||||
str += ut_strlen(":autoextend");
|
||||
|
||||
if (strlen(str) >= ut_strlen(":max:")
|
||||
&& 0 == ut_memcmp(str, ":max:",
|
||||
ut_strlen(":max:"))) {
|
||||
|
||||
str += ut_strlen(":max:");
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
*max_auto_extend_size = size;
|
||||
}
|
||||
|
||||
if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
(*data_file_is_raw_partition)[i] = 0;
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
(*data_file_is_raw_partition)[i] = SRV_NEW_RAW;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
|
||||
if ((*data_file_is_raw_partition)[i] == 0) {
|
||||
(*data_file_is_raw_partition)[i] = SRV_OLD_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads log group home directories from a character string given in
|
||||
the .cnf file. */
|
||||
|
||||
ibool
|
||||
srv_parse_log_group_home_dirs(
|
||||
/*==========================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
char* str, /* in: character string */
|
||||
char*** log_group_home_dirs) /* out, own: log group home dirs */
|
||||
{
|
||||
char* input_str;
|
||||
char* path;
|
||||
ulint i = 0;
|
||||
|
||||
input_str = str;
|
||||
|
||||
/* First calculate the number of directories and check syntax:
|
||||
path;path;... */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
*log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
|
||||
|
||||
/* Then store the actual values to our array */
|
||||
|
||||
str = input_str;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ';') {
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
(*log_group_home_dirs)[i] = path;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
I/o-handler thread function. */
|
||||
static
|
||||
@ -127,7 +429,7 @@ io_handler_thread(
|
||||
|
||||
/*************************************************************************
|
||||
Normalizes a directory path for Windows: converts slashes to backslashes. */
|
||||
static
|
||||
|
||||
void
|
||||
srv_normalize_path_for_win(
|
||||
/*=======================*/
|
||||
@ -149,7 +451,7 @@ srv_normalize_path_for_win(
|
||||
/*************************************************************************
|
||||
Adds a slash or a backslash to the end of a string if it is missing
|
||||
and the string is not empty. */
|
||||
static
|
||||
|
||||
char*
|
||||
srv_add_path_separator_if_needed(
|
||||
/*=============================*/
|
||||
@ -356,6 +658,7 @@ open_or_create_data_files(
|
||||
ibool one_created = FALSE;
|
||||
ulint size;
|
||||
ulint size_high;
|
||||
ulint rounded_size_pages;
|
||||
char name[10000];
|
||||
|
||||
if (srv_n_data_files >= 1000) {
|
||||
@ -435,17 +738,35 @@ open_or_create_data_files(
|
||||
ret = os_file_get_size(files[i], &size,
|
||||
&size_high);
|
||||
ut_a(ret);
|
||||
/* Round size downward to megabytes */
|
||||
|
||||
/* File sizes in srv_... are given in
|
||||
database pages */
|
||||
rounded_size_pages = (size / (1024 * 1024)
|
||||
+ 4096 * size_high)
|
||||
<< (20 - UNIV_PAGE_SIZE_SHIFT);
|
||||
|
||||
if (size != srv_calc_low32(
|
||||
srv_data_file_sizes[i])
|
||||
|| size_high != srv_calc_high32(
|
||||
srv_data_file_sizes[i])) {
|
||||
if (i == srv_n_data_files - 1
|
||||
&& srv_auto_extend_last_data_file) {
|
||||
|
||||
if (srv_data_file_sizes[i] >
|
||||
rounded_size_pages
|
||||
|| (srv_last_file_size_max > 0
|
||||
&& srv_last_file_size_max <
|
||||
rounded_size_pages)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: data file %s is of a different size\n"
|
||||
"InnoDB: than specified in the .cnf file!\n", name);
|
||||
}
|
||||
|
||||
srv_data_file_sizes[i] =
|
||||
rounded_size_pages;
|
||||
}
|
||||
|
||||
if (rounded_size_pages
|
||||
!= srv_data_file_sizes[i]) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: data file %s is of different size\n"
|
||||
"InnoDB: Error: data file %s is of a different size\n"
|
||||
"InnoDB: than specified in the .cnf file!\n", name);
|
||||
|
||||
return(DB_ERROR);
|
||||
@ -479,7 +800,7 @@ open_or_create_data_files(
|
||||
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Database physically writes the file full: wait...\n");
|
||||
"InnoDB: Database physically writes the file full: wait...\n");
|
||||
|
||||
ret = os_file_set_size(name, files[i],
|
||||
srv_calc_low32(srv_data_file_sizes[i]),
|
||||
@ -681,6 +1002,8 @@ innobase_start_or_create_for_mysql(void)
|
||||
os_aio_use_native_aio = TRUE;
|
||||
}
|
||||
#endif
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
if (!os_aio_use_native_aio) {
|
||||
os_aio_init(4 * SRV_N_PENDING_IOS_PER_THREAD
|
||||
* srv_n_file_io_threads,
|
||||
@ -727,12 +1050,10 @@ innobase_start_or_create_for_mysql(void)
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
if (sizeof(ulint) == 4
|
||||
&& srv_n_log_files * srv_log_file_size >= 262144) {
|
||||
if (srv_n_log_files * srv_log_file_size >= 262144) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: combined size of log files must be < 4 GB\n"
|
||||
"InnoDB: on 32-bit computers\n");
|
||||
"InnoDB: Error: combined size of log files must be < 4 GB\n");
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
@ -764,7 +1085,6 @@ innobase_start_or_create_for_mysql(void)
|
||||
&max_flushed_lsn, &max_arch_log_no,
|
||||
&sum_of_new_sizes);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
fprintf(stderr, "InnoDB: Could not open data files\n");
|
||||
|
||||
return((int) err);
|
||||
@ -803,9 +1123,9 @@ innobase_start_or_create_for_mysql(void)
|
||||
|| (log_opened && log_created)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: all log files must be created at the same time.\n"
|
||||
"InnoDB: If you want bigger or smaller log files,\n"
|
||||
"InnoDB: shut down the database and make sure there\n"
|
||||
"InnoDB: were no errors in shutdown.\n"
|
||||
"InnoDB: All log files must be created also in database creation.\n"
|
||||
"InnoDB: If you want bigger or smaller log files, shut down the\n"
|
||||
"InnoDB: database and make sure there were no errors in shutdown.\n"
|
||||
"InnoDB: Then delete the existing log files. Edit the .cnf file\n"
|
||||
"InnoDB: and start the database again.\n");
|
||||
|
||||
@ -841,9 +1161,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
recv_reset_logs(ut_dulint_align_down(max_flushed_lsn,
|
||||
OS_FILE_LOG_BLOCK_SIZE),
|
||||
max_arch_log_no + 1, TRUE);
|
||||
recv_reset_logs(max_flushed_lsn, max_arch_log_no + 1, TRUE);
|
||||
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
}
|
||||
@ -883,6 +1201,10 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
srv_startup_is_before_trx_rollback_phase = FALSE;
|
||||
|
||||
/* Initialize the fsp free limit global variable in the log
|
||||
system */
|
||||
fsp_header_get_free_limit(0);
|
||||
|
||||
recv_recovery_from_archive_finish();
|
||||
} else {
|
||||
/* We always try to do a recovery, even if the database had
|
||||
@ -899,6 +1221,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
/* Since ibuf init is in dict_boot, and ibuf is needed
|
||||
in any disk i/o, first call dict_boot */
|
||||
|
||||
dict_boot();
|
||||
trx_sys_init_at_db_start();
|
||||
|
||||
@ -906,6 +1229,11 @@ innobase_start_or_create_for_mysql(void)
|
||||
trx_sys_init_at_db_start */
|
||||
|
||||
srv_startup_is_before_trx_rollback_phase = FALSE;
|
||||
|
||||
/* Initialize the fsp free limit global variable in the log
|
||||
system */
|
||||
fsp_header_get_free_limit(0);
|
||||
|
||||
recv_recovery_from_checkpoint_finish();
|
||||
}
|
||||
|
||||
@ -975,7 +1303,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
if (err != DB_SUCCESS) {
|
||||
return((int)DB_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/* Create the master thread which monitors the database
|
||||
server, and does purge and other utility operations */
|
||||
|
||||
|
@ -20,11 +20,42 @@ Created 3/26/1996 Heikki Tuuri
|
||||
#include "srv0srv.h"
|
||||
#include "trx0purge.h"
|
||||
#include "log0log.h"
|
||||
#include "os0file.h"
|
||||
|
||||
/* The transaction system */
|
||||
trx_sys_t* trx_sys = NULL;
|
||||
trx_doublewrite_t* trx_doublewrite = NULL;
|
||||
|
||||
/********************************************************************
|
||||
Determines if a page number is located inside the doublewrite buffer. */
|
||||
|
||||
ibool
|
||||
trx_doublewrite_page_inside(
|
||||
/*========================*/
|
||||
/* out: TRUE if the location is inside
|
||||
the two blocks of the doublewrite buffer */
|
||||
ulint page_no) /* in: page number */
|
||||
{
|
||||
if (trx_doublewrite == NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (page_no >= trx_doublewrite->block1
|
||||
&& page_no < trx_doublewrite->block1
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (page_no >= trx_doublewrite->block2
|
||||
&& page_no < trx_doublewrite->block2
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Creates or initialializes the doublewrite buffer at a database start. */
|
||||
static
|
||||
@ -36,6 +67,11 @@ trx_doublewrite_init(
|
||||
{
|
||||
trx_doublewrite = mem_alloc(sizeof(trx_doublewrite_t));
|
||||
|
||||
/* When we have the doublewrite buffer in use, we do not need to
|
||||
call os_file_flush (Unix fsync) after every write. */
|
||||
|
||||
os_do_not_call_flush_at_each_write = TRUE;
|
||||
|
||||
mutex_create(&(trx_doublewrite->mutex));
|
||||
mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE);
|
||||
|
||||
|
@ -121,6 +121,7 @@ ut_malloc(
|
||||
{
|
||||
return(ut_malloc_low(n, TRUE));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Frees a memory block allocated with ut_malloc. */
|
||||
|
||||
|
@ -16,6 +16,24 @@ Created 5/11/1994 Heikki Tuuri
|
||||
|
||||
ibool ut_always_false = FALSE;
|
||||
|
||||
/************************************************************
|
||||
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
|
||||
but since there seem to be compiler bugs in both gcc and Visual C++,
|
||||
we do this by a special conversion. */
|
||||
|
||||
ulint
|
||||
ut_get_high32(
|
||||
/*==========*/
|
||||
/* out: a >> 32 */
|
||||
ulint a) /* in: ulint */
|
||||
{
|
||||
if (sizeof(ulint) == 4) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(a >> 32);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
The following function returns a clock time in milliseconds. */
|
||||
|
||||
@ -58,11 +76,11 @@ ut_print_timestamp(
|
||||
FILE* file) /* in: file where to print */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
SYSTEMTIME cal_tm;
|
||||
SYSTEMTIME cal_tm;
|
||||
|
||||
GetLocalTime(&cal_tm);
|
||||
GetLocalTime(&cal_tm);
|
||||
|
||||
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
|
||||
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
|
||||
(int)cal_tm.wYear % 100,
|
||||
(int)cal_tm.wMonth,
|
||||
(int)cal_tm.wDay,
|
||||
@ -70,23 +88,21 @@ ut_print_timestamp(
|
||||
(int)cal_tm.wMinute,
|
||||
(int)cal_tm.wSecond);
|
||||
#else
|
||||
struct tm cal_tm;
|
||||
struct tm* cal_tm_ptr;
|
||||
time_t tm;
|
||||
|
||||
struct tm cal_tm;
|
||||
struct tm* cal_tm_ptr;
|
||||
time_t tm;
|
||||
|
||||
time(&tm);
|
||||
time(&tm);
|
||||
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
localtime_r(&tm, &cal_tm);
|
||||
cal_tm_ptr = &cal_tm;
|
||||
localtime_r(&tm, &cal_tm);
|
||||
cal_tm_ptr = &cal_tm;
|
||||
#else
|
||||
cal_tm_ptr = localtime(&tm);
|
||||
cal_tm_ptr = localtime(&tm);
|
||||
#endif
|
||||
|
||||
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
|
||||
fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
|
||||
cal_tm_ptr->tm_year % 100,
|
||||
cal_tm_ptr->tm_mon+1,
|
||||
cal_tm_ptr->tm_mon + 1,
|
||||
cal_tm_ptr->tm_mday,
|
||||
cal_tm_ptr->tm_hour,
|
||||
cal_tm_ptr->tm_min,
|
||||
@ -94,6 +110,39 @@ ut_print_timestamp(
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Returns current year, month, day. */
|
||||
|
||||
void
|
||||
ut_get_year_month_day(
|
||||
/*==================*/
|
||||
ulint* year, /* out: current year */
|
||||
ulint* month, /* out: month */
|
||||
ulint* day) /* out: day */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
SYSTEMTIME cal_tm;
|
||||
|
||||
GetLocalTime(&cal_tm);
|
||||
|
||||
*year = (ulint)cal_tm.wYear;
|
||||
*month = (ulint)cal_tm.wMonth;
|
||||
*day = (ulint)cal_tm.wDay;
|
||||
#else
|
||||
struct tm cal_tm;
|
||||
struct tm* cal_tm_ptr;
|
||||
time_t tm;
|
||||
|
||||
time(&tm);
|
||||
|
||||
cal_tm_ptr = localtime(&tm);
|
||||
|
||||
*year = (ulint)cal_tm_ptr->tm_year;
|
||||
*month = (ulint)cal_tm_ptr->tm_mon + 1;
|
||||
*day = (ulint)cal_tm_ptr->tm_mday;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Runs an idle loop on CPU. The argument gives the desired delay
|
||||
in microseconds on 100 MHz Pentium + Visual C++. */
|
||||
|
@ -252,7 +252,7 @@ static struct option long_options[] =
|
||||
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("%s Ver 1.11 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE);
|
||||
printf("%s Ver 1.12 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
@ -595,10 +595,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
|
||||
else
|
||||
{
|
||||
if (tmp_dir[0])
|
||||
{
|
||||
if (!(error=my_copy(new_name,org_name,MYF(MY_WME))))
|
||||
VOID(my_delete(new_name,MYF(MY_WME)));
|
||||
}
|
||||
error=my_copy(new_name,org_name,MYF(MY_WME));
|
||||
else
|
||||
error=my_rename(new_name,org_name,MYF(MY_WME));
|
||||
if (!error)
|
||||
@ -608,13 +605,8 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
|
||||
else
|
||||
{
|
||||
if (tmp_dir[0])
|
||||
{
|
||||
|
||||
if (!(error=my_copy(new_name,org_name,
|
||||
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES
|
||||
| MY_COPYTIME))))
|
||||
VOID(my_delete(new_name,MYF(MY_WME)));
|
||||
}
|
||||
error=my_copy(new_name,org_name,
|
||||
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
|
||||
else
|
||||
error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
|
||||
}
|
||||
@ -628,6 +620,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
|
||||
if (error)
|
||||
{
|
||||
VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
|
||||
VOID(my_delete(new_name,MYF(MY_WME)));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (write_loop || verbose)
|
||||
|
@ -139,4 +139,13 @@ believe in love
|
||||
select * from t1 where aString > "believe in love" order by aString;
|
||||
aString
|
||||
believe in myself
|
||||
drop table t1;
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
389
|
||||
count(*)
|
||||
213
|
||||
|
@ -100,3 +100,66 @@ alter table t1 drop key aString;
|
||||
select * from t1 where aString < "believe in myself" order by aString;
|
||||
select * from t1 where aString > "believe in love" order by aString;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Problem with binary strings
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
t1ID int(10) unsigned NOT NULL auto_increment,
|
||||
art char(1) binary NOT NULL default '',
|
||||
KNR char(5) NOT NULL default '',
|
||||
RECHNR char(6) NOT NULL default '',
|
||||
POSNR char(2) NOT NULL default '',
|
||||
ARTNR char(10) NOT NULL default '',
|
||||
TEX char(70) NOT NULL default '',
|
||||
PRIMARY KEY (t1ID),
|
||||
KEY IdxArt (art),
|
||||
KEY IdxKnr (KNR),
|
||||
KEY IdxArtnr (ARTNR)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
INSERT INTO t1 (art) VALUES ('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),
|
||||
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j');
|
||||
select count(*) from t1 where upper(art) = 'J';
|
||||
select count(*) from t1 where art = 'J' or art = 'j';
|
||||
select count(*) from t1 where art = 'j' or art = 'J';
|
||||
select count(*) from t1 where art = 'j';
|
||||
select count(*) from t1 where art = 'J';
|
||||
drop table t1;
|
||||
|
502
sql/ha_innodb.cc
502
sql/ha_innodb.cc
@ -76,17 +76,32 @@ bool innodb_skip = 0;
|
||||
uint innobase_init_flags = 0;
|
||||
ulong innobase_cache_size = 0;
|
||||
|
||||
/* The default values for the following, type long, start-up parameters
|
||||
are declared in mysqld.cc: */
|
||||
|
||||
long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
||||
innobase_log_file_size, innobase_log_buffer_size,
|
||||
innobase_buffer_pool_size, innobase_additional_mem_pool_size,
|
||||
innobase_file_io_threads, innobase_lock_wait_timeout,
|
||||
innobase_thread_concurrency, innobase_force_recovery;
|
||||
innobase_thread_concurrency, innobase_force_recovery;
|
||||
|
||||
char *innobase_data_home_dir;
|
||||
char *innobase_log_group_home_dir, *innobase_log_arch_dir;
|
||||
char *innobase_unix_file_flush_method;
|
||||
my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
|
||||
innobase_use_native_aio, innobase_fast_shutdown;
|
||||
/* The default values for the following char* start-up parameters
|
||||
are determined in innobase_init below: */
|
||||
|
||||
/* innobase_data_file_path=ibdata:15,idata2:1,... */
|
||||
|
||||
char* innobase_data_home_dir = NULL;
|
||||
char* innobase_log_group_home_dir = NULL;
|
||||
char* innobase_log_arch_dir = NULL;
|
||||
char* innobase_unix_file_flush_method = NULL;
|
||||
|
||||
/* Below we have boolean-valued start-up parameters, and their default
|
||||
values */
|
||||
|
||||
my_bool innobase_flush_log_at_trx_commit = FALSE;
|
||||
my_bool innobase_log_archive = FALSE;
|
||||
my_bool innobase_use_native_aio = FALSE;
|
||||
my_bool innobase_fast_shutdown = TRUE;
|
||||
|
||||
/*
|
||||
Set default InnoDB size to 64M, to let users use InnoDB without having
|
||||
@ -337,227 +352,6 @@ ha_innobase::update_thd(
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads the data files and their sizes from a character string given in
|
||||
the .cnf file. */
|
||||
static
|
||||
bool
|
||||
innobase_parse_data_file_paths_and_sizes(void)
|
||||
/*==========================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
{
|
||||
char* str;
|
||||
char* endp;
|
||||
char* path;
|
||||
ulint size;
|
||||
ulint i = 0;
|
||||
|
||||
str = internal_innobase_data_file_path;
|
||||
|
||||
/* First calculate the number of data files and check syntax:
|
||||
path:size[M];path:size[M]... . Note that a Windows path may
|
||||
contain a drive name and a ':'. */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == '\0') {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
str++;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
srv_data_file_names = (char**)ut_malloc(i * sizeof(void*));
|
||||
srv_data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
srv_data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
|
||||
srv_n_data_files = i;
|
||||
|
||||
/* Then store the actual values to our arrays */
|
||||
|
||||
str = internal_innobase_data_file_path;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
/* Note that we must ignore the ':' in a Windows path */
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ':') {
|
||||
/* Make path a null-terminated string */
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
srv_data_file_is_raw_partition[i] = 0;
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
srv_data_file_is_raw_partition[i] = SRV_NEW_RAW;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
|
||||
if (srv_data_file_is_raw_partition[i] == 0) {
|
||||
srv_data_file_is_raw_partition[i] = SRV_OLD_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
srv_data_file_names[i] = path;
|
||||
srv_data_file_sizes[i] = size;
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads log group home directories from a character string given in
|
||||
the .cnf file. */
|
||||
static
|
||||
bool
|
||||
innobase_parse_log_group_home_dirs(void)
|
||||
/*====================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
{
|
||||
char* str;
|
||||
char* path;
|
||||
ulint i = 0;
|
||||
|
||||
str = innobase_log_group_home_dir;
|
||||
|
||||
/* First calculate the number of directories and check syntax:
|
||||
path;path;... */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != (ulint) innobase_mirrored_log_groups) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
srv_log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
|
||||
|
||||
/* Then store the actual values to our array */
|
||||
|
||||
str = innobase_log_group_home_dir;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ';') {
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
srv_log_group_home_dirs[i] = path;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Opens an InnoDB database. */
|
||||
|
||||
@ -581,9 +375,9 @@ innobase_init(void)
|
||||
else
|
||||
{
|
||||
/* It's better to use current lib, to keep path's short */
|
||||
current_lib[0]=FN_CURLIB;
|
||||
current_lib[1]=FN_LIBCHAR;
|
||||
current_lib[2]=0;
|
||||
current_lib[0] = FN_CURLIB;
|
||||
current_lib[1] = FN_LIBCHAR;
|
||||
current_lib[2] = 0;
|
||||
default_path=current_lib;
|
||||
}
|
||||
|
||||
@ -605,12 +399,17 @@ innobase_init(void)
|
||||
|
||||
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
|
||||
default_path);
|
||||
srv_logs_home = (char*) "";
|
||||
srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir :
|
||||
default_path);
|
||||
|
||||
ret = innobase_parse_data_file_paths_and_sizes();
|
||||
|
||||
ret = (bool)
|
||||
srv_parse_data_file_paths_and_sizes(innobase_data_file_path,
|
||||
&srv_data_file_names,
|
||||
&srv_data_file_sizes,
|
||||
&srv_data_file_is_raw_partition,
|
||||
&srv_n_data_files,
|
||||
&srv_auto_extend_last_data_file,
|
||||
&srv_last_file_size_max);
|
||||
if (ret == FALSE) {
|
||||
sql_print_error("InnoDB: syntax error in innodb_data_file_path");
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -618,12 +417,18 @@ innobase_init(void)
|
||||
|
||||
if (!innobase_log_group_home_dir)
|
||||
innobase_log_group_home_dir= default_path;
|
||||
ret = innobase_parse_log_group_home_dirs();
|
||||
|
||||
if (ret == FALSE) {
|
||||
DBUG_RETURN(TRUE);
|
||||
ret = (bool)
|
||||
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
|
||||
&srv_log_group_home_dirs);
|
||||
|
||||
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: syntax error in innodb_log_group_home_dir\n"
|
||||
"InnoDB: or a wrong number of mirrored log groups\n");
|
||||
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ?
|
||||
innobase_unix_file_flush_method :
|
||||
(char*)"fdatasync");
|
||||
@ -664,10 +469,11 @@ innobase_init(void)
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
(void) hash_init(&innobase_open_tables,32,0,0,
|
||||
(hash_get_key) innobase_get_key,0,0);
|
||||
(hash_get_key) innobase_get_key,0,0);
|
||||
pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -1353,33 +1159,43 @@ build_template(
|
||||
|
||||
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
||||
if (!prebuilt->in_update_remember_pos) {
|
||||
if (!prebuilt->hint_no_need_to_fetch_extra_cols) {
|
||||
/* We have a hint that we should at least fetch all
|
||||
columns in the key, or all columns in the table */
|
||||
|
||||
if (prebuilt->read_just_key) {
|
||||
/* MySQL has instructed us that it is enough to
|
||||
fetch the columns in the key */
|
||||
|
||||
fetch_all_in_key = TRUE;
|
||||
} else {
|
||||
/* We are building a temporary table: fetch all
|
||||
columns */
|
||||
columns; the reason is that MySQL may use the
|
||||
clustered index key to store rows, but the mechanism
|
||||
we use below to detect required columns does not
|
||||
reveal that. Actually, it might be enough to
|
||||
fetch only all in the key also in this case! */
|
||||
|
||||
templ_type = ROW_MYSQL_WHOLE_ROW;
|
||||
}
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_X) {
|
||||
/* TODO: should fix the code in sql_update so that we could do
|
||||
with fetching only the needed columns */
|
||||
/* We always retrieve the whole clustered index record if we
|
||||
use exclusive row level locks, for example, if the read is
|
||||
done in an UPDATE statement. */
|
||||
|
||||
templ_type = ROW_MYSQL_WHOLE_ROW;
|
||||
}
|
||||
|
||||
if (templ_type == ROW_MYSQL_REC_FIELDS) {
|
||||
/* In versions < 3.23.50 we always retrieved the clustered
|
||||
index record if prebuilt->select_lock_type == LOCK_S,
|
||||
but there is really not need for that, and in some cases
|
||||
performance could be seriously degraded because the MySQL
|
||||
optimizer did not know about our convention! */
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Let index be the clustered index */
|
||||
|
||||
index = clust_index;
|
||||
} else {
|
||||
index = prebuilt->index;
|
||||
}
|
||||
index = prebuilt->index;
|
||||
} else {
|
||||
index = clust_index;
|
||||
}
|
||||
@ -1475,12 +1291,6 @@ skip_field:
|
||||
(index->table->cols + templ->col_no)->clust_pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (templ_type == ROW_MYSQL_REC_FIELDS
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
prebuilt->need_to_access_clustered = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -1513,7 +1323,9 @@ ha_innobase::write_row(
|
||||
}
|
||||
|
||||
if (table->next_number_field && record == table->record[0]) {
|
||||
|
||||
/* This is the case where the table has an
|
||||
auto-increment column */
|
||||
|
||||
/* Fetch the value the user possibly has set in the
|
||||
autoincrement field */
|
||||
|
||||
@ -1597,12 +1409,6 @@ ha_innobase::write_row(
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the 'in_update_remember_pos' flag to FALSE to
|
||||
make sure all columns are fetched in the select done by
|
||||
update_auto_increment */
|
||||
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
|
||||
update_auto_increment();
|
||||
|
||||
if (auto_inc == 0) {
|
||||
@ -1626,7 +1432,7 @@ ha_innobase::write_row(
|
||||
}
|
||||
|
||||
/* We have to set sql_stat_start to TRUE because
|
||||
update_auto_increment has called a select, and
|
||||
update_auto_increment may have called a select, and
|
||||
has reset that flag; row_insert_for_mysql has to
|
||||
know to set the IX intention lock on the table, something
|
||||
it only does at the start of each statement */
|
||||
@ -1866,9 +1672,7 @@ ha_innobase::update_row(
|
||||
/* This is not a delete */
|
||||
prebuilt->upd_node->is_delete = FALSE;
|
||||
|
||||
if (!prebuilt->in_update_remember_pos) {
|
||||
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
|
||||
}
|
||||
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
|
||||
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
|
||||
@ -1914,7 +1718,6 @@ ha_innobase::delete_row(
|
||||
/* This is a delete */
|
||||
|
||||
prebuilt->upd_node->is_delete = TRUE;
|
||||
prebuilt->in_update_remember_pos = TRUE;
|
||||
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
|
||||
@ -2124,19 +1927,20 @@ ha_innobase::change_active_index(
|
||||
|
||||
active_index = keynr;
|
||||
|
||||
if (keynr != MAX_KEY && table->keys > 0)
|
||||
{
|
||||
if (keynr != MAX_KEY && table->keys > 0) {
|
||||
key = table->key_info + active_index;
|
||||
|
||||
prebuilt->index=dict_table_get_index_noninline(prebuilt->table, key->name);
|
||||
if (!prebuilt->index)
|
||||
{
|
||||
sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key->name, prebuilt->table->name);
|
||||
return(1);
|
||||
}
|
||||
prebuilt->index = dict_table_get_index_noninline(
|
||||
prebuilt->table, key->name);
|
||||
} else {
|
||||
prebuilt->index = dict_table_get_first_index_noninline(
|
||||
prebuilt->table);
|
||||
}
|
||||
|
||||
if (!prebuilt->index) {
|
||||
sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key->name, prebuilt->table->name);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
prebuilt->index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
||||
assert(prebuilt->search_tuple != 0);
|
||||
|
||||
@ -2647,7 +2451,9 @@ ha_innobase::create(
|
||||
|
||||
/* Create the table definition in InnoDB */
|
||||
|
||||
if ((error = create_table_def(trx, form, norm_name))) {
|
||||
error = create_table_def(trx, form, norm_name);
|
||||
|
||||
if (error) {
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
@ -3222,13 +3028,59 @@ ha_innobase::update_table_comment(
|
||||
pos += sprintf(pos, "InnoDB free: %lu kB",
|
||||
(ulong) innobase_get_free_space());
|
||||
|
||||
/* We assume 150 bytes of space to print info */
|
||||
|
||||
dict_print_info_on_foreign_keys(pos, 500, prebuilt->table);
|
||||
/* We assume 450 - length bytes of space to print info */
|
||||
|
||||
if (length < 450) {
|
||||
dict_print_info_on_foreign_keys(FALSE, pos, 450 - length,
|
||||
prebuilt->table);
|
||||
}
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Gets the foreign key create info for a table stored in InnoDB. */
|
||||
|
||||
char*
|
||||
ha_innobase::get_foreign_key_create_info(void)
|
||||
/*==========================================*/
|
||||
/* out, own: character string in the form which
|
||||
can be inserted to the CREATE TABLE statement,
|
||||
MUST be freed with ::free_foreign_key_create_info */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
|
||||
char* str;
|
||||
|
||||
if (prebuilt == NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: cannot get create info for foreign keys\n");
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
str = (char*)ut_malloc(10000);
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table);
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Frees the foreign key create info for a table stored in InnoDB, if it is
|
||||
non-NULL. */
|
||||
|
||||
void
|
||||
ha_innobase::free_foreign_key_create_info(
|
||||
/*======================================*/
|
||||
char* str) /* in, own: create info string to free */
|
||||
{
|
||||
if (str) {
|
||||
ut_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tells something additional to the handler about how to do things. */
|
||||
|
||||
@ -3254,7 +3106,7 @@ ha_innobase::extra(
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
|
||||
break;
|
||||
case HA_EXTRA_KEYREAD:
|
||||
prebuilt->read_just_key = 1;
|
||||
@ -3301,7 +3153,7 @@ ha_innobase::external_lock(
|
||||
trx = prebuilt->trx;
|
||||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->in_update_remember_pos = TRUE;
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
|
||||
|
||||
prebuilt->read_just_key = 0;
|
||||
|
||||
@ -3320,6 +3172,16 @@ ha_innobase::external_lock(
|
||||
thd->transaction.all.innodb_active_trans = 1;
|
||||
trx->n_mysql_tables_in_use++;
|
||||
|
||||
if (thd->tx_isolation == ISO_SERIALIZABLE
|
||||
&& prebuilt->select_lock_type == LOCK_NONE) {
|
||||
|
||||
/* To get serializable execution we let InnoDB
|
||||
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
|
||||
which otherwise would have been consistent reads */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_S;
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
trx->mysql_n_tables_locked++;
|
||||
@ -3427,8 +3289,8 @@ ha_innobase::store_lock(
|
||||
lock_type == TL_READ_NO_INSERT) {
|
||||
/* This is a SELECT ... IN SHARE MODE, or
|
||||
we are doing a complex SQL statement like
|
||||
INSERT INTO ... SELECT ... and the logical logging
|
||||
requires the use of a locking read */
|
||||
INSERT INTO ... SELECT ... and the logical logging (MySQL
|
||||
binlog) requires the use of a locking read */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_S;
|
||||
} else {
|
||||
@ -3468,37 +3330,59 @@ ha_innobase::get_auto_increment()
|
||||
/*=============================*/
|
||||
/* out: the next auto-increment column value */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
longlong nr;
|
||||
int error;
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
longlong nr;
|
||||
int error;
|
||||
|
||||
(void) extra(HA_EXTRA_KEYREAD);
|
||||
index_init(table->next_number_index);
|
||||
/* Also SHOW TABLE STATUS calls this function. Previously, when we did
|
||||
always read the max autoinc key value, setting x-locks, users were
|
||||
surprised that SHOW TABLE STATUS could end up in a deadlock with
|
||||
ordinary SQL queries. We avoid these deadlocks if the auto-inc
|
||||
counter for the table has been initialized by fetching the value
|
||||
from the table struct in dictionary cache. */
|
||||
|
||||
/* We use an exclusive lock when we read the max key value from the
|
||||
auto-increment column index. This is because then build_template will
|
||||
advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
|
||||
id of the auto-increment column is not changed, and previously InnoDB
|
||||
did not fetch it, causing SHOW TABLE STATUS to show wrong values
|
||||
for the autoinc column. */
|
||||
assert(prebuilt->table);
|
||||
|
||||
nr = dict_table_autoinc_read(prebuilt->table);
|
||||
|
||||
prebuilt->select_lock_type = LOCK_X;
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
if (nr != 0) {
|
||||
|
||||
error=index_last(table->record[1]);
|
||||
return(nr + 1);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
nr = 1;
|
||||
} else {
|
||||
nr = (longlong) table->next_number_field->
|
||||
val_int_offset(table->rec_buff_length) + 1;
|
||||
}
|
||||
(void) extra(HA_EXTRA_KEYREAD);
|
||||
index_init(table->next_number_index);
|
||||
|
||||
(void) extra(HA_EXTRA_NO_KEYREAD);
|
||||
/* We use an exclusive lock when we read the max key value from the
|
||||
auto-increment column index. This is because then build_template will
|
||||
advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
|
||||
id of the auto-increment column is not changed, and previously InnoDB
|
||||
did not fetch it, causing SHOW TABLE STATUS to show wrong values
|
||||
for the autoinc column. */
|
||||
|
||||
index_end();
|
||||
prebuilt->select_lock_type = LOCK_X;
|
||||
|
||||
return(nr);
|
||||
/* Play safe and also give in another way the hint to fetch
|
||||
all columns in the key: */
|
||||
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
|
||||
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
|
||||
error = index_last(table->record[1]);
|
||||
|
||||
if (error) {
|
||||
nr = 1;
|
||||
} else {
|
||||
nr = (longlong) table->next_number_field->
|
||||
val_int_offset(table->rec_buff_length) + 1;
|
||||
}
|
||||
|
||||
(void) extra(HA_EXTRA_NO_KEYREAD);
|
||||
|
||||
index_end();
|
||||
|
||||
return(nr);
|
||||
}
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
@ -158,7 +158,8 @@ class ha_innobase: public handler
|
||||
int rename_table(const char* from, const char* to);
|
||||
int check(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
char* update_table_comment(const char* comment);
|
||||
|
||||
char* get_foreign_key_create_info();
|
||||
void free_foreign_key_create_info(char* str);
|
||||
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
||||
enum thr_lock_type lock_type);
|
||||
longlong get_auto_increment();
|
||||
|
@ -225,13 +225,13 @@ int ha_autocommit_or_rollback(THD *thd, int error)
|
||||
/*
|
||||
This function is called when MySQL writes the log segment of a
|
||||
transaction to the binlog. It is called when the LOCK_log mutex is
|
||||
reserved. Here we communicate to transactional table handlers whta
|
||||
reserved. Here we communicate to transactional table handlers what
|
||||
binlog position corresponds to the current transaction. The handler
|
||||
can store it and in recovery print to the user, so that the user
|
||||
knows from what position in the binlog to start possible
|
||||
roll-forward, for example, if the crashed server was a slave in
|
||||
replication. This function also calls the commit of the table
|
||||
handler, because the order of trasnactions in the log of the table
|
||||
handler, because the order of transactions in the log of the table
|
||||
handler must be the same as in the binlog.
|
||||
|
||||
arguments:
|
||||
@ -263,7 +263,6 @@ int ha_report_binlog_offset_and_commit(THD *thd,
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
||||
{
|
||||
int error=0;
|
||||
|
@ -308,7 +308,9 @@ public:
|
||||
virtual char *update_table_comment(const char * comment)
|
||||
{ return (char*) comment;}
|
||||
virtual void append_create_info(String *packet) {}
|
||||
|
||||
virtual char* get_foreign_key_create_info()
|
||||
{ return(NULL);} /* gets foreign key create string from InnoDB */
|
||||
virtual void free_foreign_key_create_info(char* str) {}
|
||||
/* The following can be called without an open handler */
|
||||
virtual const char *table_type() const =0;
|
||||
virtual const char **bas_ext() const =0;
|
||||
|
23
sql/item.cc
23
sql/item.cc
@ -59,12 +59,28 @@ void Item::set_name(char *str,uint length)
|
||||
}
|
||||
}
|
||||
|
||||
bool Item::eq(const Item *item) const // Only doing this on conds
|
||||
/*
|
||||
This function is only called when comparing items in the WHERE clause
|
||||
*/
|
||||
|
||||
bool Item::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
return type() == item->type() && name && item->name &&
|
||||
!my_strcasecmp(name,item->name);
|
||||
}
|
||||
|
||||
bool Item_string::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
if (type() == item->type())
|
||||
{
|
||||
if (binary_cmp)
|
||||
return !stringcmp(&str_value, &item->str_value);
|
||||
return !sortcmp(&str_value, &item->str_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get the value of the function as a TIME structure.
|
||||
As a extra convenience the time structure is reset on error!
|
||||
@ -203,7 +219,7 @@ longlong Item_field::val_int_result()
|
||||
return result_field->val_int();
|
||||
}
|
||||
|
||||
bool Item_field::eq(const Item *item) const
|
||||
bool Item_field::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field;
|
||||
}
|
||||
@ -262,7 +278,8 @@ void Item_string::print(String *str)
|
||||
str->append('\'');
|
||||
}
|
||||
|
||||
bool Item_null::eq(const Item *item) const { return item->type() == type(); }
|
||||
bool Item_null::eq(const Item *item, bool binary_cmp) const
|
||||
{ return item->type() == type(); }
|
||||
double Item_null::val() { null_value=1; return 0.0; }
|
||||
longlong Item_null::val_int() { null_value=1; return 0; }
|
||||
/* ARGSUSED */
|
||||
|
10
sql/item.h
10
sql/item.h
@ -57,7 +57,7 @@ public:
|
||||
virtual void save_org_in_field(Field *field)
|
||||
{ (void) save_in_field(field); }
|
||||
virtual bool send(THD *thd, String *str);
|
||||
virtual bool eq(const Item *) const;
|
||||
virtual bool eq(const Item *, bool binary_cmp) const;
|
||||
virtual Item_result result_type () const { return REAL_RESULT; }
|
||||
virtual enum Type type() const =0;
|
||||
virtual double val()=0;
|
||||
@ -111,7 +111,7 @@ public:
|
||||
{}
|
||||
Item_field(Field *field);
|
||||
enum Type type() const { return FIELD_ITEM; }
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String*);
|
||||
@ -141,7 +141,7 @@ public:
|
||||
Item_null(char *name_par=0)
|
||||
{ maybe_null=null_value=TRUE; name= name_par ? name_par : (char*) "NULL";}
|
||||
enum Type type() const { return NULL_ITEM; }
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
@ -264,6 +264,7 @@ public:
|
||||
void make_field(Send_field *field);
|
||||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
bool basic_const_item() const { return 1; }
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
Item *new_item() { return new Item_string(name,str_value.ptr(),max_length); }
|
||||
String *const_string() { return &str_value; }
|
||||
inline void append(char *str,uint length) { str_value.append(str,length); }
|
||||
@ -323,7 +324,8 @@ public:
|
||||
Item_ref(Item **item, char *table_name_par,char *field_name_par)
|
||||
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
|
||||
enum Type type() const { return REF_ITEM; }
|
||||
bool eq(const Item *item) const { return (*ref)->eq(item); }
|
||||
bool eq(const Item *item, bool binary_cmp) const
|
||||
{ return (*ref)->eq(item, binary_cmp); }
|
||||
~Item_ref() { if (ref) delete *ref; }
|
||||
double val()
|
||||
{
|
||||
|
@ -148,7 +148,7 @@ void Item_func::print_op(String *str)
|
||||
str->append(')');
|
||||
}
|
||||
|
||||
bool Item_func::eq(const Item *item) const
|
||||
bool Item_func::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
/* Assume we don't have rtti */
|
||||
if (this == item)
|
||||
@ -160,7 +160,7 @@ bool Item_func::eq(const Item *item) const
|
||||
func_name() != item_func->func_name())
|
||||
return 0;
|
||||
for (uint i=0; i < arg_count ; i++)
|
||||
if (!args[i]->eq(item_func->args[i]))
|
||||
if (!args[i]->eq(item_func->args[i], binary_cmp))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@ -1975,7 +1975,7 @@ void Item_func_get_user_var::print(String *str)
|
||||
str->append(')');
|
||||
}
|
||||
|
||||
bool Item_func_get_user_var::eq(const Item *item) const
|
||||
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
/* Assume we don't have rtti */
|
||||
if (this == item)
|
||||
@ -2198,7 +2198,7 @@ err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Item_func_match::eq(const Item *item) const
|
||||
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
if (item->type() != FUNC_ITEM)
|
||||
return 0;
|
||||
@ -2209,7 +2209,7 @@ bool Item_func_match::eq(const Item *item) const
|
||||
Item_func_match *ifm=(Item_func_match*) item;
|
||||
|
||||
if (key == ifm->key && table == ifm->table &&
|
||||
key_item()->eq(ifm->key_item()))
|
||||
key_item()->eq(ifm->key_item(), binary_cmp))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
void make_field(Send_field *field);
|
||||
table_map used_tables() const;
|
||||
void update_used_tables();
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
||||
virtual bool have_rev_func() const { return 0; }
|
||||
virtual Item *key_item() const { return args[0]; }
|
||||
@ -889,7 +889,7 @@ public:
|
||||
bool const_item() const { return const_var_flag; }
|
||||
table_map used_tables() const
|
||||
{ return const_var_flag ? 0 : RAND_TABLE_BIT; }
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
@ -937,7 +937,7 @@ public:
|
||||
enum Functype functype() const { return FT_FUNC; }
|
||||
void update_used_tables() {}
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist);
|
||||
bool eq(const Item *) const;
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
longlong val_int() { return val()!=0.0; }
|
||||
double val();
|
||||
|
||||
|
@ -88,6 +88,13 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
|
||||
thd->locked=0;
|
||||
break;
|
||||
}
|
||||
else if (!thd->open_tables)
|
||||
{
|
||||
// Only using temporary tables, no need to unlock
|
||||
thd->some_tables_deleted=0;
|
||||
thd->locked=0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* some table was altered or deleted. reopen tables marked deleted */
|
||||
mysql_unlock_tables(thd,sql_lock);
|
||||
|
@ -162,6 +162,7 @@ static SECURITY_DESCRIPTOR sdPipeDescriptor;
|
||||
static HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
static pthread_cond_t COND_handler_count;
|
||||
static uint handler_count;
|
||||
static bool opt_enable_named_pipe = 0;
|
||||
#endif
|
||||
#ifdef __WIN__
|
||||
static bool opt_console=0,start_mode=0;
|
||||
@ -482,7 +483,7 @@ static void close_connections(void)
|
||||
}
|
||||
}
|
||||
#ifdef __NT__
|
||||
if ( hPipe != INVALID_HANDLE_VALUE )
|
||||
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
|
||||
{
|
||||
HANDLE temp;
|
||||
DBUG_PRINT( "quit", ("Closing named pipes") );
|
||||
@ -983,7 +984,8 @@ static void server_init(void)
|
||||
|
||||
#ifdef __NT__
|
||||
/* create named pipe */
|
||||
if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap)
|
||||
if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap &&
|
||||
opt_enable_named_pipe)
|
||||
{
|
||||
sprintf( szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port );
|
||||
ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) );
|
||||
@ -1722,7 +1724,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
|
||||
strmov(glob_hostname,"mysql");
|
||||
strmov(pidfile_name,glob_hostname);
|
||||
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
|
||||
strmov(strcend(pidfile_name,'.'),".pid"); // Add extension
|
||||
#ifndef DBUG_OFF
|
||||
strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
|
||||
@ -2043,9 +2045,11 @@ The server will not act as a slave.");
|
||||
fflush(stdout);
|
||||
|
||||
#ifdef __NT__
|
||||
if (hPipe == INVALID_HANDLE_VALUE && !have_tcpip)
|
||||
if (hPipe == INVALID_HANDLE_VALUE &&
|
||||
(!have_tcpip || opt_disable_networking)
|
||||
{
|
||||
sql_print_error("TCP/IP or Named Pipes should be installed on NT OS");
|
||||
sql_print_error("TCP/IP or --enable-named-pipe should be configured on NT OS");
|
||||
unireg_abort(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2054,7 +2058,7 @@ The server will not act as a slave.");
|
||||
{
|
||||
pthread_t hThread;
|
||||
handler_count=0;
|
||||
if ( hPipe != INVALID_HANDLE_VALUE )
|
||||
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
|
||||
{
|
||||
handler_count++;
|
||||
if (pthread_create(&hThread,&connection_attrib,
|
||||
@ -2571,9 +2575,9 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
|
||||
fConnected = ConnectNamedPipe( hPipe, NULL );
|
||||
if (abort_loop)
|
||||
break;
|
||||
if ( !fConnected )
|
||||
if (!fConnected)
|
||||
fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
|
||||
if ( !fConnected )
|
||||
if (!fConnected)
|
||||
{
|
||||
CloseHandle( hPipe );
|
||||
if ((hPipe = CreateNamedPipe(szPipeName,
|
||||
@ -2611,7 +2615,7 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
|
||||
continue; // We have to try again
|
||||
}
|
||||
|
||||
if ( !(thd = new THD))
|
||||
if (!(thd = new THD))
|
||||
{
|
||||
DisconnectNamedPipe( hConnectedPipe );
|
||||
CloseHandle( hConnectedPipe );
|
||||
@ -2695,6 +2699,7 @@ enum options {
|
||||
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
|
||||
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
|
||||
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
|
||||
OPT_HAVE_NAMED_PIPE,
|
||||
OPT_DO_PSTACK, OPT_REPORT_HOST,
|
||||
OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
|
||||
OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT,
|
||||
@ -2735,6 +2740,7 @@ static struct option long_options[] = {
|
||||
{"delay-key-write-for-all-tables",
|
||||
no_argument, 0, (int) OPT_DELAY_KEY_WRITE},
|
||||
{"enable-locking", no_argument, 0, (int) OPT_ENABLE_LOCK},
|
||||
{"enable-named-pipe", no_argument, 0, (int) OPT_HAVE_NAMED_PIPE},
|
||||
{"enable-pstack", no_argument, 0, (int) OPT_DO_PSTACK},
|
||||
{"exit-info", optional_argument, 0, 'T'},
|
||||
{"flush", no_argument, 0, (int) OPT_FLUSH},
|
||||
@ -3119,6 +3125,9 @@ struct show_var_st init_vars[]= {
|
||||
{"myisam_max_sort_file_size",(char*) &myisam_max_sort_file_size, SHOW_LONG},
|
||||
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
|
||||
{"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG},
|
||||
#ifdef __NT__
|
||||
{"named_pipe", (char*) &opt_enable_named_pipe, SHOW_BOOL},
|
||||
#endif
|
||||
{"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
|
||||
{"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG},
|
||||
{"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG},
|
||||
@ -3453,10 +3462,12 @@ Starts the MySQL server\n");
|
||||
-W, --warnings Log some not critical warnings to the log file\n");
|
||||
#ifdef __WIN__
|
||||
puts("NT and Win32 specific options:\n\
|
||||
--console Don't remove the console window\n\
|
||||
--install Install mysqld as a service (NT)\n\
|
||||
--remove Remove mysqld from the service list (NT)\n\
|
||||
--standalone Dummy option to start as a standalone program (NT)\
|
||||
--console Don't remove the console window\n\
|
||||
--install Install the default service (NT)\n\
|
||||
--install-manual Install the default service started manually (NT)\n\
|
||||
--remove Remove the default service from the service list (NT)\n\
|
||||
--enable-named-pipe Enable the named pipe (NT)\n\
|
||||
--standalone Dummy option to start as a standalone program (NT)\
|
||||
");
|
||||
#ifdef USE_SYMDIR
|
||||
puts("--use-symbolic-links Enable symbolic link support");
|
||||
@ -3543,9 +3554,10 @@ static void set_options(void)
|
||||
opt_specialflag |= SPECIAL_NO_PRIOR;
|
||||
#endif
|
||||
|
||||
(void) strmov( default_charset, MYSQL_CHARSET);
|
||||
(void) strmov( language, LANGUAGE);
|
||||
(void) strmov( mysql_real_data_home, get_relative_path(DATADIR));
|
||||
(void) strmake(default_charset, MYSQL_CHARSET, sizeof(default_charset)-1);
|
||||
(void) strmake(language, LANGUAGE, sizeof(language)-1);
|
||||
(void) strmake(mysql_real_data_home, get_relative_path(DATADIR),
|
||||
sizeof(mysql_real_data_home-1));
|
||||
#ifdef __WIN__
|
||||
/* Allow Win32 users to move MySQL anywhere */
|
||||
{
|
||||
@ -3556,9 +3568,9 @@ static void set_options(void)
|
||||
}
|
||||
#else
|
||||
const char *tmpenv;
|
||||
if ( !(tmpenv = getenv("MY_BASEDIR_VERSION")))
|
||||
if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
|
||||
tmpenv = DEFAULT_MYSQL_HOME;
|
||||
(void) strmov( mysql_home, tmpenv );
|
||||
(void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
|
||||
#endif
|
||||
|
||||
#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
|
||||
@ -3604,17 +3616,17 @@ static void get_options(int argc,char **argv)
|
||||
default_tx_isolation= ISO_SERIALIZABLE;
|
||||
break;
|
||||
case 'b':
|
||||
strmov(mysql_home,optarg);
|
||||
strmake(mysql_home,optarg,sizeof(mysql_home)-1);
|
||||
break;
|
||||
case 'l':
|
||||
opt_log=1;
|
||||
opt_logname=optarg; // Use hostname.log if null
|
||||
break;
|
||||
case 'h':
|
||||
strmov(mysql_real_data_home,optarg);
|
||||
strmake(mysql_real_data_home,optarg, sizeof(mysql_real_data_home)-1);
|
||||
break;
|
||||
case 'L':
|
||||
strmov(language,optarg);
|
||||
strmake(language, optarg, sizeof(language)-1);
|
||||
break;
|
||||
case 'n':
|
||||
opt_specialflag|= SPECIAL_NEW_FUNC;
|
||||
@ -3972,11 +3984,16 @@ static void get_options(int argc,char **argv)
|
||||
}
|
||||
break;
|
||||
case (int) OPT_PID_FILE:
|
||||
strmov(pidfile_name,optarg);
|
||||
strmake(pidfile_name, optarg, sizeof(pidfile_name)-1);
|
||||
break;
|
||||
case (int) OPT_INIT_FILE:
|
||||
opt_init_file=optarg;
|
||||
break;
|
||||
case (int) OPT_HAVE_NAMED_PIPE:
|
||||
#if __NT__
|
||||
opt_enable_named_pipe=1;
|
||||
#endif
|
||||
break;
|
||||
#ifdef __WIN__
|
||||
case (int) OPT_STANDALONE: /* Dummy option for NT */
|
||||
break;
|
||||
@ -4022,10 +4039,10 @@ static void get_options(int argc,char **argv)
|
||||
myisam_delay_key_write=0;
|
||||
break;
|
||||
case 'C':
|
||||
strmov(default_charset,optarg);
|
||||
strmake(default_charset, optarg, sizeof(default_charset)-1);
|
||||
break;
|
||||
case OPT_CHARSETS_DIR:
|
||||
strmov(mysql_charsets_dir, optarg);
|
||||
strmake(mysql_charsets_dir, optarg, sizeof(mysql_charsets_dir)-1);
|
||||
charsets_dir = mysql_charsets_dir;
|
||||
break;
|
||||
#include "sslopt-case.h"
|
||||
@ -4295,16 +4312,17 @@ static void fix_paths(void)
|
||||
|
||||
char buff[FN_REFLEN],*sharedir=get_relative_path(SHAREDIR);
|
||||
if (test_if_hard_path(sharedir))
|
||||
strmov(buff,sharedir); /* purecov: tested */
|
||||
strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */
|
||||
else
|
||||
strxmov(buff,mysql_home,sharedir,NullS);
|
||||
strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
|
||||
convert_dirname(buff,buff,NullS);
|
||||
(void) my_load_path(language,language,buff);
|
||||
|
||||
/* If --character-sets-dir isn't given, use shared library dir */
|
||||
if (charsets_dir != mysql_charsets_dir)
|
||||
{
|
||||
strmov(strmov(mysql_charsets_dir,buff),CHARSET_DIR);
|
||||
strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
|
||||
CHARSET_DIR, NullS);
|
||||
charsets_dir=mysql_charsets_dir;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ dist-hook:
|
||||
test -d $(distdir)/$$dir || mkdir $(distdir)/$$dir; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$dir/*.* $(distdir)/$$dir; \
|
||||
done; \
|
||||
sleep 1 ; touch $(srcdir)/*/errmsg.sys
|
||||
$(INSTALL_DATA) $(srcdir)/charsets/README $(distdir)/charsets
|
||||
$(INSTALL_DATA) $(srcdir)/charsets/Index $(distdir)/charsets
|
||||
|
||||
|
@ -430,6 +430,7 @@ void close_thread_tables(THD *thd, bool locked)
|
||||
|
||||
while (thd->open_tables)
|
||||
found_old_table|=close_thread_table(thd, &thd->open_tables);
|
||||
thd->some_tables_deleted=0;
|
||||
|
||||
/* Free tables to hold down open files */
|
||||
while (open_cache.records > table_cache_size && unused_tables)
|
||||
@ -1692,7 +1693,7 @@ find_item_in_list(Item *find,List<Item> &items)
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
if ((*found)->eq(item))
|
||||
if ((*found)->eq(item,0))
|
||||
continue; // Same field twice (Access?)
|
||||
if (current_thd->where)
|
||||
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
|
||||
@ -1708,7 +1709,7 @@ find_item_in_list(Item *find,List<Item> &items)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!table_name && (item->eq(find) ||
|
||||
else if (!table_name && (item->eq(find,0) ||
|
||||
find->name &&
|
||||
!my_strcasecmp(item->name,find->name)))
|
||||
{
|
||||
@ -2186,7 +2187,7 @@ int setup_ftfuncs(THD *thd)
|
||||
lj.rewind();
|
||||
while ((ftf2=lj++) != ftf)
|
||||
{
|
||||
if (ftf->eq(ftf2) && !ftf2->master)
|
||||
if (ftf->eq(ftf2,1) && !ftf2->master)
|
||||
ftf2->master=ftf;
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
||||
new_table=ren_table->next;
|
||||
|
||||
sprintf(name,"%s/%s/%s%s",mysql_data_home,
|
||||
new_table->db,new_table->name,
|
||||
new_table->db,new_table->real_name,
|
||||
reg_ext);
|
||||
if (!access(name,F_OK))
|
||||
{
|
||||
@ -134,7 +134,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
||||
DBUG_RETURN(ren_table); // This can't be skipped
|
||||
}
|
||||
sprintf(name,"%s/%s/%s%s",mysql_data_home,
|
||||
ren_table->db,ren_table->name,
|
||||
ren_table->db,ren_table->real_name,
|
||||
reg_ext);
|
||||
if ((table_type=get_table_type(name)) == DB_TYPE_UNKNOWN)
|
||||
{
|
||||
@ -143,11 +143,11 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
||||
DBUG_RETURN(ren_table);
|
||||
}
|
||||
else if (mysql_rename_table(table_type,
|
||||
ren_table->db, ren_table->name,
|
||||
new_table->db, new_table->name))
|
||||
ren_table->db, ren_table->real_name,
|
||||
new_table->db, new_table->real_name))
|
||||
{
|
||||
if (!skip_error)
|
||||
return ren_table;
|
||||
DBUG_RETURN(ren_table);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
@ -1247,14 +1247,14 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
|
||||
{
|
||||
if (new_fields->val->used_tables())
|
||||
{
|
||||
if (old->val->eq(new_fields->val))
|
||||
if (old->val->eq(new_fields->val, old->field->binary()))
|
||||
{
|
||||
old->level=old->const_level=and_level;
|
||||
old->exists_optimize&=new_fields->exists_optimize;
|
||||
}
|
||||
}
|
||||
else if (old->val->eq(new_fields->val) && old->eq_func &&
|
||||
new_fields->eq_func)
|
||||
else if (old->val->eq(new_fields->val, old->field->binary()) &&
|
||||
old->eq_func && new_fields->eq_func)
|
||||
{
|
||||
old->level=old->const_level=and_level;
|
||||
old->exists_optimize&=new_fields->exists_optimize;
|
||||
@ -2769,7 +2769,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
|
||||
ORDER *order;
|
||||
for (order=start_order ; order ; order=order->next)
|
||||
{
|
||||
if ((*ref_item)->eq(order->item[0]))
|
||||
if ((*ref_item)->eq(order->item[0],0))
|
||||
break;
|
||||
}
|
||||
if (order)
|
||||
@ -3026,7 +3026,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
|
||||
Item *right_item= func->arguments()[1];
|
||||
Item_func::Functype functype= func->functype();
|
||||
|
||||
if (right_item->eq(field) && left_item != value)
|
||||
if (right_item->eq(field,0) && left_item != value)
|
||||
{
|
||||
Item *tmp=value->new_item();
|
||||
if (tmp)
|
||||
@ -3045,7 +3045,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
|
||||
func->arguments()[1]->result_type()));
|
||||
}
|
||||
}
|
||||
else if (left_item->eq(field) && right_item != value)
|
||||
else if (left_item->eq(field,0) && right_item != value)
|
||||
{
|
||||
Item *tmp=value->new_item();
|
||||
if (tmp)
|
||||
@ -3286,7 +3286,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
||||
{ // boolan compare function
|
||||
Item *left_item= ((Item_func*) cond)->arguments()[0];
|
||||
Item *right_item= ((Item_func*) cond)->arguments()[1];
|
||||
if (left_item->eq(right_item))
|
||||
if (left_item->eq(right_item,1))
|
||||
{
|
||||
if (!left_item->maybe_null ||
|
||||
((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
|
||||
@ -3331,22 +3331,22 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
|
||||
return 0;
|
||||
Item *left_item= ((Item_func*) cond)->arguments()[0];
|
||||
Item *right_item= ((Item_func*) cond)->arguments()[1];
|
||||
if (left_item->eq(comp_item))
|
||||
if (left_item->eq(comp_item,1))
|
||||
{
|
||||
if (right_item->const_item())
|
||||
{
|
||||
if (*const_item)
|
||||
return right_item->eq(*const_item);
|
||||
return right_item->eq(*const_item, 1);
|
||||
*const_item=right_item;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (right_item->eq(comp_item))
|
||||
else if (right_item->eq(comp_item,1))
|
||||
{
|
||||
if (left_item->const_item())
|
||||
{
|
||||
if (*const_item)
|
||||
return left_item->eq(*const_item);
|
||||
return left_item->eq(*const_item, 1);
|
||||
*const_item=left_item;
|
||||
return 1;
|
||||
}
|
||||
@ -5267,7 +5267,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
|
||||
if (!field->table->const_table && !field->table->maybe_null)
|
||||
{
|
||||
Item *ref_item=part_of_refkey(field->table,field);
|
||||
if (ref_item && ref_item->eq(right_item))
|
||||
if (ref_item && ref_item->eq(right_item,1))
|
||||
{
|
||||
if (right_item->type() == Item::FIELD_ITEM)
|
||||
return (field->eq_def(((Item_field *) right_item)->field));
|
||||
@ -6513,7 +6513,7 @@ test_if_subpart(ORDER *a,ORDER *b)
|
||||
{
|
||||
for (; a && b; a=a->next,b=b->next)
|
||||
{
|
||||
if ((*a->item)->eq(*b->item))
|
||||
if ((*a->item)->eq(*b->item,1))
|
||||
a->asc=b->asc;
|
||||
else
|
||||
return 0;
|
||||
@ -6540,7 +6540,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
|
||||
|
||||
for (; a && b; a=a->next,b=b->next)
|
||||
{
|
||||
if (!(*a->item)->eq(*b->item))
|
||||
if (!(*a->item)->eq(*b->item,1))
|
||||
DBUG_RETURN(0);
|
||||
map|=a->item[0]->used_tables();
|
||||
}
|
||||
|
@ -908,9 +908,21 @@ store_create_info(THD *thd, TABLE *table, String *packet)
|
||||
}
|
||||
packet->append(')');
|
||||
}
|
||||
packet->append("\n)", 2);
|
||||
|
||||
handler *file = table->file;
|
||||
|
||||
/* Get possible foreign key definitions stored in InnoDB and append them
|
||||
to the CREATE TABLE statement */
|
||||
|
||||
char* for_str = file->get_foreign_key_create_info();
|
||||
|
||||
if (for_str) {
|
||||
packet->append(for_str, strlen(for_str));
|
||||
|
||||
file->free_foreign_key_create_info(for_str);
|
||||
}
|
||||
|
||||
packet->append("\n)", 2);
|
||||
packet->append(" TYPE=", 6);
|
||||
packet->append(file->table_type());
|
||||
char buff[128];
|
||||
|
@ -204,9 +204,17 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-/bin:/usr/bin}\" \
|
||||
make benchdir_root=$RPM_BUILD_ROOT/usr/share/
|
||||
}
|
||||
|
||||
# Use the build root for temporary storage of the shared libraries.
|
||||
# Use our own copy of glibc
|
||||
|
||||
OTHER_LIBC_DIR=/usr/local/mysql-glibc
|
||||
USE_OTHER_LIBC_DIR=""
|
||||
if test -d "$OTHER_LIBC_DIR"
|
||||
then
|
||||
USE_OTHER_LIBC_DIR="--with-other-libc=$OTHER_LIBC_DIR"
|
||||
fi
|
||||
|
||||
# Use the build root for temporary storage of the shared libraries.
|
||||
|
||||
RBR=$RPM_BUILD_ROOT
|
||||
MBD=$RPM_BUILD_DIR/mysql-%{mysql_version}
|
||||
if test -z "$RBR" -o "$RBR" = "/"
|
||||
@ -217,10 +225,16 @@ fi
|
||||
rm -rf $RBR
|
||||
mkdir -p $RBR
|
||||
|
||||
#
|
||||
# Use MYSQL_BUILD_PATH so that we can use a dedicated version of gcc
|
||||
#
|
||||
PATH=${MYSQL_BUILD_PATH:-/bin:/usr/bin}
|
||||
export PATH
|
||||
|
||||
# We need to build shared libraries separate from mysqld-max because we
|
||||
# are using --with-other-libc
|
||||
|
||||
BuildMySQL "--disable-shared --with-other-libc=$OTHER_LIBC_DIR --with-berkeley-db --with-innodb --with-mysqld-ldflags='-all-static' --with-server-suffix='-Max'"
|
||||
BuildMySQL "--disable-shared $USE_OTHER_LIBC_DIR --with-berkeley-db --with-innodb --with-mysqld-ldflags='-all-static' --with-server-suffix='-Max'"
|
||||
|
||||
# Save everything for debug
|
||||
# tar cf $RBR/all.tar .
|
||||
@ -250,7 +264,7 @@ automake
|
||||
BuildMySQL "--disable-shared" \
|
||||
"--with-mysqld-ldflags='-all-static'" \
|
||||
"--with-client-ldflags='-all-static'" \
|
||||
"--with-other-libc=$OTHER_LIBC_DIR" \
|
||||
"$USE_OTHER_LIBC_DIR" \
|
||||
"--without-berkeley-db --without-innodb"
|
||||
nm --numeric-sort sql/mysqld > sql/mysqld.sym
|
||||
|
||||
|
481
zlib/ChangeLog
Normal file
481
zlib/ChangeLog
Normal file
@ -0,0 +1,481 @@
|
||||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.1.4 (11 March 2002)
|
||||
- ZFREE was repeated on same allocation on some error conditions.
|
||||
This creates a security problem described in
|
||||
http://www.zlib.org/advisory-2002-03-11.txt
|
||||
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
|
||||
- Avoid accesses before window for invalid distances with inflate window
|
||||
less than 32K.
|
||||
- force windowBits > 8 to avoid a bug in the encoder for a window size
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5).
|
||||
|
||||
Changes in 1.1.3 (9 July 1998)
|
||||
- fix "an inflate input buffer bug that shows up on rare but persistent
|
||||
occasions" (Mark)
|
||||
- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
|
||||
- fix gzseek(..., SEEK_SET) in write mode
|
||||
- fix crc check after a gzeek (Frank Faubert)
|
||||
- fix miniunzip when the last entry in a zip file is itself a zip file
|
||||
(J Lillge)
|
||||
- add contrib/asm586 and contrib/asm686 (Brian Raiter)
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
|
||||
- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
|
||||
- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
|
||||
- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
|
||||
- added a FAQ file
|
||||
|
||||
- Support gzdopen on Mac with Metrowerks (Jason Linhart)
|
||||
- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
|
||||
- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
|
||||
- avoid some warnings with Borland C (Tom Tanner)
|
||||
- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
|
||||
- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
|
||||
- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
|
||||
- use libdir and includedir in Makefile.in (Tim Mooney)
|
||||
- support shared libraries on OSF1 V4 (Tim Mooney)
|
||||
- remove so_locations in "make clean" (Tim Mooney)
|
||||
- fix maketree.c compilation error (Glenn, Mark)
|
||||
- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
|
||||
- new Makefile.riscos (Rich Walker)
|
||||
- initialize static descriptors in trees.c for embedded targets (Nick Smith)
|
||||
- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
|
||||
- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
|
||||
- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
|
||||
- fix maketree.c to allow clean compilation of inffixed.h (Mark)
|
||||
- fix parameter check in deflateCopy (Gunther Nikl)
|
||||
- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
|
||||
- Many portability patches by Christian Spieler:
|
||||
. zutil.c, zutil.h: added "const" for zmem*
|
||||
. Make_vms.com: fixed some typos
|
||||
. Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
|
||||
. msdos/Makefile.msc: remove "default rtl link library" info from obj files
|
||||
. msdos/Makefile.*: use model-dependent name for the built zlib library
|
||||
. msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
|
||||
new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
|
||||
- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
|
||||
- replace __far with _far for better portability (Christian Spieler, Tom Lane)
|
||||
- fix test for errno.h in configure (Tim Newsham)
|
||||
|
||||
Changes in 1.1.2 (19 March 98)
|
||||
- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
|
||||
See http://www.winimage.com/zLibDll/unzip.html
|
||||
- preinitialize the inflate tables for fixed codes, to make the code
|
||||
completely thread safe (Mark)
|
||||
- some simplifications and slight speed-up to the inflate code (Mark)
|
||||
- fix gzeof on non-compressed files (Allan Schrum)
|
||||
- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
|
||||
- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
|
||||
- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
|
||||
- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
|
||||
- do not wrap extern "C" around system includes (Tom Lane)
|
||||
- mention zlib binding for TCL in README (Andreas Kupries)
|
||||
- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
|
||||
- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
|
||||
- allow "configure --prefix $HOME" (Tim Mooney)
|
||||
- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
|
||||
- move Makefile.sas to amiga/Makefile.sas
|
||||
|
||||
Changes in 1.1.1 (27 Feb 98)
|
||||
- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
|
||||
- remove block truncation heuristic which had very marginal effect for zlib
|
||||
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
|
||||
compression ratio on some files. This also allows inlining _tr_tally for
|
||||
matches in deflate_slow.
|
||||
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
|
||||
|
||||
Changes in 1.1.0 (24 Feb 98)
|
||||
- do not return STREAM_END prematurely in inflate (John Bowler)
|
||||
- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
|
||||
- compile with -DFASTEST to get compression code optimized for speed only
|
||||
- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
|
||||
- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
|
||||
on Sun but significant on HP)
|
||||
|
||||
- add a pointer to experimental unzip library in README (Gilles Vollant)
|
||||
- initialize variable gcc in configure (Chris Herborth)
|
||||
|
||||
Changes in 1.0.9 (17 Feb 1998)
|
||||
- added gzputs and gzgets functions
|
||||
- do not clear eof flag in gzseek (Mark Diekhans)
|
||||
- fix gzseek for files in transparent mode (Mark Diekhans)
|
||||
- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
|
||||
- replace EXPORT with ZEXPORT to avoid conflict with other programs
|
||||
- added compress2 in zconf.h, zlib.def, zlib.dnt
|
||||
- new asm code from Gilles Vollant in contrib/asm386
|
||||
- simplify the inflate code (Mark):
|
||||
. Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
|
||||
. ZALLOC the length list in inflate_trees_fixed() instead of using stack
|
||||
. ZALLOC the value area for huft_build() instead of using stack
|
||||
. Simplify Z_FINISH check in inflate()
|
||||
|
||||
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
|
||||
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
|
||||
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
|
||||
the declaration of FAR (Gilles VOllant)
|
||||
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
|
||||
- read_buf buf parameter of type Bytef* instead of charf*
|
||||
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
|
||||
- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
|
||||
- fix check for presence of directories in "make install" (Ian Willis)
|
||||
|
||||
Changes in 1.0.8 (27 Jan 1998)
|
||||
- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
|
||||
- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
|
||||
- added compress2() to allow setting the compression level
|
||||
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
|
||||
- use constant arrays for the static trees in trees.c instead of computing
|
||||
them at run time (thanks to Ken Raeburn for this suggestion). To create
|
||||
trees.h, compile with GEN_TREES_H and run "make test".
|
||||
- check return code of example in "make test" and display result
|
||||
- pass minigzip command line options to file_compress
|
||||
- simplifying code of inflateSync to avoid gcc 2.8 bug
|
||||
|
||||
- support CC="gcc -Wall" in configure -s (QingLong)
|
||||
- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
|
||||
- fix test for shared library support to avoid compiler warnings
|
||||
- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
|
||||
- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
|
||||
- do not use fdopen for Metrowerks on Mac (Brad Pettit))
|
||||
- add checks for gzputc and gzputc in example.c
|
||||
- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
|
||||
- use const for the CRC table (Ken Raeburn)
|
||||
- fixed "make uninstall" for shared libraries
|
||||
- use Tracev instead of Trace in infblock.c
|
||||
- in example.c use correct compressed length for test_sync
|
||||
- suppress +vnocompatwarnings in configure for HPUX (not always supported)
|
||||
|
||||
Changes in 1.0.7 (20 Jan 1998)
|
||||
- fix gzseek which was broken in write mode
|
||||
- return error for gzseek to negative absolute position
|
||||
- fix configure for Linux (Chun-Chung Chen)
|
||||
- increase stack space for MSC (Tim Wegner)
|
||||
- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
|
||||
- define EXPORTVA for gzprintf (Gilles Vollant)
|
||||
- added man page zlib.3 (Rick Rodgers)
|
||||
- for contrib/untgz, fix makedir() and improve Makefile
|
||||
|
||||
- check gzseek in write mode in example.c
|
||||
- allocate extra buffer for seeks only if gzseek is actually called
|
||||
- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
|
||||
- add inflateSyncPoint in zconf.h
|
||||
- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
|
||||
|
||||
Changes in 1.0.6 (19 Jan 1998)
|
||||
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
|
||||
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
|
||||
- Fix a deflate bug occuring only with compression level 0 (thanks to
|
||||
Andy Buckler for finding this one).
|
||||
- In minigzip, pass transparently also the first byte for .Z files.
|
||||
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
|
||||
- check Z_FINISH in inflate (thanks to Marc Schluper)
|
||||
- Implement deflateCopy (thanks to Adam Costello)
|
||||
- make static libraries by default in configure, add --shared option.
|
||||
- move MSDOS or Windows specific files to directory msdos
|
||||
- suppress the notion of partial flush to simplify the interface
|
||||
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
|
||||
- suppress history buffer provided by application to simplify the interface
|
||||
(this feature was not implemented anyway in 1.0.4)
|
||||
- next_in and avail_in must be initialized before calling inflateInit or
|
||||
inflateInit2
|
||||
- add EXPORT in all exported functions (for Windows DLL)
|
||||
- added Makefile.nt (thanks to Stephen Williams)
|
||||
- added the unsupported "contrib" directory:
|
||||
contrib/asm386/ by Gilles Vollant <info@winimage.com>
|
||||
386 asm code replacing longest_match().
|
||||
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB.
|
||||
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
|
||||
level) in minigzip (thanks to Tom Lane)
|
||||
|
||||
- use const for rommable constants in deflate
|
||||
- added test for gzseek and gztell in example.c
|
||||
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
|
||||
- add undocumented function zError to convert error code to string
|
||||
(for Tim Smithers)
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
|
||||
- Use default memcpy for Symantec MSDOS compiler.
|
||||
- Add EXPORT keyword for check_func (needed for Windows DLL)
|
||||
- add current directory to LD_LIBRARY_PATH for "make test"
|
||||
- create also a link for libz.so.1
|
||||
- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
|
||||
- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
|
||||
- added -soname for Linux in configure (Chun-Chung Chen,
|
||||
- assign numbers to the exported functions in zlib.def (for Windows DLL)
|
||||
- add advice in zlib.h for best usage of deflateSetDictionary
|
||||
- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
|
||||
- allow compilation with ANSI keywords only enabled for TurboC in large model
|
||||
- avoid "versionString"[0] (Borland bug)
|
||||
- add NEED_DUMMY_RETURN for Borland
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
|
||||
- allow compilation with CC
|
||||
- defined STDC for OS/2 (David Charlap)
|
||||
- limit external names to 8 chars for MVS (Thomas Lund)
|
||||
- in minigzip.c, use static buffers only for 16-bit systems
|
||||
- fix suffix check for "minigzip -d foo.gz"
|
||||
- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
|
||||
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
|
||||
- added makelcc.bat for lcc-win32 (Tom St Denis)
|
||||
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
|
||||
- check for unistd.h in configure (for off_t)
|
||||
- remove useless check parameter in inflate_blocks_free
|
||||
- avoid useless assignment of s->check to itself in inflate_blocks_new
|
||||
- do not flush twice in gzclose (thanks to Ken Raeburn)
|
||||
- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
|
||||
- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
|
||||
- work around buggy fclose on pipes for HP/UX
|
||||
- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
|
||||
- fix configure if CC is already equal to gcc
|
||||
|
||||
Changes in 1.0.5 (3 Jan 98)
|
||||
- Fix inflate to terminate gracefully when fed corrupted or invalid data
|
||||
- Use const for rommable constants in inflate
|
||||
- Eliminate memory leaks on error conditions in inflate
|
||||
- Removed some vestigial code in inflate
|
||||
- Update web address in README
|
||||
|
||||
Changes in 1.0.4 (24 Jul 96)
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||
|
||||
Changes in 1.0.3 (2 Jul 96)
|
||||
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
|
||||
small and medium models; this makes the library incompatible with previous
|
||||
versions for these models. (No effect in large model or on other systems.)
|
||||
- return OK instead of BUF_ERROR if previous deflate call returned with
|
||||
avail_out as zero but there is nothing to do
|
||||
- added memcmp for non STDC compilers
|
||||
- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
|
||||
- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
|
||||
- better check for 16-bit mode MSC (avoids problem with Symantec)
|
||||
|
||||
Changes in 1.0.2 (23 May 96)
|
||||
- added Windows DLL support
|
||||
- added a function zlibVersion (for the DLL support)
|
||||
- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
|
||||
- Bytef is define's instead of typedef'd only for Borland C
|
||||
- avoid reading uninitialized memory in example.c
|
||||
- mention in README that the zlib format is now RFC1950
|
||||
- updated Makefile.dj2
|
||||
- added algorithm.doc
|
||||
|
||||
Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
||||
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||
- fix inflate bug with empty stored block
|
||||
- fix MSDOS medium model which was broken in 0.99
|
||||
- fix deflateParams() which could generated bad compressed data.
|
||||
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||
- added an INDEX file
|
||||
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||
Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
|
||||
- speed up adler32 for modern machines without auto-increment
|
||||
- added -ansi for IRIX in configure
|
||||
- static_init_done in trees.c is an int
|
||||
- define unlink as delete for VMS
|
||||
- fix configure for QNX
|
||||
- add configure branch for SCO and HPUX
|
||||
- avoid many warnings (unused variables, dead assignments, etc...)
|
||||
- no fdopen for BeOS
|
||||
- fix the Watcom fix for 32 bit mode (define FAR as empty)
|
||||
- removed redefinition of Byte for MKWERKS
|
||||
- work around an MWKERKS bug (incorrect merge of all .h files)
|
||||
|
||||
Changes in 0.99 (27 Jan 96)
|
||||
- allow preset dictionary shared between compressor and decompressor
|
||||
- allow compression level 0 (no compression)
|
||||
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||
and compression strategy.
|
||||
- test large buffers and deflateParams in example.c
|
||||
- add optional "configure" to build zlib as a shared library
|
||||
- suppress Makefile.qnx, use configure instead
|
||||
- fixed deflate for 64-bit systems (detected on Cray)
|
||||
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
|
||||
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
|
||||
- always return Z_BUF_ERROR when deflate() has nothing to do
|
||||
- deflateInit and inflateInit are now macros to allow version checking
|
||||
- prefix all global functions and types with z_ with -DZ_PREFIX
|
||||
- make falloc completely reentrant (inftrees.c)
|
||||
- fixed very unlikely race condition in ct_static_init
|
||||
- free in reverse order of allocation to help memory manager
|
||||
- use zlib-1.0/* instead of zlib/* inside the tar.gz
|
||||
- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
|
||||
-Wconversion -Wstrict-prototypes -Wmissing-prototypes"
|
||||
- allow gzread on concatenated .gz files
|
||||
- deflateEnd now returns Z_DATA_ERROR if it was premature
|
||||
- deflate is finally (?) fully deterministic (no matches beyond end of input)
|
||||
- Document Z_SYNC_FLUSH
|
||||
- add uninstall in Makefile
|
||||
- Check for __cpluplus in zlib.h
|
||||
- Better test in ct_align for partial flush
|
||||
- avoid harmless warnings for Borland C++
|
||||
- initialize hash_head in deflate.c
|
||||
- avoid warning on fdopen (gzio.c) for HP cc -Aa
|
||||
- include stdlib.h for STDC compilers
|
||||
- include errno.h for Cray
|
||||
- ignore error if ranlib doesn't exist
|
||||
- call ranlib twice for NeXTSTEP
|
||||
- use exec_prefix instead of prefix for libz.a
|
||||
- renamed ct_* as _tr_* to avoid conflict with applications
|
||||
- clear z->msg in inflateInit2 before any error return
|
||||
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
|
||||
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
|
||||
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
|
||||
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
|
||||
- in fcalloc, normalize pointer if size > 65520 bytes
|
||||
- don't use special fcalloc for 32 bit Borland C++
|
||||
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||
- use Z_BINARY instead of BINARY
|
||||
- document that gzclose after gzdopen will close the file
|
||||
- allow "a" as mode in gzopen.
|
||||
- fix error checking in gzread
|
||||
- allow skipping .gz extra-field on pipes
|
||||
- added reference to Perl interface in README
|
||||
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||
- added get_crc_table
|
||||
- added a dimension to all arrays (Borland C can't count).
|
||||
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||
(what's wrong with far data in far model?).
|
||||
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||
|
||||
Changes in 0.95 (16 Aug 95)
|
||||
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||
- inlined send_bits
|
||||
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||
not completely flushed in rare occasions).
|
||||
- default window size is same for compression and decompression
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||
typedefs and because voidnp was not near in large model).
|
||||
|
||||
Changes in 0.94 (13 Aug 95)
|
||||
- support MSDOS medium model
|
||||
- fix deflate with flush (could sometimes generate bad output)
|
||||
- fix deflateReset (zlib header was incorrectly suppressed)
|
||||
- added support for VMS
|
||||
- allow a compression level in gzopen()
|
||||
- gzflush now calls fflush
|
||||
- For deflate with flush, flush even if no more input is provided.
|
||||
- rename libgz.a as libz.a
|
||||
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||
- don't use inline functions (problem with some gcc versions)
|
||||
- allow renaming of Byte, uInt, etc... with #define.
|
||||
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||
- avoid reserved word 'new' in trees.c
|
||||
|
||||
Changes in 0.93 (25 June 95)
|
||||
- temporarily disable inline functions
|
||||
- make deflate deterministic
|
||||
- give enough lookahead for PARTIAL_FLUSH
|
||||
- Set binary mode for stdin/stdout in minigzip.c for OS/2
|
||||
- don't even use signed char in inflate (not portable enough)
|
||||
- fix inflate memory leak for segmented architectures
|
||||
|
||||
Changes in 0.92 (3 May 95)
|
||||
- don't assume that char is signed (problem on SGI)
|
||||
- Clear bit buffer when starting a stored block
|
||||
- no memcpy on Pyramid
|
||||
- suppressed inftest.c
|
||||
- optimized fill_window, put longest_match inline for gcc
|
||||
- optimized inflate on stored blocks.
|
||||
- untabify all sources to simplify patches
|
||||
|
||||
Changes in 0.91 (2 May 95)
|
||||
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
|
||||
- Document the memory requirements in zconf.h
|
||||
- added "make install"
|
||||
- fix sync search logic in inflateSync
|
||||
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
|
||||
- after inflateSync, don't scare people with just "lo world"
|
||||
- added support for DJGPP
|
||||
|
||||
Changes in 0.9 (1 May 95)
|
||||
- don't assume that zalloc clears the allocated memory (the TurboC bug
|
||||
was Mark's bug after all :)
|
||||
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||
- added a test of inflateSync in example.c
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||
pointer (zero offset)
|
||||
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||
- faster crc32()
|
||||
|
||||
Changes in 0.8 (29 April 95)
|
||||
- added fast inflate (inffast.c)
|
||||
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||
is incompatible with previous versions of zlib which returned Z_OK.
|
||||
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||
(actually that was not a compiler bug, see 0.81 above)
|
||||
- gzread no longer reads one extra byte in certain cases
|
||||
- In gzio destroy(), don't reference a freed structure
|
||||
- avoid many warnings for MSDOS
|
||||
- avoid the ERROR symbol which is used by MS Windows
|
||||
|
||||
Changes in 0.71 (14 April 95)
|
||||
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||
TurboC large model.
|
||||
|
||||
Changes in 0.7 (14 April 95)
|
||||
- Added full inflate support.
|
||||
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||
(one's complement) is now done inside crc32(). WARNING: this is
|
||||
incompatible with previous versions; see zlib.h for the new usage.
|
||||
|
||||
Changes in 0.61 (12 April 95)
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||
|
||||
Changes in 0.6 (11 April 95)
|
||||
- added minigzip.c
|
||||
- added gzdopen to reopen a file descriptor as gzFile
|
||||
- added transparent reading of non-gziped files in gzread.
|
||||
- fixed bug in gzread (don't read crc as data)
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||
- don't allocate big arrays in the stack (for MSDOS)
|
||||
- fix some MSDOS compilation problems
|
||||
|
||||
Changes in 0.5:
|
||||
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||
not yet Z_FULL_FLUSH.
|
||||
- support decompression but only in a single step (forced Z_FINISH)
|
||||
- added opaque object for zalloc and zfree.
|
||||
- added deflateReset and inflateReset
|
||||
- added a variable zlib_version for consistency checking.
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||
|
||||
Changes in 0.4:
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||
if compression method == 8.
|
||||
- added adler32 and crc32
|
||||
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||
- added the method parameter for deflateInit2.
|
||||
- added inflateInit2
|
||||
- simplied considerably deflateInit and inflateInit by not supporting
|
||||
user-provided history buffer. This is supported only in deflateInit2
|
||||
and inflateInit2.
|
||||
|
||||
Changes in 0.3:
|
||||
- prefix all macro names with Z_
|
||||
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||
- added Z_HUFFMAN_ONLY
|
||||
- added gzerror()
|
115
zlib/Make_vms.com
Normal file
115
zlib/Make_vms.com
Normal file
@ -0,0 +1,115 @@
|
||||
$! make libz under VMS
|
||||
$! written by Martin P.J. Zinser <m.zinser@gsi.de>
|
||||
$!
|
||||
$! Look for the compiler used
|
||||
$!
|
||||
$ ccopt = ""
|
||||
$ if f$getsyi("HW_MODEL").ge.1024
|
||||
$ then
|
||||
$ ccopt = "/prefix=all"+ccopt
|
||||
$ comp = "__decc__=1"
|
||||
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
|
||||
$ else
|
||||
$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
|
||||
$ then
|
||||
$ comp = "__vaxc__=1"
|
||||
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
|
||||
$ else
|
||||
$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
|
||||
$ ccopt = "/decc/prefix=all"+ccopt
|
||||
$ comp = "__decc__=1"
|
||||
$ endif
|
||||
$ endif
|
||||
$!
|
||||
$! Build the thing plain or with mms
|
||||
$!
|
||||
$ write sys$output "Compiling Zlib sources ..."
|
||||
$ if f$search("SYS$SYSTEM:MMS.EXE").eqs.""
|
||||
$ then
|
||||
$ dele example.obj;*,minigzip.obj;*
|
||||
$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
|
||||
adler32.c zlib.h zconf.h
|
||||
$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
|
||||
compress.c zlib.h zconf.h
|
||||
$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
|
||||
crc32.c zlib.h zconf.h
|
||||
$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
|
||||
deflate.c deflate.h zutil.h zlib.h zconf.h
|
||||
$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
|
||||
gzio.c zutil.h zlib.h zconf.h
|
||||
$ CALL MAKE infblock.OBJ "CC ''CCOPT' infblock" -
|
||||
infblock.c zutil.h zlib.h zconf.h infblock.h
|
||||
$ CALL MAKE infcodes.OBJ "CC ''CCOPT' infcodes" -
|
||||
infcodes.c zutil.h zlib.h zconf.h inftrees.h
|
||||
$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
|
||||
inffast.c zutil.h zlib.h zconf.h inffast.h
|
||||
$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
|
||||
inflate.c zutil.h zlib.h zconf.h infblock.h
|
||||
$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
|
||||
inftrees.c zutil.h zlib.h zconf.h inftrees.h
|
||||
$ CALL MAKE infutil.OBJ "CC ''CCOPT' infutil" -
|
||||
infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h
|
||||
$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
|
||||
trees.c deflate.h zutil.h zlib.h zconf.h
|
||||
$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
|
||||
uncompr.c zlib.h zconf.h
|
||||
$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
|
||||
zutil.c zutil.h zlib.h zconf.h
|
||||
$ write sys$output "Building Zlib ..."
|
||||
$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
|
||||
$ write sys$output "Building example..."
|
||||
$ CALL MAKE example.OBJ "CC ''CCOPT' example" -
|
||||
example.c zlib.h zconf.h
|
||||
$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
|
||||
$ write sys$output "Building minigzip..."
|
||||
$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
|
||||
minigzip.c zlib.h zconf.h
|
||||
$ call make minigzip.exe -
|
||||
"LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
|
||||
minigzip.obj libz.olb
|
||||
$ else
|
||||
$ mms/macro=('comp')
|
||||
$ endif
|
||||
$ write sys$output "Zlib build completed"
|
||||
$ exit
|
||||
$!
|
||||
$!
|
||||
$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
|
||||
$ V = 'F$Verify(0)
|
||||
$! P1 = What we are trying to make
|
||||
$! P2 = Command to make it
|
||||
$! P3 - P8 What it depends on
|
||||
$
|
||||
$ If F$Search(P1) .Eqs. "" Then Goto Makeit
|
||||
$ Time = F$CvTime(F$File(P1,"RDT"))
|
||||
$arg=3
|
||||
$Loop:
|
||||
$ Argument = P'arg
|
||||
$ If Argument .Eqs. "" Then Goto Exit
|
||||
$ El=0
|
||||
$Loop2:
|
||||
$ File = F$Element(El," ",Argument)
|
||||
$ If File .Eqs. " " Then Goto Endl
|
||||
$ AFile = ""
|
||||
$Loop3:
|
||||
$ OFile = AFile
|
||||
$ AFile = F$Search(File)
|
||||
$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
|
||||
$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
|
||||
$ Goto Loop3
|
||||
$NextEL:
|
||||
$ El = El + 1
|
||||
$ Goto Loop2
|
||||
$EndL:
|
||||
$ arg=arg+1
|
||||
$ If arg .Le. 8 Then Goto Loop
|
||||
$ Goto Exit
|
||||
$
|
||||
$Makeit:
|
||||
$ VV=F$VERIFY(0)
|
||||
$ write sys$output P2
|
||||
$ 'P2
|
||||
$ VV='F$Verify(VV)
|
||||
$Exit:
|
||||
$ If V Then Set Verify
|
||||
$ENDSUBROUTINE
|
151
zlib/Makefile.riscos
Normal file
151
zlib/Makefile.riscos
Normal file
@ -0,0 +1,151 @@
|
||||
# Project: zlib_1_03
|
||||
# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430
|
||||
# test works out-of-the-box, installs `somewhere' on demand
|
||||
|
||||
# Toolflags:
|
||||
CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah
|
||||
C++flags = -c -depend !Depend -IC: -throwback
|
||||
Linkflags = -aif -c++ -o $@
|
||||
ObjAsmflags = -throwback -NoCache -depend !Depend
|
||||
CMHGflags =
|
||||
LibFileflags = -c -l -o $@
|
||||
Squeezeflags = -o $@
|
||||
|
||||
# change the line below to where _you_ want the library installed.
|
||||
libdest = lib:zlib
|
||||
|
||||
# Final targets:
|
||||
@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \
|
||||
@.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \
|
||||
@.o.uncompr @.o.zutil
|
||||
LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \
|
||||
@.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \
|
||||
@.o.trees @.o.uncompr @.o.zutil
|
||||
test: @.minigzip @.example @.lib
|
||||
@copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV
|
||||
@echo running tests: hang on.
|
||||
@/@.minigzip -f -9 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@/@.minigzip -f -1 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@/@.minigzip -h -9 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@/@.minigzip -h -1 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@/@.minigzip -9 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@/@.minigzip -1 libc
|
||||
@/@.minigzip -d libc-gz
|
||||
@diff @.lib @.libc
|
||||
@echo that should have reported '@.lib and @.libc identical' if you have diff.
|
||||
@/@.example @.fred @.fred
|
||||
@echo that will have given lots of hello!'s.
|
||||
|
||||
@.minigzip: @.o.minigzip @.lib C:o.Stubs
|
||||
Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs
|
||||
@.example: @.o.example @.lib C:o.Stubs
|
||||
Link $(Linkflags) @.o.example @.lib C:o.Stubs
|
||||
|
||||
install: @.lib
|
||||
cdir $(libdest)
|
||||
cdir $(libdest).h
|
||||
@copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV
|
||||
@copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV
|
||||
@copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV
|
||||
@echo okay, installed zlib in $(libdest)
|
||||
|
||||
clean:; remove @.minigzip
|
||||
remove @.example
|
||||
remove @.libc
|
||||
-wipe @.o.* F~r~cV
|
||||
remove @.fred
|
||||
|
||||
# User-editable dependencies:
|
||||
.c.o:
|
||||
cc $(ccflags) -o $@ $<
|
||||
|
||||
# Static dependencies:
|
||||
|
||||
# Dynamic dependencies:
|
||||
o.example: c.example
|
||||
o.example: h.zlib
|
||||
o.example: h.zconf
|
||||
o.minigzip: c.minigzip
|
||||
o.minigzip: h.zlib
|
||||
o.minigzip: h.zconf
|
||||
o.adler32: c.adler32
|
||||
o.adler32: h.zlib
|
||||
o.adler32: h.zconf
|
||||
o.compress: c.compress
|
||||
o.compress: h.zlib
|
||||
o.compress: h.zconf
|
||||
o.crc32: c.crc32
|
||||
o.crc32: h.zlib
|
||||
o.crc32: h.zconf
|
||||
o.deflate: c.deflate
|
||||
o.deflate: h.deflate
|
||||
o.deflate: h.zutil
|
||||
o.deflate: h.zlib
|
||||
o.deflate: h.zconf
|
||||
o.gzio: c.gzio
|
||||
o.gzio: h.zutil
|
||||
o.gzio: h.zlib
|
||||
o.gzio: h.zconf
|
||||
o.infblock: c.infblock
|
||||
o.infblock: h.zutil
|
||||
o.infblock: h.zlib
|
||||
o.infblock: h.zconf
|
||||
o.infblock: h.infblock
|
||||
o.infblock: h.inftrees
|
||||
o.infblock: h.infcodes
|
||||
o.infblock: h.infutil
|
||||
o.infcodes: c.infcodes
|
||||
o.infcodes: h.zutil
|
||||
o.infcodes: h.zlib
|
||||
o.infcodes: h.zconf
|
||||
o.infcodes: h.inftrees
|
||||
o.infcodes: h.infblock
|
||||
o.infcodes: h.infcodes
|
||||
o.infcodes: h.infutil
|
||||
o.infcodes: h.inffast
|
||||
o.inffast: c.inffast
|
||||
o.inffast: h.zutil
|
||||
o.inffast: h.zlib
|
||||
o.inffast: h.zconf
|
||||
o.inffast: h.inftrees
|
||||
o.inffast: h.infblock
|
||||
o.inffast: h.infcodes
|
||||
o.inffast: h.infutil
|
||||
o.inffast: h.inffast
|
||||
o.inflate: c.inflate
|
||||
o.inflate: h.zutil
|
||||
o.inflate: h.zlib
|
||||
o.inflate: h.zconf
|
||||
o.inflate: h.infblock
|
||||
o.inftrees: c.inftrees
|
||||
o.inftrees: h.zutil
|
||||
o.inftrees: h.zlib
|
||||
o.inftrees: h.zconf
|
||||
o.inftrees: h.inftrees
|
||||
o.inftrees: h.inffixed
|
||||
o.infutil: c.infutil
|
||||
o.infutil: h.zutil
|
||||
o.infutil: h.zlib
|
||||
o.infutil: h.zconf
|
||||
o.infutil: h.infblock
|
||||
o.infutil: h.inftrees
|
||||
o.infutil: h.infcodes
|
||||
o.infutil: h.infutil
|
||||
o.trees: c.trees
|
||||
o.trees: h.deflate
|
||||
o.trees: h.zutil
|
||||
o.trees: h.zlib
|
||||
o.trees: h.zconf
|
||||
o.trees: h.trees
|
||||
o.uncompr: c.uncompr
|
||||
o.uncompr: h.zlib
|
||||
o.uncompr: h.zconf
|
||||
o.zutil: c.zutil
|
||||
o.zutil: h.zutil
|
||||
o.zutil: h.zlib
|
||||
o.zutil: h.zconf
|
48
zlib/adler32.c
Normal file
48
zlib/adler32.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2002 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521L /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int k;
|
||||
|
||||
if (buf == Z_NULL) return 1L;
|
||||
|
||||
while (len > 0) {
|
||||
k = len < NMAX ? len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16) {
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0) do {
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
} while (--k);
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
213
zlib/algorithm.txt
Normal file
213
zlib/algorithm.txt
Normal file
@ -0,0 +1,213 @@
|
||||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for
|
||||
a longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only N
|
||||
steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
2.1 Introduction
|
||||
|
||||
The real question is, given a Huffman tree, how to decode fast. The most
|
||||
important realization is that shorter codes are much more common than
|
||||
longer codes, so pay attention to decoding the short codes fast, and let
|
||||
the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and set it
|
||||
for the maximum speed.
|
||||
|
||||
inflate() sends new trees relatively often, so it is possibly set for a
|
||||
smaller first level table than an application that has only one tree for
|
||||
all the data. For inflate, which has 286 possible codes for the
|
||||
literal/length tree, the size of the first table is nine bits. Also the
|
||||
distance trees have 30 possible values, and the size of the first table is
|
||||
six bits. Note that for each of those cases, the table ended up one bit
|
||||
longer than the ``average'' code length, i.e. the code length of an
|
||||
approximately flat code which would be a little more than eight bits for
|
||||
286 symbols and a little less than five bits for 30 symbols. It would be
|
||||
interesting to see if optimizing the first level table for other
|
||||
applications gave values within a bit or two of the flat code size.
|
||||
|
||||
|
||||
2.2 More details on the inflate table lookup
|
||||
|
||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
||||
in all those entries that start with that symbol's bits. For example, if the
|
||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
||||
symbol is nine bits long, it appears in the table once.
|
||||
|
||||
If the symbol is longer than nine bits, then that entry in the table points
|
||||
to another similar table for the remaining bits. Again, there are duplicated
|
||||
entries as needed. The idea is that most of the time the symbol will be short
|
||||
and there will only be one table look up. (That's whole idea behind data
|
||||
compression in the first place.) For the less frequent long symbols, there
|
||||
will be two lookups. If you had a compression method with really long
|
||||
symbols, you could have as many levels of lookups as is efficient. For
|
||||
inflate, two is enough.
|
||||
|
||||
So a table entry either points to another table (in which case nine bits in
|
||||
the above example are gobbled), or it contains the translation for the symbol
|
||||
and the number of bits to gobble. Then you start again with the next
|
||||
ungobbled bit.
|
||||
|
||||
You may wonder: why not just have one lookup table for how ever many bits the
|
||||
longest symbol is? The reason is that if you do that, you end up spending
|
||||
more time filling in duplicate symbol entries than you do actually decoding.
|
||||
At least for deflate's output that generates new trees every several 10's of
|
||||
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
|
||||
would take too long if you're only decoding several thousand symbols. At the
|
||||
other extreme, you could make a new table for every bit in the code. In fact,
|
||||
that's essentially a Huffman tree. But then you spend two much time
|
||||
traversing the tree while decoding, even for short symbols.
|
||||
|
||||
So the number of bits for the first lookup table is a trade of the time to
|
||||
fill out the table vs. the time spent looking at the second level and above of
|
||||
the table.
|
||||
|
||||
Here is an example, scaled down:
|
||||
|
||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
||||
|
||||
A: 0
|
||||
B: 10
|
||||
C: 1100
|
||||
D: 11010
|
||||
E: 11011
|
||||
F: 11100
|
||||
G: 11101
|
||||
H: 11110
|
||||
I: 111110
|
||||
J: 111111
|
||||
|
||||
Let's make the first table three bits long (eight entries):
|
||||
|
||||
000: A,1
|
||||
001: A,1
|
||||
010: A,1
|
||||
011: A,1
|
||||
100: B,2
|
||||
101: B,2
|
||||
110: -> table X (gobble 3 bits)
|
||||
111: -> table Y (gobble 3 bits)
|
||||
|
||||
Each entry is what the bits decode to and how many bits that is, i.e. how
|
||||
many bits to gobble. Or the entry points to another table, with the number of
|
||||
bits to gobble implicit in the size of the table.
|
||||
|
||||
Table X is two bits long since the longest code starting with 110 is five bits
|
||||
long:
|
||||
|
||||
00: C,1
|
||||
01: C,1
|
||||
10: D,2
|
||||
11: E,2
|
||||
|
||||
Table Y is three bits long since the longest code starting with 111 is six
|
||||
bits long:
|
||||
|
||||
000: F,2
|
||||
001: F,2
|
||||
010: G,2
|
||||
011: G,2
|
||||
100: H,2
|
||||
101: H,2
|
||||
110: I,3
|
||||
111: J,3
|
||||
|
||||
So what we have here are three tables with a total of 20 entries that had to
|
||||
be constructed. That's compared to 64 entries for a single table. Or
|
||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
||||
entry table). Assuming that the code ideally represents the probability of
|
||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
||||
Huffman tree.
|
||||
|
||||
There, I think that gives you a picture of what's going on. For inflate, the
|
||||
meaning of a particular symbol is often more than just a letter. It can be a
|
||||
byte (a "literal"), or it can be either a length or a distance which
|
||||
indicates a base value and a number of bits to fetch after the code that is
|
||||
added to the base value. Or it might be the special end-of-block code. The
|
||||
data structures created in inftrees.c try to encode all that information
|
||||
compactly in the tables.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
ftp://ds.internic.net/rfc/rfc1951.txt
|
66
zlib/amiga/Makefile.pup
Normal file
66
zlib/amiga/Makefile.pup
Normal file
@ -0,0 +1,66 @@
|
||||
# Amiga powerUP (TM) Makefile
|
||||
# makefile for libpng and SAS C V6.58/7.00 PPC compiler
|
||||
# Copyright (C) 1998 by Andreas R. Kleinert
|
||||
|
||||
CC = scppc
|
||||
CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
|
||||
OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8
|
||||
LIBNAME = libzip.a
|
||||
AR = ppc-amigaos-ar
|
||||
AR_FLAGS = cr
|
||||
RANLIB = ppc-amigaos-ranlib
|
||||
LDFLAGS = -r -o
|
||||
LDLIBS = LIB:scppc.a
|
||||
LN = ppc-amigaos-ld
|
||||
RM = delete quiet
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example minigzip
|
||||
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
$(LIBNAME): $(OBJS)
|
||||
$(AR) $(AR_FLAGS) $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
example: example.o $(LIBNAME)
|
||||
$(LN) $(LDFLAGS) example LIB:c_ppc.o example.o $(LIBNAME) $(LDLIBS) LIB:end.o
|
||||
|
||||
minigzip: minigzip.o $(LIBNAME)
|
||||
$(LN) $(LDFLAGS) minigzip LIB:c_ppc.o minigzip.o $(LIBNAME) $(LDLIBS) LIB:end.o
|
||||
|
||||
clean:
|
||||
$(RM) *.o example minigzip $(LIBNAME) foo.gz
|
||||
|
||||
zip:
|
||||
zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
|
||||
descrip.mms *.[ch]
|
||||
|
||||
tgz:
|
||||
cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
|
||||
zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zutil.h zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: zutil.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
infblock.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
|
||||
infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h infblock.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
infutil.o: zutil.h zlib.h zconf.h inftrees.h infutil.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
64
zlib/amiga/Makefile.sas
Normal file
64
zlib/amiga/Makefile.sas
Normal file
@ -0,0 +1,64 @@
|
||||
# SMakefile for zlib
|
||||
# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
|
||||
# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
|
||||
# Amiga, SAS/C 6.56 & Smake
|
||||
|
||||
CC=sc
|
||||
CFLAGS=OPT
|
||||
#CFLAGS=OPT CPU=68030
|
||||
#CFLAGS=DEBUG=LINE
|
||||
LDFLAGS=LIB z.lib
|
||||
|
||||
SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
|
||||
NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: SCOPTIONS example minigzip
|
||||
|
||||
test: all
|
||||
`cd`/example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
install: z.lib
|
||||
copy zlib.h zconf.h INCLUDE: clone
|
||||
copy z.lib LIB: clone
|
||||
|
||||
z.lib: $(OBJS)
|
||||
oml z.lib r $(OBJS)
|
||||
|
||||
example: example.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip: minigzip.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
-delete force quiet *.o example minigzip z.lib foo.gz *.lnk SCOPTIONS
|
||||
|
||||
SCOPTIONS: Smakefile
|
||||
copy to $@ <from <
|
||||
$(SCOPTIONS)
|
||||
<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zutil.h zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: zutil.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
infblock.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
|
||||
infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h infblock.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
infutil.o: zutil.h zlib.h zconf.h inftrees.h infutil.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
68
zlib/compress.c
Normal file
68
zlib/compress.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2002 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
34
zlib/contrib/README.contrib
Normal file
34
zlib/contrib/README.contrib
Normal file
@ -0,0 +1,34 @@
|
||||
All files under this contrib directory are UNSUPPORTED. There were
|
||||
provided by users of zlib and were not tested by the authors of zlib.
|
||||
Use at your own risk. Please contact the authors of the contributions
|
||||
for help about these, not the zlib authors. Thanks.
|
||||
|
||||
|
||||
asm386/ by Gilles Vollant <info@winimage.com>
|
||||
386 asm code replacing longest_match(), for Visual C++ 4.2 and ML 6.11c
|
||||
|
||||
asm586/ and asm686/ by Brian Raiter <breadbox@muppetlabs.com>
|
||||
asm code for Pentium and Pentium Pro
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
delphi/ by Bob Dellaca <bobdl@xtra.co.nz>
|
||||
Support for Delphi
|
||||
|
||||
delphi2/ by Davide Moretti <dave@rimini.com>
|
||||
Another support for C++Builder and Delphi
|
||||
|
||||
minizip/ by Gilles Vollant <info@winimage.com>
|
||||
Mini zip and unzip based on zlib
|
||||
See http://www.winimage.com/zLibDll/unzip.html
|
||||
|
||||
iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
|
||||
iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
|
||||
untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
|
||||
visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB.
|
559
zlib/contrib/asm386/gvmat32.asm
Normal file
559
zlib/contrib/asm386/gvmat32.asm
Normal file
@ -0,0 +1,559 @@
|
||||
;
|
||||
; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
|
||||
; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
|
||||
; File written by Gilles Vollant, by modifiying the longest_match
|
||||
; from Jean-loup Gailly in deflate.c
|
||||
; It need wmask == 0x7fff
|
||||
; (assembly code is faster with a fixed wmask)
|
||||
;
|
||||
; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)
|
||||
; I compile with : "ml /coff /Zi /c gvmat32.asm"
|
||||
;
|
||||
|
||||
;uInt longest_match_7fff(s, cur_match)
|
||||
; deflate_state *s;
|
||||
; IPos cur_match; /* current match */
|
||||
|
||||
NbStack equ 76
|
||||
cur_match equ dword ptr[esp+NbStack-0]
|
||||
str_s equ dword ptr[esp+NbStack-4]
|
||||
; 5 dword on top (ret,ebp,esi,edi,ebx)
|
||||
adrret equ dword ptr[esp+NbStack-8]
|
||||
pushebp equ dword ptr[esp+NbStack-12]
|
||||
pushedi equ dword ptr[esp+NbStack-16]
|
||||
pushesi equ dword ptr[esp+NbStack-20]
|
||||
pushebx equ dword ptr[esp+NbStack-24]
|
||||
|
||||
chain_length equ dword ptr [esp+NbStack-28]
|
||||
limit equ dword ptr [esp+NbStack-32]
|
||||
best_len equ dword ptr [esp+NbStack-36]
|
||||
window equ dword ptr [esp+NbStack-40]
|
||||
prev equ dword ptr [esp+NbStack-44]
|
||||
scan_start equ word ptr [esp+NbStack-48]
|
||||
wmask equ dword ptr [esp+NbStack-52]
|
||||
match_start_ptr equ dword ptr [esp+NbStack-56]
|
||||
nice_match equ dword ptr [esp+NbStack-60]
|
||||
scan equ dword ptr [esp+NbStack-64]
|
||||
|
||||
windowlen equ dword ptr [esp+NbStack-68]
|
||||
match_start equ dword ptr [esp+NbStack-72]
|
||||
strend equ dword ptr [esp+NbStack-76]
|
||||
NbStackAdd equ (NbStack-24)
|
||||
|
||||
.386p
|
||||
|
||||
name gvmatch
|
||||
.MODEL FLAT
|
||||
|
||||
|
||||
|
||||
; all the +4 offsets are due to the addition of pending_buf_size (in zlib
|
||||
; in the deflate_state structure since the asm code was first written
|
||||
; (if you compile with zlib 1.0.4 or older, remove the +4).
|
||||
; Note : these value are good with a 8 bytes boundary pack structure
|
||||
dep_chain_length equ 70h+4
|
||||
dep_window equ 2ch+4
|
||||
dep_strstart equ 60h+4
|
||||
dep_prev_length equ 6ch+4
|
||||
dep_nice_match equ 84h+4
|
||||
dep_w_size equ 20h+4
|
||||
dep_prev equ 34h+4
|
||||
dep_w_mask equ 28h+4
|
||||
dep_good_match equ 80h+4
|
||||
dep_match_start equ 64h+4
|
||||
dep_lookahead equ 68h+4
|
||||
|
||||
|
||||
_TEXT segment
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
public longest_match_7fff
|
||||
; public match_init
|
||||
ELSE
|
||||
public _longest_match_7fff
|
||||
; public _match_init
|
||||
ENDIF
|
||||
|
||||
MAX_MATCH equ 258
|
||||
MIN_MATCH equ 3
|
||||
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
|
||||
|
||||
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
;match_init proc near
|
||||
; ret
|
||||
;match_init endp
|
||||
ELSE
|
||||
;_match_init proc near
|
||||
; ret
|
||||
;_match_init endp
|
||||
ENDIF
|
||||
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
longest_match_7fff proc near
|
||||
ELSE
|
||||
_longest_match_7fff proc near
|
||||
ENDIF
|
||||
|
||||
mov edx,[esp+4]
|
||||
|
||||
|
||||
|
||||
push ebp
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
|
||||
sub esp,NbStackAdd
|
||||
|
||||
; initialize or check the variables used in match.asm.
|
||||
mov ebp,edx
|
||||
|
||||
; chain_length = s->max_chain_length
|
||||
; if (prev_length>=good_match) chain_length >>= 2
|
||||
mov edx,[ebp+dep_chain_length]
|
||||
mov ebx,[ebp+dep_prev_length]
|
||||
cmp [ebp+dep_good_match],ebx
|
||||
ja noshr
|
||||
shr edx,2
|
||||
noshr:
|
||||
; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
|
||||
inc edx
|
||||
mov edi,[ebp+dep_nice_match]
|
||||
mov chain_length,edx
|
||||
mov eax,[ebp+dep_lookahead]
|
||||
cmp eax,edi
|
||||
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
|
||||
jae nolookaheadnicematch
|
||||
mov edi,eax
|
||||
nolookaheadnicematch:
|
||||
; best_len = s->prev_length
|
||||
mov best_len,ebx
|
||||
|
||||
; window = s->window
|
||||
mov esi,[ebp+dep_window]
|
||||
mov ecx,[ebp+dep_strstart]
|
||||
mov window,esi
|
||||
|
||||
mov nice_match,edi
|
||||
; scan = window + strstart
|
||||
add esi,ecx
|
||||
mov scan,esi
|
||||
; dx = *window
|
||||
mov dx,word ptr [esi]
|
||||
; bx = *(window+best_len-1)
|
||||
mov bx,word ptr [esi+ebx-1]
|
||||
add esi,MAX_MATCH-1
|
||||
; scan_start = *scan
|
||||
mov scan_start,dx
|
||||
; strend = scan + MAX_MATCH-1
|
||||
mov strend,esi
|
||||
; bx = scan_end = *(window+best_len-1)
|
||||
|
||||
; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
|
||||
; s->strstart - (IPos)MAX_DIST(s) : NIL;
|
||||
|
||||
mov esi,[ebp+dep_w_size]
|
||||
sub esi,MIN_LOOKAHEAD
|
||||
; here esi = MAX_DIST(s)
|
||||
sub ecx,esi
|
||||
ja nodist
|
||||
xor ecx,ecx
|
||||
nodist:
|
||||
mov limit,ecx
|
||||
|
||||
; prev = s->prev
|
||||
mov edx,[ebp+dep_prev]
|
||||
mov prev,edx
|
||||
|
||||
;
|
||||
mov edx,dword ptr [ebp+dep_match_start]
|
||||
mov bp,scan_start
|
||||
mov eax,cur_match
|
||||
mov match_start,edx
|
||||
|
||||
mov edx,window
|
||||
mov edi,edx
|
||||
add edi,best_len
|
||||
mov esi,prev
|
||||
dec edi
|
||||
; windowlen = window + best_len -1
|
||||
mov windowlen,edi
|
||||
|
||||
jmp beginloop2
|
||||
align 4
|
||||
|
||||
; here, in the loop
|
||||
; eax = ax = cur_match
|
||||
; ecx = limit
|
||||
; bx = scan_end
|
||||
; bp = scan_start
|
||||
; edi = windowlen (window + best_len -1)
|
||||
; esi = prev
|
||||
|
||||
|
||||
;// here; chain_length <=16
|
||||
normalbeg0add16:
|
||||
add chain_length,16
|
||||
jz exitloop
|
||||
normalbeg0:
|
||||
cmp word ptr[edi+eax],bx
|
||||
je normalbeg2noroll
|
||||
rcontlabnoroll:
|
||||
; cur_match = prev[cur_match & wmask]
|
||||
and eax,7fffh
|
||||
mov ax,word ptr[esi+eax*2]
|
||||
; if cur_match > limit, go to exitloop
|
||||
cmp ecx,eax
|
||||
jnb exitloop
|
||||
; if --chain_length != 0, go to exitloop
|
||||
dec chain_length
|
||||
jnz normalbeg0
|
||||
jmp exitloop
|
||||
|
||||
normalbeg2noroll:
|
||||
; if (scan_start==*(cur_match+window)) goto normalbeg2
|
||||
cmp bp,word ptr[edx+eax]
|
||||
jne rcontlabnoroll
|
||||
jmp normalbeg2
|
||||
|
||||
contloop3:
|
||||
mov edi,windowlen
|
||||
|
||||
; cur_match = prev[cur_match & wmask]
|
||||
and eax,7fffh
|
||||
mov ax,word ptr[esi+eax*2]
|
||||
; if cur_match > limit, go to exitloop
|
||||
cmp ecx,eax
|
||||
jnbexitloopshort1:
|
||||
jnb exitloop
|
||||
; if --chain_length != 0, go to exitloop
|
||||
|
||||
|
||||
; begin the main loop
|
||||
beginloop2:
|
||||
sub chain_length,16+1
|
||||
; if chain_length <=16, don't use the unrolled loop
|
||||
jna normalbeg0add16
|
||||
|
||||
do16:
|
||||
cmp word ptr[edi+eax],bx
|
||||
je normalbeg2dc0
|
||||
|
||||
maccn MACRO lab
|
||||
and eax,7fffh
|
||||
mov ax,word ptr[esi+eax*2]
|
||||
cmp ecx,eax
|
||||
jnb exitloop
|
||||
cmp word ptr[edi+eax],bx
|
||||
je lab
|
||||
ENDM
|
||||
|
||||
rcontloop0:
|
||||
maccn normalbeg2dc1
|
||||
|
||||
rcontloop1:
|
||||
maccn normalbeg2dc2
|
||||
|
||||
rcontloop2:
|
||||
maccn normalbeg2dc3
|
||||
|
||||
rcontloop3:
|
||||
maccn normalbeg2dc4
|
||||
|
||||
rcontloop4:
|
||||
maccn normalbeg2dc5
|
||||
|
||||
rcontloop5:
|
||||
maccn normalbeg2dc6
|
||||
|
||||
rcontloop6:
|
||||
maccn normalbeg2dc7
|
||||
|
||||
rcontloop7:
|
||||
maccn normalbeg2dc8
|
||||
|
||||
rcontloop8:
|
||||
maccn normalbeg2dc9
|
||||
|
||||
rcontloop9:
|
||||
maccn normalbeg2dc10
|
||||
|
||||
rcontloop10:
|
||||
maccn short normalbeg2dc11
|
||||
|
||||
rcontloop11:
|
||||
maccn short normalbeg2dc12
|
||||
|
||||
rcontloop12:
|
||||
maccn short normalbeg2dc13
|
||||
|
||||
rcontloop13:
|
||||
maccn short normalbeg2dc14
|
||||
|
||||
rcontloop14:
|
||||
maccn short normalbeg2dc15
|
||||
|
||||
rcontloop15:
|
||||
and eax,7fffh
|
||||
mov ax,word ptr[esi+eax*2]
|
||||
cmp ecx,eax
|
||||
jnb exitloop
|
||||
|
||||
sub chain_length,16
|
||||
ja do16
|
||||
jmp normalbeg0add16
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
normbeg MACRO rcontlab,valsub
|
||||
; if we are here, we know that *(match+best_len-1) == scan_end
|
||||
cmp bp,word ptr[edx+eax]
|
||||
; if (match != scan_start) goto rcontlab
|
||||
jne rcontlab
|
||||
; calculate the good chain_length, and we'll compare scan and match string
|
||||
add chain_length,16-valsub
|
||||
jmp iseq
|
||||
ENDM
|
||||
|
||||
|
||||
normalbeg2dc11:
|
||||
normbeg rcontloop11,11
|
||||
|
||||
normalbeg2dc12:
|
||||
normbeg short rcontloop12,12
|
||||
|
||||
normalbeg2dc13:
|
||||
normbeg short rcontloop13,13
|
||||
|
||||
normalbeg2dc14:
|
||||
normbeg short rcontloop14,14
|
||||
|
||||
normalbeg2dc15:
|
||||
normbeg short rcontloop15,15
|
||||
|
||||
normalbeg2dc10:
|
||||
normbeg rcontloop10,10
|
||||
|
||||
normalbeg2dc9:
|
||||
normbeg rcontloop9,9
|
||||
|
||||
normalbeg2dc8:
|
||||
normbeg rcontloop8,8
|
||||
|
||||
normalbeg2dc7:
|
||||
normbeg rcontloop7,7
|
||||
|
||||
normalbeg2dc6:
|
||||
normbeg rcontloop6,6
|
||||
|
||||
normalbeg2dc5:
|
||||
normbeg rcontloop5,5
|
||||
|
||||
normalbeg2dc4:
|
||||
normbeg rcontloop4,4
|
||||
|
||||
normalbeg2dc3:
|
||||
normbeg rcontloop3,3
|
||||
|
||||
normalbeg2dc2:
|
||||
normbeg rcontloop2,2
|
||||
|
||||
normalbeg2dc1:
|
||||
normbeg rcontloop1,1
|
||||
|
||||
normalbeg2dc0:
|
||||
normbeg rcontloop0,0
|
||||
|
||||
|
||||
; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
|
||||
|
||||
normalbeg2:
|
||||
mov edi,window
|
||||
|
||||
cmp bp,word ptr[edi+eax]
|
||||
jne contloop3 ; if *(ushf*)match != scan_start, continue
|
||||
|
||||
iseq:
|
||||
; if we are here, we know that *(match+best_len-1) == scan_end
|
||||
; and (match == scan_start)
|
||||
|
||||
mov edi,edx
|
||||
mov esi,scan ; esi = scan
|
||||
add edi,eax ; edi = window + cur_match = match
|
||||
|
||||
mov edx,[esi+3] ; compare manually dword at match+3
|
||||
xor edx,[edi+3] ; and scan +3
|
||||
|
||||
jz begincompare ; if equal, go to long compare
|
||||
|
||||
; we will determine the unmatch byte and calculate len (in esi)
|
||||
or dl,dl
|
||||
je eq1rr
|
||||
mov esi,3
|
||||
jmp trfinval
|
||||
eq1rr:
|
||||
or dx,dx
|
||||
je eq1
|
||||
|
||||
mov esi,4
|
||||
jmp trfinval
|
||||
eq1:
|
||||
and edx,0ffffffh
|
||||
jz eq11
|
||||
mov esi,5
|
||||
jmp trfinval
|
||||
eq11:
|
||||
mov esi,6
|
||||
jmp trfinval
|
||||
|
||||
begincompare:
|
||||
; here we now scan and match begin same
|
||||
add edi,6
|
||||
add esi,6
|
||||
mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
|
||||
repe cmpsd ; loop until mismatch
|
||||
|
||||
je trfin ; go to trfin if not unmatch
|
||||
; we determine the unmatch byte
|
||||
sub esi,4
|
||||
mov edx,[edi-4]
|
||||
xor edx,[esi]
|
||||
|
||||
or dl,dl
|
||||
jnz trfin
|
||||
inc esi
|
||||
|
||||
or dx,dx
|
||||
jnz trfin
|
||||
inc esi
|
||||
|
||||
and edx,0ffffffh
|
||||
jnz trfin
|
||||
inc esi
|
||||
|
||||
trfin:
|
||||
sub esi,scan ; esi = len
|
||||
trfinval:
|
||||
; here we have finised compare, and esi contain len of equal string
|
||||
cmp esi,best_len ; if len > best_len, go newbestlen
|
||||
ja short newbestlen
|
||||
; now we restore edx, ecx and esi, for the big loop
|
||||
mov esi,prev
|
||||
mov ecx,limit
|
||||
mov edx,window
|
||||
jmp contloop3
|
||||
|
||||
newbestlen:
|
||||
mov best_len,esi ; len become best_len
|
||||
|
||||
mov match_start,eax ; save new position as match_start
|
||||
cmp esi,nice_match ; if best_len >= nice_match, exit
|
||||
jae exitloop
|
||||
mov ecx,scan
|
||||
mov edx,window ; restore edx=window
|
||||
add ecx,esi
|
||||
add esi,edx
|
||||
|
||||
dec esi
|
||||
mov windowlen,esi ; windowlen = window + best_len-1
|
||||
mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
|
||||
|
||||
; now we restore ecx and esi, for the big loop :
|
||||
mov esi,prev
|
||||
mov ecx,limit
|
||||
jmp contloop3
|
||||
|
||||
exitloop:
|
||||
; exit : s->match_start=match_start
|
||||
mov ebx,match_start
|
||||
mov ebp,str_s
|
||||
mov ecx,best_len
|
||||
mov dword ptr [ebp+dep_match_start],ebx
|
||||
mov eax,dword ptr [ebp+dep_lookahead]
|
||||
cmp ecx,eax
|
||||
ja minexlo
|
||||
mov eax,ecx
|
||||
minexlo:
|
||||
; return min(best_len,s->lookahead)
|
||||
|
||||
; restore stack and register ebx,esi,edi,ebp
|
||||
add esp,NbStackAdd
|
||||
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp
|
||||
ret
|
||||
InfoAuthor:
|
||||
; please don't remove this string !
|
||||
; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
|
||||
db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
|
||||
|
||||
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
longest_match_7fff endp
|
||||
ELSE
|
||||
_longest_match_7fff endp
|
||||
ENDIF
|
||||
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
cpudetect32 proc near
|
||||
ELSE
|
||||
_cpudetect32 proc near
|
||||
ENDIF
|
||||
|
||||
|
||||
pushfd ; push original EFLAGS
|
||||
pop eax ; get original EFLAGS
|
||||
mov ecx, eax ; save original EFLAGS
|
||||
xor eax, 40000h ; flip AC bit in EFLAGS
|
||||
push eax ; save new EFLAGS value on stack
|
||||
popfd ; replace current EFLAGS value
|
||||
pushfd ; get new EFLAGS
|
||||
pop eax ; store new EFLAGS in EAX
|
||||
xor eax, ecx ; can’t toggle AC bit, processor=80386
|
||||
jz end_cpu_is_386 ; jump if 80386 processor
|
||||
push ecx
|
||||
popfd ; restore AC bit in EFLAGS first
|
||||
|
||||
pushfd
|
||||
pushfd
|
||||
pop ecx
|
||||
|
||||
mov eax, ecx ; get original EFLAGS
|
||||
xor eax, 200000h ; flip ID bit in EFLAGS
|
||||
push eax ; save new EFLAGS value on stack
|
||||
popfd ; replace current EFLAGS value
|
||||
pushfd ; get new EFLAGS
|
||||
pop eax ; store new EFLAGS in EAX
|
||||
popfd ; restore original EFLAGS
|
||||
xor eax, ecx ; can’t toggle ID bit,
|
||||
je is_old_486 ; processor=old
|
||||
|
||||
mov eax,1
|
||||
db 0fh,0a2h ;CPUID
|
||||
|
||||
exitcpudetect:
|
||||
ret
|
||||
|
||||
end_cpu_is_386:
|
||||
mov eax,0300h
|
||||
jmp exitcpudetect
|
||||
|
||||
is_old_486:
|
||||
mov eax,0400h
|
||||
jmp exitcpudetect
|
||||
|
||||
IFDEF NOUNDERLINE
|
||||
cpudetect32 endp
|
||||
ELSE
|
||||
_cpudetect32 endp
|
||||
ENDIF
|
||||
|
||||
_TEXT ends
|
||||
end
|
200
zlib/contrib/asm386/gvmat32c.c
Normal file
200
zlib/contrib/asm386/gvmat32c.c
Normal file
@ -0,0 +1,200 @@
|
||||
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
|
||||
* File written by Gilles Vollant, by modifiying the longest_match
|
||||
* from Jean-loup Gailly in deflate.c
|
||||
* it prepare all parameters and call the assembly longest_match_gvasm
|
||||
* longest_match execute standard C code is wmask != 0x7fff
|
||||
* (assembly code is faster with a fixed wmask)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "deflate.h"
|
||||
|
||||
#undef FAR
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef ASMV
|
||||
#define NIL 0
|
||||
|
||||
#define UNALIGNED_OK
|
||||
|
||||
|
||||
/* if your C compiler don't add underline before function name,
|
||||
define ADD_UNDERLINE_ASMFUNC */
|
||||
#ifdef ADD_UNDERLINE_ASMFUNC
|
||||
#define longest_match_7fff _longest_match_7fff
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void match_init()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long cpudetect32();
|
||||
|
||||
uInt longest_match_c(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
|
||||
uInt longest_match_7fff(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
uInt longest_match(
|
||||
deflate_state *s,
|
||||
IPos cur_match) /* current match */
|
||||
{
|
||||
static uInt iIsPPro=2;
|
||||
|
||||
if ((s->w_mask == 0x7fff) && (iIsPPro==0))
|
||||
return longest_match_7fff(s,cur_match);
|
||||
|
||||
if (iIsPPro==2)
|
||||
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
|
||||
|
||||
return longest_match_c(s,cur_match);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uInt longest_match_c(s, cur_match)
|
||||
deflate_state *s;
|
||||
IPos cur_match; /* current match */
|
||||
{
|
||||
unsigned chain_length = s->max_chain_length;/* max hash chain length */
|
||||
register Bytef *scan = s->window + s->strstart; /* current string */
|
||||
register Bytef *match; /* matched string */
|
||||
register int len; /* length of current match */
|
||||
int best_len = s->prev_length; /* best match length so far */
|
||||
int nice_match = s->nice_match; /* stop if match long enough */
|
||||
IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
|
||||
s->strstart - (IPos)MAX_DIST(s) : NIL;
|
||||
/* Stop when cur_match becomes <= limit. To simplify the code,
|
||||
* we prevent matches with the string of window index 0.
|
||||
*/
|
||||
Posf *prev = s->prev;
|
||||
uInt wmask = s->w_mask;
|
||||
|
||||
#ifdef UNALIGNED_OK
|
||||
/* Compare two bytes at a time. Note: this is not always beneficial.
|
||||
* Try with and without -DUNALIGNED_OK to check.
|
||||
*/
|
||||
register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
|
||||
register ush scan_start = *(ushf*)scan;
|
||||
register ush scan_end = *(ushf*)(scan+best_len-1);
|
||||
#else
|
||||
register Bytef *strend = s->window + s->strstart + MAX_MATCH;
|
||||
register Byte scan_end1 = scan[best_len-1];
|
||||
register Byte scan_end = scan[best_len];
|
||||
#endif
|
||||
|
||||
/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
|
||||
* It is easy to get rid of this optimization if necessary.
|
||||
*/
|
||||
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
|
||||
|
||||
/* Do not waste too much time if we already have a good match: */
|
||||
if (s->prev_length >= s->good_match) {
|
||||
chain_length >>= 2;
|
||||
}
|
||||
/* Do not look for matches beyond the end of the input. This is necessary
|
||||
* to make deflate deterministic.
|
||||
*/
|
||||
if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
|
||||
|
||||
Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
|
||||
|
||||
do {
|
||||
Assert(cur_match < s->strstart, "no future");
|
||||
match = s->window + cur_match;
|
||||
|
||||
/* Skip to next match if the match length cannot increase
|
||||
* or if the match length is less than 2:
|
||||
*/
|
||||
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
|
||||
/* This code assumes sizeof(unsigned short) == 2. Do not use
|
||||
* UNALIGNED_OK if your compiler uses a different size.
|
||||
*/
|
||||
if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
*(ushf*)match != scan_start) continue;
|
||||
|
||||
/* It is not necessary to compare scan[2] and match[2] since they are
|
||||
* always equal when the other bytes match, given that the hash keys
|
||||
* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
|
||||
* strstart+3, +5, ... up to strstart+257. We check for insufficient
|
||||
* lookahead only every 4th comparison; the 128th check will be made
|
||||
* at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
|
||||
* necessary to put more guard bytes at the end of the window, or
|
||||
* to check more often for insufficient lookahead.
|
||||
*/
|
||||
Assert(scan[2] == match[2], "scan[2]?");
|
||||
scan++, match++;
|
||||
do {
|
||||
} while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
||||
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
||||
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
||||
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
||||
scan < strend);
|
||||
/* The funny "do {}" generates better code on most compilers */
|
||||
|
||||
/* Here, scan <= window+strstart+257 */
|
||||
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
|
||||
if (*scan == *match) scan++;
|
||||
|
||||
len = (MAX_MATCH - 1) - (int)(strend-scan);
|
||||
scan = strend - (MAX_MATCH-1);
|
||||
|
||||
#else /* UNALIGNED_OK */
|
||||
|
||||
if (match[best_len] != scan_end ||
|
||||
match[best_len-1] != scan_end1 ||
|
||||
*match != *scan ||
|
||||
*++match != scan[1]) continue;
|
||||
|
||||
/* The check at best_len-1 can be removed because it will be made
|
||||
* again later. (This heuristic is not always a win.)
|
||||
* It is not necessary to compare scan[2] and match[2] since they
|
||||
* are always equal when the other bytes match, given that
|
||||
* the hash keys are equal and that HASH_BITS >= 8.
|
||||
*/
|
||||
scan += 2, match++;
|
||||
Assert(*scan == *match, "match[2]?");
|
||||
|
||||
/* We check for insufficient lookahead only every 8th comparison;
|
||||
* the 256th check will be made at strstart+258.
|
||||
*/
|
||||
do {
|
||||
} while (*++scan == *++match && *++scan == *++match &&
|
||||
*++scan == *++match && *++scan == *++match &&
|
||||
*++scan == *++match && *++scan == *++match &&
|
||||
*++scan == *++match && *++scan == *++match &&
|
||||
scan < strend);
|
||||
|
||||
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
|
||||
|
||||
len = MAX_MATCH - (int)(strend - scan);
|
||||
scan = strend - MAX_MATCH;
|
||||
|
||||
#endif /* UNALIGNED_OK */
|
||||
|
||||
if (len > best_len) {
|
||||
s->match_start = cur_match;
|
||||
best_len = len;
|
||||
if (len >= nice_match) break;
|
||||
#ifdef UNALIGNED_OK
|
||||
scan_end = *(ushf*)(scan+best_len-1);
|
||||
#else
|
||||
scan_end1 = scan[best_len-1];
|
||||
scan_end = scan[best_len];
|
||||
#endif
|
||||
}
|
||||
} while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
&& --chain_length != 0);
|
||||
|
||||
if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
|
||||
return s->lookahead;
|
||||
}
|
||||
|
||||
#endif /* ASMV */
|
1
zlib/contrib/asm386/mkgvmt32.bat
Normal file
1
zlib/contrib/asm386/mkgvmt32.bat
Normal file
@ -0,0 +1 @@
|
||||
c:\masm611\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
|
74
zlib/contrib/asm386/zlibvc.def
Normal file
74
zlib/contrib/asm386/zlibvc.def
Normal file
@ -0,0 +1,74 @@
|
||||
LIBRARY "zlib"
|
||||
|
||||
DESCRIPTION '"""zlib data compression library"""'
|
||||
|
||||
|
||||
VERSION 1.11
|
||||
|
||||
|
||||
HEAPSIZE 1048576,8192
|
||||
|
||||
EXPORTS
|
||||
adler32 @1
|
||||
compress @2
|
||||
crc32 @3
|
||||
deflate @4
|
||||
deflateCopy @5
|
||||
deflateEnd @6
|
||||
deflateInit2_ @7
|
||||
deflateInit_ @8
|
||||
deflateParams @9
|
||||
deflateReset @10
|
||||
deflateSetDictionary @11
|
||||
gzclose @12
|
||||
gzdopen @13
|
||||
gzerror @14
|
||||
gzflush @15
|
||||
gzopen @16
|
||||
gzread @17
|
||||
gzwrite @18
|
||||
inflate @19
|
||||
inflateEnd @20
|
||||
inflateInit2_ @21
|
||||
inflateInit_ @22
|
||||
inflateReset @23
|
||||
inflateSetDictionary @24
|
||||
inflateSync @25
|
||||
uncompress @26
|
||||
zlibVersion @27
|
||||
gzprintf @28
|
||||
gzputc @29
|
||||
gzgetc @30
|
||||
gzseek @31
|
||||
gzrewind @32
|
||||
gztell @33
|
||||
gzeof @34
|
||||
gzsetparams @35
|
||||
zError @36
|
||||
inflateSyncPoint @37
|
||||
get_crc_table @38
|
||||
compress2 @39
|
||||
gzputs @40
|
||||
gzgets @41
|
||||
|
||||
unzOpen @61
|
||||
unzClose @62
|
||||
unzGetGlobalInfo @63
|
||||
unzGetCurrentFileInfo @64
|
||||
unzGoToFirstFile @65
|
||||
unzGoToNextFile @66
|
||||
unzOpenCurrentFile @67
|
||||
unzReadCurrentFile @68
|
||||
unztell @70
|
||||
unzeof @71
|
||||
unzCloseCurrentFile @72
|
||||
unzGetGlobalComment @73
|
||||
unzStringFileNameCompare @74
|
||||
unzLocateFile @75
|
||||
unzGetLocalExtrafield @76
|
||||
|
||||
zipOpen @80
|
||||
zipOpenNewFileInZip @81
|
||||
zipWriteInFileInZip @82
|
||||
zipCloseFileInZip @83
|
||||
zipClose @84
|
651
zlib/contrib/asm386/zlibvc.dsp
Normal file
651
zlib/contrib/asm386/zlibvc.dsp
Normal file
@ -0,0 +1,651 @@
|
||||
# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602
|
||||
|
||||
CFG=zlibvc - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "zlibvc.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\
|
||||
"Win32 (ALPHA) Dynamic-Link Library")
|
||||
!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\
|
||||
"Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\
|
||||
"Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "zlibvc__"
|
||||
# PROP BASE Intermediate_Dir "zlibvc__"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "zlibvc__"
|
||||
# PROP Intermediate_Dir "zlibvc__"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
|
||||
# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll"
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "zlibvc_0"
|
||||
# PROP BASE Intermediate_Dir "zlibvc_0"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "zlibvc_0"
|
||||
# PROP Intermediate_Dir "zlibvc_0"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "zlibvc_1"
|
||||
# PROP BASE Intermediate_Dir "zlibvc_1"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "zlibvc_1"
|
||||
# PROP Intermediate_Dir "zlibvc_1"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "zlibvc - Win32 Release"
|
||||
# Name "zlibvc - Win32 Debug"
|
||||
# Name "zlibvc - Win32 ReleaseAxp"
|
||||
# Name "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
# Name "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\adler32.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_ADLER=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\compress.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_COMPR=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crc32.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_CRC32=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\deflate.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_DEFLA=\
|
||||
".\deflate.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gvmat32c.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gzio.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_GZIO_=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infblock.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFBL=\
|
||||
".\infblock.h"\
|
||||
".\infcodes.h"\
|
||||
".\inftrees.h"\
|
||||
".\infutil.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infcodes.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFCO=\
|
||||
".\infblock.h"\
|
||||
".\infcodes.h"\
|
||||
".\inffast.h"\
|
||||
".\inftrees.h"\
|
||||
".\infutil.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inffast.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFFA=\
|
||||
".\infblock.h"\
|
||||
".\infcodes.h"\
|
||||
".\inffast.h"\
|
||||
".\inftrees.h"\
|
||||
".\infutil.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inflate.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFLA=\
|
||||
".\infblock.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inftrees.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFTR=\
|
||||
".\inftrees.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infutil.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_INFUT=\
|
||||
".\infblock.h"\
|
||||
".\infcodes.h"\
|
||||
".\inftrees.h"\
|
||||
".\infutil.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\trees.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_TREES=\
|
||||
".\deflate.h"\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uncompr.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_UNCOM=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\unzip.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zip.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlibvc.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zutil.c
|
||||
|
||||
!IF "$(CFG)" == "zlibvc - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
|
||||
|
||||
DEP_CPP_ZUTIL=\
|
||||
".\zconf.h"\
|
||||
".\zlib.h"\
|
||||
".\zutil.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
|
||||
|
||||
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\deflate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infblock.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infcodes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inffast.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inftrees.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\infutil.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zconf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zutil.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
41
zlib/contrib/asm386/zlibvc.dsw
Normal file
41
zlib/contrib/asm386/zlibvc.dsw
Normal file
@ -0,0 +1,41 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 5.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
354
zlib/contrib/asm586/match.s
Normal file
354
zlib/contrib/asm586/match.s
Normal file
@ -0,0 +1,354 @@
|
||||
/* match.s -- Pentium-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define wmask 0 /* local copy of s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define chainlenscanend 12 /* high word: current chain len */
|
||||
/* low word: last bytes sought */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the scanend */
|
||||
/* scanend value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
movw (%edi), %bx
|
||||
movw %bx, scanstart(%esp)
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Posf *prev = s->prev; */
|
||||
/* uInt wmask = s->w_mask; */
|
||||
|
||||
movl dsPrev(%edx), %edi
|
||||
movl dsWMask(%edx), %edx
|
||||
mov %edx, wmask(%esp)
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
|
||||
* %ecx = curmatch
|
||||
* %edx = curmatch & wmask
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*
|
||||
* Two optimization notes on the choice of instructions:
|
||||
*
|
||||
* The first instruction uses a 16-bit address, which costs an extra,
|
||||
* unpairable cycle. This is cheaper than doing a 32-bit access and
|
||||
* zeroing the high word, due to the 3-cycle misalignment penalty which
|
||||
* would occur half the time. This also turns out to be cheaper than
|
||||
* doing two separate 8-bit accesses, as the memory is so rarely in the
|
||||
* L1 cache.
|
||||
*
|
||||
* The window buffer, however, apparently spends a lot of time in the
|
||||
* cache, and so it is faster to retrieve the word at the end of the
|
||||
* match string with two 8-bit loads. The instructions that test the
|
||||
* word at the beginning of the match string, however, are executed
|
||||
* much less frequently, and there it was cheaper to use 16-bit
|
||||
* instructions, which avoided the necessity of saving off and
|
||||
* subsequently reloading one of the other registers.
|
||||
*/
|
||||
LookupLoop:
|
||||
/* 1 U & V */
|
||||
movw (%edi,%edx,2), %cx /* 2 U pipe */
|
||||
movl wmask(%esp), %edx /* 2 V pipe */
|
||||
cmpl %ebp, %ecx /* 3 U pipe */
|
||||
jbe LeaveNow /* 3 V pipe */
|
||||
subl $0x00010000, %ebx /* 4 U pipe */
|
||||
js LeaveNow /* 4 V pipe */
|
||||
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
|
||||
andl %ecx, %edx /* 5 V pipe */
|
||||
cmpb %bl, %al /* 6 U pipe */
|
||||
jnz LookupLoop /* 6 V pipe */
|
||||
movb (%esi,%ecx), %ah
|
||||
cmpb %bh, %ah
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movw (%eax,%ecx), %ax
|
||||
cmpw scanstart(%esp), %ax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
movl (%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
movl 4(%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
43
zlib/contrib/asm586/readme.586
Normal file
43
zlib/contrib/asm586/readme.586
Normal file
@ -0,0 +1,43 @@
|
||||
This is a patched version of zlib modified to use
|
||||
Pentium-optimized assembly code in the deflation algorithm. The files
|
||||
changed/added by this patch are:
|
||||
|
||||
README.586
|
||||
match.S
|
||||
|
||||
The effectiveness of these modifications is a bit marginal, as the the
|
||||
program's bottleneck seems to be mostly L1-cache contention, for which
|
||||
there is no real way to work around without rewriting the basic
|
||||
algorithm. The speedup on average is around 5-10% (which is generally
|
||||
less than the amount of variance between subsequent executions).
|
||||
However, when used at level 9 compression, the cache contention can
|
||||
drop enough for the assembly version to achieve 10-20% speedup (and
|
||||
sometimes more, depending on the amount of overall redundancy in the
|
||||
files). Even here, though, cache contention can still be the limiting
|
||||
factor, depending on the nature of the program using the zlib library.
|
||||
This may also mean that better improvements will be seen on a Pentium
|
||||
with MMX, which suffers much less from L1-cache contention, but I have
|
||||
not yet verified this.
|
||||
|
||||
Note that this code has been tailored for the Pentium in particular,
|
||||
and will not perform well on the Pentium Pro (due to the use of a
|
||||
partial register in the inner loop).
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
327
zlib/contrib/asm686/match.s
Normal file
327
zlib/contrib/asm686/match.s
Normal file
@ -0,0 +1,327 @@
|
||||
/* match.s -- Pentium-Pro-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the wmask */
|
||||
/* value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = scanend
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
34
zlib/contrib/asm686/readme.686
Normal file
34
zlib/contrib/asm686/readme.686
Normal file
@ -0,0 +1,34 @@
|
||||
This is a patched version of zlib, modified to use
|
||||
Pentium-Pro-optimized assembly code in the deflation algorithm. The
|
||||
files changed/added by this patch are:
|
||||
|
||||
README.686
|
||||
match.S
|
||||
|
||||
The speedup that this patch provides varies, depending on whether the
|
||||
compiler used to build the original version of zlib falls afoul of the
|
||||
PPro's speed traps. My own tests show a speedup of around 10-20% at
|
||||
the default compression level, and 20-30% using -9, against a version
|
||||
compiled using gcc 2.7.2.3. Your mileage may vary.
|
||||
|
||||
Note that this code has been tailored for the PPro/PII in particular,
|
||||
and will not perform particuarly well on a Pentium.
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
36
zlib/contrib/delphi/zlib.mak
Normal file
36
zlib/contrib/delphi/zlib.mak
Normal file
@ -0,0 +1,36 @@
|
||||
# Makefile for zlib32bd.lib
|
||||
# ------------- Borland C++ 4.5 -------------
|
||||
|
||||
# The (32-bit) zlib32bd.lib made with this makefile is intended for use
|
||||
# in making the (32-bit) DLL, png32bd.dll. It uses the "stdcall" calling
|
||||
# convention.
|
||||
|
||||
CFLAGS= -ps -O2 -C -K -N- -k- -d -3 -r- -w-par -w-aus -WDE
|
||||
CC=f:\bc45\bin\bcc32
|
||||
LIBFLAGS= /C
|
||||
LIB=f:\bc45\bin\tlib
|
||||
ZLIB=zlib32bd.lib
|
||||
|
||||
.autodepend
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
OBJ1=adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj
|
||||
OBJ2=infcodes.obj inflate.obj inftrees.obj infutil.obj inffast.obj
|
||||
OBJ3=trees.obj uncompr.obj zutil.obj
|
||||
pOBJ1=+adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infblock.obj
|
||||
pOBJ2=+infcodes.obj+inflate.obj+inftrees.obj+infutil.obj+inffast.obj
|
||||
pOBJ3=+trees.obj+uncompr.obj+zutil.obj
|
||||
|
||||
all: $(ZLIB)
|
||||
|
||||
$(ZLIB): $(OBJ1) $(OBJ2) $(OBJ3)
|
||||
@if exist $@ del $@
|
||||
$(LIB) @&&|
|
||||
$@ $(LIBFLAGS) &
|
||||
$(pOBJ1) &
|
||||
$(pOBJ2) &
|
||||
$(pOBJ3)
|
||||
|
|
||||
|
||||
# End of makefile for zlib32bd.lib
|
169
zlib/contrib/delphi/zlibdef.pas
Normal file
169
zlib/contrib/delphi/zlibdef.pas
Normal file
@ -0,0 +1,169 @@
|
||||
unit zlibdef;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows;
|
||||
|
||||
const
|
||||
ZLIB_VERSION = '1.1.3';
|
||||
|
||||
type
|
||||
voidpf = Pointer;
|
||||
int = Integer;
|
||||
uInt = Cardinal;
|
||||
pBytef = PChar;
|
||||
uLong = Cardinal;
|
||||
|
||||
alloc_func = function(opaque: voidpf; items, size: uInt): voidpf;
|
||||
stdcall;
|
||||
free_func = procedure(opaque, address: voidpf);
|
||||
stdcall;
|
||||
|
||||
internal_state = Pointer;
|
||||
|
||||
z_streamp = ^z_stream;
|
||||
z_stream = packed record
|
||||
next_in: pBytef; // next input byte
|
||||
avail_in: uInt; // number of bytes available at next_in
|
||||
total_in: uLong; // total nb of input bytes read so far
|
||||
|
||||
next_out: pBytef; // next output byte should be put there
|
||||
avail_out: uInt; // remaining free space at next_out
|
||||
total_out: uLong; // total nb of bytes output so far
|
||||
|
||||
msg: PChar; // last error message, NULL if no error
|
||||
state: internal_state; // not visible by applications
|
||||
|
||||
zalloc: alloc_func; // used to allocate the internal state
|
||||
zfree: free_func; // used to free the internal state
|
||||
opaque: voidpf; // private data object passed to zalloc and zfree
|
||||
|
||||
data_type: int; // best guess about the data type: ascii or binary
|
||||
adler: uLong; // adler32 value of the uncompressed data
|
||||
reserved: uLong; // reserved for future use
|
||||
end;
|
||||
|
||||
const
|
||||
Z_NO_FLUSH = 0;
|
||||
Z_SYNC_FLUSH = 2;
|
||||
Z_FULL_FLUSH = 3;
|
||||
Z_FINISH = 4;
|
||||
|
||||
Z_OK = 0;
|
||||
Z_STREAM_END = 1;
|
||||
|
||||
Z_NO_COMPRESSION = 0;
|
||||
Z_BEST_SPEED = 1;
|
||||
Z_BEST_COMPRESSION = 9;
|
||||
Z_DEFAULT_COMPRESSION = -1;
|
||||
|
||||
Z_FILTERED = 1;
|
||||
Z_HUFFMAN_ONLY = 2;
|
||||
Z_DEFAULT_STRATEGY = 0;
|
||||
|
||||
Z_BINARY = 0;
|
||||
Z_ASCII = 1;
|
||||
Z_UNKNOWN = 2;
|
||||
|
||||
Z_DEFLATED = 8;
|
||||
|
||||
MAX_MEM_LEVEL = 9;
|
||||
|
||||
function adler32(adler: uLong; const buf: pBytef; len: uInt): uLong;
|
||||
stdcall;
|
||||
function crc32(crc: uLong; const buf: pBytef; len: uInt): uLong;
|
||||
stdcall;
|
||||
function deflate(strm: z_streamp; flush: int): int;
|
||||
stdcall;
|
||||
function deflateCopy(dest, source: z_streamp): int;
|
||||
stdcall;
|
||||
function deflateEnd(strm: z_streamp): int;
|
||||
stdcall;
|
||||
function deflateInit2_(strm: z_streamp; level, method,
|
||||
windowBits, memLevel, strategy: int;
|
||||
const version: PChar; stream_size: int): int;
|
||||
stdcall;
|
||||
function deflateInit_(strm: z_streamp; level: int;
|
||||
const version: PChar; stream_size: int): int;
|
||||
stdcall;
|
||||
function deflateParams(strm: z_streamp; level, strategy: int): int;
|
||||
stdcall;
|
||||
function deflateReset(strm: z_streamp): int;
|
||||
stdcall;
|
||||
function deflateSetDictionary(strm: z_streamp;
|
||||
const dictionary: pBytef;
|
||||
dictLength: uInt): int;
|
||||
stdcall;
|
||||
function inflate(strm: z_streamp; flush: int): int;
|
||||
stdcall;
|
||||
function inflateEnd(strm: z_streamp): int;
|
||||
stdcall;
|
||||
function inflateInit2_(strm: z_streamp; windowBits: int;
|
||||
const version: PChar; stream_size: int): int;
|
||||
stdcall;
|
||||
function inflateInit_(strm: z_streamp; const version: PChar;
|
||||
stream_size: int): int;
|
||||
stdcall;
|
||||
function inflateReset(strm: z_streamp): int;
|
||||
stdcall;
|
||||
function inflateSetDictionary(strm: z_streamp;
|
||||
const dictionary: pBytef;
|
||||
dictLength: uInt): int;
|
||||
stdcall;
|
||||
function inflateSync(strm: z_streamp): int;
|
||||
stdcall;
|
||||
|
||||
function deflateInit(strm: z_streamp; level: int): int;
|
||||
function deflateInit2(strm: z_streamp; level, method, windowBits,
|
||||
memLevel, strategy: int): int;
|
||||
function inflateInit(strm: z_streamp): int;
|
||||
function inflateInit2(strm: z_streamp; windowBits: int): int;
|
||||
|
||||
implementation
|
||||
|
||||
function deflateInit(strm: z_streamp; level: int): int;
|
||||
begin
|
||||
Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream));
|
||||
end;
|
||||
|
||||
function deflateInit2(strm: z_streamp; level, method, windowBits,
|
||||
memLevel, strategy: int): int;
|
||||
begin
|
||||
Result := deflateInit2_(strm, level, method, windowBits, memLevel,
|
||||
strategy, ZLIB_VERSION, sizeof(z_stream));
|
||||
end;
|
||||
|
||||
function inflateInit(strm: z_streamp): int;
|
||||
begin
|
||||
Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream));
|
||||
end;
|
||||
|
||||
function inflateInit2(strm: z_streamp; windowBits: int): int;
|
||||
begin
|
||||
Result := inflateInit2_(strm, windowBits, ZLIB_VERSION,
|
||||
sizeof(z_stream));
|
||||
end;
|
||||
|
||||
const
|
||||
zlibDLL = 'png32bd.dll';
|
||||
|
||||
function adler32; external zlibDLL;
|
||||
function crc32; external zlibDLL;
|
||||
function deflate; external zlibDLL;
|
||||
function deflateCopy; external zlibDLL;
|
||||
function deflateEnd; external zlibDLL;
|
||||
function deflateInit2_; external zlibDLL;
|
||||
function deflateInit_; external zlibDLL;
|
||||
function deflateParams; external zlibDLL;
|
||||
function deflateReset; external zlibDLL;
|
||||
function deflateSetDictionary; external zlibDLL;
|
||||
function inflate; external zlibDLL;
|
||||
function inflateEnd; external zlibDLL;
|
||||
function inflateInit2_; external zlibDLL;
|
||||
function inflateInit_; external zlibDLL;
|
||||
function inflateReset; external zlibDLL;
|
||||
function inflateSetDictionary; external zlibDLL;
|
||||
function inflateSync; external zlibDLL;
|
||||
|
||||
end.
|
224
zlib/contrib/delphi2/d_zlib.bpr
Normal file
224
zlib/contrib/delphi2/d_zlib.bpr
Normal file
@ -0,0 +1,224 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCB)
|
||||
BCB = $(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# IDE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# The following section of the project makefile is managed by the BCB IDE.
|
||||
# It is recommended to use the IDE to change any of the values in this
|
||||
# section.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
VERSION = BCB.03
|
||||
# ---------------------------------------------------------------------------
|
||||
PROJECT = d_zlib.lib
|
||||
OBJFILES = d_zlib.obj adler32.obj deflate.obj infblock.obj infcodes.obj inffast.obj \
|
||||
inflate.obj inftrees.obj infutil.obj trees.obj
|
||||
RESFILES =
|
||||
RESDEPEN = $(RESFILES)
|
||||
LIBFILES =
|
||||
LIBRARIES = VCL35.lib
|
||||
SPARELIBS = VCL35.lib
|
||||
DEFFILE =
|
||||
PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \
|
||||
dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \
|
||||
NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi
|
||||
# ---------------------------------------------------------------------------
|
||||
PATHCPP = .;
|
||||
PATHASM = .;
|
||||
PATHPAS = .;
|
||||
PATHRC = .;
|
||||
DEBUGLIBPATH = $(BCB)\lib\debug
|
||||
RELEASELIBPATH = $(BCB)\lib\release
|
||||
# ---------------------------------------------------------------------------
|
||||
CFLAG1 = -O2 -Ve -d -k- -vi
|
||||
CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm
|
||||
CFLAG3 = -ff -pr -5
|
||||
PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M
|
||||
RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl
|
||||
AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn
|
||||
LFLAGS =
|
||||
IFLAGS = -g -Gn
|
||||
# ---------------------------------------------------------------------------
|
||||
ALLOBJ = c0w32.obj $(OBJFILES)
|
||||
ALLRES = $(RESFILES)
|
||||
ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib
|
||||
# ---------------------------------------------------------------------------
|
||||
!!ifdef IDEOPTIONS
|
||||
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1040
|
||||
CodePage=1252
|
||||
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
|
||||
[HistoryLists\hlIncludePath]
|
||||
Count=2
|
||||
Item0=$(BCB)\include
|
||||
Item1=$(BCB)\include;$(BCB)\include\vcl
|
||||
|
||||
[HistoryLists\hlLibraryPath]
|
||||
Count=1
|
||||
Item0=$(BCB)\lib\obj;$(BCB)\lib
|
||||
|
||||
[HistoryLists\hlDebugSourcePath]
|
||||
Count=1
|
||||
Item0=$(BCB)\source\vcl
|
||||
|
||||
[Debugging]
|
||||
DebugSourceDirs=
|
||||
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
|
||||
!endif
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
# MAKE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# This section of the project file is not used by the BCB IDE. It is for
|
||||
# the benefit of building from the command-line using the MAKE utility.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
.autodepend
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCC32)
|
||||
BCC32 = bcc32
|
||||
!endif
|
||||
|
||||
!if !$d(DCC32)
|
||||
DCC32 = dcc32
|
||||
!endif
|
||||
|
||||
!if !$d(TASM32)
|
||||
TASM32 = tasm32
|
||||
!endif
|
||||
|
||||
!if !$d(LINKER)
|
||||
LINKER = TLib
|
||||
!endif
|
||||
|
||||
!if !$d(BRCC32)
|
||||
BRCC32 = brcc32
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
!if $d(PATHCPP)
|
||||
.PATH.CPP = $(PATHCPP)
|
||||
.PATH.C = $(PATHCPP)
|
||||
!endif
|
||||
|
||||
!if $d(PATHPAS)
|
||||
.PATH.PAS = $(PATHPAS)
|
||||
!endif
|
||||
|
||||
!if $d(PATHASM)
|
||||
.PATH.ASM = $(PATHASM)
|
||||
!endif
|
||||
|
||||
!if $d(PATHRC)
|
||||
.PATH.RC = $(PATHRC)
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
!ifdef IDEOPTIONS
|
||||
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1040
|
||||
CodePage=1252
|
||||
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
|
||||
[HistoryLists\hlIncludePath]
|
||||
Count=2
|
||||
Item0=$(BCB)\include;$(BCB)\include\vcl
|
||||
Item1=$(BCB)\include
|
||||
|
||||
[HistoryLists\hlLibraryPath]
|
||||
Count=1
|
||||
Item0=$(BCB)\lib\obj;$(BCB)\lib
|
||||
|
||||
[HistoryLists\hlDebugSourcePath]
|
||||
Count=1
|
||||
Item0=$(BCB)\source\vcl
|
||||
|
||||
[Debugging]
|
||||
DebugSourceDirs=
|
||||
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
|
||||
!endif
|
||||
|
||||
$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
|
||||
$(BCB)\BIN\$(LINKER) @&&!
|
||||
$(LFLAGS) $(IFLAGS) +
|
||||
$(ALLOBJ), +
|
||||
$(PROJECT),, +
|
||||
$(ALLLIB), +
|
||||
$(DEFFILE), +
|
||||
$(ALLRES)
|
||||
!
|
||||
# ---------------------------------------------------------------------------
|
||||
.pas.hpp:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.pas.obj:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.cpp.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.c.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.asm.obj:
|
||||
$(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@
|
||||
|
||||
.rc.res:
|
||||
$(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $<
|
||||
# ---------------------------------------------------------------------------
|
17
zlib/contrib/delphi2/d_zlib.cpp
Normal file
17
zlib/contrib/delphi2/d_zlib.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <condefs.h>
|
||||
#pragma hdrstop
|
||||
//---------------------------------------------------------------------------
|
||||
USEUNIT("adler32.c");
|
||||
USEUNIT("deflate.c");
|
||||
USEUNIT("infblock.c");
|
||||
USEUNIT("infcodes.c");
|
||||
USEUNIT("inffast.c");
|
||||
USEUNIT("inflate.c");
|
||||
USEUNIT("inftrees.c");
|
||||
USEUNIT("infutil.c");
|
||||
USEUNIT("trees.c");
|
||||
//---------------------------------------------------------------------------
|
||||
#define Library
|
||||
|
||||
// To add a file to the library use the Project menu 'Add to Project'.
|
||||
|
17
zlib/contrib/delphi2/readme.txt
Normal file
17
zlib/contrib/delphi2/readme.txt
Normal file
@ -0,0 +1,17 @@
|
||||
These are files used to compile zlib under Borland C++ Builder 3.
|
||||
|
||||
zlib.bpg is the main project group that can be loaded in the BCB IDE and
|
||||
loads all other *.bpr projects
|
||||
|
||||
zlib.bpr is a project used to create a static zlib.lib library with C calling
|
||||
convention for functions.
|
||||
|
||||
zlib32.bpr creates a zlib32.dll dynamic link library with Windows standard
|
||||
calling convention.
|
||||
|
||||
d_zlib.bpr creates a set of .obj files with register calling convention.
|
||||
These files are used by zlib.pas to create a Delphi unit containing zlib.
|
||||
The d_zlib.lib file generated isn't useful and can be deleted.
|
||||
|
||||
zlib.cpp, zlib32.cpp and d_zlib.cpp are used by the above projects.
|
||||
|
26
zlib/contrib/delphi2/zlib.bpg
Normal file
26
zlib/contrib/delphi2/zlib.bpg
Normal file
@ -0,0 +1,26 @@
|
||||
#------------------------------------------------------------------------------
|
||||
VERSION = BWS.01
|
||||
#------------------------------------------------------------------------------
|
||||
!ifndef ROOT
|
||||
ROOT = $(MAKEDIR)\..
|
||||
!endif
|
||||
#------------------------------------------------------------------------------
|
||||
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
|
||||
DCC = $(ROOT)\bin\dcc32.exe $**
|
||||
BRCC = $(ROOT)\bin\brcc32.exe $**
|
||||
#------------------------------------------------------------------------------
|
||||
PROJECTS = zlib zlib32 d_zlib
|
||||
#------------------------------------------------------------------------------
|
||||
default: $(PROJECTS)
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
zlib: zlib.bpr
|
||||
$(MAKE)
|
||||
|
||||
zlib32: zlib32.bpr
|
||||
$(MAKE)
|
||||
|
||||
d_zlib: d_zlib.bpr
|
||||
$(MAKE)
|
||||
|
||||
|
225
zlib/contrib/delphi2/zlib.bpr
Normal file
225
zlib/contrib/delphi2/zlib.bpr
Normal file
@ -0,0 +1,225 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCB)
|
||||
BCB = $(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# IDE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# The following section of the project makefile is managed by the BCB IDE.
|
||||
# It is recommended to use the IDE to change any of the values in this
|
||||
# section.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
VERSION = BCB.03
|
||||
# ---------------------------------------------------------------------------
|
||||
PROJECT = zlib.lib
|
||||
OBJFILES = zlib.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \
|
||||
infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \
|
||||
uncompr.obj zutil.obj
|
||||
RESFILES =
|
||||
RESDEPEN = $(RESFILES)
|
||||
LIBFILES =
|
||||
LIBRARIES = VCL35.lib
|
||||
SPARELIBS = VCL35.lib
|
||||
DEFFILE =
|
||||
PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \
|
||||
dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \
|
||||
NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi
|
||||
# ---------------------------------------------------------------------------
|
||||
PATHCPP = .;
|
||||
PATHASM = .;
|
||||
PATHPAS = .;
|
||||
PATHRC = .;
|
||||
DEBUGLIBPATH = $(BCB)\lib\debug
|
||||
RELEASELIBPATH = $(BCB)\lib\release
|
||||
# ---------------------------------------------------------------------------
|
||||
CFLAG1 = -O2 -Ve -d -k- -vi
|
||||
CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm
|
||||
CFLAG3 = -ff -5
|
||||
PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M
|
||||
RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl
|
||||
AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn
|
||||
LFLAGS =
|
||||
IFLAGS = -g -Gn
|
||||
# ---------------------------------------------------------------------------
|
||||
ALLOBJ = c0w32.obj $(OBJFILES)
|
||||
ALLRES = $(RESFILES)
|
||||
ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib
|
||||
# ---------------------------------------------------------------------------
|
||||
!!ifdef IDEOPTIONS
|
||||
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1040
|
||||
CodePage=1252
|
||||
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
|
||||
[HistoryLists\hlIncludePath]
|
||||
Count=2
|
||||
Item0=$(BCB)\include
|
||||
Item1=$(BCB)\include;$(BCB)\include\vcl
|
||||
|
||||
[HistoryLists\hlLibraryPath]
|
||||
Count=1
|
||||
Item0=$(BCB)\lib\obj;$(BCB)\lib
|
||||
|
||||
[HistoryLists\hlDebugSourcePath]
|
||||
Count=1
|
||||
Item0=$(BCB)\source\vcl
|
||||
|
||||
[Debugging]
|
||||
DebugSourceDirs=
|
||||
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
|
||||
!endif
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
# MAKE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# This section of the project file is not used by the BCB IDE. It is for
|
||||
# the benefit of building from the command-line using the MAKE utility.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
.autodepend
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCC32)
|
||||
BCC32 = bcc32
|
||||
!endif
|
||||
|
||||
!if !$d(DCC32)
|
||||
DCC32 = dcc32
|
||||
!endif
|
||||
|
||||
!if !$d(TASM32)
|
||||
TASM32 = tasm32
|
||||
!endif
|
||||
|
||||
!if !$d(LINKER)
|
||||
LINKER = TLib
|
||||
!endif
|
||||
|
||||
!if !$d(BRCC32)
|
||||
BRCC32 = brcc32
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
!if $d(PATHCPP)
|
||||
.PATH.CPP = $(PATHCPP)
|
||||
.PATH.C = $(PATHCPP)
|
||||
!endif
|
||||
|
||||
!if $d(PATHPAS)
|
||||
.PATH.PAS = $(PATHPAS)
|
||||
!endif
|
||||
|
||||
!if $d(PATHASM)
|
||||
.PATH.ASM = $(PATHASM)
|
||||
!endif
|
||||
|
||||
!if $d(PATHRC)
|
||||
.PATH.RC = $(PATHRC)
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
!ifdef IDEOPTIONS
|
||||
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1040
|
||||
CodePage=1252
|
||||
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
|
||||
[HistoryLists\hlIncludePath]
|
||||
Count=2
|
||||
Item0=$(BCB)\include;$(BCB)\include\vcl
|
||||
Item1=$(BCB)\include
|
||||
|
||||
[HistoryLists\hlLibraryPath]
|
||||
Count=1
|
||||
Item0=$(BCB)\lib\obj;$(BCB)\lib
|
||||
|
||||
[HistoryLists\hlDebugSourcePath]
|
||||
Count=1
|
||||
Item0=$(BCB)\source\vcl
|
||||
|
||||
[Debugging]
|
||||
DebugSourceDirs=
|
||||
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
|
||||
!endif
|
||||
|
||||
$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
|
||||
$(BCB)\BIN\$(LINKER) @&&!
|
||||
$(LFLAGS) $(IFLAGS) +
|
||||
$(ALLOBJ), +
|
||||
$(PROJECT),, +
|
||||
$(ALLLIB), +
|
||||
$(DEFFILE), +
|
||||
$(ALLRES)
|
||||
!
|
||||
# ---------------------------------------------------------------------------
|
||||
.pas.hpp:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.pas.obj:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.cpp.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.c.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.asm.obj:
|
||||
$(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@
|
||||
|
||||
.rc.res:
|
||||
$(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $<
|
||||
# ---------------------------------------------------------------------------
|
22
zlib/contrib/delphi2/zlib.cpp
Normal file
22
zlib/contrib/delphi2/zlib.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include <condefs.h>
|
||||
#pragma hdrstop
|
||||
//---------------------------------------------------------------------------
|
||||
USEUNIT("adler32.c");
|
||||
USEUNIT("compress.c");
|
||||
USEUNIT("crc32.c");
|
||||
USEUNIT("deflate.c");
|
||||
USEUNIT("gzio.c");
|
||||
USEUNIT("infblock.c");
|
||||
USEUNIT("infcodes.c");
|
||||
USEUNIT("inffast.c");
|
||||
USEUNIT("inflate.c");
|
||||
USEUNIT("inftrees.c");
|
||||
USEUNIT("infutil.c");
|
||||
USEUNIT("trees.c");
|
||||
USEUNIT("uncompr.c");
|
||||
USEUNIT("zutil.c");
|
||||
//---------------------------------------------------------------------------
|
||||
#define Library
|
||||
|
||||
// To add a file to the library use the Project menu 'Add to Project'.
|
||||
|
534
zlib/contrib/delphi2/zlib.pas
Normal file
534
zlib/contrib/delphi2/zlib.pas
Normal file
@ -0,0 +1,534 @@
|
||||
{*******************************************************}
|
||||
{ }
|
||||
{ Delphi Supplemental Components }
|
||||
{ ZLIB Data Compression Interface Unit }
|
||||
{ }
|
||||
{ Copyright (c) 1997 Borland International }
|
||||
{ }
|
||||
{*******************************************************}
|
||||
|
||||
{ Modified for zlib 1.1.3 by Davide Moretti <dave@rimini.com }
|
||||
|
||||
unit zlib;
|
||||
|
||||
interface
|
||||
|
||||
uses Sysutils, Classes;
|
||||
|
||||
type
|
||||
TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer;
|
||||
TFree = procedure (AppData, Block: Pointer);
|
||||
|
||||
// Internal structure. Ignore.
|
||||
TZStreamRec = packed record
|
||||
next_in: PChar; // next input byte
|
||||
avail_in: Integer; // number of bytes available at next_in
|
||||
total_in: Integer; // total nb of input bytes read so far
|
||||
|
||||
next_out: PChar; // next output byte should be put here
|
||||
avail_out: Integer; // remaining free space at next_out
|
||||
total_out: Integer; // total nb of bytes output so far
|
||||
|
||||
msg: PChar; // last error message, NULL if no error
|
||||
internal: Pointer; // not visible by applications
|
||||
|
||||
zalloc: TAlloc; // used to allocate the internal state
|
||||
zfree: TFree; // used to free the internal state
|
||||
AppData: Pointer; // private data object passed to zalloc and zfree
|
||||
|
||||
data_type: Integer; // best guess about the data type: ascii or binary
|
||||
adler: Integer; // adler32 value of the uncompressed data
|
||||
reserved: Integer; // reserved for future use
|
||||
end;
|
||||
|
||||
// Abstract ancestor class
|
||||
TCustomZlibStream = class(TStream)
|
||||
private
|
||||
FStrm: TStream;
|
||||
FStrmPos: Integer;
|
||||
FOnProgress: TNotifyEvent;
|
||||
FZRec: TZStreamRec;
|
||||
FBuffer: array [Word] of Char;
|
||||
protected
|
||||
procedure Progress(Sender: TObject); dynamic;
|
||||
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
|
||||
constructor Create(Strm: TStream);
|
||||
end;
|
||||
|
||||
{ TCompressionStream compresses data on the fly as data is written to it, and
|
||||
stores the compressed data to another stream.
|
||||
|
||||
TCompressionStream is write-only and strictly sequential. Reading from the
|
||||
stream will raise an exception. Using Seek to move the stream pointer
|
||||
will raise an exception.
|
||||
|
||||
Output data is cached internally, written to the output stream only when
|
||||
the internal output buffer is full. All pending output data is flushed
|
||||
when the stream is destroyed.
|
||||
|
||||
The Position property returns the number of uncompressed bytes of
|
||||
data that have been written to the stream so far.
|
||||
|
||||
CompressionRate returns the on-the-fly percentage by which the original
|
||||
data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100
|
||||
If raw data size = 100 and compressed data size = 25, the CompressionRate
|
||||
is 75%
|
||||
|
||||
The OnProgress event is called each time the output buffer is filled and
|
||||
written to the output stream. This is useful for updating a progress
|
||||
indicator when you are writing a large chunk of data to the compression
|
||||
stream in a single call.}
|
||||
|
||||
|
||||
TCompressionLevel = (clNone, clFastest, clDefault, clMax);
|
||||
|
||||
TCompressionStream = class(TCustomZlibStream)
|
||||
private
|
||||
function GetCompressionRate: Single;
|
||||
public
|
||||
constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
|
||||
destructor Destroy; override;
|
||||
function Read(var Buffer; Count: Longint): Longint; override;
|
||||
function Write(const Buffer; Count: Longint): Longint; override;
|
||||
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
||||
property CompressionRate: Single read GetCompressionRate;
|
||||
property OnProgress;
|
||||
end;
|
||||
|
||||
{ TDecompressionStream decompresses data on the fly as data is read from it.
|
||||
|
||||
Compressed data comes from a separate source stream. TDecompressionStream
|
||||
is read-only and unidirectional; you can seek forward in the stream, but not
|
||||
backwards. The special case of setting the stream position to zero is
|
||||
allowed. Seeking forward decompresses data until the requested position in
|
||||
the uncompressed data has been reached. Seeking backwards, seeking relative
|
||||
to the end of the stream, requesting the size of the stream, and writing to
|
||||
the stream will raise an exception.
|
||||
|
||||
The Position property returns the number of bytes of uncompressed data that
|
||||
have been read from the stream so far.
|
||||
|
||||
The OnProgress event is called each time the internal input buffer of
|
||||
compressed data is exhausted and the next block is read from the input stream.
|
||||
This is useful for updating a progress indicator when you are reading a
|
||||
large chunk of data from the decompression stream in a single call.}
|
||||
|
||||
TDecompressionStream = class(TCustomZlibStream)
|
||||
public
|
||||
constructor Create(Source: TStream);
|
||||
destructor Destroy; override;
|
||||
function Read(var Buffer; Count: Longint): Longint; override;
|
||||
function Write(const Buffer; Count: Longint): Longint; override;
|
||||
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
||||
property OnProgress;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ CompressBuf compresses data, buffer to buffer, in one call.
|
||||
In: InBuf = ptr to compressed data
|
||||
InBytes = number of bytes in InBuf
|
||||
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
||||
OutBytes = number of bytes in OutBuf }
|
||||
procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||
out OutBuf: Pointer; out OutBytes: Integer);
|
||||
|
||||
|
||||
{ DecompressBuf decompresses data, buffer to buffer, in one call.
|
||||
In: InBuf = ptr to compressed data
|
||||
InBytes = number of bytes in InBuf
|
||||
OutEstimate = zero, or est. size of the decompressed data
|
||||
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
||||
OutBytes = number of bytes in OutBuf }
|
||||
procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
|
||||
|
||||
const
|
||||
zlib_version = '1.1.3';
|
||||
|
||||
type
|
||||
EZlibError = class(Exception);
|
||||
ECompressionError = class(EZlibError);
|
||||
EDecompressionError = class(EZlibError);
|
||||
|
||||
function adler32(adler: Integer; buf: PChar; len: Integer): Integer;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
Z_NO_FLUSH = 0;
|
||||
Z_PARTIAL_FLUSH = 1;
|
||||
Z_SYNC_FLUSH = 2;
|
||||
Z_FULL_FLUSH = 3;
|
||||
Z_FINISH = 4;
|
||||
|
||||
Z_OK = 0;
|
||||
Z_STREAM_END = 1;
|
||||
Z_NEED_DICT = 2;
|
||||
Z_ERRNO = (-1);
|
||||
Z_STREAM_ERROR = (-2);
|
||||
Z_DATA_ERROR = (-3);
|
||||
Z_MEM_ERROR = (-4);
|
||||
Z_BUF_ERROR = (-5);
|
||||
Z_VERSION_ERROR = (-6);
|
||||
|
||||
Z_NO_COMPRESSION = 0;
|
||||
Z_BEST_SPEED = 1;
|
||||
Z_BEST_COMPRESSION = 9;
|
||||
Z_DEFAULT_COMPRESSION = (-1);
|
||||
|
||||
Z_FILTERED = 1;
|
||||
Z_HUFFMAN_ONLY = 2;
|
||||
Z_DEFAULT_STRATEGY = 0;
|
||||
|
||||
Z_BINARY = 0;
|
||||
Z_ASCII = 1;
|
||||
Z_UNKNOWN = 2;
|
||||
|
||||
Z_DEFLATED = 8;
|
||||
|
||||
_z_errmsg: array[0..9] of PChar = (
|
||||
'need dictionary', // Z_NEED_DICT (2)
|
||||
'stream end', // Z_STREAM_END (1)
|
||||
'', // Z_OK (0)
|
||||
'file error', // Z_ERRNO (-1)
|
||||
'stream error', // Z_STREAM_ERROR (-2)
|
||||
'data error', // Z_DATA_ERROR (-3)
|
||||
'insufficient memory', // Z_MEM_ERROR (-4)
|
||||
'buffer error', // Z_BUF_ERROR (-5)
|
||||
'incompatible version', // Z_VERSION_ERROR (-6)
|
||||
''
|
||||
);
|
||||
|
||||
{$L deflate.obj}
|
||||
{$L inflate.obj}
|
||||
{$L inftrees.obj}
|
||||
{$L trees.obj}
|
||||
{$L adler32.obj}
|
||||
{$L infblock.obj}
|
||||
{$L infcodes.obj}
|
||||
{$L infutil.obj}
|
||||
{$L inffast.obj}
|
||||
|
||||
procedure _tr_init; external;
|
||||
procedure _tr_tally; external;
|
||||
procedure _tr_flush_block; external;
|
||||
procedure _tr_align; external;
|
||||
procedure _tr_stored_block; external;
|
||||
function adler32; external;
|
||||
procedure inflate_blocks_new; external;
|
||||
procedure inflate_blocks; external;
|
||||
procedure inflate_blocks_reset; external;
|
||||
procedure inflate_blocks_free; external;
|
||||
procedure inflate_set_dictionary; external;
|
||||
procedure inflate_trees_bits; external;
|
||||
procedure inflate_trees_dynamic; external;
|
||||
procedure inflate_trees_fixed; external;
|
||||
procedure inflate_codes_new; external;
|
||||
procedure inflate_codes; external;
|
||||
procedure inflate_codes_free; external;
|
||||
procedure _inflate_mask; external;
|
||||
procedure inflate_flush; external;
|
||||
procedure inflate_fast; external;
|
||||
|
||||
procedure _memset(P: Pointer; B: Byte; count: Integer);cdecl;
|
||||
begin
|
||||
FillChar(P^, count, B);
|
||||
end;
|
||||
|
||||
procedure _memcpy(dest, source: Pointer; count: Integer);cdecl;
|
||||
begin
|
||||
Move(source^, dest^, count);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
// deflate compresses data
|
||||
function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
|
||||
recsize: Integer): Integer; external;
|
||||
function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
|
||||
function deflateEnd(var strm: TZStreamRec): Integer; external;
|
||||
|
||||
// inflate decompresses data
|
||||
function inflateInit_(var strm: TZStreamRec; version: PChar;
|
||||
recsize: Integer): Integer; external;
|
||||
function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
|
||||
function inflateEnd(var strm: TZStreamRec): Integer; external;
|
||||
function inflateReset(var strm: TZStreamRec): Integer; external;
|
||||
|
||||
|
||||
function zcalloc(AppData: Pointer; Items, Size: Integer): Pointer;
|
||||
begin
|
||||
GetMem(Result, Items*Size);
|
||||
end;
|
||||
|
||||
procedure zcfree(AppData, Block: Pointer);
|
||||
begin
|
||||
FreeMem(Block);
|
||||
end;
|
||||
|
||||
function zlibCheck(code: Integer): Integer;
|
||||
begin
|
||||
Result := code;
|
||||
if code < 0 then
|
||||
raise EZlibError.Create('error'); //!!
|
||||
end;
|
||||
|
||||
function CCheck(code: Integer): Integer;
|
||||
begin
|
||||
Result := code;
|
||||
if code < 0 then
|
||||
raise ECompressionError.Create('error'); //!!
|
||||
end;
|
||||
|
||||
function DCheck(code: Integer): Integer;
|
||||
begin
|
||||
Result := code;
|
||||
if code < 0 then
|
||||
raise EDecompressionError.Create('error'); //!!
|
||||
end;
|
||||
|
||||
procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||
out OutBuf: Pointer; out OutBytes: Integer);
|
||||
var
|
||||
strm: TZStreamRec;
|
||||
P: Pointer;
|
||||
begin
|
||||
FillChar(strm, sizeof(strm), 0);
|
||||
OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
|
||||
GetMem(OutBuf, OutBytes);
|
||||
try
|
||||
strm.next_in := InBuf;
|
||||
strm.avail_in := InBytes;
|
||||
strm.next_out := OutBuf;
|
||||
strm.avail_out := OutBytes;
|
||||
CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
|
||||
try
|
||||
while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
|
||||
begin
|
||||
P := OutBuf;
|
||||
Inc(OutBytes, 256);
|
||||
ReallocMem(OutBuf, OutBytes);
|
||||
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
||||
strm.avail_out := 256;
|
||||
end;
|
||||
finally
|
||||
CCheck(deflateEnd(strm));
|
||||
end;
|
||||
ReallocMem(OutBuf, strm.total_out);
|
||||
OutBytes := strm.total_out;
|
||||
except
|
||||
FreeMem(OutBuf);
|
||||
raise
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
|
||||
var
|
||||
strm: TZStreamRec;
|
||||
P: Pointer;
|
||||
BufInc: Integer;
|
||||
begin
|
||||
FillChar(strm, sizeof(strm), 0);
|
||||
BufInc := (InBytes + 255) and not 255;
|
||||
if OutEstimate = 0 then
|
||||
OutBytes := BufInc
|
||||
else
|
||||
OutBytes := OutEstimate;
|
||||
GetMem(OutBuf, OutBytes);
|
||||
try
|
||||
strm.next_in := InBuf;
|
||||
strm.avail_in := InBytes;
|
||||
strm.next_out := OutBuf;
|
||||
strm.avail_out := OutBytes;
|
||||
DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
|
||||
try
|
||||
while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do
|
||||
begin
|
||||
P := OutBuf;
|
||||
Inc(OutBytes, BufInc);
|
||||
ReallocMem(OutBuf, OutBytes);
|
||||
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
||||
strm.avail_out := BufInc;
|
||||
end;
|
||||
finally
|
||||
DCheck(inflateEnd(strm));
|
||||
end;
|
||||
ReallocMem(OutBuf, strm.total_out);
|
||||
OutBytes := strm.total_out;
|
||||
except
|
||||
FreeMem(OutBuf);
|
||||
raise
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
// TCustomZlibStream
|
||||
|
||||
constructor TCustomZLibStream.Create(Strm: TStream);
|
||||
begin
|
||||
inherited Create;
|
||||
FStrm := Strm;
|
||||
FStrmPos := Strm.Position;
|
||||
end;
|
||||
|
||||
procedure TCustomZLibStream.Progress(Sender: TObject);
|
||||
begin
|
||||
if Assigned(FOnProgress) then FOnProgress(Sender);
|
||||
end;
|
||||
|
||||
|
||||
// TCompressionStream
|
||||
|
||||
constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
|
||||
Dest: TStream);
|
||||
const
|
||||
Levels: array [TCompressionLevel] of ShortInt =
|
||||
(Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
|
||||
begin
|
||||
inherited Create(Dest);
|
||||
FZRec.next_out := FBuffer;
|
||||
FZRec.avail_out := sizeof(FBuffer);
|
||||
CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
|
||||
end;
|
||||
|
||||
destructor TCompressionStream.Destroy;
|
||||
begin
|
||||
FZRec.next_in := nil;
|
||||
FZRec.avail_in := 0;
|
||||
try
|
||||
if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
|
||||
while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
|
||||
and (FZRec.avail_out = 0) do
|
||||
begin
|
||||
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
|
||||
FZRec.next_out := FBuffer;
|
||||
FZRec.avail_out := sizeof(FBuffer);
|
||||
end;
|
||||
if FZRec.avail_out < sizeof(FBuffer) then
|
||||
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
|
||||
finally
|
||||
deflateEnd(FZRec);
|
||||
end;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
|
||||
begin
|
||||
raise ECompressionError.Create('Invalid stream operation');
|
||||
end;
|
||||
|
||||
function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
|
||||
begin
|
||||
FZRec.next_in := @Buffer;
|
||||
FZRec.avail_in := Count;
|
||||
if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
|
||||
while (FZRec.avail_in > 0) do
|
||||
begin
|
||||
CCheck(deflate(FZRec, 0));
|
||||
if FZRec.avail_out = 0 then
|
||||
begin
|
||||
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
|
||||
FZRec.next_out := FBuffer;
|
||||
FZRec.avail_out := sizeof(FBuffer);
|
||||
FStrmPos := FStrm.Position;
|
||||
Progress(Self);
|
||||
end;
|
||||
end;
|
||||
Result := Count;
|
||||
end;
|
||||
|
||||
function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||||
begin
|
||||
if (Offset = 0) and (Origin = soFromCurrent) then
|
||||
Result := FZRec.total_in
|
||||
else
|
||||
raise ECompressionError.Create('Invalid stream operation');
|
||||
end;
|
||||
|
||||
function TCompressionStream.GetCompressionRate: Single;
|
||||
begin
|
||||
if FZRec.total_in = 0 then
|
||||
Result := 0
|
||||
else
|
||||
Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
|
||||
end;
|
||||
|
||||
|
||||
// TDecompressionStream
|
||||
|
||||
constructor TDecompressionStream.Create(Source: TStream);
|
||||
begin
|
||||
inherited Create(Source);
|
||||
FZRec.next_in := FBuffer;
|
||||
FZRec.avail_in := 0;
|
||||
DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
|
||||
end;
|
||||
|
||||
destructor TDecompressionStream.Destroy;
|
||||
begin
|
||||
inflateEnd(FZRec);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
|
||||
begin
|
||||
FZRec.next_out := @Buffer;
|
||||
FZRec.avail_out := Count;
|
||||
if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
|
||||
while (FZRec.avail_out > 0) do
|
||||
begin
|
||||
if FZRec.avail_in = 0 then
|
||||
begin
|
||||
FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
|
||||
if FZRec.avail_in = 0 then
|
||||
begin
|
||||
Result := Count - FZRec.avail_out;
|
||||
Exit;
|
||||
end;
|
||||
FZRec.next_in := FBuffer;
|
||||
FStrmPos := FStrm.Position;
|
||||
Progress(Self);
|
||||
end;
|
||||
DCheck(inflate(FZRec, 0));
|
||||
end;
|
||||
Result := Count;
|
||||
end;
|
||||
|
||||
function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
|
||||
begin
|
||||
raise EDecompressionError.Create('Invalid stream operation');
|
||||
end;
|
||||
|
||||
function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||||
var
|
||||
I: Integer;
|
||||
Buf: array [0..4095] of Char;
|
||||
begin
|
||||
if (Offset = 0) and (Origin = soFromBeginning) then
|
||||
begin
|
||||
DCheck(inflateReset(FZRec));
|
||||
FZRec.next_in := FBuffer;
|
||||
FZRec.avail_in := 0;
|
||||
FStrm.Position := 0;
|
||||
FStrmPos := 0;
|
||||
end
|
||||
else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
|
||||
( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
|
||||
begin
|
||||
if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
|
||||
if Offset > 0 then
|
||||
begin
|
||||
for I := 1 to Offset div sizeof(Buf) do
|
||||
ReadBuffer(Buf, sizeof(Buf));
|
||||
ReadBuffer(Buf, Offset mod sizeof(Buf));
|
||||
end;
|
||||
end
|
||||
else
|
||||
raise EDecompressionError.Create('Invalid stream operation');
|
||||
Result := FZRec.total_out;
|
||||
end;
|
||||
|
||||
end.
|
174
zlib/contrib/delphi2/zlib32.bpr
Normal file
174
zlib/contrib/delphi2/zlib32.bpr
Normal file
@ -0,0 +1,174 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCB)
|
||||
BCB = $(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# IDE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# The following section of the project makefile is managed by the BCB IDE.
|
||||
# It is recommended to use the IDE to change any of the values in this
|
||||
# section.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
VERSION = BCB.03
|
||||
# ---------------------------------------------------------------------------
|
||||
PROJECT = zlib32.dll
|
||||
OBJFILES = zlib32.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \
|
||||
infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \
|
||||
uncompr.obj zutil.obj
|
||||
RESFILES =
|
||||
RESDEPEN = $(RESFILES)
|
||||
LIBFILES =
|
||||
LIBRARIES =
|
||||
SPARELIBS =
|
||||
DEFFILE =
|
||||
PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \
|
||||
dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \
|
||||
NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi
|
||||
# ---------------------------------------------------------------------------
|
||||
PATHCPP = .;
|
||||
PATHASM = .;
|
||||
PATHPAS = .;
|
||||
PATHRC = .;
|
||||
DEBUGLIBPATH = $(BCB)\lib\debug
|
||||
RELEASELIBPATH = $(BCB)\lib\release
|
||||
# ---------------------------------------------------------------------------
|
||||
CFLAG1 = -WD -O2 -Ve -d -k- -vi -c -tWD
|
||||
CFLAG2 = -D_NO_VCL;ZLIB_DLL -I$(BCB)\include
|
||||
CFLAG3 = -ff -5
|
||||
PFLAGS = -D_NO_VCL;ZLIB_DLL -U$(BCB)\lib;$(RELEASELIBPATH) -I$(BCB)\include -$I- -v \
|
||||
-JPHN -M
|
||||
RFLAGS = -D_NO_VCL;ZLIB_DLL -i$(BCB)\include
|
||||
AFLAGS = /i$(BCB)\include /d_NO_VCL /dZLIB_DLL /mx /w2 /zn
|
||||
LFLAGS = -L$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gi
|
||||
IFLAGS = -Gn -g
|
||||
# ---------------------------------------------------------------------------
|
||||
ALLOBJ = c0d32.obj $(OBJFILES)
|
||||
ALLRES = $(RESFILES)
|
||||
ALLLIB = $(LIBFILES) import32.lib cw32mt.lib
|
||||
# ---------------------------------------------------------------------------
|
||||
!ifdef IDEOPTIONS
|
||||
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=1
|
||||
Locale=1040
|
||||
CodePage=1252
|
||||
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=DLL (GUI)
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
|
||||
[HistoryLists\hlIncludePath]
|
||||
Count=1
|
||||
Item0=$(BCB)\include
|
||||
|
||||
[HistoryLists\hlLibraryPath]
|
||||
Count=1
|
||||
Item0=$(BCB)\lib
|
||||
|
||||
[HistoryLists\hlConditionals]
|
||||
Count=1
|
||||
Item0=_NO_VCL;ZLIB_DLL
|
||||
|
||||
[Debugging]
|
||||
DebugSourceDirs=
|
||||
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
|
||||
!endif
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MAKE SECTION
|
||||
# ---------------------------------------------------------------------------
|
||||
# This section of the project file is not used by the BCB IDE. It is for
|
||||
# the benefit of building from the command-line using the MAKE utility.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
.autodepend
|
||||
# ---------------------------------------------------------------------------
|
||||
!if !$d(BCC32)
|
||||
BCC32 = bcc32
|
||||
!endif
|
||||
|
||||
!if !$d(DCC32)
|
||||
DCC32 = dcc32
|
||||
!endif
|
||||
|
||||
!if !$d(TASM32)
|
||||
TASM32 = tasm32
|
||||
!endif
|
||||
|
||||
!if !$d(LINKER)
|
||||
LINKER = ilink32
|
||||
!endif
|
||||
|
||||
!if !$d(BRCC32)
|
||||
BRCC32 = brcc32
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
!if $d(PATHCPP)
|
||||
.PATH.CPP = $(PATHCPP)
|
||||
.PATH.C = $(PATHCPP)
|
||||
!endif
|
||||
|
||||
!if $d(PATHPAS)
|
||||
.PATH.PAS = $(PATHPAS)
|
||||
!endif
|
||||
|
||||
!if $d(PATHASM)
|
||||
.PATH.ASM = $(PATHASM)
|
||||
!endif
|
||||
|
||||
!if $d(PATHRC)
|
||||
.PATH.RC = $(PATHRC)
|
||||
!endif
|
||||
# ---------------------------------------------------------------------------
|
||||
$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
|
||||
$(BCB)\BIN\$(LINKER) @&&!
|
||||
$(LFLAGS) $(IFLAGS) +
|
||||
$(ALLOBJ), +
|
||||
$(PROJECT),, +
|
||||
$(ALLLIB), +
|
||||
$(DEFFILE), +
|
||||
$(ALLRES)
|
||||
!
|
||||
# ---------------------------------------------------------------------------
|
||||
.pas.hpp:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.pas.obj:
|
||||
$(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
|
||||
|
||||
.cpp.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.c.obj:
|
||||
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< }
|
||||
|
||||
.asm.obj:
|
||||
$(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@
|
||||
|
||||
.rc.res:
|
||||
$(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $<
|
||||
# ---------------------------------------------------------------------------
|
42
zlib/contrib/delphi2/zlib32.cpp
Normal file
42
zlib/contrib/delphi2/zlib32.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
#include <windows.h>
|
||||
#pragma hdrstop
|
||||
#include <condefs.h>
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Important note about DLL memory management in a VCL DLL:
|
||||
//
|
||||
//
|
||||
//
|
||||
// If your DLL uses VCL and exports any functions that pass VCL String objects
|
||||
// (or structs/classes containing nested Strings) as parameter or function
|
||||
// results, you will need to build both your DLL project and any EXE projects
|
||||
// that use your DLL with the dynamic RTL (the RTL DLL). This will change your
|
||||
// DLL and its calling EXE's to use BORLNDMM.DLL as their memory manager. In
|
||||
// these cases, the file BORLNDMM.DLL should be deployed along with your DLL
|
||||
// and the RTL DLL (CP3240MT.DLL). To avoid the requiring BORLNDMM.DLL in
|
||||
// these situations, pass string information using "char *" or ShortString
|
||||
// parameters and then link with the static RTL.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
USEUNIT("adler32.c");
|
||||
USEUNIT("compress.c");
|
||||
USEUNIT("crc32.c");
|
||||
USEUNIT("deflate.c");
|
||||
USEUNIT("gzio.c");
|
||||
USEUNIT("infblock.c");
|
||||
USEUNIT("infcodes.c");
|
||||
USEUNIT("inffast.c");
|
||||
USEUNIT("inflate.c");
|
||||
USEUNIT("inftrees.c");
|
||||
USEUNIT("infutil.c");
|
||||
USEUNIT("trees.c");
|
||||
USEUNIT("uncompr.c");
|
||||
USEUNIT("zutil.c");
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma argsused
|
||||
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
|
||||
{
|
||||
return 1;
|
||||
}
|
24
zlib/contrib/iostream/test.cpp
Normal file
24
zlib/contrib/iostream/test.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include "zfstream.h"
|
||||
|
||||
int main() {
|
||||
|
||||
// Construct a stream object with this filebuffer. Anything sent
|
||||
// to this stream will go to standard out.
|
||||
gzofstream os( 1, ios::out );
|
||||
|
||||
// This text is getting compressed and sent to stdout.
|
||||
// To prove this, run 'test | zcat'.
|
||||
os << "Hello, Mommy" << endl;
|
||||
|
||||
os << setcompressionlevel( Z_NO_COMPRESSION );
|
||||
os << "hello, hello, hi, ho!" << endl;
|
||||
|
||||
setcompressionlevel( os, Z_DEFAULT_COMPRESSION )
|
||||
<< "I'm compressing again" << endl;
|
||||
|
||||
os.close();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
329
zlib/contrib/iostream/zfstream.cpp
Normal file
329
zlib/contrib/iostream/zfstream.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
|
||||
#include <memory.h>
|
||||
#include "zfstream.h"
|
||||
|
||||
gzfilebuf::gzfilebuf() :
|
||||
file(NULL),
|
||||
mode(0),
|
||||
own_file_descriptor(0)
|
||||
{ }
|
||||
|
||||
gzfilebuf::~gzfilebuf() {
|
||||
|
||||
sync();
|
||||
if ( own_file_descriptor )
|
||||
close();
|
||||
|
||||
}
|
||||
|
||||
gzfilebuf *gzfilebuf::open( const char *name,
|
||||
int io_mode ) {
|
||||
|
||||
if ( is_open() )
|
||||
return NULL;
|
||||
|
||||
char char_mode[10];
|
||||
char *p;
|
||||
memset(char_mode,'\0',10);
|
||||
p = char_mode;
|
||||
|
||||
if ( io_mode & ios::in ) {
|
||||
mode = ios::in;
|
||||
*p++ = 'r';
|
||||
} else if ( io_mode & ios::app ) {
|
||||
mode = ios::app;
|
||||
*p++ = 'a';
|
||||
} else {
|
||||
mode = ios::out;
|
||||
*p++ = 'w';
|
||||
}
|
||||
|
||||
if ( io_mode & ios::binary ) {
|
||||
mode |= ios::binary;
|
||||
*p++ = 'b';
|
||||
}
|
||||
|
||||
// Hard code the compression level
|
||||
if ( io_mode & (ios::out|ios::app )) {
|
||||
*p++ = '9';
|
||||
}
|
||||
|
||||
if ( (file = gzopen(name, char_mode)) == NULL )
|
||||
return NULL;
|
||||
|
||||
own_file_descriptor = 1;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
gzfilebuf *gzfilebuf::attach( int file_descriptor,
|
||||
int io_mode ) {
|
||||
|
||||
if ( is_open() )
|
||||
return NULL;
|
||||
|
||||
char char_mode[10];
|
||||
char *p;
|
||||
memset(char_mode,'\0',10);
|
||||
p = char_mode;
|
||||
|
||||
if ( io_mode & ios::in ) {
|
||||
mode = ios::in;
|
||||
*p++ = 'r';
|
||||
} else if ( io_mode & ios::app ) {
|
||||
mode = ios::app;
|
||||
*p++ = 'a';
|
||||
} else {
|
||||
mode = ios::out;
|
||||
*p++ = 'w';
|
||||
}
|
||||
|
||||
if ( io_mode & ios::binary ) {
|
||||
mode |= ios::binary;
|
||||
*p++ = 'b';
|
||||
}
|
||||
|
||||
// Hard code the compression level
|
||||
if ( io_mode & (ios::out|ios::app )) {
|
||||
*p++ = '9';
|
||||
}
|
||||
|
||||
if ( (file = gzdopen(file_descriptor, char_mode)) == NULL )
|
||||
return NULL;
|
||||
|
||||
own_file_descriptor = 0;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
gzfilebuf *gzfilebuf::close() {
|
||||
|
||||
if ( is_open() ) {
|
||||
|
||||
sync();
|
||||
gzclose( file );
|
||||
file = NULL;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::setcompressionlevel( short comp_level ) {
|
||||
|
||||
return gzsetparams(file, comp_level, -2);
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::setcompressionstrategy( short comp_strategy ) {
|
||||
|
||||
return gzsetparams(file, -2, comp_strategy);
|
||||
|
||||
}
|
||||
|
||||
|
||||
streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) {
|
||||
|
||||
return streampos(EOF);
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::underflow() {
|
||||
|
||||
// If the file hasn't been opened for reading, error.
|
||||
if ( !is_open() || !(mode & ios::in) )
|
||||
return EOF;
|
||||
|
||||
// if a buffer doesn't exists, allocate one.
|
||||
if ( !base() ) {
|
||||
|
||||
if ( (allocate()) == EOF )
|
||||
return EOF;
|
||||
setp(0,0);
|
||||
|
||||
} else {
|
||||
|
||||
if ( in_avail() )
|
||||
return (unsigned char) *gptr();
|
||||
|
||||
if ( out_waiting() ) {
|
||||
if ( flushbuf() == EOF )
|
||||
return EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Attempt to fill the buffer.
|
||||
|
||||
int result = fillbuf();
|
||||
if ( result == EOF ) {
|
||||
// disable get area
|
||||
setg(0,0,0);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return (unsigned char) *gptr();
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::overflow( int c ) {
|
||||
|
||||
if ( !is_open() || !(mode & ios::out) )
|
||||
return EOF;
|
||||
|
||||
if ( !base() ) {
|
||||
if ( allocate() == EOF )
|
||||
return EOF;
|
||||
setg(0,0,0);
|
||||
} else {
|
||||
if (in_avail()) {
|
||||
return EOF;
|
||||
}
|
||||
if (out_waiting()) {
|
||||
if (flushbuf() == EOF)
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
int bl = blen();
|
||||
setp( base(), base() + bl);
|
||||
|
||||
if ( c != EOF ) {
|
||||
|
||||
*pptr() = c;
|
||||
pbump(1);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::sync() {
|
||||
|
||||
if ( !is_open() )
|
||||
return EOF;
|
||||
|
||||
if ( out_waiting() )
|
||||
return flushbuf();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::flushbuf() {
|
||||
|
||||
int n;
|
||||
char *q;
|
||||
|
||||
q = pbase();
|
||||
n = pptr() - q;
|
||||
|
||||
if ( gzwrite( file, q, n) < n )
|
||||
return EOF;
|
||||
|
||||
setp(0,0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int gzfilebuf::fillbuf() {
|
||||
|
||||
int required;
|
||||
char *p;
|
||||
|
||||
p = base();
|
||||
|
||||
required = blen();
|
||||
|
||||
int t = gzread( file, p, required );
|
||||
|
||||
if ( t <= 0) return EOF;
|
||||
|
||||
setg( base(), base(), base()+t);
|
||||
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
gzfilestream_common::gzfilestream_common() :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{ }
|
||||
|
||||
gzfilestream_common::~gzfilestream_common()
|
||||
{ }
|
||||
|
||||
void gzfilestream_common::attach( int fd, int io_mode ) {
|
||||
|
||||
if ( !buffer.attach( fd, io_mode) )
|
||||
clear( ios::failbit | ios::badbit );
|
||||
else
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
void gzfilestream_common::open( const char *name, int io_mode ) {
|
||||
|
||||
if ( !buffer.open( name, io_mode ) )
|
||||
clear( ios::failbit | ios::badbit );
|
||||
else
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
void gzfilestream_common::close() {
|
||||
|
||||
if ( !buffer.close() )
|
||||
clear( ios::failbit | ios::badbit );
|
||||
|
||||
}
|
||||
|
||||
gzfilebuf *gzfilestream_common::rdbuf() {
|
||||
|
||||
return &buffer;
|
||||
|
||||
}
|
||||
|
||||
gzifstream::gzifstream() :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
clear( ios::badbit );
|
||||
}
|
||||
|
||||
gzifstream::gzifstream( const char *name, int io_mode ) :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
gzfilestream_common::open( name, io_mode );
|
||||
}
|
||||
|
||||
gzifstream::gzifstream( int fd, int io_mode ) :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
gzfilestream_common::attach( fd, io_mode );
|
||||
}
|
||||
|
||||
gzifstream::~gzifstream() { }
|
||||
|
||||
gzofstream::gzofstream() :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
clear( ios::badbit );
|
||||
}
|
||||
|
||||
gzofstream::gzofstream( const char *name, int io_mode ) :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
gzfilestream_common::open( name, io_mode );
|
||||
}
|
||||
|
||||
gzofstream::gzofstream( int fd, int io_mode ) :
|
||||
ios( gzfilestream_common::rdbuf() )
|
||||
{
|
||||
gzfilestream_common::attach( fd, io_mode );
|
||||
}
|
||||
|
||||
gzofstream::~gzofstream() { }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user